diff --git a/znai-core/src/main/java/org/testingisdocumenting/znai/extensions/footnote/ParsedFootnote.java b/znai-core/src/main/java/org/testingisdocumenting/znai/extensions/footnote/ParsedFootnote.java index 035e9bf63..3e2e5987a 100644 --- a/znai-core/src/main/java/org/testingisdocumenting/znai/extensions/footnote/ParsedFootnote.java +++ b/znai-core/src/main/java/org/testingisdocumenting/znai/extensions/footnote/ParsedFootnote.java @@ -41,6 +41,7 @@ public static ParsedFootnote parse(ComponentsRegistry componentsRegistry, Path m var visitor = new MarkdownVisitor(componentsRegistry, markdownPath, new MarkdownParsingContext(), parserHandler); visit(visitor, footnote); + parserHandler.onParsingEnd(); List searchEntries = searchHandler.getSearchEntries(); DocElement docElement = docElementsHandler.getDocElement(); diff --git a/znai-core/src/main/java/org/testingisdocumenting/znai/markdown/MarkdownGeneratorParserHandler.java b/znai-core/src/main/java/org/testingisdocumenting/znai/markdown/MarkdownGeneratorParserHandler.java index 8b10ddf7d..de90a33f1 100644 --- a/znai-core/src/main/java/org/testingisdocumenting/znai/markdown/MarkdownGeneratorParserHandler.java +++ b/znai-core/src/main/java/org/testingisdocumenting/znai/markdown/MarkdownGeneratorParserHandler.java @@ -288,28 +288,12 @@ public void onSnippet(PluginParams pluginParams, String lang, String lineNumber, @Override public void onTable(MarkupTableData tableData) { - List columnTitles = tableData.getColumnTitles(); - List> data = tableData.getData(); - - if (columnTitles.isEmpty()) { + String markdownTable = tableData.toMarkdown(); + if (markdownTable.isEmpty()) { return; } - currentMarkdown.append("| ").append(String.join(" | ", columnTitles)).append(" |\n"); - currentMarkdown.append("|").append(" --- |".repeat(columnTitles.size())).append("\n"); - - for (List row : data) { - currentMarkdown.append("| "); - for (int i = 0; i < columnTitles.size(); i++) { - String cell = i < row.size() && row.get(i) != null ? row.get(i).toString() : ""; - currentMarkdown.append(cell.replace("|", "\\|")); - if (i < columnTitles.size() - 1) { - currentMarkdown.append(" | "); - } - } - currentMarkdown.append(" |\n"); - } - currentMarkdown.append("\n\n"); + currentMarkdown.append(markdownTable).append("\n\n"); } @Override diff --git a/znai-core/src/main/java/org/testingisdocumenting/znai/parser/table/MarkupTableData.java b/znai-core/src/main/java/org/testingisdocumenting/znai/parser/table/MarkupTableData.java index f159b16aa..2599db6ae 100644 --- a/znai-core/src/main/java/org/testingisdocumenting/znai/parser/table/MarkupTableData.java +++ b/znai-core/src/main/java/org/testingisdocumenting/znai/parser/table/MarkupTableData.java @@ -93,6 +93,31 @@ public String allText() { return String.join(" ", textParts); } + public String toMarkdown() { + if (header.isEmpty()) { + return ""; + } + + StringBuilder markdown = new StringBuilder(); + List columnTitles = getColumnTitles(); + markdown.append("| ").append(String.join(" | ", columnTitles)).append(" |\n"); + markdown.append("|").append(" --- |".repeat(columnTitles.size())).append("\n"); + + for (List row : getData()) { + markdown.append("| "); + for (int i = 0; i < columnTitles.size(); i++) { + String cell = i < row.size() && row.get(i) != null ? row.get(i).toString() : ""; + markdown.append(cell.replace("|", "\\|")); + if (i < columnTitles.size() - 1) { + markdown.append(" | "); + } + } + markdown.append(" |\n"); + } + + return markdown.toString().stripTrailing(); + } + public MarkupTableData withColumnsInOrder(List columnNames) { List newIdxOrder = findColumnIdxes(columnNames); @@ -111,7 +136,7 @@ public MarkupTableData withoutRowsMatchingRegexp(List regexpList) { } public MarkupTableData withRowsRegexpPredicate(List regexpList, BiFunction predicate) { - List patternsList = regexpList.stream().map(Pattern::compile).collect(toList()); + List patternsList = regexpList.stream().map(Pattern::compile).toList(); List newRows = data.stream() .filter(row -> patternsList.stream().anyMatch(regexp -> predicate.apply(row, regexp))) .collect(toList()); diff --git a/znai-docs/znai/llm.txt b/znai-docs/znai/llm.txt index 4848613a0..9deadeda6 100644 --- a/znai-docs/znai/llm.txt +++ b/znai-docs/znai/llm.txt @@ -146,8 +146,8 @@ answer-link: znai-from-export/introduction/getting-started#command-line ## CLI download Download and unzip -[znai](https://repo.maven.apache.org/maven2/org/testingisdocumenting/znai/znai-dist/1.91/znai-dist-1.91-znai.zip). Add -it to your `PATH`. +[znai](https://repo.maven.apache.org/maven2/org/testingisdocumenting/znai/znai-dist/1.92-SNAPSHOT/znai-dist-1.92-SNAPSHOT-znai.zip). +Add it to your `PATH`. ## Brew @@ -162,7 +162,7 @@ answer-link: znai-from-export/introduction/getting-started#maven-plugin org.testingisdocumenting.znai znai-maven-plugin - 1.91 + 1.92-SNAPSHOT ``` @@ -910,7 +910,7 @@ To define a footnote use To add a reference to the footnote use `[^my-id]` which will result in [^my-id] -[^my-id]: +[^my-id]: extra content for my footnote goes here potentially including code blocks Constructor Note: numeric footnotes are treated as text footnotes, and they will be assigned the auto incremented number in order of appearance. @@ -938,7 +938,7 @@ answer-link: znai-from-export/flow/footnotes#footnotes-list A footnotes list is automatically appended at the end of the page when footnotes are present. Clicking the number in the list navigates back to the reference [^another-note]. -[^another-note]: +[^another-note]: This is another footnote to demonstrate the list with multiple entries To hide the footnotes list, set `hideFootnoteList` to `true` in `meta.json`: @@ -4766,7 +4766,7 @@ package webtauexamples import static org.testingisdocumenting.webtau.WebTauGroovyDsl.* -def homeSearchInput = $('input[class*="searchbox_input"], input[class*="search-input"]') +def homeSearchInput = $('textarea[class*="search-input"], input[class*="searchbox_input"], input[class*="search-input"]') def resultSearchInput = $("#search_form_input") def result = $('article[data-testid="result"]') @@ -6945,6 +6945,12 @@ Account, Price, Description ``` ``` +| Account | Price | Description | +| --- | --- | --- | +| #12BGD3 | 100 | custom table with a long attachment | +| #12BGD3 | 150 | chair | +| #91AGB1 | 10 | lunch | + # Layout :: Tables :: Multiline Content answer-link: znai-from-export/layout/tables#multiline-content @@ -8978,7 +8984,7 @@ package webtauexamples import static org.testingisdocumenting.webtau.WebTauGroovyDsl.* -def homeSearchInput = $('input[class*="searchbox_input"], input[class*="search-input"]') +def homeSearchInput = $('textarea[class*="search-input"], input[class*="searchbox_input"], input[class*="search-input"]') def resultSearchInput = $("#search_form_input") def result = $('article[data-testid="result"]') @@ -10089,6 +10095,11 @@ export PATH=$(pwd)/dist:$PATH znai --version ``` +# Release Notes :: 2026 :: 1.92 +answer-link: znai-from-export/release-notes/2026#192 + + + # Release Notes :: 2026 :: 1.91 answer-link: znai-from-export/release-notes/2026#191 diff --git a/znai-docs/znai/release-notes/1.92/fix-2026-08-25-llm-txt-missing-table-and-footnote.md b/znai-docs/znai/release-notes/1.92/fix-2026-08-25-llm-txt-missing-table-and-footnote.md new file mode 100644 index 000000000..640dc5240 --- /dev/null +++ b/znai-docs/znai/release-notes/1.92/fix-2026-08-25-llm-txt-missing-table-and-footnote.md @@ -0,0 +1,2 @@ +* Fix: llm.txt no longer misses content from Table fence plugin +* Fix: llm.txt no longer misses content from footnotes diff --git a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/extensions/table/TableFencePlugin.java b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/extensions/table/TableFencePlugin.java index 1e56c1b91..f3c6aeb42 100644 --- a/znai-website-gen/src/main/java/org/testingisdocumenting/znai/extensions/table/TableFencePlugin.java +++ b/znai-website-gen/src/main/java/org/testingisdocumenting/znai/extensions/table/TableFencePlugin.java @@ -69,4 +69,9 @@ public PluginResult process(ComponentsRegistry componentsRegistry, Path markupPa public List textForSearch() { return List.of(SearchScore.STANDARD.text(docElementFromParams.getModifiedTable().allText())); } + + @Override + public String markdownRepresentation() { + return docElementFromParams.getModifiedTable().toMarkdown(); + } } diff --git a/znai-website-gen/src/test/groovy/org/testingisdocumenting/znai/website/LlmContentGeneratorTest.groovy b/znai-website-gen/src/test/groovy/org/testingisdocumenting/znai/website/LlmContentGeneratorTest.groovy index 752706979..36f979349 100644 --- a/znai-website-gen/src/test/groovy/org/testingisdocumenting/znai/website/LlmContentGeneratorTest.groovy +++ b/znai-website-gen/src/test/groovy/org/testingisdocumenting/znai/website/LlmContentGeneratorTest.groovy @@ -323,6 +323,55 @@ def hello(): """ } + @Test + void "includes table fence block as markdown table"() { + def markdown = """# Table Section + +```table +Account, Price, Description +#12BGD3, 100, custom table +#91AGB1, 150, chair +``` +""" + + def content = generateContent(markdown) + + content.should == """[//]: # (this is an auto generated file) +"Test Guide" full guide: + +# Chapter :: Page One :: Table Section +answer-link: https://example.com/test/chapter/page-one#table-section + +| Account | Price | Description | +| --- | --- | --- | +| #12BGD3 | 100 | custom table | +| #91AGB1 | 150 | chair | +""" + } + + @Test + void "includes footnotes"() { + def markdown = """# Footnote Section + +Main text[^my-note] here. + +[^my-note]: additional footnote text +""" + + def content = generateContent(markdown) + + content.should == """[//]: # (this is an auto generated file) +"Test Guide" full guide: + +# Chapter :: Page One :: Footnote Section +answer-link: https://example.com/test/chapter/page-one#footnote-section + +Main text[^my-note] here. + +[^my-note]: additional footnote text +""" + } + private static String generateContent(String markdown) { def docMeta = new DocMeta([id: "test", title: "Test Guide"])