| opendj-doc-generated-ref/CHECKS.md | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/pom.xml | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/src/main/asciidoc/getting-started/first-steps.adoc | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/src/main/asciidoc/getting-started/overview.adoc | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/src/main/asciidoc/release-notes/release-5.2.0.adoc | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/src/main/asciidoc/release-notes/requirements-and-upgrade.adoc | ●●●●● patch | view | raw | blame | history | |
| opendj-doc-generated-ref/src/test/java/org/openidentityplatform/opendj/doc/AntoraPageTitlesIT.java | ●●●●● patch | view | raw | blame | history |
opendj-doc-generated-ref/CHECKS.md
@@ -98,3 +98,37 @@ ```sh mvn compiler:testCompile surefire:test ``` The `man-pages` profile also runs `AntoraPageTitlesIT` during `verify`, after Antora conversion. It parses the headers of the four Release Notes and Getting Started chapter pages and checks their expected document titles, then renders their bodies with Antora's `env-site` attribute to check all 16 published chapter and subsection fragment IDs. A `:title:` attribute must not substitute for a document header: Asciidoctor can return that attribute as the title even without a header, but Antora does not use it. A section heading alone must fail: Antora needs a document header to populate default xref labels, navigation labels and browser titles. The tests also parse both preprocessed books to preserve their chapter titles, IDs and levels for PDF generation. Missing generated inputs fail rather than skipping the check. After preprocessing and Antora conversion, rerun this check from this module: ```sh mvn -Pman-pages compiler:testCompile surefire:test@test-antora-page-titles ``` Chapter sources keep `==` headings for the combined books. With doc-maven-plugin 3.2.2, keep `:table-caption!:` before each chapter heading: the Antora converter uses this existing attribute as the insertion point for `:leveloffset: -1`, which promotes the chapter heading to a standalone page title only in its output. Do not put the level offset directly in the book sources. The chapter ID stays on the heading outside `env-site`. On the site, it is emitted as a separate inline anchor after the page title: Antora's default UI does not render the document ID as an HTML anchor. Keep both forms so incoming fragments work in HTML and the combined books retain their chapter IDs. Keep a blank line after the anchor's `endif::[]`: Asciidoctor does not end a paragraph at a section title, so a heading directly below the anchor joins its paragraph and disappears together with its fragment ID. Do not turn the anchor into a block anchor (`[[id]]` or `[#id]`) either: a block anchor attaches to the next block and replaces that section's automatic ID. opendj-doc-generated-ref/pom.xml
@@ -415,6 +415,29 @@ </activation> <build><finalName>${project.groupId}.${project.artifactId}</finalName> <plugins> <!-- These tests consume the Antora pages generated during package. --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <executions> <execution> <id>test-antora-page-titles</id> <phase>verify</phase> <goals> <goal>test</goal> </goals> <configuration> <includes> <include>**/AntoraPageTitlesIT.java</include> </includes> <failIfNoTests>true</failIfNoTests> <systemPropertyVariables> <docBuildDirectory>${project.build.directory}/asciidoc</docBuildDirectory> </systemPropertyVariables> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.openidentityplatform.opendj</groupId> <artifactId>opendj-doc-maven-plugin</artifactId> opendj-doc-generated-ref/src/main/asciidoc/getting-started/first-steps.adoc
@@ -14,11 +14,18 @@ Copyright 2026 3A Systems, LLC. //// :table-caption!: :opendj-example-version: 5.2.0 ifndef::env-site[] [#getting-started-first-directory] endif::[] == Your First Directory ifdef::env-site[] anchor:getting-started-first-directory[] endif::[] This exercise uses the published OpenDJ {opendj-example-version} ZIP distribution on Linux or macOS with Bash. It creates a new evaluation instance, uses a self-signed certificate for LDAPS, and leaves existing installations alone. For Windows, native packages or Docker, use the xref:../install-guide/chap-install.adoc[Installation Guide]. === Prepare the Environment opendj-doc-generated-ref/src/main/asciidoc/getting-started/overview.adoc
@@ -14,9 +14,17 @@ Copyright 2026 3A Systems, LLC. //// :table-caption!: ifndef::env-site[] [#getting-started-overview] endif::[] == Directory Concepts ifdef::env-site[] anchor:getting-started-overview[] endif::[] OpenDJ stores directory entries and makes them available to applications through LDAP. A directory is commonly used to hold users, groups and application configuration. Applications bind to the server to authenticate, then search or update entries according to their access rights. Entry:: opendj-doc-generated-ref/src/main/asciidoc/release-notes/release-5.2.0.adoc
@@ -14,9 +14,17 @@ Copyright 2026 3A Systems, LLC. //// :table-caption!: ifndef::env-site[] [#release-5-2-0] endif::[] == OpenDJ 5.2.0 ifdef::env-site[] anchor:release-5-2-0[] endif::[] OpenDJ 5.2.0 was published on 21 October 2026. These notes describe that released version. Documentation built from a development branch can also describe changes intended for a later release; a `SNAPSHOT` build is not a published release. The link:https://github.com/OpenIdentityPlatform/OpenDJ/releases/tag/5.2.0[5.2.0 release record] is the authoritative list of release assets and changes. The link:https://github.com/OpenIdentityPlatform/OpenDJ/compare/5.1.2...5.2.0[complete comparison with 5.1.2] provides the corresponding source history. For newer releases, consult the link:https://github.com/OpenIdentityPlatform/OpenDJ/releases[release list]. opendj-doc-generated-ref/src/main/asciidoc/release-notes/requirements-and-upgrade.adoc
@@ -14,9 +14,17 @@ Copyright 2026 3A Systems, LLC. //// :table-caption!: ifndef::env-site[] [#release-requirements] endif::[] == Requirements and Upgrade Considerations ifdef::env-site[] anchor:release-requirements[] endif::[] === Java and Installation Environment OpenDJ 5.2.0 requires Java 11 or later. This is the minimum in the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/5.2.0/README.md[release README]; the server ZIP does not supply a Java runtime. The Docker image supplies its own Java environment. opendj-doc-generated-ref/src/test/java/org/openidentityplatform/opendj/doc/AntoraPageTitlesIT.java
New file @@ -0,0 +1,115 @@ /* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2026 3A Systems, LLC. */ package org.openidentityplatform.opendj.doc; import static org.assertj.core.api.Assertions.assertThat; import java.io.File; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.asciidoctor.Asciidoctor; import org.asciidoctor.Options; import org.asciidoctor.SafeMode; import org.asciidoctor.ast.Document; import org.asciidoctor.ast.Section; import org.forgerock.testng.ForgeRockTestCase; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** Checks the real Antora output after package and the chapter structure used by PDF generation. */ @Test public class AntoraPageTitlesIT extends ForgeRockTestCase { private Asciidoctor asciidoctor; private File buildDirectory; @BeforeClass public void start() { buildDirectory = new File(System.getProperty("docBuildDirectory", new File(System.getProperty("basedir", "."), "target/asciidoc").getPath())); asciidoctor = Asciidoctor.Factory.create(); } @AfterClass(alwaysRun = true) public void shutdown() { if (asciidoctor != null) { asciidoctor.shutdown(); } } @DataProvider public Object[][] pages() { return new Object[][] { { "release-notes", "release-5.2.0", "OpenDJ 5.2.0", new String[] { "release-5-2-0", "_selected_changes", "_distributions" } }, { "release-notes", "requirements-and-upgrade", "Requirements and Upgrade Considerations", new String[] { "release-requirements", "_java_and_installation_environment", "_plan_an_upgrade", "_compatibility_checks", "_known_issues_and_help" } }, { "getting-started", "overview", "Directory Concepts", new String[] { "getting-started-overview" } }, { "getting-started", "first-steps", "Your First Directory", new String[] { "getting-started-first-directory", "_prepare_the_environment", "_set_up_and_start_the_server", "_add_a_person", "_search_and_change_the_entry", "_restart_and_remove_the_sample_data", "_next_steps" } } }; } @Test(dataProvider = "pages") public void generatedPageHasDocumentTitle(String guide, String page, String title, String[] fragments) { final File input = new File(buildDirectory, "antora/modules/" + guide + "/pages/" + page + ".adoc"); assertThat(input).isFile(); // Antora extracts metadata from the header. A full parse can fall back to a section // title and conceal a missing document header, although Antora publishes "Untitled". final Document document = asciidoctor.loadFile(input, Options.builder().safe(SafeMode.SAFE).attributes(Map.of("env-site", "")) .parseHeaderOnly(true).build()); assertThat(document.getDoctitle()).as("document title of %s", input).isEqualTo(title); // Without a header, Asciidoctor can still return the title attribute, which Antora ignores. assertThat(document.hasAttribute("title")) .as("%s must have a document header rather than a :title: attribute", input).isFalse(); final String html = asciidoctor.convertFile(input, Options.builder().safe(SafeMode.SAFE).attributes(Map.of("env-site", "")) .standalone(false).toFile(false).build()); for (final String fragment : fragments) { assertThat(html).as("published fragment %s in the rendered body of %s", fragment, input) .contains("id=\"" + fragment + "\""); } } @DataProvider public Object[][] books() { return new Object[][] { { "release-notes", new String[] { "OpenDJ 5.2.0", "Requirements and Upgrade Considerations" }, new String[] { "release-5-2-0", "release-requirements" } }, { "getting-started", new String[] { "Directory Concepts", "Your First Directory" }, new String[] { "getting-started-overview", "getting-started-first-directory" } } }; } @Test(dataProvider = "books") public void combinedBookKeepsChapters(String guide, String[] titles, String[] ids) { final File input = new File(buildDirectory, "source/" + guide + "/index.adoc"); assertThat(input).isFile(); final Document document = asciidoctor.loadFile(input, Options.builder().safe(SafeMode.UNSAFE).build()); final List<Section> chapters = document.getBlocks().stream() .filter(Section.class::isInstance).map(Section.class::cast).collect(Collectors.toList()); assertThat(chapters).extracting(Section::getTitle).containsExactly(titles); assertThat(chapters).extracting(Section::getId).containsExactly(ids); assertThat(chapters).extracting(Section::getLevel).containsOnly(1); } }