From 1b1f04e67d8bf9a6a3011b843b074938e6cb28e4 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 29 Jan 2024 16:39:00 +0100 Subject: [PATCH 1/3] Update Asciidoctor Maven plugin to 2.2.5 --- docs/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pom.xml b/docs/pom.xml index e74b32a435af1..dc16b7ef656d1 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -23,7 +23,7 @@ jdk-21 3.5.0 - 2.0.0 + 2.2.5 1.5.0-beta.8 WARN 2.26.0.Final From 1c6572831d13a35dd9eb0a6f8713e17be223b4ea Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Mon, 29 Jan 2024 18:03:50 +0100 Subject: [PATCH 2/3] Add a tool to check cross references Unfortunately, it doesn't support additional ids added just after the title as in: [id1] == [id2] [id3] Title so it will force people to use the canonical id but I think it's acceptable in our reference doc to enforce the canonical id. Also move the link transformation to downstream documentation only as this alters the ability of Asciidoctor to check the internal links. --- docs/pom.xml | 21 ++ .../AssembleDownstreamDocumentation.java | 143 +++++++++- .../docs/generation/CheckCrossReferences.java | 246 ++++++++++++++++++ .../generation/ReferenceIndexGenerator.java | 95 ++----- 4 files changed, 425 insertions(+), 80 deletions(-) create mode 100644 docs/src/main/java/io/quarkus/docs/generation/CheckCrossReferences.java diff --git a/docs/pom.xml b/docs/pom.xml index dc16b7ef656d1..b64f175513abd 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -3081,6 +3081,26 @@ + + check-cross-references + prepare-package + + java + + + ${skipDocs} + + false + io.quarkus.docs.generation.CheckCrossReferences + + ${project.basedir}/target/asciidoc/sources + ${project.basedir}/target/referenceIndex.yaml + + + ${env.MAVEN_CMD_LINE_ARGS} + + + assemble-downstream-doc prepare-package @@ -3096,6 +3116,7 @@ -classpath io.quarkus.docs.generation.AssembleDownstreamDocumentation + ${project.basedir}/target/referenceIndex.yaml ${project.basedir} diff --git a/docs/src/main/java/io/quarkus/docs/generation/AssembleDownstreamDocumentation.java b/docs/src/main/java/io/quarkus/docs/generation/AssembleDownstreamDocumentation.java index f1ac96a2dbcef..65a974b7e1964 100755 --- a/docs/src/main/java/io/quarkus/docs/generation/AssembleDownstreamDocumentation.java +++ b/docs/src/main/java/io/quarkus/docs/generation/AssembleDownstreamDocumentation.java @@ -11,8 +11,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -27,6 +29,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; + +import io.quarkus.docs.generation.ReferenceIndexGenerator.Index; public class AssembleDownstreamDocumentation { @@ -46,7 +51,12 @@ public class AssembleDownstreamDocumentation { DOC_PATH.resolve("_attributes-local.adoc")); private static final String ADOC_SUFFIX = ".adoc"; - private static final Pattern XREF_PATTERN = Pattern.compile("xref:([^\\.#\\[ ]+)\\" + ADOC_SUFFIX); + private static final Pattern XREF_GUIDE_PATTERN = Pattern.compile("xref:([^\\.#\\[ ]+)\\" + ADOC_SUFFIX); + private static final Pattern XREF_PATTERN = Pattern.compile("xref:([^\\[]+)\\[]"); + private static final Pattern ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?)>>", + Pattern.CASE_INSENSITIVE); + private static final Pattern ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?),([^>]+?)>>", + Pattern.CASE_INSENSITIVE); private static final String SOURCE_BLOCK_PREFIX = "[source"; private static final String SOURCE_BLOCK_DELIMITER = "--"; @@ -89,6 +99,17 @@ public static void main(String[] args) throws Exception { if (!Files.isDirectory(GENERATED_FILES_PATH)) { throw new IllegalStateException("Generated files directory does not exist. Have you built the documentation?"); } + Path referenceIndexPath = Path.of(args[0]); + if (!Files.isReadable(Path.of(args[0]))) { + throw new IllegalStateException("Reference index does not exist? Have you built the documentation?"); + } + + ObjectMapper om = new ObjectMapper(new YAMLFactory().enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); + Index referenceIndex = om.readValue(referenceIndexPath.toFile(), Index.class); + + Map> linkRewritingErrors = new LinkedHashMap<>(); + Map titlesByReference = referenceIndex.getReferences().stream() + .collect(Collectors.toMap(s -> s.getReference(), s -> s.getTitle())); try { deleteDirectory(TARGET_ROOT_DIRECTORY); @@ -157,7 +178,8 @@ public static void main(String[] args) throws Exception { for (Path guide : guides) { System.out.println("[INFO] Processing guide " + guide.getFileName()); - copyAsciidoc(guide, TARGET_ROOT_DIRECTORY.resolve(guide.getFileName()), downstreamGuides); + copyAsciidoc(guide, TARGET_ROOT_DIRECTORY.resolve(guide.getFileName()), downstreamGuides, titlesByReference, + linkRewritingErrors); } for (Path simpleInclude : simpleIncludes) { Path sourceFile = DOC_PATH.resolve(simpleInclude); @@ -171,7 +193,7 @@ public static void main(String[] args) throws Exception { allResolvedPaths.add(sourceFile); Path targetFile = TARGET_ROOT_DIRECTORY.resolve(simpleInclude); Files.createDirectories(targetFile.getParent()); - copyAsciidoc(sourceFile, targetFile, downstreamGuides); + copyAsciidoc(sourceFile, targetFile, downstreamGuides, titlesByReference, linkRewritingErrors); } for (Path include : includes) { Path sourceFile = INCLUDES_PATH.resolve(include); @@ -184,7 +206,7 @@ public static void main(String[] args) throws Exception { allResolvedPaths.add(sourceFile); Path targetFile = TARGET_INCLUDES_DIRECTORY.resolve(include); Files.createDirectories(targetFile.getParent()); - copyAsciidoc(sourceFile, targetFile, downstreamGuides); + copyAsciidoc(sourceFile, targetFile, downstreamGuides, titlesByReference, linkRewritingErrors); } for (Path generatedFile : generatedFiles) { Path sourceFile = GENERATED_FILES_PATH.resolve(generatedFile); @@ -197,7 +219,7 @@ public static void main(String[] args) throws Exception { allResolvedPaths.add(sourceFile); Path targetFile = TARGET_GENERATED_DIRECTORY.resolve(generatedFile); Files.createDirectories(targetFile.getParent()); - copyAsciidoc(sourceFile, targetFile, downstreamGuides); + copyAsciidoc(sourceFile, targetFile, downstreamGuides, titlesByReference, linkRewritingErrors); } for (Path image : images) { Path sourceFile = IMAGES_PATH.resolve(image); @@ -216,6 +238,24 @@ public static void main(String[] args) throws Exception { Files.writeString(TARGET_LISTING, allResolvedPaths.stream().map(p -> p.toString()).collect(Collectors.joining("\n"))); + if (!linkRewritingErrors.isEmpty()) { + System.out.println(); + System.out.println("################################################"); + System.out.println("# Errors occurred while transforming references"); + System.out.println("################################################"); + System.out.println(); + + for (Entry> errorEntry : linkRewritingErrors.entrySet()) { + System.out.println("- " + errorEntry.getKey()); + for (String error : errorEntry.getValue()) { + System.out.println(" . " + error); + } + } + + System.out.println(); + System.exit(1); + } + LOG.info("Downstream documentation tree is available in: " + TARGET_ROOT_DIRECTORY); LOG.info("Downstream documentation listing is available in: " + TARGET_LISTING); } catch (IOException e) { @@ -295,7 +335,9 @@ private static void deleteDirectory(Path directory) throws IOException { .forEach(File::delete); } - private static void copyAsciidoc(Path sourceFile, Path targetFile, Set downstreamGuides) throws IOException { + private static void copyAsciidoc(Path sourceFile, Path targetFile, Set downstreamGuides, + Map titlesByReference, + Map> linkRewritingErrors) throws IOException { List guideLines = Files.readAllLines(sourceFile); StringBuilder rewrittenGuide = new StringBuilder(); @@ -342,7 +384,8 @@ private static void copyAsciidoc(Path sourceFile, Path targetFile, Set d if (currentBuffer.length() > 0) { rewrittenGuide.append( - rewriteLinks(currentBuffer.toString(), downstreamGuides)); + rewriteLinks(sourceFile.getFileName().toString(), currentBuffer.toString(), downstreamGuides, + titlesByReference, linkRewritingErrors)); currentBuffer.setLength(0); } rewrittenGuide.append(line + "\n"); @@ -353,8 +396,9 @@ private static void copyAsciidoc(Path sourceFile, Path targetFile, Set d } if (currentBuffer.length() > 0) { - rewrittenGuide - .append(rewriteLinks(currentBuffer.toString(), downstreamGuides)); + rewrittenGuide.append( + rewriteLinks(sourceFile.getFileName().toString(), currentBuffer.toString(), downstreamGuides, + titlesByReference, linkRewritingErrors)); } String rewrittenGuideWithoutTabs = rewrittenGuide.toString().trim(); @@ -367,8 +411,36 @@ private static void copyAsciidoc(Path sourceFile, Path targetFile, Set d Files.writeString(targetFile, rewrittenGuideWithoutTabs.trim()); } - private static String rewriteLinks(String content, Set downstreamGuides) { + private static String rewriteLinks(String fileName, + String content, + Set downstreamGuides, + Map titlesByReference, + Map> errors) { content = XREF_PATTERN.matcher(content).replaceAll(mr -> { + String reference = getQualifiedReference(fileName, mr.group(1)); + String title = titlesByReference.get(reference); + if (title == null || title.isBlank()) { + addError(errors, fileName, "Unable to find title for: " + mr.group() + " [" + reference + "]"); + title = "~~ unknown title ~~"; + } + return "xref:" + trimReference(mr.group(1)) + "[" + title.trim() + "]"; + }); + + content = ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN.matcher(content).replaceAll(mr -> { + String reference = getQualifiedReference(fileName, mr.group(1)); + String title = titlesByReference.get(reference); + if (title == null || title.isBlank()) { + addError(errors, fileName, "Unable to find title for: " + mr.group() + " [" + reference + "]"); + title = "~~ unknown title ~~"; + } + return "xref:" + trimReference(mr.group(1)) + "[" + title.trim() + "]"; + }); + + content = ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN.matcher(content).replaceAll(mr -> { + return "xref:" + trimReference(mr.group(1)) + "[" + mr.group(2).trim() + "]"; + }); + + content = XREF_GUIDE_PATTERN.matcher(content).replaceAll(mr -> { if (downstreamGuides.contains(mr.group(1) + ADOC_SUFFIX)) { return mr.group(0); } @@ -379,6 +451,57 @@ private static String rewriteLinks(String content, Set downstreamGuides) return content; } + private static String trimReference(String reference) { + reference = normalizeAdoc(reference); + + if (reference.startsWith("#")) { + return reference.substring(1); + } + + if (reference.contains(".adoc")) { + return reference; + } + + if (reference.contains("#")) { + int hashIndex = reference.indexOf('#'); + return reference.substring(0, hashIndex) + ".adoc" + reference.substring(hashIndex); + } + + return reference; + } + + private static String getQualifiedReference(String fileName, String reference) { + reference = normalizeAdoc(reference); + + if (reference.startsWith("#")) { + return fileName + reference; + } + + if (reference.contains(".adoc")) { + return reference; + } + + if (reference.contains("#")) { + int hashIndex = reference.indexOf('#'); + return reference.substring(0, hashIndex) + ".adoc" + reference.substring(hashIndex); + } + + return fileName + "#" + reference; + } + + private static String normalizeAdoc(String adoc) { + if (adoc.startsWith("./")) { + return adoc.substring(2); + } + + return adoc; + } + + private static void addError(Map> errors, String fileName, String error) { + errors.computeIfAbsent(fileName, f -> new ArrayList<>()) + .add(error); + } + public static class GuideContent { public Path guide; diff --git a/docs/src/main/java/io/quarkus/docs/generation/CheckCrossReferences.java b/docs/src/main/java/io/quarkus/docs/generation/CheckCrossReferences.java new file mode 100644 index 0000000000000..f3395f1d814f2 --- /dev/null +++ b/docs/src/main/java/io/quarkus/docs/generation/CheckCrossReferences.java @@ -0,0 +1,246 @@ +package io.quarkus.docs.generation; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.fasterxml.jackson.core.exc.StreamReadException; +import com.fasterxml.jackson.databind.DatabindException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; + +import io.quarkus.docs.generation.ReferenceIndexGenerator.Index; + +/** + * Iterate over the documents in the source directory and check the cross references. + */ +public class CheckCrossReferences { + + private static final String SOURCE_BLOCK_PREFIX = "[source"; + private static final String SOURCE_BLOCK_DELIMITER = "--"; + private static final Pattern XREF_PATTERN = Pattern.compile("xref:([^\\[]+)\\[[^\\]]*\\]"); + private static final Pattern ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?)>>", + Pattern.CASE_INSENSITIVE); + private static final Pattern ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?),([^>]+?)>>", + Pattern.CASE_INSENSITIVE); + + private static final Set IGNORED_GUIDES = Set.of( + // contains a reference to container-image.adoc#s2i that I don't know how to fix + "deploying-to-kubernetes.adoc", + // contains a reference to container-image.adoc#s2i that I don't know how to fix + "deploying-to-openshift.adoc"); + + private final Path srcDir; + private final Index referenceIndex; + + public static void main(String[] args) throws Exception { + CheckCrossReferences checker = new CheckCrossReferences(args.length >= 1 + ? Path.of(args[0]) + : docsDir().resolve("src/main/asciidoc"), + args.length >= 2 + ? Path.of(args[1]) + : docsDir().resolve("target/referenceIndex.yaml")); + System.out.println("[INFO] Checking cross references using: " + args[0]); + + Map> errors = checker.check(); + + if (!errors.isEmpty()) { + StringBuffer errorLog = new StringBuffer("Unable to find cross reference for:\n\n"); + + for (Entry> errorEntry : errors.entrySet()) { + errorLog.append("- " + errorEntry.getKey() + "\n"); + for (String error : errorEntry.getValue()) { + errorLog.append(" . " + error + "\n"); + } + } + + throw new IllegalStateException(errorLog.toString()); + } + + System.out.println("[INFO] Done"); + } + + public CheckCrossReferences(Path srcDir, Path referenceIndexPath) + throws StreamReadException, DatabindException, IOException { + if (!Files.exists(srcDir) || !Files.isDirectory(srcDir)) { + throw new IllegalStateException( + String.format("Source directory (%s) does not exist", srcDir.toAbsolutePath())); + } + this.srcDir = srcDir; + + if (!Files.exists(referenceIndexPath) || !Files.isReadable(referenceIndexPath)) { + throw new IllegalStateException( + String.format("Reference index does not exist or is not readable", referenceIndexPath.toAbsolutePath())); + } + + ObjectMapper om = new ObjectMapper(new YAMLFactory().enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)); + this.referenceIndex = om.readValue(referenceIndexPath.toFile(), Index.class); + } + + private Map> check() throws IOException { + final Map titlesByReference = referenceIndex.getReferences().stream() + .collect(Collectors.toMap(s -> s.getReference(), s -> s.getTitle())); + final Map> errors = new TreeMap<>(); + + try (Stream pathStream = Files.list(srcDir)) { + pathStream.filter(path -> includeFile(path.getFileName().toString())) + .forEach(path -> { + List guideLines; + try { + guideLines = Files.readAllLines(path); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + String fileName = path.getFileName().toString(); + + StringBuilder currentBuffer = new StringBuilder(); + boolean inSourceBlock = false; + boolean findDelimiter = false; + String currentSourceBlockDelimiter = "----"; + int lineNumber = 0; + + for (String line : guideLines) { + lineNumber++; + + if (inSourceBlock) { + if (findDelimiter) { + if (line.isBlank() || line.startsWith(".")) { + continue; + } + if (!line.startsWith(SOURCE_BLOCK_DELIMITER)) { + throw new IllegalStateException("Unable to find source block delimiter in file " + + fileName + " at line " + lineNumber); + } + currentSourceBlockDelimiter = line.stripTrailing(); + findDelimiter = false; + continue; + } + + if (line.stripTrailing().equals(currentSourceBlockDelimiter)) { + inSourceBlock = false; + } + continue; + } + if (line.startsWith(SOURCE_BLOCK_PREFIX)) { + inSourceBlock = true; + findDelimiter = true; + + if (currentBuffer.length() > 0) { + checkLinks(titlesByReference, errors, fileName, currentBuffer.toString()); + currentBuffer.setLength(0); + } + continue; + } + + currentBuffer.append(line + "\n"); + } + + if (currentBuffer.length() > 0) { + checkLinks(titlesByReference, errors, fileName, currentBuffer.toString()); + } + }); + } + + return errors; + } + + private static void checkLinks(Map titlesByReference, + Map> errors, + String fileName, + String content) { + Matcher matcher = XREF_PATTERN.matcher(content); + while (matcher.find()) { + String reference = getQualifiedReference(fileName, matcher.group(1)); + if (!titlesByReference.containsKey(reference)) { + addError(errors, fileName, reference + " in link " + matcher.group()); + } + } + + matcher = ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN.matcher(content); + while (matcher.find()) { + String reference = getQualifiedReference(fileName, matcher.group(1)); + if (!titlesByReference.containsKey(reference)) { + addError(errors, fileName, reference + " in link " + matcher.group()); + } + } + + matcher = ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN.matcher(content); + while (matcher.find()) { + String reference = getQualifiedReference(fileName, matcher.group(1)); + if (!titlesByReference.containsKey(reference)) { + addError(errors, fileName, reference + " in link " + matcher.group()); + } + } + } + + private boolean includeFile(String fileName) { + if (fileName.startsWith("_attributes") || fileName.equals("README.adoc")) { + return false; + } + if (fileName.startsWith("doc-")) { + // these files are for the doc infrastructure and contain a lot of examples that would be hard to ignore in the checks + return false; + } + if (IGNORED_GUIDES.contains(fileName)) { + return false; + } + if (fileName.endsWith(".adoc")) { + return true; + } + return false; + } + + private static String getQualifiedReference(String fileName, String reference) { + reference = normalizeAdoc(reference); + + if (reference.startsWith("#")) { + return fileName + reference; + } + + if (reference.contains(".adoc")) { + return reference; + } + + if (reference.contains("#")) { + int hashIndex = reference.indexOf('#'); + return reference.substring(0, hashIndex) + ".adoc" + reference.substring(hashIndex); + } + + return fileName + "#" + reference; + } + + private static String normalizeAdoc(String adoc) { + if (adoc.startsWith("./")) { + return adoc.substring(2); + } + + return adoc; + } + + private static void addError(Map> errors, String fileName, String error) { + errors.computeIfAbsent(fileName, f -> new ArrayList<>()) + .add(error); + } + + private static Path docsDir() { + Path path = Paths.get(System.getProperty("user.dir")); + if (path.endsWith("docs")) { + return path; + } + return path.resolve("docs"); + } +} diff --git a/docs/src/main/java/io/quarkus/docs/generation/ReferenceIndexGenerator.java b/docs/src/main/java/io/quarkus/docs/generation/ReferenceIndexGenerator.java index 08adb28e67ee8..228c9abc3b2ff 100644 --- a/docs/src/main/java/io/quarkus/docs/generation/ReferenceIndexGenerator.java +++ b/docs/src/main/java/io/quarkus/docs/generation/ReferenceIndexGenerator.java @@ -18,7 +18,9 @@ import org.asciidoctor.Options; import org.asciidoctor.SafeMode; import org.asciidoctor.ast.Block; +import org.asciidoctor.ast.Cell; import org.asciidoctor.ast.Document; +import org.asciidoctor.ast.Row; import org.asciidoctor.ast.Section; import org.asciidoctor.ast.StructuralNode; import org.asciidoctor.ast.Table; @@ -35,14 +37,11 @@ public class ReferenceIndexGenerator { private static final String YAML_FRONTMATTER = "---\n"; - private static final Pattern XREF_PATTERN = Pattern.compile("xref:([^\\[]+)\\[]"); - private static final Pattern ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?)>>", - Pattern.CASE_INSENSITIVE); - private static final Pattern ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN = Pattern.compile("<<([a-z0-9_\\-#\\.]+?),([^>]+?)>>", - Pattern.CASE_INSENSITIVE); private static final String SOURCE_BLOCK_PREFIX = "[source"; private static final String SOURCE_BLOCK_DELIMITER = "--"; + private static final Pattern ICON_PATTERN = Pattern.compile("icon:[^\\[]+\\[[^\\]]*\\] "); + private final Path srcDir; private final Path targetDir; @@ -158,11 +157,11 @@ private Index generateIndex() throws IOException { private void addBlocks(Index index, String fileName, List blocks) { for (StructuralNode block : blocks) { if (block instanceof Section || block instanceof Table || block instanceof Block) { - if (block.getId() != null && block.getTitle() != null) { + if (block.getId() != null) { // unfortunately, AsciiDoc already formats the title in the AST // and I couldn't find a way to get the original one IndexReference reference = new IndexReference(fileName, block.getId(), - block.getTitle().replace("", "`") + block.getTitle() != null ? block.getTitle().replace("", "`") .replace("", "`") .replace('\n', ' ') .replace("’", "'") @@ -174,11 +173,28 @@ private void addBlocks(Index index, String fileName, List blocks .replace("", "*") .replace("", "*") .replace("", "*") - .replaceAll(" ", "")); + .replaceAll(" ", "") : "~~ unknown title ~~"); index.add(reference); } } + // we go into the content of the tables to add references for the configuration properties + if (block instanceof Table) { + for (Row row : ((Table) block).getBody()) { + for (Cell cell : row.getCells()) { + String cellContent = ICON_PATTERN.matcher(cell.getSource()).replaceAll("").trim(); + + if (!cellContent.startsWith("[[") || !cellContent.contains("]]")) { + continue; + } + + IndexReference reference = new IndexReference(fileName, + cellContent.substring(2, cellContent.indexOf("]]")), + "Configuration property documentation"); + index.add(reference); + } + } + } addBlocks(index, fileName, block.getBlocks()); } } @@ -267,72 +283,11 @@ private String rewriteLinks(Map titlesByReference, Map> errors, String fileName, String content) { - content = XREF_PATTERN.matcher(content).replaceAll(mr -> { - String reference = getQualifiedReference(fileName, mr.group(1)); - String title = titlesByReference.get(reference); - if (title == null || title.isBlank()) { - addError(errors, fileName, "Unable to find title for: " + mr.group() + " [" + reference + "]"); - title = "~~ unknown title ~~"; - } - return "xref:" + trimReference(mr.group(1)) + "[" + title.trim() + "]"; - }); - - content = ANGLE_BRACKETS_WITHOUT_DESCRIPTION_PATTERN.matcher(content).replaceAll(mr -> { - String reference = getQualifiedReference(fileName, mr.group(1)); - String title = titlesByReference.get(reference); - if (title == null || title.isBlank()) { - addError(errors, fileName, "Unable to find title for: " + mr.group() + " [" + reference + "]"); - title = "~~ unknown title ~~"; - } - return "xref:" + trimReference(mr.group(1)) + "[" + title.trim() + "]"; - }); - - content = ANGLE_BRACKETS_WITH_DESCRIPTION_PATTERN.matcher(content).replaceAll(mr -> { - return "xref:" + trimReference(mr.group(1)) + "[" + mr.group(2).trim() + "]"; - }); + // we don't do anything here from now, this code was moved to AssembleDownstreamDocumentation return content; } - private String trimReference(String reference) { - if (reference.startsWith("#")) { - return reference.substring(1); - } - - if (reference.contains(".adoc")) { - return reference; - } - - if (reference.contains("#")) { - int hashIndex = reference.indexOf('#'); - return reference.substring(0, hashIndex) + ".adoc" + reference.substring(hashIndex); - } - - return reference; - } - - private String getQualifiedReference(String fileName, String reference) { - if (reference.startsWith("#")) { - return fileName + reference; - } - - if (reference.contains(".adoc")) { - return reference; - } - - if (reference.contains("#")) { - int hashIndex = reference.indexOf('#'); - return reference.substring(0, hashIndex) + ".adoc" + reference.substring(hashIndex); - } - - return fileName + "#" + reference; - } - - private void addError(Map> errors, String fileName, String error) { - errors.computeIfAbsent(fileName, f -> new ArrayList<>()) - .add(error); - } - private boolean includeFile(String fileName) { if (fileName.startsWith("_attributes") || fileName.equals("README.adoc")) { return false; From cb5d8e83413f951d7552550ca167fcd3a6b39440 Mon Sep 17 00:00:00 2001 From: Guillaume Smet Date: Tue, 30 Jan 2024 12:54:42 +0100 Subject: [PATCH 3/3] Fix some invalid references --- .../main/asciidoc/building-my-first-extension.adoc | 2 +- docs/src/main/asciidoc/cdi-integration.adoc | 2 +- docs/src/main/asciidoc/cdi-reference.adoc | 9 +++++---- docs/src/main/asciidoc/cdi.adoc | 2 +- docs/src/main/asciidoc/config-reference.adoc | 10 ++++------ docs/src/main/asciidoc/config-yaml.adoc | 2 +- docs/src/main/asciidoc/config.adoc | 4 ++-- docs/src/main/asciidoc/datasource.adoc | 2 +- docs/src/main/asciidoc/deploying-to-kubernetes.adoc | 2 +- docs/src/main/asciidoc/deploying-to-openshift.adoc | 4 ++-- docs/src/main/asciidoc/getting-started.adoc | 2 +- docs/src/main/asciidoc/grpc-kubernetes.adoc | 2 +- docs/src/main/asciidoc/hibernate-orm.adoc | 4 ++-- docs/src/main/asciidoc/init-tasks.adoc | 4 ++-- docs/src/main/asciidoc/pulsar-getting-started.adoc | 11 +++++------ docs/src/main/asciidoc/redis-reference.adoc | 3 ++- docs/src/main/asciidoc/resteasy-reactive.adoc | 4 +--- docs/src/main/asciidoc/security-customization.adoc | 2 +- docs/src/main/asciidoc/security-jwt.adoc | 2 +- .../main/asciidoc/security-oidc-auth0-tutorial.adoc | 2 +- .../security-oidc-bearer-token-authentication.adoc | 2 +- ...curity-oidc-code-flow-authentication-tutorial.adoc | 2 +- docs/src/main/asciidoc/writing-extensions.adoc | 6 +++--- .../asciidoc/writing-native-applications-tips.adoc | 2 +- 24 files changed, 42 insertions(+), 45 deletions(-) diff --git a/docs/src/main/asciidoc/building-my-first-extension.adoc b/docs/src/main/asciidoc/building-my-first-extension.adoc index 8ac26e8b6165a..407796f683e66 100644 --- a/docs/src/main/asciidoc/building-my-first-extension.adoc +++ b/docs/src/main/asciidoc/building-my-first-extension.adoc @@ -928,4 +928,4 @@ As usual, along the path Quarkus simplifies things under the hood (Maven Mojo, b == Further reading - xref:writing-extensions.adoc[Writing your own extension] for the full documentation. -- xref:dev-ui-v2.adoc[Quarkus Dev UI] to learn how to support the Dev UI in your extension +- xref:dev-ui.adoc[Quarkus Dev UI] to learn how to support the Dev UI in your extension diff --git a/docs/src/main/asciidoc/cdi-integration.adoc b/docs/src/main/asciidoc/cdi-integration.adoc index 2a7b4641079b1..2da15c9731dcd 100644 --- a/docs/src/main/asciidoc/cdi-integration.adoc +++ b/docs/src/main/asciidoc/cdi-integration.adoc @@ -32,7 +32,7 @@ Attributes of these components are fully controlled by the extensions, i.e. are Finally, the _deployment is validated_. For example, the container validates every injection point in the application and fails the build if there is no bean that satisfies the given required type and qualifiers. -TIP: You can see more information about the bootstrap by enabling additional logging. Simply run the Maven build with `-X` or `--debug` and grep the lines that contain `io.quarkus.arc`. In the <>, you can use `quarkus.log.category."io.quarkus.arc.processor".level=DEBUG` and two special endpoints are also registered automatically to provide some basic debug info in the JSON format. +TIP: You can see more information about the bootstrap by enabling additional logging. Simply run the Maven build with `-X` or `--debug` and grep the lines that contain `io.quarkus.arc`. In <>, you can use `quarkus.log.category."io.quarkus.arc.processor".level=DEBUG` and two special endpoints are also registered automatically to provide some basic debug info in the JSON format. Quarkus build steps can produce and consume various build items and hook into each phase. In the following sections we will describe all the relevant build items and common scenarios. diff --git a/docs/src/main/asciidoc/cdi-reference.adoc b/docs/src/main/asciidoc/cdi-reference.adoc index 22b9b11ab7c6c..62231b035b001 100644 --- a/docs/src/main/asciidoc/cdi-reference.adoc +++ b/docs/src/main/asciidoc/cdi-reference.adoc @@ -1072,9 +1072,10 @@ The downside of this approach is that CDI Portable Extensions cannot be supporte Nevertheless, most of the functionality can be achieved using Quarkus xref:writing-extensions.adoc[extensions]. See the xref:cdi-integration.adoc[integration guide] for more information. -== Development Mode +[[dev_mode]] +== [[development-mode]] Dev mode -In the development mode, two special endpoints are registered automatically to provide some basic debug info in the JSON format: +In dev mode, two special endpoints are registered automatically to provide some basic debug info in the JSON format: * HTTP GET `/q/arc` - returns the summary; number of beans, config properties, etc. * HTTP GET `/q/arc/beans` - returns the list of all beans @@ -1085,11 +1086,11 @@ In the development mode, two special endpoints are registered automatically to p * HTTP GET `/q/arc/removed-beans` - returns the list of unused beans removed during build * HTTP GET `/q/arc/observers` - returns the list of all observer methods -NOTE: These endpoints are only available in the development mode, i.e. when you run your application via `mvn quarkus:dev` (or `./gradlew quarkusDev`). +NOTE: These endpoints are only available in dev mode, i.e. when you run your application via `mvn quarkus:dev` (or `./gradlew quarkusDev`). === Monitoring Business Method Invocations and Events -In the development mode, it is also possible to enable monitoring of business method invocations and fired events. +In dev mode, it is also possible to enable monitoring of business method invocations and fired events. Simply set the `quarkus.arc.dev-mode.monitoring-enabled` configuration property to `true` and explore the relevant Dev UI pages. [[strict_mode]] diff --git a/docs/src/main/asciidoc/cdi.adoc b/docs/src/main/asciidoc/cdi.adoc index 0cdc9da9d2fb3..7b6fa294a2774 100644 --- a/docs/src/main/asciidoc/cdi.adoc +++ b/docs/src/main/asciidoc/cdi.adoc @@ -520,7 +520,7 @@ TIP: For more info about events/observers visit https://docs.jboss.org/weld/refe In this guide, we've covered some basic topics of the Quarkus programming model that is based on the https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0.html[Jakarta Contexts and Dependency Injection 4.0, window="_blank"] specification. Quarkus implements the CDI Lite specification, but not CDI Full. -See also <> and <>. +See also <>. There are also quite a few <> and <>. TIP: If you wish to learn more about Quarkus-specific features and limitations there is a Quarkus xref:cdi-reference.adoc[CDI Reference Guide]. diff --git a/docs/src/main/asciidoc/config-reference.adoc b/docs/src/main/asciidoc/config-reference.adoc index 286d6f5601177..1980740a757c3 100644 --- a/docs/src/main/asciidoc/config-reference.adoc +++ b/docs/src/main/asciidoc/config-reference.adoc @@ -169,8 +169,8 @@ is to use Quarkus `application.properties`. Quarkus provides additional extensions which cover other configuration formats and stores: * xref:config-yaml.adoc[YAML] -* xref:vault.adoc[HashiCorp Vault] -* xref:consul-config.adoc[Consul] +* https://github.com/quarkiverse/quarkus-vault[HashiCorp Vault] +* https://github.com/quarkiverse/quarkus-config-extensions[Consul] * xref:spring-cloud-config-client.adoc[Spring Cloud] TIP: It is also possible to create a xref:config-extending-support.adoc#custom-config-source[Custom Config Source]. @@ -788,10 +788,8 @@ public class MyBeanNoFailure { == Additional Information * xref:config-yaml.adoc[YAML ConfigSource Extension] -// Moved to Quarkiverse. There is a redirect to resolve the link -* xref:vault.adoc[HashiCorp Vault ConfigSource Extension] -// Moved to Quarkiverse. There is a redirect to resolve the link -* xref:consul-config.adoc[Consul ConfigSource Extension] +* https://github.com/quarkiverse/quarkus-vault[HashiCorp Vault ConfigSource Extension] +* https://github.com/quarkiverse/quarkus-config-extensions[Consul ConfigSource Extension] * xref:spring-cloud-config-client.adoc[Spring Cloud ConfigSource Extension] * xref:config-mappings.adoc[Mapping configuration to objects] * xref:config-extending-support.adoc[Extending configuration support] diff --git a/docs/src/main/asciidoc/config-yaml.adoc b/docs/src/main/asciidoc/config-yaml.adoc index 8a916f25fdc9f..074132c8bc895 100644 --- a/docs/src/main/asciidoc/config-yaml.adoc +++ b/docs/src/main/asciidoc/config-yaml.adoc @@ -112,7 +112,7 @@ app: == Profiles -As you can see in the previous snippet, you can use xref:{doc-guides}/config-reference.adoc#profiles[profiles] in YAML. +As you can see in the previous snippet, you can use xref:config-reference.adoc#profiles[profiles] in YAML. In YAML, keys that begin with `%` are not allowed. diff --git a/docs/src/main/asciidoc/config.adoc b/docs/src/main/asciidoc/config.adoc index 1ae0e1a14e725..89f0d72eabc23 100644 --- a/docs/src/main/asciidoc/config.adoc +++ b/docs/src/main/asciidoc/config.adoc @@ -242,8 +242,8 @@ application behaviour at runtime. * xref:config-reference.adoc[Configuration Reference Guide] * xref:config-yaml.adoc[YAML ConfigSource Extension] -* xref:vault.adoc[HashiCorp Vault ConfigSource Extension] -* xref:consul-config.adoc[Consul ConfigSource Extension] +* https://github.com/quarkiverse/quarkus-vault[HashiCorp Vault ConfigSource Extension] +* https://github.com/quarkiverse/quarkus-config-extensions[Consul ConfigSource Extension] * xref:spring-cloud-config-client.adoc[Spring Cloud ConfigSource Extension] * xref:config-mappings.adoc[Mapping configuration to objects] * xref:config-extending-support.adoc[Extending configuration support] diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index 6164e60e32676..d8876dbc1fdc5 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -523,7 +523,7 @@ quarkus.datasource."datasource-name".health-exclude=true === Datasource metrics -If you are using the xref:micrometer.adoc[`quarkus-micrometer`] or xref:smallrye-metrics.adoc[`quarkus-smallrye-metrics`] extension, `quarkus-agroal` can contribute some datasource-related metrics to the metric registry. +If you are using the xref:telemetry-micrometer.adoc[`quarkus-micrometer`] or xref:smallrye-metrics.adoc[`quarkus-smallrye-metrics`] extension, `quarkus-agroal` can contribute some datasource-related metrics to the metric registry. This can be activated by setting the `quarkus.datasource.metrics.enabled` property to `true`. For the exposed metrics to contain any actual values, a metric collection must be enabled internally by the Agroal mechanisms. diff --git a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc index a097956a8ce67..382e724a36d14 100644 --- a/docs/src/main/asciidoc/deploying-to-kubernetes.adoc +++ b/docs/src/main/asciidoc/deploying-to-kubernetes.adoc @@ -645,7 +645,7 @@ implementation("io.quarkus:quarkus-smallrye-health") ---- The values of the generated probes will be determined by the configured health properties: `quarkus.smallrye-health.root-path`, `quarkus.smallrye-health.liveness-path` and `quarkus.smallrye-health.readiness-path`. -More information about the health extension can be found in the relevant xref:microprofile-health.adoc[guide]. +More information about the health extension can be found in the relevant xref:smallrye-health.adoc[guide]. === Customizing the readiness probe To set the initial delay of the probe to 20 seconds and the period to 45: diff --git a/docs/src/main/asciidoc/deploying-to-openshift.adoc b/docs/src/main/asciidoc/deploying-to-openshift.adoc index 5611e90d45cf1..57a53873faf38 100644 --- a/docs/src/main/asciidoc/deploying-to-openshift.adoc +++ b/docs/src/main/asciidoc/deploying-to-openshift.adoc @@ -31,8 +31,8 @@ First, we need a new project that contains the OpenShift extension. This can be include::{includes}/devtools/create-app.adoc[] Quarkus offers the ability to automatically generate OpenShift resources based on sane defaults and user supplied configuration. -The OpenShift extension is actually a wrapper extension that brings together the xref:deploying-to-kubernetes.adoc[kubernetes] and xref:container-image.adoc#s2i[container-image-s2i] -extensions with sensible defaults so that it's easier for the user to get started with Quarkus on OpenShift. +The OpenShift extension is actually a wrapper extension that brings configures the xref:deploying-to-kubernetes.adoc[Kubernetes] +extension with sensible defaults so that it's easier for the user to get started with Quarkus on OpenShift. When we added the OpenShift extension to the command line invocation above, the following dependency was added to the `pom.xml` diff --git a/docs/src/main/asciidoc/getting-started.adoc b/docs/src/main/asciidoc/getting-started.adoc index 83b5d1f3955d3..cb48c24485267 100644 --- a/docs/src/main/asciidoc/getting-started.adoc +++ b/docs/src/main/asciidoc/getting-started.adoc @@ -429,7 +429,7 @@ As a result, most of the Quarkus extensions will not work properly if this build This index is created by default on the project on which Quarkus is configured for, thanks to our Maven and Gradle plugins. However, when working with a multi-module project, be sure to read the `Working with multi-module projects` section of the -xref:maven-tooling.adoc#multi-module-maven[Maven] or xref:gradle-tooling.adoc#multi-module-maven[Gradle] guides. +xref:maven-tooling.adoc#multi-module-maven[Maven] or xref:gradle-tooling.adoc#multi-module-gradle[Gradle] guides. If you plan to use external modules (for example, an external library for all your domain objects), you will need to make these modules known to the indexing process either by adding the Jandex plugin (if you can modify them) diff --git a/docs/src/main/asciidoc/grpc-kubernetes.adoc b/docs/src/main/asciidoc/grpc-kubernetes.adoc index ee092e2e6caca..3fc6a52ab52e2 100644 --- a/docs/src/main/asciidoc/grpc-kubernetes.adoc +++ b/docs/src/main/asciidoc/grpc-kubernetes.adoc @@ -82,7 +82,7 @@ By default, the Kubernetes resources do not contain readiness and liveness probe implementation("io.quarkus:quarkus-smallrye-health") ---- -TIP: More information about the health extension can be found in xref:microprofile-health.adoc[the Microprofile Health guide]. +TIP: More information about the health extension can be found in xref:smallrye-health.adoc[the SmallRye Health guide]. By the default, this extension will configure the probes to use the HTTP server (which is provided by some extensions like the Quarkus RESTEasy reactive extension). Internally, this probe will also use xref:grpc-service-implementation.adoc#health[the generated gRPC Health services]. diff --git a/docs/src/main/asciidoc/hibernate-orm.adoc b/docs/src/main/asciidoc/hibernate-orm.adoc index 6b383977bb45f..e682cc45ceda6 100644 --- a/docs/src/main/asciidoc/hibernate-orm.adoc +++ b/docs/src/main/asciidoc/hibernate-orm.adoc @@ -907,10 +907,10 @@ For more information about Hibernate Envers, see link:https://hibernate.org/orm/ [[metrics]] == Metrics -Either xref:telemetry-micrometer.adoc[Micrometer] or xref:microprofile-metrics.adoc[SmallRye Metrics] are +Either xref:telemetry-micrometer.adoc[Micrometer] or xref:smallrye-metrics.adoc[SmallRye Metrics] are capable of exposing metrics that Hibernate ORM collects at runtime. To enable exposure of Hibernate metrics on the `/q/metrics` endpoint, make sure your project depends on a metrics extension and set the configuration property `quarkus.hibernate-orm.metrics.enabled` to `true`. -When using link:microprofile-metrics[SmallRye Metrics], metrics will be available under the `vendor` scope. +When using xref:smallrye-metrics.adoc[SmallRye Metrics], metrics will be available under the `vendor` scope. == Limitations and other things you should know diff --git a/docs/src/main/asciidoc/init-tasks.adoc b/docs/src/main/asciidoc/init-tasks.adoc index b29a45a398d40..eaccf6eea7965 100644 --- a/docs/src/main/asciidoc/init-tasks.adoc +++ b/docs/src/main/asciidoc/init-tasks.adoc @@ -19,7 +19,7 @@ Quarkus allows externalization of such tasks as Kubernetes https://kubernetes.io application instance only starts once the initialization jobs have finished. With this approach even if an application has multiple replicas, the initialization logic will only run once. -This approach is reflected in the manifests generated by xref:kubernetes.adoc[Kubernetes extension]. +This approach is reflected in the manifests generated by xref:deploying-to-kubernetes.adoc#kubernetes[Kubernetes extension]. == Disabling the feature @@ -135,7 +135,7 @@ quarkus.kubernetes.init-containers.wait-for-flyway=my/wait-for-image:1.0 For an init container to be able to perform the `wait for job` it needs to be able to perform `get` operations on the job resource. This is done automatically and the generated manifests include the required `Role` and `RoleBinding` resources. -If for any reason additional permissions are required either by the init container or the job, they can be configured with through the xref:deploying-to-kuberentes.adoc#generating-rbac-resources[Kubernetes RBAC configuration]. +If for any reason additional permissions are required either by the init container or the job, they can be configured with through the xref:deploying-to-kubernetes.adoc#generating-rbac-resources[Kubernetes RBAC configuration]. **Note**: The application, the init container and the job use the same `ServiceAccount` and therefore, share the same permissions. diff --git a/docs/src/main/asciidoc/pulsar-getting-started.adoc b/docs/src/main/asciidoc/pulsar-getting-started.adoc index 3d08b39a7d713..c775deabf1e30 100644 --- a/docs/src/main/asciidoc/pulsar-getting-started.adoc +++ b/docs/src/main/asciidoc/pulsar-getting-started.adoc @@ -104,7 +104,7 @@ Open the two projects in your favorite IDE. ==== No need to start a Pulsar broker when using the dev mode or for tests. Quarkus starts a broker for you automatically. -See xref:pulsar.adoc[Dev Services for Pulsar] for details. +See xref:pulsar-dev-services.adoc[Dev Services for Pulsar] for details. ==== == The Quote object @@ -268,7 +268,7 @@ The `channel-name` segment must match the value set in the `@Incoming` and `@Out ==== More details about this configuration is available on the https://pulsar.apache.org/docs/3.0.x/concepts-messaging/ section from the Pulsar documentation. These properties are configured with the prefix `pulsar`. -An exhaustive list of configuration properties is available in xref:pulsar.adoc#pulsar-configuration[Pulsar Reference Guide - Configuration]. +An exhaustive list of configuration properties is available in xref:pulsar.adoc#configuration-reference[Pulsar Reference Guide - Configuration]. ==== `mp.messaging.incoming.requests.subscriptionInitialPosition=Earliest` instructs the application to start reading the topics from the first message on the topic, when there is no previously acked messages. @@ -312,8 +312,7 @@ It will also generate a deserializer for the `Quote` class. ==== .Message Schemas in Pulsar In this example we used JSON Schema with Pulsar messages. -For more options on Pulsar Schemas, see xref:pulsar.adoc#pulsar-schema[Pulsar Reference Guide - Schema]. - +For more information on Pulsar Schemas, see xref:pulsar.adoc#pulsar-schema-configuration[Pulsar Reference Guide - Schema]. ==== == The HTML page @@ -390,7 +389,7 @@ mvn -f pulsar-quickstart-processor quarkus:dev ---- Quarkus starts a Pulsar broker automatically, configures the application and shares the Pulsar broker instance between different applications. -See xref:pulsar.adoc[Dev Services for Pulsar] for more details. +See xref:pulsar-dev-services.adoc[Dev Services for Pulsar] for more details. Open `http://localhost:8080/quotes.html` in your browser and request some quotes by clicking the button. @@ -511,5 +510,5 @@ For the exhaustive list of features and configuration options, check the xref:pu [NOTE] ==== In this guide we explore Smallrye Reactive Messaging framework to interact with Apache Pulsar. -xref:pulsar.adoc#pulsar-clients[using Pulsar clients directly]. +xref:pulsar.adoc#configuring-pulsar-clients[using Pulsar clients directly]. ==== diff --git a/docs/src/main/asciidoc/redis-reference.adoc b/docs/src/main/asciidoc/redis-reference.adoc index 61f5d47becac0..12ec1bb96f910 100644 --- a/docs/src/main/asciidoc/redis-reference.adoc +++ b/docs/src/main/asciidoc/redis-reference.adoc @@ -87,7 +87,8 @@ To help you select the suitable API for you, here are some recommendations: * If you have existing Vert.x code, use `io.vertx.redis.client.RedisAPI` * If you need to emit custom commands, you can either use the data sources (reactive or imperative) or the `io.vertx.mutiny.redis.client.Redis`. -== Inject the default and named clients +[[default-and-named-clients]] +== [[inject-the-default-and-named-clients]] Inject the default and named clients This extension lets you configure a _default_ Redis client/data sources or _named_ ones. The latter is essential when you need to connect to multiple Redis instances. diff --git a/docs/src/main/asciidoc/resteasy-reactive.adoc b/docs/src/main/asciidoc/resteasy-reactive.adoc index 8b23992d27078..1b456e8b94b5f 100644 --- a/docs/src/main/asciidoc/resteasy-reactive.adoc +++ b/docs/src/main/asciidoc/resteasy-reactive.adoc @@ -394,9 +394,8 @@ public class Endpoint { ---- <1> `BeanParam` is required to comply with the Jakarta REST specification so that libraries like OpenAPI can introspect the parameters. -=== Declaring URI parameters - [[uri-parameters]] +=== [[declaring-uri-parameters]] Declaring URI parameters You can declare URI parameters and use regular expressions in your path, so for instance the following endpoint will serve requests for `/hello/stef/23` and `/hello` but not @@ -435,7 +434,6 @@ its HTTP representation to the Java type of the parameter. The following parameter types will be supported out of the box: [[resource-types]] - .Request body parameter types |=== |Type|Usage diff --git a/docs/src/main/asciidoc/security-customization.adoc b/docs/src/main/asciidoc/security-customization.adoc index edc525b969e50..a60c30a0ca2e0 100644 --- a/docs/src/main/asciidoc/security-customization.adoc +++ b/docs/src/main/asciidoc/security-customization.adoc @@ -177,7 +177,7 @@ public class RolesAugmentor implements SecurityIdentityAugmentor { } ---- -Here is another example showing how to use the client certificate available in the current xref:security-authentication-mechanisms.adoc#mutual-TLS-authentication[mutual TLS (mTLS) authentication] request to add more roles: +Here is another example showing how to use the client certificate available in the current xref:security-authentication-mechanisms.adoc#mutual-tls[mutual TLS (mTLS) authentication] request to add more roles: [source,java] ---- diff --git a/docs/src/main/asciidoc/security-jwt.adoc b/docs/src/main/asciidoc/security-jwt.adoc index 36c7f267f587e..586feadd7d8d3 100644 --- a/docs/src/main/asciidoc/security-jwt.adoc +++ b/docs/src/main/asciidoc/security-jwt.adoc @@ -817,7 +817,7 @@ To prevent it, set `quarkus.smallrye-jwt.blocking-authentication=true`. === Token Propagation -Please see the xref:security-openid-connect-client.adoc#token-propagation[Token Propagation] section about the Bearer access token propagation to the downstream services. +Please see the xref:security-openid-connect-client-reference.adoc#token-propagation[Token Propagation] section about the Bearer access token propagation to the downstream services. [[integration-testing]] === Testing diff --git a/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc index e0796c3b007c0..0983304d2d839 100644 --- a/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc @@ -166,7 +166,7 @@ To learn more about why this behavior occurs, you can use OIDC Dev UI as explain == Looking at Auth0 tokens in the OIDC Dev UI -Quarkus provides a great xref:dev-ui-v2.adoc[Dev UI] experience. +Quarkus provides a great xref:dev-ui.adoc[Dev UI] experience. Specifically, Quarkus offers built-in support for developing and testing OIDC endpoints with a Keycloak container. xref:security-openid-connect-dev-services.adoc#dev-services-for-keycloak[DevService for Keycloak] is automatically started and used if the address of the OIDC provider is not specified for the Quarkus `quarkus.oidc.auth-server-url` configuration property. diff --git a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc index d9926bdb370e2..175926e088469 100644 --- a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc +++ b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc @@ -1236,7 +1236,7 @@ Authentication that requires a dynamic tenant will fail. == OIDC request filters You can filter OIDC requests made by Quarkus to the OIDC provider by registering one or more `OidcRequestFilter` implementations, which can update or add new request headers, and log requests. -For more information, see xref:security-code-flow-authentication#oidc-request-filters[OIDC request filters]. +For more information, see xref:security-oidc-code-flow-authentication#oidc-request-filters[OIDC request filters]. == References diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc index c266583b568bd..05f3861b76bdb 100644 --- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc @@ -157,7 +157,7 @@ It returns a `preferred_username` claim from the ID token, a `scope` claim from You only need to inject the tokens if the endpoint needs to use the ID token to interact with the currently authenticated user or use the access token to access a downstream service on behalf of this user. -// SJ: TO DO - update link to point to new reference guide. For more information, see <> section. +For more information, see the xref:security-oidc-code-flow-authentication.adoc#access_id_and_access_tokens[Access ID and Access Tokens] section of the reference guide. == Configure the application diff --git a/docs/src/main/asciidoc/writing-extensions.adoc b/docs/src/main/asciidoc/writing-extensions.adoc index 40d6399d6e61e..36f38ed605e3e 100644 --- a/docs/src/main/asciidoc/writing-extensions.adoc +++ b/docs/src/main/asciidoc/writing-extensions.adoc @@ -276,7 +276,7 @@ Instead, the attributes are specified by an extension. NOTE: Since the CDI container does not control the instantiation of a synthetic bean the dependency injection and other services (such as interceptors) are not supported. In other words, it's up to the extension to provide all required services to a synthetic bean instance. -There are several ways to register a <> in Quarkus. +There are several ways to register a <> in Quarkus. In this chapter, we will cover a use case that can be used to initialize extension beans in a safe manner (compared to <>). The `SyntheticBeanBuildItem` can be used to register a synthetic bean: @@ -1594,7 +1594,7 @@ Instead, Quarkus extensions can make use of various xref:cdi-reference.adoc[Buil === Quarkus Dev UI -You can make your extension support the xref:dev-ui-v2.adoc[Quarkus Dev UI] for a greater developer experience. +You can make your extension support the xref:dev-ui.adoc[Quarkus Dev UI] for a greater developer experience. === Extension-defined endpoints @@ -1952,7 +1952,7 @@ The JSON-B extension will then use the produced build item to register your seri If you need more customization capabilities than registering a serializer or a deserializer, you can produce a CDI bean that implements `io.quarkus.jsonb.JsonbConfigCustomizer` via an `AdditionalBeanBuildItem`. -More info about customizing JSON-B can be found on the JSON guide xref:rest-json.adoc#configuring-json-support[Configuring JSON support] +More info about customizing JSON-B can be found on the JSON guide xref:rest-json.adoc#json[Configuring JSON support] === Integrating with Development Mode diff --git a/docs/src/main/asciidoc/writing-native-applications-tips.adoc b/docs/src/main/asciidoc/writing-native-applications-tips.adoc index 728ee3356d1d2..aef14713a464a 100644 --- a/docs/src/main/asciidoc/writing-native-applications-tips.adoc +++ b/docs/src/main/asciidoc/writing-native-applications-tips.adoc @@ -734,4 +734,4 @@ For more information about Proxy Classes, see the link:https://www.graalvm.org/{ If you are using dependencies that require logging components such as Apache Commons Logging or Log4j and are experiencing a `ClassNotFoundException` when building the native executable, you can resolve this by excluding the logging library and adding the corresponding JBoss Logging adapter. -For more details please refer to the xref:logging.adoc#logging-adapters[Logging guide]. +For more details please refer to the xref:logging.adoc#logging-apis[Logging guide].