This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 3e5c153767f1db0b339db42c97c69e9ba5f92c33 Author: Stephen Mallette <[email protected]> AuthorDate: Thu Jul 30 11:01:03 2026 -0400 Point each Markdown docs page at its own version's llms.txt Pages carried a hardcoded site-root /llms.txt, so a 3.7 page sent agents to whichever version published last. MarkdownSplitter now takes --version and emits the absolute versioned URL, matching the HTML footer. Stops publish-docs.sh from writing a copy of the index to the site root. Assisted-by: Claude Code:claude-opus-5 --- bin/process-docs.sh | 12 ++--- bin/publish-docs.sh | 11 ----- .../tinkerpop/tinkeradoc/MarkdownSplitter.java | 51 ++++++++++++++++++---- .../tinkerpop/tinkeradoc/MarkdownSplitterTest.java | 22 ++++++++++ 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/bin/process-docs.sh b/bin/process-docs.sh index efeea29986..aa0468bf7f 100755 --- a/bin/process-docs.sh +++ b/bin/process-docs.sh @@ -97,6 +97,11 @@ port_open() { fi } +# Resolve version from pom.xml. Needed by both the dry-run and full-build paths (the Markdown split +# stamps it into each page's llms.txt pointer), so it is resolved before either runs. +TP_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout 2>/dev/null || \ + grep -A1 '<artifactId>tinkerpop</artifactId>' pom.xml | grep -o 'version>[^<]*' | grep -o '>.*' | cut -d '>' -f2 | head -n1) + # --------------------------------------------------------------------------- # Markdown split (agentdocsspec.com) # --------------------------------------------------------------------------- @@ -119,7 +124,8 @@ split_markdown() { [ -z "${books}" ] && return 0 echo "Splitting Markdown books into agent-sized pages (summary-driven)..." # shellcheck disable=SC2086 - java -cp "${ext_classes}" org.apache.tinkerpop.tinkeradoc.MarkdownSplitter --strict ${books} + java -cp "${ext_classes}" org.apache.tinkerpop.tinkeradoc.MarkdownSplitter \ + --strict --version "${TP_VERSION}" ${books} # Generate the llms.txt discovery index over the split pages (agentdocsspec.com). echo "Generating llms.txt discovery index..." @@ -147,10 +153,6 @@ fi # Full build mode # --------------------------------------------------------------------------- -# Resolve version from pom.xml -TP_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout 2>/dev/null || \ - grep -A1 '<artifactId>tinkerpop</artifactId>' pom.xml | grep -o 'version>[^<]*' | grep -o '>.*' | cut -d '>' -f2 | head -n1) - # 1. Validate console distribution CONSOLE_DIR=$(ls -d gremlin-console/target/apache-tinkerpop-gremlin-console-*-standalone 2>/dev/null | head -n1) if [ -z "${CONSOLE_DIR}" ] || [ ! -d "${CONSOLE_DIR}" ]; then diff --git a/bin/publish-docs.sh b/bin/publish-docs.sh index 06639ce989..316ebb76e9 100755 --- a/bin/publish-docs.sh +++ b/bin/publish-docs.sh @@ -124,17 +124,6 @@ do fi done -# Generate the site-root /llms.txt (agentdocsspec.com discovery index) with ABSOLUTE links into the -# versioned docs tree, matching the per-page "> ... see [llms.txt](/llms.txt)" pointer. Absolute -# URLs are required for the spec's link-resolution checks. This index lives at the site root; the -# per-version llms.txt (also absolute now) is published alongside the pages via the loop above. -if [ -d "../docs/markdown" ] && [ -d "${PUBLISH_EXT_CLASSES}" ]; then - echo "Generating site-root llms.txt..." - java -cp "${PUBLISH_EXT_CLASSES}" org.apache.tinkerpop.tinkeradoc.LlmsTxtGenerator \ - --prefix "${SITE_DOCS_URL}/${VERSION}/" --out llms.txt ../docs/markdown - ${SVN_CMD} add --force llms.txt 2>/dev/null || true -fi - pushd "docs/${VERSION}/"; cat ../../../publish-docs.docs | awk '/^A/ {print $2}' | grep -v '.graffle$' | xargs --no-run-if-empty svn add --parents; popd pushd "javadocs/${VERSION}/"; cat ../../../publish-docs.javadocs | awk '/^A/ {print $2}' | xargs --no-run-if-empty svn add --parents; popd pushd "jsdocs/${VERSION}/"; cat ../../../publish-docs.jsdocs | awk '/^A/ {print $2}' | xargs --no-run-if-empty svn add --parents; popd diff --git a/docs/tinkeradoc-extension/src/main/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitter.java b/docs/tinkeradoc-extension/src/main/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitter.java index 6eabea91d0..70e284dd37 100644 --- a/docs/tinkeradoc-extension/src/main/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitter.java +++ b/docs/tinkeradoc-extension/src/main/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitter.java @@ -71,13 +71,28 @@ class MarkdownSplitter { private static final Logger LOG = Logger.getLogger(MarkdownSplitter.class.getName()); private final int budget; + private final String llmsPointer; MarkdownSplitter() { this(DEFAULT_BUDGET); } MarkdownSplitter(final int budget) { + this(budget, null); + } + + /** + * @param version the TinkerPop version these pages are published under, used to build the + * per-page index pointer. When {@code null} the pointer falls back to the + * site-root {@code /llms.txt}, which is not version-correct. + */ + MarkdownSplitter(final int budget, final String version) { this.budget = budget; + this.llmsPointer = llmsPointer(version); + if (version == null || version.isEmpty()) { + LOG.warning("No version supplied; pages will point at the site-root /llms.txt rather " + + "than this version's index. Pass --version to make the pointer version-correct."); + } } /** @@ -124,19 +139,23 @@ class MarkdownSplitter { } /** - * CLI entry point: {@code MarkdownSplitter [--budget N] [--strict] <book.md> [<book.md> ...]}. + * CLI entry point: + * {@code MarkdownSplitter [--budget N] [--strict] [--version x.y.z] <book.md> [<book.md> ...]}. * Each named rendered book file is split in place (summary-driven) into pages in its own * directory. Pages over the byte budget that are not flagged {@code allow-oversize} are reported; * with {@code --strict} the process exits non-zero when any such violation exists, so the docs - * build can gate on it. + * build can gate on it. {@code --version} sets the version the per-page index pointer resolves to. */ public static void main(final String[] args) throws IOException { int budget = DEFAULT_BUDGET; boolean strict = false; + String version = null; final List<String> files = new ArrayList<>(); for (int i = 0; i < args.length; i++) { if ("--budget".equals(args[i]) && i + 1 < args.length) { budget = Integer.parseInt(args[++i]); + } else if ("--version".equals(args[i]) && i + 1 < args.length) { + version = args[++i]; } else if ("--strict".equals(args[i])) { strict = true; } else { @@ -144,10 +163,11 @@ class MarkdownSplitter { } } if (files.isEmpty()) { - System.err.println("usage: MarkdownSplitter [--budget N] [--strict] <book.md> [<book.md> ...]"); + System.err.println("usage: MarkdownSplitter [--budget N] [--strict] [--version x.y.z] " + + "<book.md> [<book.md> ...]"); System.exit(2); } - final MarkdownSplitter splitter = new MarkdownSplitter(budget); + final MarkdownSplitter splitter = new MarkdownSplitter(budget, version); final List<String> violations = new ArrayList<>(); for (final String f : files) { final Path p = Path.of(f); @@ -250,7 +270,7 @@ class MarkdownSplitter { final StringBuilder body = new StringBuilder(); renderPage(plan.owner, body, plan == index, nodeToFile); final String rewritten = rewriteLinks(body.toString(), plan.fileName, anchorToFile); - pages.add(new Page(plan.fileName, LLMS_POINTER + rewritten, isAllowOversize(plan.owner))); + pages.add(new Page(plan.fileName, llmsPointer + rewritten, isAllowOversize(plan.owner))); } return pages; } @@ -380,12 +400,27 @@ class MarkdownSplitter { return null; } + /** Canonical base for the versioned documentation tree. */ + private static final String DOCS_BASE_URL = "https://tinkerpop.apache.org/docs"; + /** * The agent-facing directive prepended to every page (agentdocsspec.com {@code - * llms-txt-directive-md} check): a top-of-page blockquote pointing at the site-root index. + * llms-txt-directive-md} check): a top-of-page blockquote pointing at this version's index. + * <p> + * The URL is absolute and version-qualified so a page always points at the index describing that + * same version, mirroring the HTML backend's directive in {@code docs/src/docinfo-footer.html}. + * A site-root {@code /llms.txt} would instead resolve to whichever version published last. + * <p> + * The version cannot be substituted from the {@code x.y.z} placeholder the way the rest of the + * Markdown is: {@link MarkdownConverter} does that substitution while rendering, and the splitter + * runs afterwards as a separate pass over the already-rendered book. */ - static final String LLMS_POINTER = - "> For the complete documentation index, see [llms.txt](/llms.txt)\n\n"; + static String llmsPointer(final String version) { + final String url = version == null || version.isEmpty() + ? "/llms.txt" + : DOCS_BASE_URL + "/" + version + "/llms.txt"; + return "> For the complete documentation index, see [llms.txt](" + url + ")\n\n"; + } // ---- parsing ----------------------------------------------------------- diff --git a/docs/tinkeradoc-extension/src/test/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitterTest.java b/docs/tinkeradoc-extension/src/test/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitterTest.java index f6587e3d1a..9b389413a7 100644 --- a/docs/tinkeradoc-extension/src/test/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitterTest.java +++ b/docs/tinkeradoc-extension/src/test/java/org/apache/tinkerpop/tinkeradoc/MarkdownSplitterTest.java @@ -224,4 +224,26 @@ public class MarkdownSplitterTest { assertThat(body, containsString("```properties")); assertThat(body, containsString("After the block.")); } + + @Test + public void everyPagePointsAtItsOwnVersionsIndex() { + final String md = "preamble\n\n" + heading("io", 1, "IO Reference") + "\nintro\n\n" + + summarized("graphson", 1, "GraphSON", "The GraphSON format.") + "\nbody\n"; + final List<MarkdownSplitter.Page> pages = new MarkdownSplitter(MarkdownSplitter.DEFAULT_BUDGET, "3.7.7") + .split(md, "index.md"); + // Both the index page and the split-off page carry the directive, and it names 3.7.7 rather + // than resolving to whichever version published to the site root last. + for (final MarkdownSplitter.Page p : pages) { + assertThat(p.getContent(), containsString( + "> For the complete documentation index, see " + + "[llms.txt](https://tinkerpop.apache.org/docs/3.7.7/llms.txt)")); + assertThat(p.getContent(), not(containsString("[llms.txt](/llms.txt)"))); + } + } + + @Test + public void pointerFallsBackToSiteRootWithoutAVersion() { + assertThat(MarkdownSplitter.llmsPointer(null), containsString("[llms.txt](/llms.txt)")); + assertThat(MarkdownSplitter.llmsPointer(""), containsString("[llms.txt](/llms.txt)")); + } }
