This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 9dfbf8f5a5 Document Camel Quarkus build items
9dfbf8f5a5 is described below

commit 9dfbf8f5a52ebc03fbfe92f4e1a1f8d215621544
Author: Abdullah <[email protected]>
AuthorDate: Wed Sep 30 15:47:36 2026 +0300

    Document Camel Quarkus build items
    
    Fixes #2900
    
    * Document Camel Quarkus build items
    
    Add a contributor-guide summary of the core and Camel Main build
    items, similar to the Quarkus all-builditems page.
    
    * Generate the build items page from all deployment modules
    
    Scan *BuildItem classes across extensions-core, extensions,
    extensions-support and extensions-jvm, and write the
    contributor-guide page from the docs module so the main
    build is not involved.
    
    * Rework the build items doc generator along QuarkusBuildItemDoc lines
    
    Parse the sources with JavaParser instead of regular expressions, group
    the build items by the <name> of the Maven module declaring them, list
    their fields, skip the non-public and deprecated ones and flag the
    abstract ones, mirroring io.quarkus.docs.generation.QuarkusBuildItemDoc.
    
    Move the mojo execution from validate to process-classes, so that
    mvn clean validate, as run by the check-format CI job, does not have to
    resolve camel-quarkus-maven-plugin before the reactor has packaged it.
    The execution now sits in the full profile, hence -Dquickly builds skip
    it.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    
    * Drop the :: separator from the build items doc section headings
    
    Camel Quarkus :: Support :: DSL :: Deployment now yields a Support DSL
    section instead of Support :: DSL.
    
    Note in AGENTS.md how to regenerate the page too, as -Dquickly builds
    skip the generator.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: James Netherton <[email protected]>
    Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
 AGENTS.md                                          |   6 +
 docs/modules/ROOT/nav.adoc                         |   1 +
 .../ROOT/pages/contributor-guide/build-items.adoc  | 545 +++++++++++++++++++++
 .../ROOT/pages/user-guide/custom-components.adoc   |   2 +
 docs/pom.xml                                       |  29 ++
 tooling/maven-plugin/pom.xml                       |   5 +
 .../quarkus/maven/UpdateBuildItemsDocMojo.java     | 348 +++++++++++++
 7 files changed, 936 insertions(+)

diff --git a/AGENTS.md b/AGENTS.md
index deac1f0f7e..a709c84673 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -94,6 +94,12 @@ Always include `:camel-quarkus` (the root project) in `-pl`: 
it runs the root-on
 
 To regenerate one extension's docs on its own: `./mvnw -pl 
