diff --git a/include/mrdocs/Generator.hpp b/include/mrdocs/Generator.hpp
index dcc4f7c417..f847d4de64 100644
--- a/include/mrdocs/Generator.hpp
+++ b/include/mrdocs/Generator.hpp
@@ -82,10 +82,19 @@ class MRDOCS_VISIBLE
depending on the generator and how it is
configured.
+ The default implentation assumes the output
+ is single-page and emits the file `reference.ext`
+ using @ref buildOne to generate the content.
+
+ The typical implementation will have behavior
+ similar to the default implementation if the
+ output is single-page, or will iterate over
+ the symbols in the corpus to generate multiple
+ files if the output is multi-page.
+
@return The error, if any occurred.
- @param outputPath An existing directory or
- a filename.
+ @param outputPath A directory or filename.
@param corpus The symbols to emit. The
generator may modify the contents of
diff --git a/include/mrdocs/Support/Error.hpp b/include/mrdocs/Support/Error.hpp
index 10730dd2f2..a713bc4424 100644
--- a/include/mrdocs/Support/Error.hpp
+++ b/include/mrdocs/Support/Error.hpp
@@ -2747,6 +2747,13 @@ void
setMinimumLevel(
Level level) noexcept;
+/** If true, source location information will be
+ printed with warnings, errors, and fatal messages.
+*/
+MRDOCS_DECL
+void
+setSourceLocationWarnings(bool b) noexcept;
+
/** Report a message to the console.
@param text The message to print. A
diff --git a/share/mrdocs/addons/generator/asciidoc/helpers/add.js b/share/mrdocs/addons/generator/adoc/helpers/add.js
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/helpers/add.js
rename to share/mrdocs/addons/generator/adoc/helpers/add.js
diff --git a/share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs b/share/mrdocs/addons/generator/adoc/layouts/overload-set.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/layouts/overload-set.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/layouts/single-footer.adoc.hbs b/share/mrdocs/addons/generator/adoc/layouts/single-footer.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/layouts/single-footer.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/layouts/single-footer.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/layouts/single-header.adoc.hbs b/share/mrdocs/addons/generator/adoc/layouts/single-header.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/layouts/single-header.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/layouts/single-header.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/layouts/single-symbol.adoc.hbs b/share/mrdocs/addons/generator/adoc/layouts/single-symbol.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/layouts/single-symbol.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/layouts/single-symbol.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/alias.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/alias.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/alias.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/alias.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/concept.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/concept.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/concept.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/concept.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/enum.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/enum.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/enum.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/enum.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/enumerator.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/enumerator.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/enumerator.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/enumerator.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/field.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/field.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/field.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/field.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/friend.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/friend.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/friend.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/friend.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/function.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/function.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/guide.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/guide.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/guide.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/guide.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/namespace.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/namespace.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/namespace.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/namespace.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/record.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/record.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/record.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/record.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/specialization.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/specialization.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/specialization.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/specialization.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/typedef.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/typedef.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/typedef.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/typedef.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/undefined.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/undefined.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/undefined.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/undefined.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/using.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/using.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/using.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/using.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/variable.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/signature/variable.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/signature/variable.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/signature/variable.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/alias.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/alias.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/alias.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/alias.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/concept.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/concept.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/concept.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/concept.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/enum.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/enum.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/enum.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/enum.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/enumerator.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/enumerator.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/field.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/field.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/field.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/field.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/friend.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/friend.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/friend.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/friend.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/function.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/function.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/guide.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/guide.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/guide.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/guide.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/namespace.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/namespace.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/record.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/record.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/specialization.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/specialization.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/specialization.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/specialization.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/typedef.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/typedef.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/typedef.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/typedef.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/undefined.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/undefined.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/undefined.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/undefined.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/using.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/using.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/using.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/using.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/variable.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/symbols/variable.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/symbols/variable.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/symbols/variable.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/declarator-after.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/declarator-after.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/declarator-after.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/declarator-after.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/declarator-before.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/declarator-before.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/declarator-before.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/declarator-before.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/declarator-id.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/declarator-id.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/declarator-id.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/declarator-id.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/declarator.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/declarator.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/declarator.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/declarator.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/info-list.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/info-list.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/info-list.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/info-list.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/info-member.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/info-member.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/info-member.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/info-member.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/name-info.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/name-info.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/name-info.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/name-info.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/nested-name-specifier.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/nested-name-specifier.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/nested-name-specifier.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/nested-name-specifier.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/qualified-path.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/qualified-path.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/qualified-path.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/qualified-path.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/source.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/source.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/source.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/source.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/special-name-suffix.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/special-name-suffix.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/special-name-suffix.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/special-name-suffix.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/template-arg.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/template-arg.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/template-arg.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/template-arg.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/template-args.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/template-args.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/template-args.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/template-args.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/template-head.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/template-head.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/template-head.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/template-head.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/template-param.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/template-param.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/template-param.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/template-param.adoc.hbs
diff --git a/share/mrdocs/addons/generator/asciidoc/partials/types/tranche.adoc.hbs b/share/mrdocs/addons/generator/adoc/partials/types/tranche.adoc.hbs
similarity index 100%
rename from share/mrdocs/addons/generator/asciidoc/partials/types/tranche.adoc.hbs
rename to share/mrdocs/addons/generator/adoc/partials/types/tranche.adoc.hbs
diff --git a/share/mrdocs/addons/generator/html/layouts/single-symbol.html.hbs b/share/mrdocs/addons/generator/html/layouts/single-symbol.html.hbs
index 915f24a300..1b45a76848 100644
--- a/share/mrdocs/addons/generator/html/layouts/single-symbol.html.hbs
+++ b/share/mrdocs/addons/generator/html/layouts/single-symbol.html.hbs
@@ -1,5 +1,2 @@
{{! The section with a symbol in single page output or the symbol page in multi page output }}
-{{#if relfileprefix}}:relfileprefix: {{relfileprefix}}{{/if}}
-[#{{#if (is_multipage)}}{{symbol.id}}{{else}}{{symbol.ref}}{{/if}}]
-
{{> (concat 'symbols' '/' (lookup symbol 'kind')) symbol=symbol}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/alias.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/alias.html.hbs
index 308220cd34..cca2c2c403 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/alias.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/alias.html.hbs
@@ -1,5 +1,5 @@
{{!-- alias --}}
-
+
{{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/concept.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/concept.html.hbs
index c2898ddbe4..07383ce78a 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/concept.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/concept.html.hbs
@@ -1,5 +1,5 @@
{{!-- concept --}}
-
+
{{>types/nested-name-specifier symbol=symbol.parent includeNamespace=true}}{{symbol.name}}
{{symbol.doc.brief}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/enum.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/enum.html.hbs
index 048f355446..742ec243fa 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/enum.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/enum.html.hbs
@@ -1,5 +1,5 @@
{{!-- enum --}}
-
+
{{#if symbol.name}}Enum {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else}}Unnamed enum{{/if}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/enumerator.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/enumerator.html.hbs
index 1c626b81c5..a41686249d 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/enumerator.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/enumerator.html.hbs
@@ -1,5 +1,5 @@
{{!-- enumerator --}}
-
+
Enumerator {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/field.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/field.html.hbs
index 589e8be00a..96dadaf0dc 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/field.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/field.html.hbs
@@ -1,5 +1,5 @@
{{!-- field --}}
-
+
{{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/friend.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/friend.html.hbs
index 1082ffa2ba..18284214ee 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/friend.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/friend.html.hbs
@@ -1,5 +1,5 @@
{{!-- friend --}}
-
+
Friend {{#if symbol.symbol}}{{symbol.symbol.name}}{{else}}{{symbol.type.name}}{{/if}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/function.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/function.html.hbs
index 1942ab1867..cd1843752e 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/function.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/function.html.hbs
@@ -1,5 +1,5 @@
{{!-- function --}}
-
+
Function {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/guide.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/guide.html.hbs
index deb421ff09..c4bb7a5354 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/guide.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/guide.html.hbs
@@ -1,5 +1,5 @@
{{!-- guides --}}
-
+
Deduction guide {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/namespace.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/namespace.html.hbs
index a71d6e77ba..736c9799a9 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/namespace.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/namespace.html.hbs
@@ -1,5 +1,5 @@
{{!-- namespace --}}
-
+
{{#if symbol.name}}Namespace {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else if symbol.parent}}Unnamed namespace{{else}}Global namespace{{/if}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/record.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/record.html.hbs
index 4dd0c49080..edb886d40b 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/record.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/record.html.hbs
@@ -1,5 +1,5 @@
{{!-- record --}}
-
+
{{#if symbol.name}}Class {{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else}}Unnamed class{{/if}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/typedef.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/typedef.html.hbs
index 2f9d45ea95..31f5c3c335 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/typedef.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/typedef.html.hbs
@@ -1,5 +1,5 @@
{{!-- typedef --}}
-
+
{{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/using.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/using.html.hbs
index e06142af9f..395ca55874 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/using.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/using.html.hbs
@@ -1,5 +1,5 @@
{{!-- symbols/using.html.hbs --}}
-
+
Using {{#if (eq symbol.class "namespace")}}Directive: {{symbol.qualifier.name}}{{else}}Declaration: {{symbol.name}}{{/if}}
{{{symbol.doc.brief}}}
diff --git a/share/mrdocs/addons/generator/html/partials/symbols/variable.html.hbs b/share/mrdocs/addons/generator/html/partials/symbols/variable.html.hbs
index 0d98635b84..dced19b8f7 100644
--- a/share/mrdocs/addons/generator/html/partials/symbols/variable.html.hbs
+++ b/share/mrdocs/addons/generator/html/partials/symbols/variable.html.hbs
@@ -1,5 +1,5 @@
{{!-- variable --}}
-
+
{{>types/nested-name-specifier symbol=symbol.parent}}{{symbol.name}}
{{{symbol.doc.brief}}}
diff --git a/src/lib/Dom/LazyObject.hpp b/src/lib/Dom/LazyObject.hpp
index d20a0be60f..4d5cc5d324 100644
--- a/src/lib/Dom/LazyObject.hpp
+++ b/src/lib/Dom/LazyObject.hpp
@@ -266,6 +266,10 @@ namespace detail
}
}
};
+
+ // Deduction guide
+ template
+ LazyObjectIO(MapFn, DeferFn = {}) -> LazyObjectIO;
}
template
@@ -274,7 +278,7 @@ std::size_t
LazyObjectImpl::
size() const
{
- std::size_t result;
+ std::size_t result = 0;
detail::LazyObjectIO io(
[&result, this](std::string_view name, auto const& /* value or deferred */)
{
diff --git a/src/lib/Gen/adoc/AdocCorpus.cpp b/src/lib/Gen/adoc/AdocCorpus.cpp
deleted file mode 100644
index 40c09e7e2c..0000000000
--- a/src/lib/Gen/adoc/AdocCorpus.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "AdocCorpus.hpp"
-#include "lib/Support/Radix.hpp"
-#include
-#include
-#include
-#include
-
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace adoc {
-
-namespace {
-
-std::string
-escapeAdoc(
- std::string_view str)
-{
- std::string result;
- result.reserve(str.size());
- for(char ch : str)
- {
- switch(ch)
- {
- case '&':
- result.append("&");
- break;
- case '<':
- result.append("<");
- break;
- case '>':
- result.append(">");
- break;
- case '[':
- result.append("[");
- break;
- case ']':
- result.append("]");
- break;
- case '|':
- result.append("|");
- break;
- case '=':
- result.append("=");
- break;
- case '/':
- result.append("/");
- break;
- default:
- result.push_back(ch);
- break;
- }
- }
- return result;
-}
-
-class DocVisitor
-{
- const AdocCorpus& corpus_;
- std::string& dest_;
- std::back_insert_iterator ins_;
-
- template
- bool
- write(
- const doc::Node& node,
- Fn&& fn)
- {
- const auto n_before = dest_.size();
- doc::visit(node, std::forward(fn));
- return dest_.size() != n_before;
- }
-
-public:
- DocVisitor(
- AdocCorpus const& corpus,
- std::string& dest) noexcept
- : corpus_(corpus)
- , dest_(dest)
- , ins_(std::back_inserter(dest_))
- {
- }
-
- void operator()(doc::Admonition const& I);
- void operator()(doc::Code const& I);
- void operator()(doc::Heading const& I);
- void operator()(doc::Paragraph const& I);
- void operator()(doc::Link const& I);
- void operator()(doc::ListItem const& I);
- void operator()(doc::Param const& I);
- void operator()(doc::Returns const& I);
- void operator()(doc::Text const& I);
- void operator()(doc::Styled const& I);
- void operator()(doc::TParam const& I);
- void operator()(doc::Reference const& I);
- void operator()(doc::Throws const& I);
-
- std::size_t measureLeftMargin(
- doc::List const& list);
-};
-
-void
-DocVisitor::
-operator()(
- doc::Admonition const& I)
-{
- std::string_view label;
- switch(I.admonish)
- {
- case doc::Admonish::note:
- label = "NOTE";
- break;
- case doc::Admonish::tip:
- label = "TIP";
- break;
- case doc::Admonish::important:
- label = "IMPORTANT";
- break;
- case doc::Admonish::caution:
- label = "CAUTION";
- break;
- case doc::Admonish::warning:
- label = "WARNING";
- break;
- default:
- MRDOCS_UNREACHABLE();
- }
- fmt::format_to(std::back_inserter(dest_), "[{}]\n", label);
- (*this)(static_cast(I));
-}
-
-void
-DocVisitor::
-operator()(
- doc::Code const& I)
-{
- auto const leftMargin = measureLeftMargin(I.children);
- dest_ +=
- "[,cpp]\n"
- "----\n";
- for(auto const& it : RangeFor(I.children))
- {
- doc::visit(*it.value,
- [&](T const& text)
- {
- if constexpr(std::is_same_v)
- {
- if(! text.string.empty())
- {
- std::string_view s = text.string;
- s.remove_prefix(leftMargin);
- dest_.append(s);
- }
- dest_.push_back('\n');
- }
- else
- {
- MRDOCS_UNREACHABLE();
- }
- });
- }
- dest_ += "----\n";
-}
-
-void
-DocVisitor::
-operator()(
- doc::Heading const& I)
-{
- fmt::format_to(ins_, "\n=== {}\n", escapeAdoc(I.string));
-}
-
-// Also handles doc::Brief
-void
-DocVisitor::
-operator()(
- doc::Paragraph const& I)
-{
- std::span children = I.children;
- if(children.empty())
- return;
- dest_.append("\n");
- bool non_empty = write(*children.front(), *this);
- for(auto const& child : children.subspan(1))
- {
- if(non_empty)
- dest_.push_back('\n');
- non_empty = write(*child, *this);
- }
- dest_.push_back('\n');
-}
-
-void
-DocVisitor::
-operator()(
- doc::Link const& I)
-{
- dest_.append("link:");
- dest_.append(I.href);
- dest_.push_back('[');
- dest_.append(escapeAdoc(I.string));
- dest_.push_back(']');
-}
-
-void
-DocVisitor::
-operator()(
- doc::ListItem const& I)
-{
- std::span children = I.children;
- if(children.empty())
- return;
- dest_.append("\n* ");
- bool non_empty = write(*children.front(), *this);
- for(auto const& child : children.subspan(1))
- {
- if(non_empty)
- dest_.push_back('\n');
- non_empty = write(*child, *this);
- }
- dest_.push_back('\n');
-}
-
-void
-DocVisitor::
-operator()(doc::Param const& I)
-{
-}
-
-void
-DocVisitor::
-operator()(doc::TParam const& I)
-{
-}
-
-void
-DocVisitor::
-operator()(doc::Throws const& I)
-{
-}
-
-void
-DocVisitor::
-operator()(doc::Returns const& I)
-{
- (*this)(static_cast(I));
-}
-
-void
-DocVisitor::
-operator()(doc::Text const& I)
-{
- // Asciidoc text must not have leading
- // else they can be rendered up as code.
- std::string_view s = trim(I.string);
- // Render empty lines as paragraph delimiters.
- if(s.empty())
- s = "\n";
- dest_.append(escapeAdoc(s));
-}
-
-void
-DocVisitor::
-operator()(doc::Styled const& I)
-{
- // VFALCO We need to apply Asciidoc escaping
- // depending on the contents of the string.
- std::string_view s = trim(I.string);
- switch(I.style)
- {
- case doc::Style::none:
- dest_.append(s);
- break;
- case doc::Style::bold:
- fmt::format_to(std::back_inserter(dest_), "*{}*", s);
- break;
- case doc::Style::mono:
- fmt::format_to(std::back_inserter(dest_), "`{}`", s);
- break;
- case doc::Style::italic:
- fmt::format_to(std::back_inserter(dest_), "_{}_", s);
- break;
- default:
- MRDOCS_UNREACHABLE();
- }
-}
-
-void
-DocVisitor::
-operator()(doc::Reference const& I)
-{
- if(I.id == SymbolID::invalid)
- return (*this)(static_cast(I));
- fmt::format_to(std::back_inserter(dest_), "xref:{}[{}]",
- corpus_.getXref(corpus_->get(I.id)), escapeAdoc(I.string));
-}
-
-std::size_t
-DocVisitor::
-measureLeftMargin(
- doc::List const& list)
-{
- if(list.empty())
- return 0;
- auto n = std::size_t(-1);
- for(auto& text : list)
- {
- if(trim(text->string).empty())
- continue;
- auto const space =
- text->string.size() - ltrim(text->string).size();
- if( n > space)
- n = space;
- }
- return n;
-}
-
-dom::Value
-domCreate(
- const doc::Param& I,
- const AdocCorpus& corpus)
-{
- dom::Object::storage_type entries = {
- { "name", I.name }
- };
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- if(! s.empty())
- entries.emplace_back(
- "description", std::move(s));
- return dom::Object(std::move(entries));
-}
-
-dom::Value
-domCreate(
- const doc::TParam& I,
- const AdocCorpus& corpus)
-{
- dom::Object::storage_type entries = {
- { "name", I.name }
- };
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- if(! s.empty())
- entries.emplace_back(
- "description", std::move(s));
- return dom::Object(std::move(entries));
-}
-
-dom::Value
-domCreate(
- const doc::Throws& I,
- const AdocCorpus& corpus)
-{
- dom::Object::storage_type entries = {
- { "exception", I.exception }
- };
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- if(! s.empty())
- entries.emplace_back(
- "description", std::move(s));
- return dom::Object(std::move(entries));
-}
-
-dom::Value
-domCreate(
- const doc::See& I,
- const AdocCorpus& corpus)
-{
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- return s;
-}
-
-dom::Value
-domCreate(
- const doc::Precondition& I,
- const AdocCorpus& corpus)
-{
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- return s;
-}
-
-dom::Value
-domCreate(
- const doc::Postcondition& I,
- const AdocCorpus& corpus)
-{
- std::string s;
- DocVisitor visitor(corpus, s);
- visitor(static_cast(I));
- return s;
-}
-
-} // (anon)
-
-dom::Object
-AdocCorpus::
-construct(Info const& I) const
-{
- dom::Object obj = this->DomCorpus::construct(I);
- obj.set("ref", getXref(I));
- return obj;
-}
-
-std::string
-AdocCorpus::
-getXref(Info const& I) const
-{
- bool multipage = getCorpus().config->multipage;
- // use '/' as the seperator for multipage, and '-' for single-page
- std::string xref = names_.getQualified(
- I.id, multipage ? '/' : '-');
- // add the file extension if in multipage mode
- if(multipage)
- xref.append(".adoc");
- return xref;
-}
-
-std::string
-AdocCorpus::
-getXref(OverloadSet const& os) const
-{
- bool multipage = getCorpus().config->multipage;
- // use '/' as the seperator for multipage, and '-' for single-page
- std::string xref = names_.getQualified(
- os, multipage ? '/' : '-');
- // add the file extension if in multipage mode
- if(multipage)
- xref.append(".adoc");
- return xref;
-}
-
-dom::Value
-AdocCorpus::
-getJavadoc(
- Javadoc const& jd) const
-{
- dom::Object::storage_type list;
- list.reserve(2);
-
- auto maybeEmplace = [&](
- std::string_view key,
- auto const& I)
- {
- std::string s;
- DocVisitor visitor(*this, s);
- using T = std::decay_t;
- if constexpr (std::derived_from)
- {
- doc::visit(I, visitor);
- }
- else if constexpr (std::ranges::range)
- {
- for(auto const& t : I)
- doc::visit(*t, visitor);
- }
- if(! s.empty())
- {
- list.emplace_back(key, std::move(s));
- }
- };
-
- auto maybeEmplaceArray = [&](
- std::string_view key,
- /* std::vector */ auto const& nodes)
- {
- dom::Array::storage_type elements;
- elements.reserve(nodes.size());
- for(auto const& elem : nodes)
- {
- if(!elem)
- continue;
- elements.emplace_back(
- domCreate(*elem, *this));
- }
- if(elements.empty())
- return;
- list.emplace_back(key, dom::newArray<
- dom::DefaultArrayImpl>(std::move(elements)));
- };
-
- auto ov = jd.makeOverview(this->getCorpus());
- // brief
- if(ov.brief)
- maybeEmplace("brief", *ov.brief);
- maybeEmplace("description", ov.blocks);
- if(ov.returns)
- maybeEmplace("returns", *ov.returns);
- maybeEmplaceArray("params", ov.params);
- maybeEmplaceArray("tparams", ov.tparams);
- maybeEmplaceArray("exceptions", ov.exceptions);
- maybeEmplaceArray("see", ov.sees);
- maybeEmplaceArray("preconditions", ov.preconditions);
- maybeEmplaceArray("postconditions", ov.postconditions);
- return dom::Object(std::move(list));
-}
-
-dom::Object
-AdocCorpus::
-getOverloads(
- OverloadSet const& os) const
-{
- auto obj = DomCorpus::getOverloads(os);
- // KRYSTIAN FIXME: need a better way to generate IDs
- // std::string xref =
- obj.set("ref", getXref(os));
- // std::replace(xref.begin(), xref.end(), '/', '-');
- obj.set("id", fmt::format("{}-{}",
- toBase16(os.Parent), os.Name));
- return obj;
- // return dom::newObject(os, *this);
-}
-
-} // adoc
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/adoc/AdocGenerator.cpp b/src/lib/Gen/adoc/AdocGenerator.cpp
index 5c02bf54d7..e39afdfc7d 100644
--- a/src/lib/Gen/adoc/AdocGenerator.cpp
+++ b/src/lib/Gen/adoc/AdocGenerator.cpp
@@ -9,125 +9,28 @@
// Official repository: https://github.com/cppalliance/mrdocs
//
-#include "AdocCorpus.hpp"
#include "AdocGenerator.hpp"
-#include "Builder.hpp"
-#include "MultiPageVisitor.hpp"
-#include "SinglePageVisitor.hpp"
-#include "lib/Support/LegibleNames.hpp"
-#include
-#include
-#include
-#include
+#include "DocVisitor.hpp"
namespace clang {
namespace mrdocs {
namespace adoc {
-Expected>
-createExecutors(
- AdocCorpus const& adocCorpus)
-{
- auto const& config = adocCorpus->config;
- auto& threadPool = config.threadPool();
- ExecutorGroup group(threadPool);
- for(auto i = threadPool.getThreadCount(); i--;)
- {
- try
- {
- group.emplace(adocCorpus);
- }
- catch(Exception const& ex)
- {
- return Unexpected(ex.error());
- }
- }
- return group;
-}
-
-//------------------------------------------------
-//
-// AdocGenerator
-//
-//------------------------------------------------
-
-Error
AdocGenerator::
-build(
- std::string_view outputPath,
- Corpus const& corpus) const
-{
- if(! corpus.config->multipage)
- return Generator::build(outputPath, corpus);
-
- auto options = loadOptions(corpus);
- if(! options)
- return options.error();
-
- AdocCorpus domCorpus(corpus, *std::move(options));
- auto ex = createExecutors(domCorpus);
- if(! ex)
- return ex.error();
-
- MultiPageVisitor visitor(*ex, outputPath, corpus);
- visitor(corpus.globalNamespace());
-
- auto errors = ex->wait();
- if(! errors.empty())
- return Error(errors);
- return Error::success();
-}
-
-Error
-AdocGenerator::
-buildOne(
- std::ostream& os,
- Corpus const& corpus) const
-{
- auto options = loadOptions(corpus);
- if(! options)
- return options.error();
-
- AdocCorpus domCorpus(corpus, *std::move(options));
- auto ex = createExecutors(domCorpus);
- if(! ex)
- return ex.error();
-
- std::vector errors;
-
- ex->async(
- [&os](Builder& builder)
- {
- auto pageText = builder.renderSinglePageHeader().value();
- os.write(pageText.data(), pageText.size());
- });
- errors = ex->wait();
- if(! errors.empty())
- return {errors};
-
- SinglePageVisitor visitor(*ex, corpus, os);
- visitor(corpus.globalNamespace());
- errors = ex->wait();
- if(! errors.empty())
- return {errors};
-
- ex->async(
- [&os](Builder& builder)
- {
- auto pageText = builder.renderSinglePageFooter().value();
- os.write(pageText.data(), pageText.size());
- });
- errors = ex->wait();
- if(! errors.empty())
- return {errors};
-
- return Error::success();
-}
+AdocGenerator()
+ : hbs::HandlebarsGenerator("Asciidoc", "adoc", [](
+ hbs::HandlebarsCorpus const& c,
+ doc::Node const& I) -> std::string
+ {
+ std::string s;
+ DocVisitor visitor(c, s);
+ doc::visit(I, visitor);
+ return s;
+ })
+{}
} // adoc
-//------------------------------------------------
-
std::unique_ptr
makeAdocGenerator()
{
diff --git a/src/lib/Gen/adoc/AdocGenerator.hpp b/src/lib/Gen/adoc/AdocGenerator.hpp
index 452e42b807..ea212feb2f 100644
--- a/src/lib/Gen/adoc/AdocGenerator.hpp
+++ b/src/lib/Gen/adoc/AdocGenerator.hpp
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
@@ -14,42 +15,17 @@
#include
#include
+#include
namespace clang {
namespace mrdocs {
namespace adoc {
class AdocGenerator
- : public Generator
+ : public hbs::HandlebarsGenerator
{
public:
- std::string_view
- id() const noexcept override
- {
- return "adoc";
- }
-
- std::string_view
- displayName() const noexcept override
- {
- return "Asciidoc";
- }
-
- std::string_view
- fileExtension() const noexcept override
- {
- return "adoc";
- }
-
- Error
- build(
- std::string_view outputPath,
- Corpus const& corpus) const override;
-
- Error
- buildOne(
- std::ostream& os,
- Corpus const& corpus) const override;
+ AdocGenerator();
};
} // adoc
diff --git a/src/lib/Gen/adoc/DocVisitor.cpp b/src/lib/Gen/adoc/DocVisitor.cpp
new file mode 100644
index 0000000000..edba062748
--- /dev/null
+++ b/src/lib/Gen/adoc/DocVisitor.cpp
@@ -0,0 +1,288 @@
+//
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#include "DocVisitor.hpp"
+#include "lib/Support/Radix.hpp"
+#include
+#include
+#include
+#include
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace adoc {
+
+std::string
+escapeAdoc(
+ std::string_view str)
+{
+ std::string result;
+ result.reserve(str.size());
+ for(char ch : str)
+ {
+ switch(ch)
+ {
+ case '&':
+ result.append("&");
+ break;
+ case '<':
+ result.append("<");
+ break;
+ case '>':
+ result.append(">");
+ break;
+ case '[':
+ result.append("[");
+ break;
+ case ']':
+ result.append("]");
+ break;
+ case '|':
+ result.append("|");
+ break;
+ case '=':
+ result.append("=");
+ break;
+ case '/':
+ result.append("/");
+ break;
+ default:
+ result.push_back(ch);
+ break;
+ }
+ }
+ return result;
+}
+
+void
+DocVisitor::
+operator()(
+ doc::Admonition const& I)
+{
+ std::string_view label;
+ switch(I.admonish)
+ {
+ case doc::Admonish::note:
+ label = "NOTE";
+ break;
+ case doc::Admonish::tip:
+ label = "TIP";
+ break;
+ case doc::Admonish::important:
+ label = "IMPORTANT";
+ break;
+ case doc::Admonish::caution:
+ label = "CAUTION";
+ break;
+ case doc::Admonish::warning:
+ label = "WARNING";
+ break;
+ default:
+ MRDOCS_UNREACHABLE();
+ }
+ fmt::format_to(std::back_inserter(dest_), "[{}]\n", label);
+ (*this)(static_cast(I));
+}
+
+void
+DocVisitor::
+operator()(
+ doc::Code const& I)
+{
+ auto const leftMargin = measureLeftMargin(I.children);
+ dest_ +=
+ "[,cpp]\n"
+ "----\n";
+ for(auto const& it : RangeFor(I.children))
+ {
+ doc::visit(*it.value,
+ [&](T const& text)
+ {
+ if constexpr(std::is_same_v)
+ {
+ if(! text.string.empty())
+ {
+ std::string_view s = text.string;
+ s.remove_prefix(leftMargin);
+ dest_.append(s);
+ }
+ dest_.push_back('\n');
+ }
+ else
+ {
+ MRDOCS_UNREACHABLE();
+ }
+ });
+ }
+ dest_ += "----\n";
+}
+
+void
+DocVisitor::
+operator()(
+ doc::Heading const& I)
+{
+ fmt::format_to(ins_, "\n=== {}\n", escapeAdoc(I.string));
+}
+
+// Also handles doc::Brief
+void
+DocVisitor::
+operator()(
+ doc::Paragraph const& I)
+{
+ std::span children = I.children;
+ if(children.empty())
+ return;
+ dest_.append("\n");
+ bool non_empty = write(*children.front(), *this);
+ for(auto const& child : children.subspan(1))
+ {
+ if(non_empty)
+ dest_.push_back('\n');
+ non_empty = write(*child, *this);
+ }
+ dest_.push_back('\n');
+}
+
+void
+DocVisitor::
+operator()(
+ doc::Link const& I)
+{
+ dest_.append("link:");
+ dest_.append(I.href);
+ dest_.push_back('[');
+ dest_.append(escapeAdoc(I.string));
+ dest_.push_back(']');
+}
+
+void
+DocVisitor::
+operator()(
+ doc::ListItem const& I)
+{
+ std::span children = I.children;
+ if(children.empty())
+ return;
+ dest_.append("\n* ");
+ bool non_empty = write(*children.front(), *this);
+ for(auto const& child : children.subspan(1))
+ {
+ if(non_empty)
+ dest_.push_back('\n');
+ non_empty = write(*child, *this);
+ }
+ dest_.push_back('\n');
+}
+
+void
+DocVisitor::
+operator()(doc::Param const& I)
+{
+ this->operator()(static_cast(I));
+}
+
+void
+DocVisitor::
+operator()(doc::TParam const& I)
+{
+ this->operator()(static_cast(I));
+}
+
+void
+DocVisitor::
+operator()(doc::Throws const& I)
+{
+ this->operator()(static_cast(I));
+}
+
+void
+DocVisitor::
+operator()(doc::Returns const& I)
+{
+ (*this)(static_cast(I));
+}
+
+void
+DocVisitor::
+operator()(doc::Text const& I)
+{
+ // Asciidoc text must not have leading
+ // else they can be rendered up as code.
+ std::string_view s = trim(I.string);
+ // Render empty lines as paragraph delimiters.
+ if(s.empty())
+ s = "\n";
+ dest_.append(escapeAdoc(s));
+}
+
+void
+DocVisitor::
+operator()(doc::Styled const& I)
+{
+ // VFALCO We need to apply Asciidoc escaping
+ // depending on the contents of the string.
+ std::string_view s = trim(I.string);
+ switch(I.style)
+ {
+ case doc::Style::none:
+ dest_.append(s);
+ break;
+ case doc::Style::bold:
+ fmt::format_to(std::back_inserter(dest_), "*{}*", s);
+ break;
+ case doc::Style::mono:
+ fmt::format_to(std::back_inserter(dest_), "`{}`", s);
+ break;
+ case doc::Style::italic:
+ fmt::format_to(std::back_inserter(dest_), "_{}_", s);
+ break;
+ default:
+ MRDOCS_UNREACHABLE();
+ }
+}
+
+void
+DocVisitor::
+operator()(doc::Reference const& I)
+{
+ if(I.id == SymbolID::invalid)
+ return (*this)(static_cast(I));
+ fmt::format_to(std::back_inserter(dest_), "xref:{}[{}]",
+ corpus_.getXref(corpus_->get(I.id)), escapeAdoc(I.string));
+}
+
+std::size_t
+DocVisitor::
+measureLeftMargin(
+ doc::List const& list)
+{
+ if(list.empty())
+ return 0;
+ auto n = std::size_t(-1);
+ for(auto& text : list)
+ {
+ if(trim(text->string).empty())
+ continue;
+ auto const space =
+ text->string.size() - ltrim(text->string).size();
+ if( n > space)
+ n = space;
+ }
+ return n;
+}
+
+} // adoc
+} // mrdocs
+} // clang
diff --git a/src/lib/Gen/adoc/DocVisitor.hpp b/src/lib/Gen/adoc/DocVisitor.hpp
new file mode 100644
index 0000000000..ba59908b0b
--- /dev/null
+++ b/src/lib/Gen/adoc/DocVisitor.hpp
@@ -0,0 +1,72 @@
+//
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#ifndef MRDOCS_LIB_GEN_ADOC_DOCVISITOR_HPP
+#define MRDOCS_LIB_GEN_ADOC_DOCVISITOR_HPP
+
+#include
+#include "lib/Gen/hbs/HandlebarsCorpus.hpp"
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace adoc {
+
+class DocVisitor
+{
+ hbs::HandlebarsCorpus const& corpus_;
+ std::string& dest_;
+ std::back_insert_iterator ins_;
+
+ template
+ bool
+ write(
+ const doc::Node& node,
+ Fn&& fn)
+ {
+ const auto n_before = dest_.size();
+ doc::visit(node, std::forward(fn));
+ return dest_.size() != n_before;
+ }
+
+public:
+ DocVisitor(
+ hbs::HandlebarsCorpus const& corpus,
+ std::string& dest) noexcept
+ : corpus_(corpus)
+ , dest_(dest)
+ , ins_(std::back_inserter(dest_))
+ {
+ }
+
+ void operator()(doc::Admonition const& I);
+ void operator()(doc::Code const& I);
+ void operator()(doc::Heading const& I);
+ void operator()(doc::Paragraph const& I);
+ void operator()(doc::Link const& I);
+ void operator()(doc::ListItem const& I);
+ void operator()(doc::Param const& I);
+ void operator()(doc::Returns const& I);
+ void operator()(doc::Text const& I);
+ void operator()(doc::Styled const& I);
+ void operator()(doc::TParam const& I);
+ void operator()(doc::Reference const& I);
+ void operator()(doc::Throws const& I);
+
+ std::size_t measureLeftMargin(
+ doc::List const& list);
+};
+
+} // hbs
+} // mrdocs
+} // clang
+
+#endif
diff --git a/src/lib/Gen/adoc/Options.cpp b/src/lib/Gen/adoc/Options.cpp
deleted file mode 100644
index 6f19d4a83f..0000000000
--- a/src/lib/Gen/adoc/Options.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-//
-// This is a derivative work. originally part of the LLVM Project.
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "Options.hpp"
-#include "lib/Support/Yaml.hpp"
-#include "lib/Lib/ConfigImpl.hpp" // VFALCO This is a problem
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace adoc {
-
-struct YamlKey
-{
- Options& opt;
-
- explicit
- YamlKey(
- Options& opt_) noexcept
- : opt(opt_)
- {
- }
-};
-
-struct YamlGenKey
-{
- Options& opt;
-
- explicit
- YamlGenKey(
- Options& opt_)
- : opt(opt_)
- {
- }
-};
-
-} // adoc
-} // mrdocs
-} // clang
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::adoc::YamlKey>
-{
- static void mapping(IO& io,
- clang::mrdocs::adoc::YamlKey& yk)
- {
- auto& opt= yk.opt;
- io.mapOptional("legible-names", opt.legible_names);
- io.mapOptional("template-dir", opt.template_dir);
- }
-};
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::adoc::YamlGenKey>
-{
- static void mapping(IO& io,
- clang::mrdocs::adoc::YamlGenKey& ygk)
- {
- clang::mrdocs::adoc::YamlKey yk(ygk.opt);
- io.mapOptional("adoc", yk);
- }
-};
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::adoc::Options>
-{
- static void mapping(IO& io,
- clang::mrdocs::adoc::Options& opt)
- {
- clang::mrdocs::adoc::YamlGenKey ygk(opt);
- io.mapOptional("generator", ygk);
- }
-};
-
-//------------------------------------------------
-
-namespace clang {
-namespace mrdocs {
-namespace adoc {
-
-Expected
-loadOptions(
- Corpus const& corpus)
-{
- Options opt;
-
- YamlReporter reporter;
-
- // config
- {
- llvm::yaml::Input yin(
- corpus.config->configYaml,
- &reporter, reporter);
- yin.setAllowUnknownKeys(true);
- yin >> opt;
- if(auto ec = yin.error())
- return Unexpected(Error(ec));
- }
-
- // adjust relative paths
- if(! opt.template_dir.empty())
- {
- opt.template_dir = files::makeAbsolute(
- opt.template_dir,
- corpus.config->configDir);
- }
- else
- {
- opt.template_dir = files::appendPath(
- corpus.config->addons,
- "generator",
- "asciidoc"
- );
- }
-
- if(! opt.template_dir.empty())
- {
- opt.template_dir = files::makeAbsolute(
- opt.template_dir,
- corpus.config->configDir);
- }
- else
- {
- opt.template_dir = files::appendPath(
- corpus.config->addons,
- "generator",
- "asciidoc"
- );
- }
-
- return opt;
-}
-
-} // adoc
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/adoc/Options.hpp b/src/lib/Gen/adoc/Options.hpp
deleted file mode 100644
index 8db45b71e0..0000000000
--- a/src/lib/Gen/adoc/Options.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_ADOC_OPTIONS_HPP
-#define MRDOCS_LIB_GEN_ADOC_OPTIONS_HPP
-
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-
-class Corpus;
-
-namespace adoc {
-
-/** Generator-specific options.
-*/
-struct Options
-{
- bool legible_names = true;
- std::string template_dir;
-};
-
-/** Return loaded Options from a configuration.
-*/
-Expected
-loadOptions(
- Corpus const& corpus);
-
-} // adoc
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Gen/adoc/SinglePageVisitor.cpp b/src/lib/Gen/adoc/SinglePageVisitor.cpp
deleted file mode 100644
index bc21794f36..0000000000
--- a/src/lib/Gen/adoc/SinglePageVisitor.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "SinglePageVisitor.hpp"
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace adoc {
-
-template
-void
-SinglePageVisitor::
-operator()(T const& I)
-{
- ex_.async([this, &I, page = numPages_++](Builder& builder)
- {
- if(auto r = builder(I))
- writePage(*r, page);
- else
- r.error().Throw();
- });
- if constexpr(
- T::isNamespace() ||
- T::isRecord() ||
- T::isEnum())
- {
- // corpus_.traverse(I, *this);
- corpus_.traverseOverloads(I, *this);
- }
-}
-
-void
-SinglePageVisitor::
-operator()(OverloadSet const& OS)
-{
- ex_.async([this, OS, page = numPages_++](Builder& builder)
- {
- if(auto r = builder(OS))
- writePage(*r, page);
- else
- r.error().Throw();
- corpus_.traverse(OS, *this);
- });
-}
-
-// pageNumber is zero-based
-void
-SinglePageVisitor::
-writePage(
- std::string pageText,
- std::size_t pageNumber)
-{
- std::unique_lock lock(mutex_);
-
- if(pageNumber > topPage_)
- {
- // defer this page
- if( pages_.size() <= pageNumber)
- pages_.resize(pageNumber + 1);
- pages_[pageNumber] = std::move(pageText);
- return;
- }
-
- // write contiguous pages
- for(;;)
- {
- {
- unlock_guard unlock(mutex_);
- os_.write(pageText.data(), pageText.size());
- ++pageNumber;
- }
- topPage_ = pageNumber;
- if(pageNumber >= pages_.size())
- return;
- if(! pages_[pageNumber])
- return;
- pageText = std::move(*pages_[pageNumber]);
- // VFALCO this is in theory not needed but
- // I am paranoid about the std::move of the
- // string not resulting in a deallocation.
- pages_[pageNumber].reset();
- }
-}
-
-#define DEFINE(T) template void \
- SinglePageVisitor::operator()(T const&)
-
-#define INFO(Type) DEFINE(Type##Info);
-#include
-
-} // adoc
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/adoc/Builder.cpp b/src/lib/Gen/hbs/Builder.cpp
similarity index 90%
rename from src/lib/Gen/adoc/Builder.cpp
rename to src/lib/Gen/hbs/Builder.cpp
index 18a2f9f5bb..7e40f627e9 100644
--- a/src/lib/Gen/adoc/Builder.cpp
+++ b/src/lib/Gen/hbs/Builder.cpp
@@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
@@ -25,11 +26,11 @@ namespace lua {
extern void lua_dump(dom::Object const& obj);
}
-namespace adoc {
+namespace hbs {
Builder::
Builder(
- AdocCorpus const& corpus)
+ HandlebarsCorpus const& corpus)
: domCorpus(corpus)
{
namespace fs = std::filesystem;
@@ -38,7 +39,7 @@ Builder(
// load partials
std::string partialsPath = files::appendPath(
- config->addons, "generator", "asciidoc", "partials");
+ config->addons, "generator", domCorpus.fileExtension, "partials");
forEachFile(partialsPath, true,
[&](std::string_view pathName) -> Error
{
@@ -60,7 +61,7 @@ Builder(
// Load JavaScript helpers
std::string helpersPath = files::appendPath(
- config->addons, "generator", "asciidoc", "helpers");
+ config->addons, "generator", domCorpus.fileExtension, "helpers");
forEachFile(helpersPath, true,
[&](std::string_view pathName)-> Expected
{
@@ -134,7 +135,7 @@ callTemplate(
Config const& config = domCorpus->config;
auto layoutDir = files::appendPath(config->addons,
- "generator", "asciidoc", "layouts");
+ "generator", domCorpus.fileExtension, "layouts");
auto pathName = files::appendPath(layoutDir, name);
MRDOCS_TRY(auto fileText, files::getFileText(pathName));
HandlebarsOptions options;
@@ -152,14 +153,14 @@ Expected
Builder::
renderSinglePageHeader()
{
- return callTemplate("single-header.adoc.hbs", {});
+ return callTemplate(fmt::format("single-header.{}.hbs", domCorpus.fileExtension), {});
}
Expected
Builder::
renderSinglePageFooter()
{
- return callTemplate("single-footer.adoc.hbs", {});
+ return callTemplate(fmt::format("single-footer.{}.hbs", domCorpus.fileExtension), {});
}
//------------------------------------------------
@@ -218,7 +219,7 @@ Builder::
operator()(T const& I)
{
return callTemplate(
- "single-symbol.adoc.hbs",
+ fmt::format("single-symbol.{}.hbs", domCorpus.fileExtension),
createContext(I));
}
@@ -227,7 +228,7 @@ Builder::
operator()(OverloadSet const& OS)
{
return callTemplate(
- "overload-set.adoc.hbs",
+ fmt::format("overload-set.{}.hbs", domCorpus.fileExtension),
createContext(OS));
}
@@ -237,6 +238,6 @@ operator()(OverloadSet const& OS)
#define INFO(Type) DEFINE(Type##Info);
#include
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/adoc/Builder.hpp b/src/lib/Gen/hbs/Builder.hpp
similarity index 82%
rename from src/lib/Gen/adoc/Builder.hpp
rename to src/lib/Gen/hbs/Builder.hpp
index 208cbbef96..2f0f9ea811 100644
--- a/src/lib/Gen/adoc/Builder.hpp
+++ b/src/lib/Gen/hbs/Builder.hpp
@@ -4,15 +4,16 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
-#ifndef MRDOCS_LIB_GEN_ADOC_BUILDER_HPP
-#define MRDOCS_LIB_GEN_ADOC_BUILDER_HPP
+#ifndef MRDOCS_LIB_GEN_HBS_BUILDER_HPP
+#define MRDOCS_LIB_GEN_HBS_BUILDER_HPP
#include "Options.hpp"
-#include "AdocCorpus.hpp"
+#include "HandlebarsCorpus.hpp"
#include "lib/Support/Radix.hpp"
#include
#include
@@ -22,7 +23,7 @@
namespace clang {
namespace mrdocs {
-namespace adoc {
+namespace hbs {
/** Builds reference output.
@@ -37,11 +38,11 @@ class Builder
std::string getRelPrefix(std::size_t depth);
public:
- AdocCorpus const& domCorpus;
+ HandlebarsCorpus const& domCorpus;
explicit
Builder(
- AdocCorpus const& corpus);
+ HandlebarsCorpus const& corpus);
dom::Value createContext(Info const& I);
dom::Value createContext(OverloadSet const& OS);
@@ -62,7 +63,7 @@ class Builder
operator()(OverloadSet const&);
};
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/hbs/HandlebarsCorpus.cpp b/src/lib/Gen/hbs/HandlebarsCorpus.cpp
new file mode 100644
index 0000000000..1bebc80566
--- /dev/null
+++ b/src/lib/Gen/hbs/HandlebarsCorpus.cpp
@@ -0,0 +1,240 @@
+//
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#include "HandlebarsCorpus.hpp"
+#include "lib/Support/Radix.hpp"
+#include
+#include
+#include
+#include
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace hbs {
+
+namespace {
+
+dom::Value
+domCreate(
+ const doc::Param& I,
+ const HandlebarsCorpus& corpus)
+{
+ dom::Object::storage_type entries = {
+ { "name", I.name }
+ };
+ std::string s = corpus.toStringFn(corpus, I);
+ if (!s.empty())
+ {
+ entries.emplace_back(
+ "description", std::move(s));
+ }
+ return dom::Object(std::move(entries));
+}
+
+dom::Value
+domCreate(
+ const doc::TParam& I,
+ const HandlebarsCorpus& corpus)
+{
+ dom::Object::storage_type entries = {
+ { "name", I.name }
+ };
+ std::string s = corpus.toStringFn(corpus, I);
+ if (!s.empty())
+ {
+ entries.emplace_back(
+ "description", std::move(s));
+ }
+ return dom::Object(std::move(entries));
+}
+
+dom::Value
+domCreate(
+ const doc::Throws& I,
+ const HandlebarsCorpus& corpus)
+{
+ dom::Object::storage_type entries = {
+ { "exception", I.exception }
+ };
+ std::string s = corpus.toStringFn(corpus, I);
+ if (!s.empty())
+ {
+ entries.emplace_back(
+ "description", std::move(s));
+ }
+ return dom::Object(std::move(entries));
+}
+
+dom::Value
+domCreate(
+ const doc::See& I,
+ const HandlebarsCorpus& corpus)
+{
+ return corpus.toStringFn(corpus, I);
+}
+
+dom::Value
+domCreate(
+ const doc::Precondition& I,
+ const HandlebarsCorpus& corpus)
+{
+ return corpus.toStringFn(corpus, I);
+}
+
+dom::Value
+domCreate(
+ const doc::Postcondition& I,
+ const HandlebarsCorpus& corpus)
+{
+ return corpus.toStringFn(corpus, I);
+}
+
+} // (anon)
+
+dom::Object
+HandlebarsCorpus::
+construct(Info const& I) const
+{
+ dom::Object obj = this->DomCorpus::construct(I);
+ obj.set("ref", getXref(I));
+ return obj;
+}
+
+std::string
+HandlebarsCorpus::
+getXref(Info const& I) const
+{
+ bool multipage = getCorpus().config->multipage;
+ // use '/' as the seperator for multipage, and '-' for single-page
+ std::string xref = names_.getQualified(
+ I.id, multipage ? '/' : '-');
+ // add the file extension if in multipage mode
+ if(multipage)
+ {
+ xref.append(".");
+ xref.append(fileExtension);
+ }
+ return xref;
+}
+
+std::string
+HandlebarsCorpus::
+getXref(OverloadSet const& os) const
+{
+ bool multipage = getCorpus().config->multipage;
+ // use '/' as the seperator for multipage, and '-' for single-page
+ std::string xref = names_.getQualified(
+ os, multipage ? '/' : '-');
+ // add the file extension if in multipage mode
+ if(multipage)
+ {
+ xref.append(".");
+ xref.append(fileExtension);
+ }
+ return xref;
+}
+
+dom::Value
+HandlebarsCorpus::
+getJavadoc(
+ Javadoc const& jd) const
+{
+ dom::Object::storage_type objKeyValues;
+ objKeyValues.reserve(2);
+
+ /* Emplace the string value representing the
+ Javadoc node.
+
+ When the string is empty, the object key
+ is undefined.
+ */
+ auto emplaceString = [&](
+ std::string_view key,
+ auto const& I)
+ {
+ std::string s;
+ using T = std::decay_t;
+ if constexpr (std::derived_from)
+ {
+ // doc::visit(*t, visitor);
+ s += toStringFn(*this, I);
+ }
+ else if constexpr (std::ranges::range)
+ {
+ // Range value type
+ for(doc::Node const* t : I)
+ s += toStringFn(*this, *t);
+ }
+ if(! s.empty())
+ {
+ objKeyValues.emplace_back(key, std::move(s));
+ }
+ };
+
+ /* Emplace an array of objects where each element
+ represents the properties of the node type,
+ such as "name" and "description".
+ */
+ auto emplaceObjectArray = [&](
+ std::string_view key,
+ /* std::vector */ auto const& nodes)
+ {
+ dom::Array::storage_type elements;
+ elements.reserve(nodes.size());
+ for(auto const& elem : nodes)
+ {
+ if(!elem)
+ continue;
+ elements.emplace_back(
+ domCreate(*elem, *this));
+ }
+ if(elements.empty())
+ return;
+ objKeyValues.emplace_back(key, dom::newArray<
+ dom::DefaultArrayImpl>(std::move(elements)));
+ };
+
+ auto ov = jd.makeOverview(this->getCorpus());
+ // brief
+ if(ov.brief)
+ emplaceString("brief", *ov.brief);
+ emplaceString("description", ov.blocks);
+ if(ov.returns)
+ emplaceString("returns", *ov.returns);
+ emplaceObjectArray("params", ov.params);
+ emplaceObjectArray("tparams", ov.tparams);
+ emplaceObjectArray("exceptions", ov.exceptions);
+ emplaceObjectArray("see", ov.sees);
+ emplaceObjectArray("preconditions", ov.preconditions);
+ emplaceObjectArray("postconditions", ov.postconditions);
+ return dom::Object(std::move(objKeyValues));
+}
+
+dom::Object
+HandlebarsCorpus::
+getOverloads(
+ OverloadSet const& os) const
+{
+ auto obj = DomCorpus::getOverloads(os);
+ // KRYSTIAN FIXME: need a better way to generate IDs
+ // std::string xref =
+ obj.set("ref", getXref(os));
+ // std::replace(xref.begin(), xref.end(), '/', '-');
+ obj.set("id", fmt::format("{}-{}",
+ toBase16(os.Parent), os.Name));
+ return obj;
+}
+
+} // hbs
+} // mrdocs
+} // clang
diff --git a/src/lib/Gen/adoc/AdocCorpus.hpp b/src/lib/Gen/hbs/HandlebarsCorpus.hpp
similarity index 68%
rename from src/lib/Gen/adoc/AdocCorpus.hpp
rename to src/lib/Gen/hbs/HandlebarsCorpus.hpp
index 341d0264f8..cb78d9c1ae 100644
--- a/src/lib/Gen/adoc/AdocCorpus.hpp
+++ b/src/lib/Gen/hbs/HandlebarsCorpus.hpp
@@ -9,8 +9,8 @@
// Official repository: https://github.com/cppalliance/mrdocs
//
-#ifndef MRDOCS_LIB_GEN_ADOC_ADOCCORPUS_HPP
-#define MRDOCS_LIB_GEN_ADOC_ADOCCORPUS_HPP
+#ifndef MRDOCS_LIB_GEN_HBS_HANDLEBARSCORPUS_HPP
+#define MRDOCS_LIB_GEN_HBS_HANDLEBARSCORPUS_HPP
#include
#include "lib/Support/LegibleNames.hpp"
@@ -20,35 +20,47 @@
namespace clang {
namespace mrdocs {
-namespace adoc {
+namespace hbs {
-/** A specialized DomCorpus for generating Adoc nodes.
+/** A specialized DomCorpus for generating Handlebars values.
This class extends @ref DomCorpus to provide
- additional functionality specific to Adoc generation.
+ additional functionality specific to Handlebars
+ generation.
+
*/
-class AdocCorpus : public DomCorpus
+class HandlebarsCorpus : public DomCorpus
{
public:
- /** Options for the Adoc corpus. */
+ /** Options for the Handlebars corpus. */
Options options;
- /** Legible names for the Adoc corpus. */
+ /** Legible names for the Handlebars corpus. */
LegibleNames names_;
+ /** File extension for the markup files. */
+ std::string fileExtension;
+
+ /** Function to convert a Javadoc node to a string. */
+ std::function toStringFn;
+
/** Constructor.
- Initializes the AdocCorpus with the given corpus and options.
+ Initializes the HandlebarsCorpus with the given corpus and options.
@param corpus The base corpus.
- @param opts Options for the Adoc corpus.
+ @param opts Options for the Handlebars corpus.
*/
- AdocCorpus(
+ HandlebarsCorpus(
Corpus const& corpus,
- Options&& opts)
+ Options&& opts,
+ std::string_view fileExtension,
+ std::function toStringFn)
: DomCorpus(corpus)
, options(std::move(opts))
, names_(corpus, options.legible_names)
+ , fileExtension(fileExtension)
+ , toStringFn(std::move(toStringFn))
{
}
@@ -95,7 +107,7 @@ class AdocCorpus : public DomCorpus
OverloadSet const& os) const override;
};
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/hbs/HandlebarsGenerator.cpp b/src/lib/Gen/hbs/HandlebarsGenerator.cpp
new file mode 100644
index 0000000000..248180f034
--- /dev/null
+++ b/src/lib/Gen/hbs/HandlebarsGenerator.cpp
@@ -0,0 +1,161 @@
+//
+// This is a derivative work. originally part of the LLVM Project.
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#include "HandlebarsGenerator.hpp"
+#include "HandlebarsCorpus.hpp"
+#include "Builder.hpp"
+#include "Options.hpp"
+#include "MultiPageVisitor.hpp"
+#include "SinglePageVisitor.hpp"
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace hbs {
+
+Expected>
+createExecutors(
+ HandlebarsCorpus const& hbsCorpus)
+{
+ auto const& config = hbsCorpus->config;
+ auto& threadPool = config.threadPool();
+ ExecutorGroup group(threadPool);
+ for(auto i = threadPool.getThreadCount(); i--;)
+ {
+ try
+ {
+ group.emplace(hbsCorpus);
+ }
+ catch(Exception const& ex)
+ {
+ return Unexpected(ex.error());
+ }
+ }
+ return group;
+}
+
+//------------------------------------------------
+//
+// HandlebarsGenerator
+//
+//------------------------------------------------
+
+/** Return loaded Options from a configuration.
+*/
+Options
+loadOptions(
+ std::string_view fileExtension,
+ Config const& config)
+{
+ Options opt;
+ dom::Value domOpts = config.object().get("generator").get(fileExtension);
+ if (domOpts.get("legible-names").isBoolean())
+ {
+ opt.legible_names = domOpts.get("legible-names").getBool();
+ }
+ if (domOpts.get("template-dir").isString())
+ {
+ opt.template_dir = domOpts.get("template-dir").getString();
+ opt.template_dir = files::makeAbsolute(
+ opt.template_dir,
+ config->configDir);
+ }
+ else
+ {
+ opt.template_dir = files::appendPath(
+ config->addons,
+ "generator",
+ fileExtension);
+ }
+ return opt;
+}
+
+Error
+HandlebarsGenerator::
+build(
+ std::string_view outputPath,
+ Corpus const& corpus) const
+{
+ if (!corpus.config->multipage)
+ {
+ return Generator::build(outputPath, corpus);
+ }
+
+ Options options = loadOptions(fileExtension(), corpus.config);
+ HandlebarsCorpus domCorpus(
+ corpus, std::move(options), fileExtension(), toStringFn);
+ auto ex = createExecutors(domCorpus);
+ if (!ex)
+ {
+ return ex.error();
+ }
+
+ MultiPageVisitor visitor(*ex, outputPath, corpus);
+ visitor(corpus.globalNamespace());
+
+ auto errors = ex->wait();
+ if (!errors.empty())
+ {
+ return Error(errors);
+ }
+ return Error::success();
+}
+
+Error
+HandlebarsGenerator::
+buildOne(
+ std::ostream& os,
+ Corpus const& corpus) const
+{
+ auto options = loadOptions(fileExtension(), corpus.config);
+
+ HandlebarsCorpus domCorpus(
+ corpus, std::move(options), fileExtension(), toStringFn);
+ auto ex = createExecutors(domCorpus);
+ if (!ex)
+ {
+ return ex.error();
+ }
+
+ std::vector errors;
+ ex->async(
+ [&os](Builder& builder)
+ {
+ auto pageText = builder.renderSinglePageHeader().value();
+ os.write(pageText.data(), pageText.size());
+ });
+ errors = ex->wait();
+ if(! errors.empty())
+ return {errors};
+
+ SinglePageVisitor visitor(*ex, corpus, os);
+ visitor(corpus.globalNamespace());
+ errors = ex->wait();
+ if(! errors.empty())
+ return {errors};
+
+ ex->async(
+ [&os](Builder& builder)
+ {
+ auto pageText = builder.renderSinglePageFooter().value();
+ os.write(pageText.data(), pageText.size());
+ });
+ errors = ex->wait();
+ if(! errors.empty())
+ return {errors};
+
+ return Error::success();
+}
+
+} // hbs
+} // mrdocs
+} // clang
diff --git a/src/lib/Gen/hbs/HandlebarsGenerator.hpp b/src/lib/Gen/hbs/HandlebarsGenerator.hpp
new file mode 100644
index 0000000000..03e1cbe898
--- /dev/null
+++ b/src/lib/Gen/hbs/HandlebarsGenerator.hpp
@@ -0,0 +1,77 @@
+//
+// This is a derivative work. originally part of the LLVM Project.
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#ifndef MRDOCS_LIB_GEN_HBS_HANDLEBARSGENERATOR_HPP
+#define MRDOCS_LIB_GEN_HBS_HANDLEBARSGENERATOR_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace hbs {
+
+class HandlebarsGenerator
+ : public Generator
+{
+ std::string displayName_;
+ std::string fileExtension_;
+ using JavadocToStringFn = std::function;
+ JavadocToStringFn toStringFn;
+
+public:
+ HandlebarsGenerator(
+ std::string_view displayName,
+ std::string_view fileExtension,
+ JavadocToStringFn toStringFn)
+ : displayName_(displayName)
+ , fileExtension_(fileExtension)
+ , toStringFn(std::move(toStringFn))
+ {}
+
+ std::string_view
+ id() const noexcept override
+ {
+ return fileExtension_;
+ }
+
+ std::string_view
+ displayName() const noexcept override
+ {
+ return displayName_;
+ }
+
+ std::string_view
+ fileExtension() const noexcept override
+ {
+ return fileExtension_;
+ }
+
+ Error
+ build(
+ std::string_view outputPath,
+ Corpus const& corpus) const override;
+
+ Error
+ buildOne(
+ std::ostream& os,
+ Corpus const& corpus) const override;
+};
+
+} // hbs
+} // mrdocs
+} // clang
+
+#endif
diff --git a/src/lib/Gen/adoc/MultiPageVisitor.cpp b/src/lib/Gen/hbs/MultiPageVisitor.cpp
similarity index 94%
rename from src/lib/Gen/adoc/MultiPageVisitor.cpp
rename to src/lib/Gen/hbs/MultiPageVisitor.cpp
index df5e4b3193..875acd7a36 100644
--- a/src/lib/Gen/adoc/MultiPageVisitor.cpp
+++ b/src/lib/Gen/hbs/MultiPageVisitor.cpp
@@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
@@ -14,7 +15,7 @@
namespace clang {
namespace mrdocs {
-namespace adoc {
+namespace hbs {
void
MultiPageVisitor::
@@ -43,7 +44,7 @@ writePage(
}
}
-template
+template T>
void
MultiPageVisitor::
operator()(T const& I)
@@ -85,6 +86,6 @@ operator()(OverloadSet const& OS)
#define INFO(Type) DEFINE(Type##Info);
#include
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/adoc/MultiPageVisitor.hpp b/src/lib/Gen/hbs/MultiPageVisitor.hpp
similarity index 61%
rename from src/lib/Gen/adoc/MultiPageVisitor.hpp
rename to src/lib/Gen/hbs/MultiPageVisitor.hpp
index 3707d3ff38..74fb7d07d7 100644
--- a/src/lib/Gen/adoc/MultiPageVisitor.hpp
+++ b/src/lib/Gen/hbs/MultiPageVisitor.hpp
@@ -4,15 +4,17 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
-#ifndef MRDOCS_LIB_GEN_ADOC_MULTIPAGEVISITOR_HPP
-#define MRDOCS_LIB_GEN_ADOC_MULTIPAGEVISITOR_HPP
+#ifndef MRDOCS_LIB_GEN_HBS_MULTIPAGEVISITOR_HPP
+#define MRDOCS_LIB_GEN_HBS_MULTIPAGEVISITOR_HPP
#include "Builder.hpp"
#include
+#include
#include
#include
#include
@@ -20,7 +22,7 @@
namespace clang {
namespace mrdocs {
-namespace adoc {
+namespace hbs {
/** Visitor which emites a multi-page reference.
*/
@@ -46,12 +48,25 @@ class MultiPageVisitor
{
}
- template
+ /** Push a task for the specified Info to the executor group.
+
+ If the Info object refers to other Info objects, their
+ respective tasks are also pushed to the executor group.
+
+ */
+ template T>
void operator()(T const& I);
+
+ /** Push a task for the specified OverloadSet to the executor group.
+
+ If the OverloadSet object refers to other Info objects, their
+ respective tasks are also pushed to the executor group.
+
+ */
void operator()(OverloadSet const& OS);
};
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/hbs/Options.hpp b/src/lib/Gen/hbs/Options.hpp
new file mode 100644
index 0000000000..a163d03a3b
--- /dev/null
+++ b/src/lib/Gen/hbs/Options.hpp
@@ -0,0 +1,53 @@
+//
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#ifndef MRDOCS_LIB_GEN_HBS_OPTIONS_HPP
+#define MRDOCS_LIB_GEN_HBS_OPTIONS_HPP
+
+#include
+#include
+
+namespace clang {
+namespace mrdocs {
+
+class Corpus;
+
+namespace hbs {
+
+/** Generator-specific options.
+*/
+struct Options
+{
+ /** True if the generator should produce legible names.
+
+ Legible names are symbol names safe for URLs and
+ file names.
+
+ When disabled, the generator produces hashes
+ for symbol references.
+ */
+ bool legible_names = true;
+
+ /** Directory with the templates used to generate the output.
+
+ The templates are written in Handlebars.
+
+ The default directory is `generator/`
+ relative to the addons directory.
+ */
+ std::string template_dir;
+};
+
+} // hbs
+} // mrdocs
+} // clang
+
+#endif
diff --git a/src/lib/Gen/html/SinglePageVisitor.cpp b/src/lib/Gen/hbs/SinglePageVisitor.cpp
similarity index 96%
rename from src/lib/Gen/html/SinglePageVisitor.cpp
rename to src/lib/Gen/hbs/SinglePageVisitor.cpp
index d327a20366..86974ed239 100644
--- a/src/lib/Gen/html/SinglePageVisitor.cpp
+++ b/src/lib/Gen/hbs/SinglePageVisitor.cpp
@@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
@@ -13,7 +14,7 @@
namespace clang {
namespace mrdocs {
-namespace html {
+namespace hbs {
template
void
@@ -96,6 +97,6 @@ writePage(
#define INFO(Type) DEFINE(Type##Info);
#include
-} // html
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/adoc/SinglePageVisitor.hpp b/src/lib/Gen/hbs/SinglePageVisitor.hpp
similarity index 86%
rename from src/lib/Gen/adoc/SinglePageVisitor.hpp
rename to src/lib/Gen/hbs/SinglePageVisitor.hpp
index f5cb3207d1..e333df5e9e 100644
--- a/src/lib/Gen/adoc/SinglePageVisitor.hpp
+++ b/src/lib/Gen/hbs/SinglePageVisitor.hpp
@@ -4,12 +4,13 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
-#ifndef MRDOCS_LIB_GEN_ADOC_SINGLEPAGEVISITOR_HPP
-#define MRDOCS_LIB_GEN_ADOC_SINGLEPAGEVISITOR_HPP
+#ifndef MRDOCS_LIB_GEN_HBS_SINGLEPAGEVISITOR_HPP
+#define MRDOCS_LIB_GEN_HBS_SINGLEPAGEVISITOR_HPP
#include "Builder.hpp"
#include
@@ -21,7 +22,7 @@
namespace clang {
namespace mrdocs {
-namespace adoc {
+namespace hbs {
/** Visitor which writes everything to a single page.
*/
@@ -50,11 +51,12 @@ class SinglePageVisitor
template
void operator()(T const& I);
+
void operator()(OverloadSet const& OS);
};
-} // adoc
+} // hbs
} // mrdocs
} // clang
diff --git a/src/lib/Gen/html/Builder.cpp b/src/lib/Gen/html/Builder.cpp
deleted file mode 100644
index 2a76d71cba..0000000000
--- a/src/lib/Gen/html/Builder.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "Builder.hpp"
-#include "lib/Support/Radix.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-
-namespace lua {
-extern void lua_dump(dom::Object const& obj);
-}
-
-namespace html {
-
-Builder::
-Builder(
- DomCorpus const& domCorpus,
- Options const& options)
- : domCorpus_(domCorpus)
- , corpus_(domCorpus_.getCorpus())
- , options_(options)
-{
- namespace fs = std::filesystem;
-
- Config const& config = corpus_.config;
-
- // load partials
- std::string partialsPath = files::appendPath(
- config->addons, "generator", "html", "partials");
- forEachFile(partialsPath, true,
- [&](std::string_view pathName) -> Error
- {
- fs::path path = pathName;
- if(path.extension() != ".hbs")
- return Error::success();
- path = path.lexically_relative(partialsPath);
- while(path.has_extension())
- path.replace_extension();
-
- auto text = files::getFileText(pathName);
- if (! text)
- return text.error();
-
- hbs_.registerPartial(
- path.generic_string(), *text);
- return Error::success();
- }).maybeThrow();
-
- // Load JavaScript helpers
- std::string helpersPath = files::appendPath(
- config->addons, "generator", "html", "helpers");
- forEachFile(helpersPath, true,
- [&](std::string_view pathName)-> Expected
- {
- // Register JS helper function in the global object
- constexpr std::string_view ext = ".js";
- if (!pathName.ends_with(ext)) return {};
- auto name = files::getFileName(pathName);
- name.remove_suffix(ext.size());
- MRDOCS_TRY(auto script, files::getFileText(pathName));
- MRDOCS_TRY(js::registerHelper(hbs_, name, ctx_, script));
- return {};
- }).maybeThrow();
-
- hbs_.registerHelper(
- "is_multipage",
- dom::makeInvocable([res = config->multipage]() -> Expected {
- return res;
- }));
-
- hbs_.registerHelper("primary_location",
- dom::makeInvocable([](dom::Value const& v) ->
- dom::Value
- {
- dom::Value src_loc = v.get("loc");
- if(! src_loc)
- return nullptr;
- dom::Value decls = src_loc.get("decl");
- if(dom::Value def = src_loc.get("def"))
- {
- // for classes/enums, prefer the definition
- dom::Value kind = v.get("kind");
- if(kind == "record" || kind == "enum")
- return def;
-
- // we only every want to use the definition
- // for non-tag types when no other declaration
- // exists
- if(! decls)
- return def;
- }
- if(! decls.isArray())
- return nullptr;
- dom::Value first;
- // otherwise, use whatever declaration had docs.
- // if no declaration had docs, fallback to the
- // first declaration
- for(const dom::Value& loc : decls.getArray())
- {
- if(loc.get("documented"))
- return loc;
- else if(! first)
- first = loc;
- }
- return first;
- }));
-
- helpers::registerStringHelpers(hbs_);
- helpers::registerAntoraHelpers(hbs_);
- helpers::registerContainerHelpers(hbs_);
-}
-
-//------------------------------------------------
-
-Expected
-Builder::
-callTemplate(
- std::string_view name,
- dom::Value const& context)
-{
- Config const& config = corpus_.config;
-
- js::Scope scope(ctx_);
-
-
- auto Handlebars = scope.getGlobal("Handlebars");
- auto layoutDir = files::appendPath(config->addons,
- "generator", "html", "layouts");
- auto pathName = files::appendPath(layoutDir, name);
- MRDOCS_TRY(auto fileText, files::getFileText(pathName));
- HandlebarsOptions options;
- options.noEscape = true;
- Expected exp =
- hbs_.try_render(fileText, context, options);
- if (!exp)
- {
- return Unexpected(Error(exp.error().what()));
- }
- return *exp;
-}
-
-Expected
-Builder::
-renderSinglePageHeader()
-{
- return callTemplate("single-header.html.hbs", {});
-}
-
-Expected
-Builder::
-renderSinglePageFooter()
-{
- return callTemplate("single-footer.html.hbs", {});
-}
-
-//------------------------------------------------
-
-std::string
-Builder::
-getRelPrefix(std::size_t depth)
-{
- std::string rel_prefix;
- if(! depth ||! domCorpus_->config->multipage)
- return rel_prefix;
- --depth;
- rel_prefix.reserve(depth * 3);
- while(depth--)
- rel_prefix.append("../");
- return rel_prefix;
-}
-
-dom::Value
-Builder::
-createContext(
- SymbolID const& id)
-{
- return dom::Object({
- { "symbol", domCorpus_.get(id) }
- });
-}
-
-dom::Value
-Builder::
-createContext(
- OverloadSet const& OS)
-{
- dom::Object::storage_type props;
- props.emplace_back("symbol",
- domCorpus_.getOverloads(OS));
- const Info& Parent = domCorpus_->get(OS.Parent);
- props.emplace_back("relfileprefix",
- getRelPrefix(Parent.Namespace.size() + 1));
- return dom::Object(std::move(props));
-}
-
-template
-Expected
-Builder::
-operator()(T const& I)
-{
- return callTemplate(
- "single-symbol.html.hbs",
- createContext(I.id));
-}
-
-Expected
-Builder::
-operator()(OverloadSet const& OS)
-{
- return callTemplate(
- "overload-set.html.hbs",
- createContext(OS));
-}
-
-#define DEFINE(T) template Expected \
- Builder::operator()(T const&)
-
-#define INFO(Type) DEFINE(Type##Info);
-#include
-
-} // html
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/html/Builder.hpp b/src/lib/Gen/html/Builder.hpp
deleted file mode 100644
index 0c92c4566d..0000000000
--- a/src/lib/Gen/html/Builder.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_HTML_BUILDER_HPP
-#define MRDOCS_LIB_GEN_HTML_BUILDER_HPP
-
-#include "Options.hpp"
-#include "lib/Support/Radix.hpp"
-#include
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-/** Builds reference output.
-
- This contains all the state information
- for a single thread to generate output.
-*/
-class Builder
-{
- DomCorpus const& domCorpus_;
- Corpus const& corpus_;
- Options options_;
- js::Context ctx_;
- Handlebars hbs_;
-
- std::string getRelPrefix(std::size_t depth);
-
-public:
- Builder(
- DomCorpus const& domCorpus,
- Options const& options);
-
- dom::Value createContext(SymbolID const& id);
- dom::Value createContext(OverloadSet const& OS);
-
- Expected
- callTemplate(
- std::string_view name,
- dom::Value const& context);
-
- Expected renderSinglePageHeader();
- Expected renderSinglePageFooter();
-
- template
- Expected
- operator()(T const&);
-
- Expected
- operator()(OverloadSet const& OS);
-};
-
-} // html
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Gen/html/HTMLCorpus.cpp b/src/lib/Gen/html/DocVisitor.cpp
similarity index 72%
rename from src/lib/Gen/html/HTMLCorpus.cpp
rename to src/lib/Gen/html/DocVisitor.cpp
index a2a01aaa42..29741830bc 100644
--- a/src/lib/Gen/html/HTMLCorpus.cpp
+++ b/src/lib/Gen/html/DocVisitor.cpp
@@ -5,56 +5,23 @@
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
-#include "HTMLCorpus.hpp"
-#include
-#include
-#include
+#include "DocVisitor.hpp"
+#include "lib/Support/Radix.hpp"
#include
-
+#include
#include
+#include
+#include
namespace clang {
namespace mrdocs {
namespace html {
-namespace {
-
-class DocVisitor
-{
- std::string& dest_;
- std::back_insert_iterator ins_;
-
-public:
- explicit DocVisitor(std::string& dest) noexcept;
-
- void operator()(doc::Admonition const& I);
- void operator()(doc::Code const& I);
- void operator()(doc::Heading const& I);
- void operator()(doc::Paragraph const& I);
- void operator()(doc::Link const& I);
- void operator()(doc::ListItem const& I);
- void operator()(doc::Param const& I);
- void operator()(doc::Returns const& I);
- void operator()(doc::Text const& I);
- void operator()(doc::Styled const& I);
- void operator()(doc::TParam const& I);
-
- std::size_t measureLeftMargin(
- doc::List const& list);
-};
-
-DocVisitor::
-DocVisitor(
- std::string& dest) noexcept
- : dest_(dest)
- , ins_(std::back_inserter(dest_))
-{
-}
-
void
DocVisitor::
operator()(
@@ -238,6 +205,22 @@ operator()(doc::TParam const& I)
//dest_ += I.string;
}
+void
+DocVisitor::
+operator()(doc::Reference const& I)
+{
+ if(I.id == SymbolID::invalid)
+ return (*this)(static_cast(I));
+ fmt::format_to(std::back_inserter(dest_), "{}",
+ corpus_.getXref(corpus_->get(I.id)), I.string);
+}
+
+void
+DocVisitor::
+operator()(doc::Throws const& I)
+{
+}
+
std::size_t
DocVisitor::
measureLeftMargin(
@@ -258,50 +241,6 @@ measureLeftMargin(
return n;
}
-} // (anon)
-
-dom::Value
-HTMLCorpus::
-getJavadoc(
- Javadoc const& jd) const
-{
- dom::Object::storage_type list;
-
- auto maybeEmplace = [&](
- std::string_view key,
- auto const& I)
- {
- std::string s;
- DocVisitor visitor(s);
- using T = std::decay_t;
- if constexpr (std::derived_from)
- {
- doc::visit(I, visitor);
- }
- else if constexpr (std::ranges::range)
- {
- for(auto const& node : I)
- doc::visit(*node, visitor);
- }
- if(!s.empty())
- {
- list.emplace_back(key, std::move(s));
- }
- };
-
- list.reserve(2);
- auto ov = jd.makeOverview(this->getCorpus());
- // brief
- if(ov.brief)
- maybeEmplace("brief", *ov.brief);
- maybeEmplace("description", ov.blocks);
- if(ov.returns)
- maybeEmplace("returns", *ov.returns);
- maybeEmplace("params", ov.params);
- maybeEmplace("tparams", ov.tparams);
- return dom::Object(std::move(list));
-}
-
} // html
} // mrdocs
} // clang
diff --git a/src/lib/Gen/html/DocVisitor.hpp b/src/lib/Gen/html/DocVisitor.hpp
new file mode 100644
index 0000000000..53f0038e3c
--- /dev/null
+++ b/src/lib/Gen/html/DocVisitor.hpp
@@ -0,0 +1,72 @@
+//
+// Licensed under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
+//
+// Official repository: https://github.com/cppalliance/mrdocs
+//
+
+#ifndef MRDOCS_LIB_GEN_HTML_DOCVISITOR_HPP
+#define MRDOCS_LIB_GEN_HTML_DOCVISITOR_HPP
+
+#include
+#include "lib/Gen/hbs/HandlebarsCorpus.hpp"
+#include
+
+namespace clang {
+namespace mrdocs {
+namespace html {
+
+class DocVisitor
+{
+ hbs::HandlebarsCorpus const& corpus_;
+ std::string& dest_;
+ std::back_insert_iterator ins_;
+
+ template
+ bool
+ write(
+ const doc::Node& node,
+ Fn&& fn)
+ {
+ const auto n_before = dest_.size();
+ doc::visit(node, std::forward(fn));
+ return dest_.size() != n_before;
+ }
+
+public:
+ DocVisitor(
+ hbs::HandlebarsCorpus const& corpus,
+ std::string& dest) noexcept
+ : corpus_(corpus)
+ , dest_(dest)
+ , ins_(std::back_inserter(dest_))
+ {
+ }
+
+ void operator()(doc::Admonition const& I);
+ void operator()(doc::Code const& I);
+ void operator()(doc::Heading const& I);
+ void operator()(doc::Paragraph const& I);
+ void operator()(doc::Link const& I);
+ void operator()(doc::ListItem const& I);
+ void operator()(doc::Param const& I);
+ void operator()(doc::Returns const& I);
+ void operator()(doc::Text const& I);
+ void operator()(doc::Styled const& I);
+ void operator()(doc::TParam const& I);
+ void operator()(doc::Reference const& I);
+ void operator()(doc::Throws const& I);
+
+ std::size_t measureLeftMargin(
+ doc::List const& list);
+};
+
+} // html
+} // mrdocs
+} // clang
+
+#endif
diff --git a/src/lib/Gen/html/HTMLCorpus.hpp b/src/lib/Gen/html/HTMLCorpus.hpp
deleted file mode 100644
index bdee006d1a..0000000000
--- a/src/lib/Gen/html/HTMLCorpus.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_HTML_HTMLCORPUS_HPP
-#define MRDOCS_LIB_GEN_HTML_HTMLCORPUS_HPP
-
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-/** A specialized DomCorpus for generating HTML nodes.
-
- This class extends @ref DomCorpus to provide
- additional functionality specific to HTML generation.
-*/
-class HTMLCorpus : public DomCorpus
-{
-public:
- /** Constructor.
-
- Initializes the HTMLCorpus with the given corpus and options.
-
- @param corpus The base corpus.
- @param opts Options for the HTML corpus.
- */
- explicit
- HTMLCorpus(
- Corpus const& corpus)
- : DomCorpus(corpus)
- {
- }
-
- /** Return a Dom value representing the Javadoc.
-
- @param jd The Javadoc object to get the Javadoc for.
- @return A dom::Value representing the Javadoc.
- */
- dom::Value
- getJavadoc(
- Javadoc const& jd) const override;
-};
-
-} // html
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Gen/html/HTMLGenerator.cpp b/src/lib/Gen/html/HTMLGenerator.cpp
index 40fe09f24f..1073aa6e63 100644
--- a/src/lib/Gen/html/HTMLGenerator.cpp
+++ b/src/lib/Gen/html/HTMLGenerator.cpp
@@ -9,113 +9,25 @@
// Official repository: https://github.com/cppalliance/mrdocs
//
-#include "HTMLCorpus.hpp"
#include "HTMLGenerator.hpp"
-#include "Builder.hpp"
-#include "MultiPageVisitor.hpp"
-#include "SinglePageVisitor.hpp"
-#include "lib/Support/LegibleNames.hpp"
-#include
-#include
-#include
-#include
-#include
+#include "DocVisitor.hpp"
namespace clang {
namespace mrdocs {
namespace html {
-Expected>
-createExecutors(
- DomCorpus const& domCorpus)
-{
- MRDOCS_TRY(auto options, loadOptions(*domCorpus));
- auto const& config = domCorpus->config;
- auto& threadPool = config.threadPool();
- ExecutorGroup group(threadPool);
- for(auto i = threadPool.getThreadCount(); i--;)
- {
- try
- {
- group.emplace(domCorpus, options);
- }
- catch(Exception const& ex)
- {
- return Unexpected(ex.error());
- }
- }
- return group;
-}
-
-//------------------------------------------------
-//
-// HTMLGenerator
-//
-//------------------------------------------------
-
-Error
HTMLGenerator::
-build(
- std::string_view outputPath,
- Corpus const& corpus) const
-{
- if(! corpus.config->multipage)
- return Generator::build(outputPath, corpus);
-
- HTMLCorpus domCorpus(corpus);
- auto ex = createExecutors(domCorpus);
- if(! ex)
- return ex.error();
-
- MultiPageVisitor visitor(*ex, outputPath, corpus);
- visitor(corpus.globalNamespace());
- auto errors = ex->wait();
- if(! errors.empty())
- return Error(errors);
- return Error::success();
-}
-
-Error
-HTMLGenerator::
-buildOne(
- std::ostream& os,
- Corpus const& corpus) const
-{
- HTMLCorpus domCorpus(corpus);
- auto ex = createExecutors(domCorpus);
- if(! ex)
- return ex.error();
-
- std::vector errors;
-
- ex->async(
- [&os](Builder& builder)
- {
- auto pageText = builder.renderSinglePageHeader().value();
- os.write(pageText.data(), pageText.size());
- });
- errors = ex->wait();
- if(! errors.empty())
- return Error(errors);
-
- SinglePageVisitor visitor(*ex, corpus, os);
- visitor(corpus.globalNamespace());
- errors = ex->wait();
- if(! errors.empty())
- return Error(errors);
-
- ex->async(
- [&os](Builder& builder)
- {
- auto pageText = builder.renderSinglePageFooter().value();
- os.write(pageText.data(), pageText.size());
- });
- errors = ex->wait();
- if(! errors.empty())
- return Error(errors);
-
- return Error::success();
-}
+HTMLGenerator()
+ : hbs::HandlebarsGenerator("HTML", "html", [](
+ hbs::HandlebarsCorpus const& c,
+ doc::Node const& I) -> std::string
+ {
+ std::string s;
+ DocVisitor visitor(c, s);
+ doc::visit(I, visitor);
+ return s;
+ })
+{}
} // html
diff --git a/src/lib/Gen/html/HTMLGenerator.hpp b/src/lib/Gen/html/HTMLGenerator.hpp
index c74c132474..ff9059ac63 100644
--- a/src/lib/Gen/html/HTMLGenerator.hpp
+++ b/src/lib/Gen/html/HTMLGenerator.hpp
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
+// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//
@@ -14,42 +15,17 @@
#include
#include
+#include
namespace clang {
namespace mrdocs {
namespace html {
class HTMLGenerator
- : public Generator
+ : public hbs::HandlebarsGenerator
{
public:
- std::string_view
- id() const noexcept override
- {
- return "html";
- }
-
- std::string_view
- displayName() const noexcept override
- {
- return "HTML";
- }
-
- std::string_view
- fileExtension() const noexcept override
- {
- return "html";
- }
-
- Error
- build(
- std::string_view outputPath,
- Corpus const& corpus) const override;
-
- Error
- buildOne(
- std::ostream& os,
- Corpus const& corpus) const override;
+ HTMLGenerator();
};
} // html
diff --git a/src/lib/Gen/html/MultiPageVisitor.cpp b/src/lib/Gen/html/MultiPageVisitor.cpp
deleted file mode 100644
index eaa08034ee..0000000000
--- a/src/lib/Gen/html/MultiPageVisitor.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "MultiPageVisitor.hpp"
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-template
-void
-MultiPageVisitor::
-operator()(T const& I)
-{
- renderPage(I);
- if constexpr(
- T::isNamespace() ||
- T::isRecord() ||
- T::isEnum())
- corpus_.traverse(I, *this);
-}
-
-void
-MultiPageVisitor::
-renderPage(
- auto const& I)
-{
- ex_.async(
- [this, &I](Builder& builder)
- {
- auto pageText = builder(I).value();
-
- std::string fileName = files::appendPath(
- outputPath_, toBase16(I.id) + ".html");
- std::ofstream os;
- try
- {
- os.open(fileName,
- std::ios_base::binary |
- std::ios_base::out |
- std::ios_base::trunc // | std::ios_base::noreplace
- );
- os.write(pageText.data(), pageText.size());
- }
- catch(std::exception const& ex)
- {
- formatError("std::ofstream(\"{}\") threw \"{}\"", fileName, ex.what()).Throw();
- }
- });
-}
-
-#define DEFINE(T) template void \
- MultiPageVisitor::operator()(T const&)
-
-#define INFO(Type) DEFINE(Type##Info);
-#include
-
-} // html
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/html/MultiPageVisitor.hpp b/src/lib/Gen/html/MultiPageVisitor.hpp
deleted file mode 100644
index 0c355aba05..0000000000
--- a/src/lib/Gen/html/MultiPageVisitor.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_HTML_MULTIPAGEVISITOR_HPP
-#define MRDOCS_LIB_GEN_HTML_MULTIPAGEVISITOR_HPP
-
-#include "Builder.hpp"
-#include
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-/** Visitor which emites a multi-page reference.
-*/
-class MultiPageVisitor
-{
- ExecutorGroup& ex_;
- std::string_view outputPath_;
- Corpus const& corpus_;
-
-public:
- MultiPageVisitor(
- ExecutorGroup& ex,
- std::string_view outputPath,
- Corpus const& corpus) noexcept
- : ex_(ex)
- , outputPath_(outputPath)
- , corpus_(corpus)
- {
- }
-
- template
- void operator()(T const& I);
- void renderPage(auto const& I);
-};
-
-} // html
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Gen/html/Options.cpp b/src/lib/Gen/html/Options.cpp
deleted file mode 100644
index e701a0137e..0000000000
--- a/src/lib/Gen/html/Options.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-// This is a derivative work. originally part of the LLVM Project.
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#include "Options.hpp"
-#include "lib/Support/Yaml.hpp"
-#include "lib/Lib/ConfigImpl.hpp" // VFALCO This is a problem
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-struct YamlKey
-{
- Options& opt;
-
- explicit
- YamlKey(
- Options& opt_) noexcept
- : opt(opt_)
- {
- }
-};
-
-struct YamlGenKey
-{
- Options& opt;
-
- explicit
- YamlGenKey(
- Options& opt_)
- : opt(opt_)
- {
- }
-};
-
-} // html
-} // mrdocs
-} // clang
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::html::YamlKey>
-{
- static void mapping(IO& io,
- clang::mrdocs::html::YamlKey& yk)
- {
- auto& opt= yk.opt;
- io.mapOptional("legible-names", opt.legible_names);
- io.mapOptional("template-dir", opt.template_dir);
- }
-};
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::html::YamlGenKey>
-{
- static void mapping(IO& io,
- clang::mrdocs::html::YamlGenKey& ygk)
- {
- clang::mrdocs::html::YamlKey yk(ygk.opt);
- io.mapOptional("html", yk);
- }
-};
-
-template<>
-struct llvm::yaml::MappingTraits<
- clang::mrdocs::html::Options>
-{
- static void mapping(IO& io,
- clang::mrdocs::html::Options& opt)
- {
- clang::mrdocs::html::YamlGenKey ygk(opt);
- io.mapOptional("generator", ygk);
- }
-};
-
-//------------------------------------------------
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-Expected
-loadOptions(
- Corpus const& corpus)
-{
- Options opt;
-
- YamlReporter reporter;
-
- // config
- {
- llvm::yaml::Input yin(
- corpus.config->configYaml,
- &reporter, reporter);
- yin.setAllowUnknownKeys(true);
- yin >> opt;
- if(auto ec = yin.error())
- return Unexpected(Error(ec));
- }
-
- // adjust relative paths
- if(! opt.template_dir.empty())
- {
- opt.template_dir = files::makeAbsolute(
- opt.template_dir,
- corpus.config->configDir);
- }
- else
- {
- // VFALCO TODO get process executable
- // and form a path relative to that.
- }
-
- if(! opt.template_dir.empty())
- {
- opt.template_dir = files::makeAbsolute(
- opt.template_dir,
- corpus.config->configDir);
- }
- else
- {
- // VFALCO TODO get process executable
- // and form a path relative to that.
- }
-
- return opt;
-}
-
-} // html
-} // mrdocs
-} // clang
diff --git a/src/lib/Gen/html/Options.hpp b/src/lib/Gen/html/Options.hpp
deleted file mode 100644
index faac05fe75..0000000000
--- a/src/lib/Gen/html/Options.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_HTML_OPTIONS_HPP
-#define MRDOCS_LIB_GEN_HTML_OPTIONS_HPP
-
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-
-class Corpus;
-
-namespace html {
-
-/** Generator-specific options.
-*/
-struct Options
-{
- bool legible_names = false;
- std::string template_dir;
-};
-
-/** Return loaded Options from a configuration.
-*/
-Expected
-loadOptions(
- Corpus const& corpus);
-
-} // html
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Gen/html/SinglePageVisitor.hpp b/src/lib/Gen/html/SinglePageVisitor.hpp
deleted file mode 100644
index e153dbe702..0000000000
--- a/src/lib/Gen/html/SinglePageVisitor.hpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Licensed under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
-//
-// Official repository: https://github.com/cppalliance/mrdocs
-//
-
-#ifndef MRDOCS_LIB_GEN_HTML_SINGLEPAGEVISITOR_HPP
-#define MRDOCS_LIB_GEN_HTML_SINGLEPAGEVISITOR_HPP
-
-#include "Builder.hpp"
-#include
-#include
-#include
-#include
-#include
-
-namespace clang {
-namespace mrdocs {
-namespace html {
-
-/** Visitor which writes everything to a single page.
-*/
-class SinglePageVisitor
-{
- ExecutorGroup& ex_;
- Corpus const& corpus_;
- std::ostream& os_;
- std::size_t numPages_ = 0;
- std::mutex mutex_;
- std::size_t topPage_ = 0;
- std::vector> pages_;
-
-public:
- SinglePageVisitor(
- ExecutorGroup& ex,
- Corpus const& corpus,
- std::ostream& os) noexcept
- : ex_(ex)
- , corpus_(corpus)
- , os_(os)
- {
- }
-
- template
- void operator()(T const& I);
- void operator()(OverloadSet const& OS);
- void renderPage(auto const& I, std::size_t pageNumber);
- void writePage(std::string pageText, std::size_t pageNumber);
-};
-
-} // html
-} // mrdocs
-} // clang
-
-#endif
diff --git a/src/lib/Metadata/Template.cpp b/src/lib/Metadata/Template.cpp
index 0aa7f36a30..5c845db373 100644
--- a/src/lib/Metadata/Template.cpp
+++ b/src/lib/Metadata/Template.cpp
@@ -119,11 +119,11 @@ tag_invoke(
dom::LazyObjectMapTag,
IO& io,
TArg const& I,
- DomCorpus const* domCorpus)
+ DomCorpus const*)
{
io.map("kind", toString(I.Kind));
io.map("is-pack", I.IsPackExpansion);
- visit(I, [domCorpus, &io](const T& t) {
+ visit(I, [&io](const T& t) {
if constexpr(T::isType())
{
io.map("type", t.Type);
diff --git a/src/lib/Support/Error.cpp b/src/lib/Support/Error.cpp
index 584a5cab45..c950e8f939 100644
--- a/src/lib/Support/Error.cpp
+++ b/src/lib/Support/Error.cpp
@@ -166,6 +166,7 @@ namespace report {
static llvm::sys::Mutex mutex_;
static Level level_ = Level::debug;
+static bool sourceLocationWarnings_ = true;
constinit Results results{};
@@ -191,6 +192,12 @@ setMinimumLevel(
level_ = level;
}
+void
+setSourceLocationWarnings(bool b) noexcept
+{
+ sourceLocationWarnings_ = b;
+}
+
void
print(
std::string const& text)
@@ -240,10 +247,11 @@ call_impl(
{
llvm::raw_string_ostream os(s);
f(os);
- if(loc && (
- level == Level::warn ||
- level == Level::error ||
- level == Level::fatal))
+ if(sourceLocationWarnings_ &&
+ loc && (
+ level == Level::warn ||
+ level == Level::error ||
+ level == Level::fatal))
{
os << "\n\n";
os << "An issue occurred during execution.\n";
diff --git a/src/lib/Support/Generator.cpp b/src/lib/Support/Generator.cpp
index 39f423f127..9e81012252 100644
--- a/src/lib/Support/Generator.cpp
+++ b/src/lib/Support/Generator.cpp
@@ -25,7 +25,7 @@ namespace mrdocs {
Generator::
~Generator() noexcept = default;
-/* default implementation of this function
+/* Default implementation of this function
assumes the output is single page, and emits
the file reference.ext using the extension
of the generator.
diff --git a/src/lib/Support/GeneratorsImpl.hpp b/src/lib/Support/GeneratorsImpl.hpp
index 8d738de597..e2e6fe26d9 100644
--- a/src/lib/Support/GeneratorsImpl.hpp
+++ b/src/lib/Support/GeneratorsImpl.hpp
@@ -26,7 +26,7 @@ namespace mrdocs {
class MRDOCS_VISIBLE
GeneratorsImpl : public Generators
{
- llvm::SmallVector plist_;
+ llvm::SmallVector