Skip to content

[#315] Fix AntoraMojo xref and leveloffset conversion - #316

Merged
vharseko merged 2 commits into
OpenIdentityPlatform:masterfrom
vharseko:issue-315-antora-xref
Oct 1, 2026
Merged

vharseko merged 2 commits into
OpenIdentityPlatform:masterfrom
vharseko:issue-315-antora-xref

Conversation

@vharseko

@vharseko vharseko commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Fixes #315

Changes in AntoraMojo

  1. xref:./file.adoc → invalid .:file.adoc. Every run of ./ segments, leading or inner (./, ././, a/././b), is now dropped from xref targets before / is converted to :, so xref:./chap-jee-agent-config.adoc#configure-j2ee-policy-agent[...] becomes xref:chap-jee-agent-config.adoc#configure-j2ee-policy-agent[...] and xref:a/././b.adoc[...] becomes xref:a:b.adoc[...]. Cross-module xrefs (../reference/ch02.adoc → reference:ch02.adoc) are unchanged.
  2. Stray quote after :leveloffset: -1. The inserted line is now :leveloffset: -1 without the trailing ".
  3. Legacy cross-guide links. Links like link:../../../openam/13/admin-guide/... cannot be converted automatically: nothing maps them to their target. The mojo now logs a warning for each one, naming the file and the link. It does not fail the build, because the OpenAM and OpenIDM doc builds still contain about 40 of these links and would break until those are fixed in the product repositories.

convertForAntora / convertXrefsToAntora are now package-private static so they can be unit-tested; the legacy-link lookup is extracted into findLegacyLinks, and warnLegacyLinks is package-private.

Tests

Added six unit tests to AntoraMojoTest: an xref with ./, repeated ./ segments (leading and inner), a cross-module xref, leveloffset without the quote, legacy-link detection, and the legacy-link warning naming the file and the link. The two warnLegacyLinks call sites in execute() are not covered: that needs a fixture that runs the whole mojo. mvn -pl commons/doc-maven-plugin -am test -Dtest=AntoraMojoTest: 7 tests, 0 failures.

…sion

- Drop leading "./" and "/./" segments from xref targets before
  converting them to Antora resource IDs, so xref:./file.adoc no longer
  becomes the invalid .:file.adoc.
- Remove the stray quote inserted after ":leveloffset: -1".
- Warn about legacy cross-guide links (link:../../../...) that are not
  converted and resolve to 404 on the Antora site.

Fixes OpenIdentityPlatform#315
@vharseko vharseko added bug documentation Documentation and Javadoc changes tests Test code changes java Pull requests that update java code labels Sep 30, 2026

@maximthomas maximthomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: The fix is in the right place, and each of the three changes has a unit test.

  • convertXrefsToAntora now strips a leading ./ and inner /./ before converting / to : (AntoraMojo.java:159-163). As a result, xref:./chap-jee-agent-config.adoc#… becomes a valid page id.
  • findLegacyLinks is extracted into its own method. testFindLegacyLinks pins it, including the link:../attachments/ case that must not match.
  • testLeveloffsetHasNoStrayQuote checks that :leveloffset: -1 no longer has the trailing quote.

issue (non-blocking): Back-to-back /./ segments are only partly removed, so the xref still becomes an invalid resource id.

commons/doc-maven-plugin/src/main/java/org/openidentityplatform/doc/maven/AntoraMojo.java:160

String.replace("/./", "/") makes a single pass and does not re-check the text it has just replaced. The while at :161 only removes a leading ./. As a result, xref:a/././b.adoc[x] becomes xref:a:.:b.adoc[x], and xref:../mod/././p.adoc[x] becomes xref:mod:.:p.adoc[x]. Both results come from running an exact copy of :159-164 in jshell, and the build prints no warning for them. No .adoc file in this repository contains such an xref. The product doc repositories were not checked.

while (url.contains("/./")) {
    url = url.replace("/./", "/");
}

Pin: AntoraMojo.convertXrefsToAntora("xref:a/././b.adoc[B]") should return xref:a:b.adoc[B]. At the head it returns xref:a:.:b.adoc[B], so the test fails.


suggestion (non-blocking): No test would fail if the while at AntoraMojo.java:161 were changed to an if.

commons/doc-maven-plugin/src/test/java/org/openidentityplatform/doc/maven/AntoraMojoTest.java:53-65

Every xref input in the tests gives the same output with while and with if. ././x.adoc does not tell them apart either, because the /./ replace at :160 first turns it into ./x.adoc. ./././x.adoc does: it gives x.adoc with while and .:x.adoc with if. If you apply the /./ fix above, the while and an if behave the same, and this test simply pins the output.

@Test
public void testConvertXrefWithRepeatedCurrentDirPrefix() {
    assertThat(AntoraMojo.convertXrefsToAntora("xref:./././a.adoc[A]"))
            .isEqualTo("xref:a.adoc[A]");
}

Pin: at the head, this test fails if the while at :161 is changed to an if.


suggestion (non-blocking): No test reaches warnLegacyLinks or the two places that call it, AntoraMojo.java:95 and :133.

commons/doc-maven-plugin/src/test/java/org/openidentityplatform/doc/maven/AntoraMojoTest.java:42-50

testExecute only calls lookupMojo and configureMojo. No test in the module calls execute(), and execute() is the only way to reach warnLegacyLinks. Deleting either call site, or the getLog().warn at :191, leaves all 5 tests green. The only part that is tested is the regex in findLegacyLinks.

// AntoraMojo: drop `private` from warnLegacyLinks.
// AntoraMojoTest imports: java.util.ArrayList, java.util.List,
// org.apache.maven.plugin.logging.SystemStreamLog
@Test
public void testWarnLegacyLinksNamesFileAndLink() {
    AntoraMojo mojo = new AntoraMojo();
    List<String> warnings = new ArrayList<>();
    mojo.setLog(new SystemStreamLog() {
        @Override
        public void warn(CharSequence content) {
            warnings.add(content.toString());
        }
    });
    mojo.warnLegacyLinks(new File("chap-cdsso.adoc"),
            "link:../../../openam/13/admin-guide/#chap-cdsso[CDSSO]");
    assertThat(warnings).hasSize(1);
    assertThat(warnings.get(0)).contains("chap-cdsso.adoc", "link:../../../openam/13/admin-guide/#chap-cdsso");
}

Pin: this test fails if the warning is removed or stops naming the file or the link. To also cover the calls at :95 and :133, a test would need a fixture that runs execute().

- Drop every run of "./" segments, leading or inner, with one regex, so
  xref:a/././b.adoc no longer becomes the invalid a:.:b.adoc.
- Test repeated ./ segments and the legacy-link warning.
@vharseko

vharseko commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

@maximthomas all three points are addressed in 8fa80d9.

Back-to-back /./ segments. Fixed. The replace("/./", "/") and the leading-./ while loop are replaced by one regex that drops every run of ./ segments, leading or inner:

url = url.replaceAll("(^|/)(\\./)+", "$1");

xref:a/././b.adoc[B] now becomes xref:a:b.adoc[B], and xref:../mod/././p.adoc[P] becomes xref:mod:p.adoc[P]. Segments that only start with a dot, such as a/.b/c.adoc or x./y.adoc, are left as they were.

while vs if. The loop is gone with the change above. testConvertXrefWithRepeatedCurrentDirSegments pins ./././a.adoc → a.adoc together with the two inputs from the first point. At the previous head it fails on a/././b.adoc.

warnLegacyLinks coverage. warnLegacyLinks is now package-private, and testWarnLegacyLinksNamesFileAndLink captures the log and checks that the warning names both the file and the link. The two call sites in execute() are still not covered: that needs a fixture that runs the whole mojo, so I left it out of this PR.

mvn -pl commons/doc-maven-plugin -am test -Dtest=AntoraMojoTest: 7 tests, 0 failures.

@vharseko
vharseko requested a review from maximthomas October 1, 2026 12:43

@maximthomas maximthomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: Round 1's xref finding is fixed at the right place and pinned.

  • AntoraMojo.java:160: one anchored replaceAll("(^|/)(\\./)+", "$1") replaces the single-pass /./ replace and the leading-./ loop. Leading runs and inner runs now both convert: a/././b.adoc -> a:b.adoc, ../mod/././p.adoc -> mod:p.adoc.
  • testConvertXrefWithRepeatedCurrentDirSegments pins both forms. testWarnLegacyLinksNamesFileAndLink pins the warning text through a capturing SystemStreamLog.

@vharseko
vharseko merged commit 46a9c2b into OpenIdentityPlatform:master Oct 1, 2026
13 of 14 checks passed
@vharseko
vharseko deleted the issue-315-antora-xref branch October 1, 2026 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug documentation Documentation and Javadoc changes java Pull requests that update java code tests Test code changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

doc-maven-plugin AntoraMojo: xref:./file.adoc is converted to an invalid .:file.adoc

2 participants