extensions/kafka/deployment process-classes`.
 
+After adding or removing a `*BuildItem` class, or changing its Javadoc or 
fields, regenerate the build items page:
+```bash
+./mvnw -pl docs process-classes            # 
docs/modules/ROOT/pages/contributor-guide/build-items.adoc
+```
+A full build does this already, but `-Dquickly` builds skip it, so a stale 
page otherwise surfaces only as a CI failure.
+
 It rewrites files in place, so run it **before `git add`**, or re-stage after. 
Always run it from the project root.
 
 ## Extension Structure
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index c1f9ae1443..ca3d148479 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -18,6 +18,7 @@
 ** xref:migration-guide/3.2.0.adoc[Camel Quarkus 3.2.0 migration guide]
 * xref:contributor-guide/index.adoc[Contributor guide]
 ** xref:contributor-guide/create-new-extension.adoc[Create new extension]
+** xref:contributor-guide/build-items.adoc[Build items]
 ** xref:contributor-guide/promote-jvm-to-native.adoc[Promote JVM extension to 
Native]
 ** xref:contributor-guide/create-jvm-only-extension.adoc[Create JVM-only 
extension]
 ** xref:contributor-guide/extension-metadata.adoc[Extension metadata]
diff --git a/docs/modules/ROOT/pages/contributor-guide/build-items.adoc 
b/docs/modules/ROOT/pages/contributor-guide/build-items.adoc
new file mode 100644
index 0000000000..f9e7798354
--- /dev/null
+++ b/docs/modules/ROOT/pages/contributor-guide/build-items.adoc
@@ -0,0 +1,545 @@
+// Do not edit directly!
+// This file was generated by camel-quarkus-maven-plugin:update-build-items-doc
+= Camel Quarkus build items
+:linkattrs:
+
+Quarkus extensions pass information to each other at build time through build 
items produced and
+consumed by `@BuildStep` methods.
+This page lists the build items declared by the Camel Quarkus deployment 
modules.
+The build items provided by Quarkus itself are listed on the
+https://quarkus.io/guides/all-builditems[Quarkus build items] page.
+
+== Core
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/main/spi/CamelMainBuildItem.java[`org.apache.camel.quarkus.core.deployment.main.spi.CamelMainBuildItem`,window=_blank]
+
+Holds the `CamelMain` `RuntimeValue`.
+a|`RuntimeValue<CamelMain> main`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/main/spi/CamelMainListenerBuildItem.java[`org.apache.camel.quarkus.core.deployment.main.spi.CamelMainListenerBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding `MainListener`s to add to `CamelMain`.
+a|`RuntimeValue<MainListener> listener`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/AnnouncedSyntheticBeanBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.AnnouncedSyntheticBeanBuildItem`,window=_blank]
+
+Announces a bean that another extension registers synthetically. 
`BeanDiscoveryFinishedBuildItem` lists
+class-based beans only, so a build step that counts beans of a type through it 
misses the synthetic ones; the
+extension knowing about such a bean produces one item per bean, naming the 
type it counts as and, for a bean
+qualified by a name, that name. A consumer looking for the default bean of a 
type must skip the named
+announcements: a named bean does not carry the `@Default` qualifier.
+a|`DotName beanType`
+
+`String name`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/BuildTimeCamelCatalogBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.BuildTimeCamelCatalogBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`BuildTimeCamelCatalog catalog`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelBeanBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelBeanBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding beans to add to `org.apache.camel.spi.Registry` 
during
+`ExecutionTime#STATIC_INIT` phase.
+
+You can use the sibling `CamelRuntimeBeanBuildItem` to register beans in the 
`ExecutionTime#RUNTIME_INIT`
+phase - i.e. those ones that cannot be produced during 
`ExecutionTime#STATIC_INIT` phase.
+
+Note that the field type should refer to the most specialized class to avoid 
the issue described in
+https://issues.apache.org/jira/browse/CAMEL-13948.
+a|`String name`
+
+`String type`
+
+`RuntimeValue<?> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelBeanQualifierResolverBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelBeanQualifierResolverBuildItem`,window=_blank]
+
+Holds a `CamelBeanQualifierResolver` for a specified bean type.
+a|`RuntimeValue<CamelBeanQualifierResolver> runtimeValue`
+
+`Class<?> beanType`
+
+`String beanName`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelBootClockBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelBootClockBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`RuntimeValue<Clock> bootClockRuntimeValue`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelBootstrapCompletedBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelBootstrapCompletedBuildItem`,window=_blank]
+
+A build item that does not carry any data but it is used to signal that all 
the bootstrap steps have been
+completed.
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelComponentNameResolverBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelComponentNameResolverBuildItem`,window=_blank]
+
+Holds the `ComponentNameResolver` `RuntimeValue`.
+a|`RuntimeValue<ComponentNameResolver> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelContextBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem`,window=_blank]
+
+Holds the `CamelContext` `RuntimeValue`.
+a|`RuntimeValue<CamelContext> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelContextCustomizerBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelContextCustomizerBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding the `CamelContextCustomizer` `RuntimeValue` and 
could be used
+to customize the camel context before produce the `CamelContextBuildItem`
+a|`RuntimeValue<CamelContextCustomizer> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelFactoryFinderResolverBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelFactoryFinderResolverBuildItem`,window=_blank]
+
+A `SimpleBuildItem` holding a `FactoryFinderResolver` `RuntimeValue`.
+a|`RuntimeValue<FactoryFinderResolver> factoryFinderResolver`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelModelJAXBContextFactoryBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelModelJAXBContextFactoryBuildItem`,window=_blank]
+
+Holds the `ModelJAXBContextFactory` instance.
+a|`RuntimeValue<ModelJAXBContextFactory> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelModelReifierFactoryBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelModelReifierFactoryBuildItem`,window=_blank]
+
+A `SimpleBuildItem` holding a `ModelReifierFactory` `RuntimeValue`.
+a|`RuntimeValue<ModelReifierFactory> modelReifierFactory`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelModelToXMLDumperBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelModelToXMLDumperBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`RuntimeValue<ModelToXMLDumper> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelModelToYAMLDumperBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelModelToYAMLDumperBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`RuntimeValue<ModelToYAMLDumper> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelPackageScanClassBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelPackageScanClassBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding the names of a types that will be scanned by the 
Camel PackageScanClassResolver.
+a|`Set<String> classNames`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelPackageScanClassResolverBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelPackageScanClassResolverBuildItem`,window=_blank]
+
+Holds the `PackageScanClassResolver` `RuntimeValue`.
+a|`RuntimeValue<PackageScanClassResolver> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRegistryBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRegistryBuildItem`,window=_blank]
+
+Holds the `Registry` `RuntimeValue`. It is made available after the beans from
+`CamelBeanBuildItem`s were registered in the underlying `Registry`.
+a|`RuntimeValue<Registry> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRouteResourceBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRouteResourceBuildItem`,window=_blank]
+
+Holds a `Resource` relating to discovered Camel DSL route definition files 
defined by
+route inclusion patterns configuration.
+a|`String location`
+
+`String sourcePath`
+
+`boolean isHotReloadable`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRoutesBuilderClassBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRoutesBuilderClassBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding class names of all `RoutesBuilder` implementations.
+
+The class names are gathered from Jandex by `camel-quarkus-core`. Extensions 
are free to add
+`CamelRoutesBuilderClassBuildItem`s programmatically.
+a|`DotName dotName`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRuntimeBeanBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBeanBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding beans to add to `org.apache.camel.spi.Registry` 
during
+`ExecutionTime#RUNTIME_INIT` phase.
+
+You should use the sibling `CamelBeanBuildItem` for all beans that can be 
produced during
+`ExecutionTime#STATIC_INIT` phase.
+
+Note that the field type should refer to the most specialized class to avoid 
the issue described in
+https://issues.apache.org/jira/browse/CAMEL-13948.
+a|`String name`
+
+`String type`
+
+`RuntimeValue<?> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRuntimeBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`RuntimeValue<CamelRuntime> runtime`
+
+`boolean autoStartup`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelRuntimeTaskBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelRuntimeTaskBuildItem`,window=_blank]
+
+Marker used as synchronization item for Build Steps to ensure all the Build 
Steps that need to record
+`ExecutionTime#RUNTIME_INIT`.
+
+As example some beans can be bound to the `org.apache.camel.spi.Registry` at 
`ExecutionTime#STATIC_INIT`
+but others can only be bound at `ExecutionTime#RUNTIME_INIT` and to be sure 
that the binding happens before the
+`org.apache.camel.quarkus.core.CamelRuntime` is assembled and started a 
CamelRuntimeTaskBuildItem is produced
+and the Build Steps producing `CamelRuntimeBuildItem` depends on it.
+
+The initial barrier required two symmetric Build Items:
+
+* CamelRegistryBuildItem
+
+* CamelRuntimeRegistryBuildItem
+
+Where the second Build Item was useless except for synchronization purpose and 
has been replaced to this generic
+CamelRuntimeTaskBuildItem.
+a|`String name`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelSerializationBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelSerializationBuildItem`,window=_blank]
+
+Signal that the basic classes listed in
+`org.apache.camel.quarkus.core.deployment.CamelSerializationProcessor.BASE_SERIALIZATION_CLASSES`,
 together
+with any
+additional classes passed to this build item, should be registered for 
serialization.
+
+Registrations requested via this build item can be vetoed by the user with
+`quarkus.camel.native.reflection.serialization-enabled=false`. Extensions that 
need the base set of classes
+must
+therefore route their serialization registrations through this build item, 
instead of producing
+`ReflectiveClassBuildItem.serializationClass(..)` directly.
+a|`List<String> classNames`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelServiceBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelServiceBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding information about a service defined in a property 
file somewhere under
+`META-INF/services/org/apache/camel`.
+a|`Path path`
+
+`String name`
+
+`String type`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelServiceFilterBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelServiceFilterBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`CamelServiceFilter predicate`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelServicePatternBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelServicePatternBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding a collection of path patterns to select files under
+`META-INF/services/org/apache/camel` which define discoverable Camel services.
+a|`CamelServiceDestination destination`
+
+`boolean include`
+
+`List<String> patterns`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelTypeConverterLoaderBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelTypeConverterLoaderBuildItem`,window=_blank]
+
+Holds the `TypeConverterLoader` `RuntimeValue`.
+a|`RuntimeValue<TypeConverterLoader> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CamelTypeConverterRegistryBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CamelTypeConverterRegistryBuildItem`,window=_blank]
+
+Holds the `org.apache.camel.spi.TypeConverterRegistry` `RuntimeValue`.
+a|`RuntimeValue<TypeConverterRegistry> value`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/CompiledCSimpleExpressionBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.CompiledCSimpleExpressionBuildItem`,window=_blank]
+
+A `MultiBuildItem` bearing info about a compiled CSimple language expression.
+a|`String sourceCode`
+
+`String className`
+
+`boolean predicate`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/ContainerBeansBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.ContainerBeansBuildItem`,window=_blank]
+
+Hold a set of beans known to the ArC container.
+a|`Set<CamelBeanInfo> beans`
+
+`Set<DotName> classes`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/RoutesBuilderClassExcludeBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.RoutesBuilderClassExcludeBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding patterns whose matching classes will be excluded 
from the set of classes from which
+routes will be instantiated. This is a programmatic way of doing the same 
thing as can be done via
+`RoutesDiscoveryConfig#excludePatterns`.
+a|`String pattern`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi/RuntimeCamelContextCustomizerBuildItem.java[`org.apache.camel.quarkus.core.deployment.spi.RuntimeCamelContextCustomizerBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding the `CamelContextCustomizer` `RuntimeValue` and 
could be used
+to customize the camel context before starting it.
+a|`RuntimeValue<CamelContextCustomizer> value`
+|===
+
+== BeanIO
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/beanio/deployment/src/main/java/org/apache/camel/quarkus/component/beanio/deployment/BeanioPropertiesBuildItem.java[`org.apache.camel.quarkus.component.beanio.deployment.BeanioPropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`Properties properties`
+|===
+
+== CSimple
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/csimple/deployment/src/main/java/org/apache/camel/quarkus/component/csimple/deployment/CSimpleExpressionSourceBuildItem.java[`org.apache.camel.quarkus.component.csimple.deployment.CSimpleExpressionSourceBuildItem`,window=_blank]
+
+A `MultiBuildItem` bearing info about a CSimple language expression that needs 
to get compiled.
+a|`String sourceCode`
+
+`String classNameBase`
+
+`boolean predicate`
+|===
+
+== DataSonnet
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/datasonnet/deployment/src/main/java/org/apache/camel/quarkus/component/datasonnet/deployment/DatasonnetLibrariesBuildItem.java[`org.apache.camel.quarkus.component.datasonnet.deployment.DatasonnetLibrariesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`Map<String,String> libraries`
+|===
+
+== FHIR
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|icon:building[title=Non-instantiatable Build Item (can be inherited from)] 
https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/AbstractPropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.AbstractPropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`Map<String,String> properties`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/dstu2/Dstu2PropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.dstu2.Dstu2PropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/dstu2Hl7Org/Dstu2Hl7OrgPropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.dstu2Hl7Org.Dstu2Hl7OrgPropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/dstu2_1/Dstu2_1PropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.dstu2_1.Dstu2_1PropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/dstu3/Dstu3PropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.dstu3.Dstu3PropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/r4/R4PropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.r4.R4PropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/fhir/deployment/src/main/java/org/apache/camel/quarkus/component/fhir/deployment/r5/R5PropertiesBuildItem.java[`org.apache.camel.quarkus.component.fhir.deployment.r5.R5PropertiesBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|None
+|===
+
+== Groovy
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/groovy/deployment/src/main/java/org/apache/camel/quarkus/component/groovy/deployment/GroovyExpressionSourceBuildItem.java[`org.apache.camel.quarkus.component.groovy.deployment.GroovyExpressionSourceBuildItem`,window=_blank]
+
+A `MultiBuildItem` bearing info about a Groovy language expression that needs 
to get compiled.
+a|`String sourceCode`
+
+`String originalCode`
+
+`String className`
+|===
+
+== Java jOOR DSL
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/java-joor-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/java/joor/deployment/JavaJoorGeneratedClassBuildItem.java[`org.apache.camel.quarkus.dsl.java.joor.deployment.JavaJoorGeneratedClassBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`String name`
+
+`String location`
+
+`byte[] classData`
+|===
+
+== jOOR
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/joor/deployment/src/main/java/org/apache/camel/quarkus/component/joor/deployment/JoorExpressionSourceBuildItem.java[`org.apache.camel.quarkus.component.joor.deployment.JoorExpressionSourceBuildItem`,window=_blank]
+
+A `MultiBuildItem` bearing info about a jOOR language expression that needs to 
get compiled.
+a|`String sourceCode`
+
+`String className`
+
+`String id`
+
+`boolean script`
+|===
+
+== LangChain4j Embedding Store
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/langchain4j-embeddingstore/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/embeddingstore/deployment/DefaultRetrievalAugmentorBuildItem.java[`org.apache.camel.quarkus.component.langchain4j.embeddingstore.deployment.DefaultRetrievalAugmentorBuildItem`,window=_blank]
+
+Produced when the auto-detected default `RetrievalAugmentor` is registered, so 
that its
+`@Default` store and model can be verified once the synthetic beans exist.
+a|None
+|===
+
+== MapStruct
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/mapstruct/deployment/src/main/java/org/apache/camel/quarkus/component/mapstruct/deployment/ConversionMethodInfoRuntimeValuesBuildItem.java[`org.apache.camel.quarkus.component.mapstruct.deployment.ConversionMethodInfoRuntimeValuesBuildItem`,window=_blank]
+
+Holds info about generated TypeConverter ConversionMethod.
+a|`Set<RuntimeValue<ConversionMethodInfo>> conversionMethodInfoRuntimeValues`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/mapstruct/deployment/src/main/java/org/apache/camel/quarkus/component/mapstruct/deployment/MapStructMapperPackagesBuildItem.java[`org.apache.camel.quarkus.component.mapstruct.deployment.MapStructMapperPackagesBuildItem`,window=_blank]
+
+Holds the set of discovered MapStruct Mapper packages.
+a|`Set<String> mapperPackages`
+|===
+
+== Platform HTTP
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/platform-http/deployment/src/main/java/org/apache/camel/quarkus/component/platform/http/deployment/PlatformHttpEngineBuildItem.java[`org.apache.camel.quarkus.component.platform.http.deployment.PlatformHttpEngineBuildItem`,window=_blank]
+
+Holds the `PlatformHttpEngine` `RuntimeValue`.
+a|`RuntimeValue<PlatformHttpEngine> instance`
+|===
+
+== Support Bouncy Castle
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/bouncycastle/deployment/src/main/java/org/apache/camel/quarkus/support/bouncycastle/deployment/BouncyCastleAdditionalProviderBuildItem.java[`org.apache.camel.quarkus.support.bouncycastle.deployment.BouncyCastleAdditionalProviderBuildItem`,window=_blank]
+
+In case that non-default BC provider has to be registered, use this buildItem.
+(provider available for registration is `BCPQC`)
+a|`String proivderName`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/bouncycastle/deployment/src/main/java/org/apache/camel/quarkus/support/bouncycastle/deployment/CipherTransformationBuildItem.java[`org.apache.camel.quarkus.support.bouncycastle.deployment.CipherTransformationBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding cipher transformations to be explicitly
+registered as security services. Extensions should provide all cipher 
transformations
+that are reachable at runtime. Those cipher transformations will be explicitly 
instantiated
+at bootstrap so that graal can proceed with security services automatic 
registration.
+a|`List<String> cipherTransformations`
+|===
+
+== Support DSL
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/dsl/deployment/src/main/java/org/apache/camel/quarkus/support/dsl/deployment/DslGeneratedClassBuildItem.java[`org.apache.camel.quarkus.support.dsl.deployment.DslGeneratedClassBuildItem`,window=_blank]
+
+_No Javadoc found_
+a|`String name`
+
+`String location`
+
+`boolean instantiateWithCamelContext`
+|===
+
+== Support Language
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ExpressionBuildItem.java[`org.apache.camel.quarkus.support.language.deployment.ExpressionBuildItem`,window=_blank]
+
+`ExpressionBuildItem` represents an expression in a given language that has 
been extracted from the route
+definitions.
+a|`String language`
+
+`String expression`
+
+`String loadedExpression`
+
+`boolean predicate`
+
+`Object[] properties`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ExpressionExtractionResultBuildItem.java[`org.apache.camel.quarkus.support.language.deployment.ExpressionExtractionResultBuildItem`,window=_blank]
+
+`ExpressionBuildItem` represents the result of the expression extraction 
process.
+a|`boolean success`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions-support/language/deployment/src/main/java/org/apache/camel/quarkus/support/language/deployment/ScriptBuildItem.java[`org.apache.camel.quarkus.support.language.deployment.ScriptBuildItem`,window=_blank]
+
+`ScriptBuildItem` represents a script and its binding context in a given 
language that has been extracted from
+the route definitions.
+a|`String language`
+
+`String content`
+
+`String loadedContent`
+
+`Map<String,Object> bindings`
+|===
+
+== XSLT
+
+[width="100%",cols="50,50",options="header"]
+|===
+| Class name | Attributes
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/UriResolverEntryBuildItem.java[`org.apache.camel.quarkus.component.xslt.deployment.UriResolverEntryBuildItem`,window=_blank]
+
+Holds a pair of XSLT template URI and the unqualified translet name to use 
when creating a
+`RuntimeUriResolver`.
+a|`String templateUri`
+
+`String transletClassName`
+
+a|https://github.com/apache/camel-quarkus/blob/main/extensions/xslt/deployment/src/main/java/org/apache/camel/quarkus/component/xslt/deployment/XsltGeneratedClassBuildItem.java[`org.apache.camel.quarkus.component.xslt.deployment.XsltGeneratedClassBuildItem`,window=_blank]
+
+A `MultiBuildItem` holding names of the XSLT translets (and possibly also 
names of their ancillary classes)
+generated at build time.
+a|`String className`
+|===
diff --git a/docs/modules/ROOT/pages/user-guide/custom-components.adoc 
b/docs/modules/ROOT/pages/user-guide/custom-components.adoc
index b8473ab272..311c5df000 100644
--- a/docs/modules/ROOT/pages/user-guide/custom-components.adoc
+++ b/docs/modules/ROOT/pages/user-guide/custom-components.adoc
@@ -80,6 +80,8 @@ Creating a Quarkus extension provides the most control and 
allows you to:
 
 See the https://quarkus.io/guides/writing-extensions[Quarkus Writing 
Extensions Guide] for detailed instructions.
 
+The Camel-specific build items you can produce or consume are listed in 
xref:contributor-guide/build-items.adoc[Camel Quarkus build items].
+
 == Additional considerations
 
 === Camel service discovery
diff --git a/docs/pom.xml b/docs/pom.xml
index 6a10b93d70..fd72964e41 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -64,4 +64,33 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <profile>
+            <id>full</id>
+            <activation>
+                <property>
+                    <name>!quickly</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.camel.quarkus</groupId>
+                        <artifactId>camel-quarkus-maven-plugin</artifactId>
+                        <version>${project.version}</version>
+                        <executions>
+                            <execution>
+                                <id>update-build-items-doc</id>
+                                <goals>
+                                    <goal>update-build-items-doc</goal>
+                                </goals>
+                                <phase>process-classes</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/tooling/maven-plugin/pom.xml b/tooling/maven-plugin/pom.xml
index d12a3805a8..f7906a5fca 100644
--- a/tooling/maven-plugin/pom.xml
+++ b/tooling/maven-plugin/pom.xml
@@ -85,6 +85,11 @@
             <artifactId>jackson-databind</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.javaparser</groupId>
+            <artifactId>javaparser-core</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-extension-processor</artifactId>
diff --git 
a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateBuildItemsDocMojo.java
 
b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateBuildItemsDocMojo.java
new file mode 100644
index 0000000000..90b977d86b
--- /dev/null
+++ 
b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateBuildItemsDocMojo.java
@@ -0,0 +1,348 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.comments.JavadocComment;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+/**
+ * Scans the deployment modules of the current source tree for {@code 
*BuildItem.java} classes and regenerates
+ * {@code docs/modules/ROOT/pages/contributor-guide/build-items.adoc}.
+ * <p>
+ * Modelled on the {@code io.quarkus.docs.generation.QuarkusBuildItemDoc} 
generator of Quarkus, so that the Camel
+ * Quarkus page stays consistent with the
+ * <a href="https://quarkus.io/guides/all-builditems";>Quarkus build items</a> 
page: build items are grouped by the
+ * Maven module declaring them, documented with their Javadoc and their 
fields, and abstract ones are flagged rather
+ * than omitted.
+ */
+@Mojo(name = "update-build-items-doc", threadSafe = true)
+public class UpdateBuildItemsDocMojo extends AbstractExtensionListMojo {
+
+    private static final String[] SOURCE_ROOTS = {
+            "extensions-core",
+            "extensions-support",
+            "extensions",
+            "extensions-jvm"
+    };
+    /** Printed before all other sections, like {@code Core} on the Quarkus 
page */
+    private static final String CORE_SECTION = "Core";
+    private static final String MODULE_NAME_PREFIX = "Camel Quarkus :: ";
+    private static final String MODULE_NAME_SUFFIX = " :: Deployment";
+    private static final Pattern MODULE_NAME_SEPARATOR = 
Pattern.compile("\\s*::\\s*");
+    private static final String GITHUB_SOURCE_BASE = 
"https://github.com/apache/camel-quarkus/blob/";;
+    private static final String NO_JAVADOC = "_No Javadoc found_";
+    private static final Pattern ANCHOR_PATTERN = 
Pattern.compile("(?s)<a\\s+href=\\s*\"([^\"]*?)\"\\s*>(.*?)</a>");
+
+    /**
+     * Skip the execution of this mojo.
+     */
+    @Parameter(defaultValue = "false", property = 
"camel-quarkus.update-build-items-doc.skip")
+    boolean skip;
+
+    /**
+     * The page to generate.
+     */
+    @Parameter(defaultValue = 
"${maven.multiModuleProjectDirectory}/docs/modules/ROOT/pages/contributor-guide/build-items.adoc",
 property = "camel-quarkus.buildItemsDocFile")
+    File outputFile;
+
+    /**
+     * Used to select the git ref the generated source links point at. 
Snapshot versions link to {@code main}.
+     */
+    @Parameter(defaultValue = "${project.version}", readonly = true)
+    String projectVersion;
+
+    private final JavaParser javaParser = new JavaParser(
+            new 
ParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_17));
+
+    @Override
+    public void execute() throws MojoExecutionException {
+        if (skip) {
+            getLog().info("Skipping per user request");
+            return;
+        }
+
+        final Path root = getRootModuleDirectory();
+        final Map<String, List<BuildItem>> sections = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        for (String sourceRoot : SOURCE_ROOTS) {
+            final Path dir = root.resolve(sourceRoot);
+            if (Files.isDirectory(dir)) {
+                collect(dir, root, sections);
+            }
+        }
+        sections.values().forEach(items -> 
items.sort(Comparator.comparing(item -> item.className)));
+
+        final Path out = outputFile.toPath();
+        final String page = render(sections);
+        try {
+            if (Files.isRegularFile(out) && page.equals(Files.readString(out, 
getCharset()))) {
+                getLog().info("Build items doc is up to date: " + out);
+                return;
+            }
+            Files.createDirectories(out.getParent());
+            Files.writeString(out, page, getCharset());
+            getLog().info("Wrote " + 
sections.values().stream().mapToInt(List::size).sum() + " build items to " + 
out);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Could not write " + out, e);
+        }
+    }
+
+    void collect(Path dir, Path root, Map<String, List<BuildItem>> sections) 
throws MojoExecutionException {
+        try (Stream<Path> files = Files.walk(dir)) {
+            final List<Path> buildItemFiles = files
+                    .filter(Files::isRegularFile)
+                    .filter(file -> 
file.getFileName().toString().endsWith("BuildItem.java"))
+                    .filter(file -> relativize(root, 
file).contains("/src/main/java/"))
+                    .toList();
+            for (Path file : buildItemFiles) {
+                parse(file, root, sections);
+            }
+        } catch (IOException e) {
+            throw new MojoExecutionException("Could not walk " + dir, e);
+        }
+    }
+
+    void parse(Path file, Path root, Map<String, List<BuildItem>> sections) 
throws MojoExecutionException {
+        final ParseResult<CompilationUnit> result;
+        try {
+            result = javaParser.parse(file);
+        } catch (IOException e) {
+            throw new MojoExecutionException("Could not read " + file, e);
+        }
+        final Optional<CompilationUnit> compilationUnit = result.getResult();
+        if (compilationUnit.isEmpty()) {
+            throw new MojoExecutionException("Could not parse " + file + ": " 
+ result.getProblems());
+        }
+        final Optional<ClassOrInterfaceDeclaration> primaryType = 
compilationUnit.get()
+                .findFirst(ClassOrInterfaceDeclaration.class);
+        if (primaryType.isEmpty()) {
+            return;
+        }
+        final ClassOrInterfaceDeclaration declaration = primaryType.get();
+        /* Ignore non-public and deprecated build items */
+        if (!declaration.isPublic() || 
declaration.getAnnotationByClass(Deprecated.class).isPresent()) {
+            return;
+        }
+        sections.computeIfAbsent(sectionOf(file), k -> new ArrayList<>())
+                .add(new BuildItem(relativize(root, file), declaration));
+    }
+
+    /**
+     * @return the section the given build item belongs to, derived from the 
{@code <name>} of the Maven module
+     *         declaring it
+     */
+    String sectionOf(Path file) throws MojoExecutionException {
+        final Path pom = findPom(file);
+        if (pom == null) {
+            return file.getParent().getFileName().toString();
+        }
+        final String name;
+        try (Reader reader = Files.newBufferedReader(pom, getCharset())) {
+            name = new MavenXpp3Reader().read(reader).getName();
+        } catch (Exception e) {
+            throw new MojoExecutionException("Could not read " + pom, e);
+        }
+        return name == null || name.isEmpty()
+                ? pom.getParent().getFileName().toString()
+                : sanitizeModuleName(name);
+    }
+
+    static String sanitizeModuleName(String name) {
+        String result = name.trim();
+        if (result.startsWith(MODULE_NAME_PREFIX)) {
+            result = result.substring(MODULE_NAME_PREFIX.length());
+        }
+        if (result.endsWith(MODULE_NAME_SUFFIX)) {
+            result = result.substring(0, result.length() - 
MODULE_NAME_SUFFIX.length());
+        }
+        /* Nested modules, such as Camel Quarkus :: Support :: DSL :: 
Deployment, keep a separator */
+        return MODULE_NAME_SEPARATOR.matcher(result).replaceAll(" ").trim();
+    }
+
+    static Path findPom(Path file) {
+        Path parent = file;
+        while ((parent = parent.getParent()) != null) {
+            final Path pom = parent.resolve("pom.xml");
+            if (Files.isRegularFile(pom)) {
+                return pom;
+            }
+        }
+        return null;
+    }
+
+    static String relativize(Path root, Path file) {
+        return 
root.relativize(file.toAbsolutePath().normalize()).toString().replace(File.separatorChar,
 '/');
+    }
+
+    String render(Map<String, List<BuildItem>> sections) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("// Do not edit directly!\n");
+        sb.append("// This file was generated by 
camel-quarkus-maven-plugin:update-build-items-doc\n");
+        sb.append("= Camel Quarkus build items\n");
+        sb.append(":linkattrs:\n\n");
+        sb.append("Quarkus extensions pass information to each other at build 
time through build items produced and\n");
+        sb.append("consumed by `@BuildStep` methods.\n");
+        sb.append("This page lists the build items declared by the Camel 
Quarkus deployment modules.\n");
+        sb.append("The build items provided by Quarkus itself are listed on 
the\n");
+        sb.append("https://quarkus.io/guides/all-builditems[Quarkus build 
items] page.\n");
+
+        /* Note that TreeMap(Map) would not retain the case insensitive 
comparator */
+        final Map<String, List<BuildItem>> remaining = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        remaining.putAll(sections);
+        final List<BuildItem> core = remaining.remove(CORE_SECTION);
+        if (core != null) {
+            renderSection(sb, CORE_SECTION, core);
+        }
+        remaining.forEach((section, items) -> renderSection(sb, section, 
items));
+        return sb.toString();
+    }
+
+    void renderSection(StringBuilder sb, String section, List<BuildItem> 
items) {
+        sb.append("\n== ").append(section).append("\n\n");
+        sb.append("[width=\"100%\",cols=\"50,50\",options=\"header\"]\n");
+        sb.append("|===\n");
+        sb.append("| Class name | Attributes\n");
+        for (BuildItem item : items) {
+            sb.append('\n');
+            sb.append("a|");
+            if (item.declaration.isAbstract()) {
+                sb.append("icon:building[title=Non-instantiatable Build Item 
(can be inherited from)] ");
+            }
+            
sb.append(GITHUB_SOURCE_BASE).append(gitRef()).append('/').append(item.path)
+                    
.append("[`").append(item.className).append("`,window=_blank]\n\n");
+            sb.append(item.description()).append('\n');
+            sb.append("a|").append(item.attributes()).append('\n');
+        }
+        sb.append("|===\n");
+    }
+
+    String gitRef() {
+        return projectVersion == null || projectVersion.endsWith("-SNAPSHOT") 
? "main" : projectVersion;
+    }
+
+    static String javadocOf(Optional<JavadocComment> javadocComment) {
+        if (javadocComment.isEmpty()) {
+            return NO_JAVADOC;
+        }
+        return 
javadocToAsciidoc(cleanJavadocComment(javadocComment.get().getContent()));
+    }
+
+    static String cleanJavadocComment(String rawContent) {
+        return rawContent.lines()
+                .map(line -> line.replaceFirst("^\\s*\\*\\s?", ""))
+                .filter(line -> !line.trim().startsWith("@"))
+                .reduce((a, b) -> a + "\n" + b)
+                .orElse("")
+                .strip();
+    }
+
+    static String javadocToAsciidoc(String content) {
+        final String result = content
+                .replaceAll("<p> *", "\n")
+                .replaceAll("</p> *", "\n")
+                .replaceAll("<br> *", "\n")
+                .replaceAll("\\{?@(link|linkplain|see|code|literal|value) 
([^}]*)}", "`$2`")
+                .replaceAll("(?m)^@see ", "See ")
+                .replaceAll("<pre>", "\n[source]\n----\n")
+                .replaceAll("</pre>", "\n----\n")
+                .replaceAll("<h2>", "\n[discrete]\n== ")
+                .replaceAll("</h2> *", "\n\n")
+                .replaceAll("</?i>", "_")
+                .replaceAll("</?em>", "_")
+                .replaceAll("</?b>", "*")
+                .replaceAll("</?ul> *", "\n")
+                .replaceAll("<li>", "\n* ")
+                .replaceAll("</li> *", "\n\n")
+                .replaceAll("</?tt>", "`")
+                .replace("|", "\\|");
+        final String asciidoc = convertAnchors(result).strip();
+        /* Collapse the blank line runs left behind by the replacements above, 
unless they are part of a listing */
+        return asciidoc.contains("----") ? asciidoc : 
asciidoc.replaceAll("\n{3,}", "\n\n");
+    }
+
+    static String convertAnchors(String content) {
+        final Matcher matcher = ANCHOR_PATTERN.matcher(content);
+        final StringBuilder sb = new StringBuilder();
+        while (matcher.find()) {
+            final String url = matcher.group(1).strip();
+            final String text = matcher.group(2).replaceAll("\\s+", " 
").strip();
+            matcher.appendReplacement(sb, Matcher.quoteReplacement(url + "[" + 
text + ",window=_blank]"));
+        }
+        matcher.appendTail(sb);
+        return sb.toString();
+    }
+
+    static final class BuildItem {
+        private final String path;
+        private final String className;
+        private final ClassOrInterfaceDeclaration declaration;
+
+        BuildItem(String path, ClassOrInterfaceDeclaration declaration) {
+            this.path = path;
+            this.className = 
declaration.getFullyQualifiedName().orElseGet(declaration::getNameAsString);
+            this.declaration = declaration;
+        }
+
+        String description() {
+            return javadocOf(declaration.getJavadocComment());
+        }
+
+        String attributes() {
+            final StringBuilder sb = new StringBuilder();
+            for (FieldDeclaration field : declaration.getFields()) {
+                if (field.isStatic()) {
+                    continue;
+                }
+                for (VariableDeclarator variable : field.getVariables()) {
+                    if (sb.length() > 0) {
+                        sb.append("\n\n");
+                    }
+                    
sb.append('`').append(variable.getType().asString().replace("|", "\\|"))
+                            .append(' 
').append(variable.getNameAsString()).append('`');
+                    field.getJavadocComment()
+                            .ifPresent(javadoc -> sb.append("\n\n")
+                                    
.append(javadocToAsciidoc(cleanJavadocComment(javadoc.getContent()))));
+                }
+            }
+            return sb.length() == 0 ? "None" : sb.toString();
+        }
+    }
+}

Reply via email to