Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,44 @@ if (MRDOCS_BUILD_TESTS)
)
endforeach ()

#-------------------------------------------------
# Template-only generators
#
# Fixtures under test-files/template-only-generators/<id> ship an
# addon defining their own Handlebars generator. They live outside
# test-files/golden-tests so the xml/adoc/html runs do not walk
# into them and demand expected files in their own formats.
#-------------------------------------------------
set(MRDOCS_TEMPLATE_ONLY_ROOT "${PROJECT_SOURCE_DIR}/test-files/template-only-generators")
add_test(NAME mrdocs-golden-tests-mock-md
COMMAND
mrdocs-test
--unit=false
--action=test
"${MRDOCS_TEMPLATE_ONLY_ROOT}/mock-md"
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=mock-md
"--stdlib-includes=${LIBCXX_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
)
foreach (action IN ITEMS test create update)
add_custom_target(
mrdocs-${action}-test-fixtures-mock-md
COMMAND
mrdocs-test
--unit=false
--action=${action}
"${MRDOCS_TEMPLATE_ONLY_ROOT}/mock-md"
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=mock-md
"--stdlib-includes=${LIBCXX_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
DEPENDS mrdocs-test
)
endforeach ()

#-------------------------------------------------
# Self-documentation test (warn-as-error toggled by strict flag)
#-------------------------------------------------
Expand Down
10 changes: 3 additions & 7 deletions docs/mrdocs.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,9 @@
},
"generator": {
"default": "adoc",
"description": "The generator is responsible for creating the documentation from the extracted symbols. The generator uses the extracted symbols and the templates to create the documentation. The generator can create different types of documentation such as HTML, XML, and AsciiDoc.",
"enum": [
"adoc",
"html",
"xml"
],
"title": "Generator used to create the documentation"
"description": "The generator is responsible for creating the documentation from the extracted symbols. The generator uses the extracted symbols and the templates to create the documentation. The built-in generators include `adoc`, `html`, and `xml`; addon-defined generators can be added by dropping a template folder under <addon>/generator/<name>/.",
"title": "Generator used to create the documentation",
"type": "string"
},
"global-namespace-index": {
"default": true,
Expand Down
13 changes: 13 additions & 0 deletions include/mrdocs/Support/Handlebars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,19 @@ HTMLEscape(
OutputRef& out,
std::string_view str);

/** Character-to-entity table used by `HTMLEscape`.
*/
inline constexpr std::pair<char, std::string_view>
htmlEscapeEntities[] = {
{'&', "&amp;"},
{'<', "&lt;"},
{'>', "&gt;"},
{'"', "&quot;"},
{'\'', "&#x27;"},
{'`', "&#x60;"},
{'=', "&#x3D;"}
};

/** \brief HTML escapes the specified string.
*
* This function HTML escapes the specified string, making it safe for
Expand Down
9 changes: 2 additions & 7 deletions src/lib/ConfigOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,8 @@
{
"name": "generator",
"brief": "Generator used to create the documentation",
"details": "The generator is responsible for creating the documentation from the extracted symbols. The generator uses the extracted symbols and the templates to create the documentation. The generator can create different types of documentation such as HTML, XML, and AsciiDoc.",
"type": "enum",
"values": [
"adoc",
"html",
"xml"
],
"details": "The generator is responsible for creating the documentation from the extracted symbols. The generator uses the extracted symbols and the templates to create the documentation. The built-in generators include `adoc`, `html`, and `xml`; addon-defined generators can be added by dropping a template folder under <addon>/generator/<name>/.",
"type": "string",
"default": "adoc"
},
{
Expand Down
100 changes: 0 additions & 100 deletions src/lib/Gen/adoc/AdocEscape.cpp

This file was deleted.

34 changes: 0 additions & 34 deletions src/lib/Gen/adoc/AdocEscape.hpp

This file was deleted.

77 changes: 72 additions & 5 deletions src/lib/Gen/adoc/AdocGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,89 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com)
//
// Official repository: https://github.com/cppalliance/mrdocs
//

#include "AdocGenerator.hpp"
#include "AdocEscape.hpp"
#include <mrdocs/Support/Handlebars.hpp>
#include <format>
#include <memory>

namespace mrdocs {
namespace adoc {

void
namespace {

// Return the HTML named entity for `c`, or an empty view if there
// is no suitable named entity.
//
// https://docs.asciidoctor.org/asciidoc/latest/subs/replacements/
constexpr std::string_view
namedEntity(char const c) noexcept
{
switch (c)
{
// There's no named entity for '~' (U+007E / &#126;) in HTML
// - "&tilde;" represents a small tilde (U+02DC)
// - "&Tilde;" or "&sim;" represent the tilde operator (U+223C)
// The 'tilde operator' (U+223C) is not the same character as
// "tilde" (U+007E) although the same glyph might be used to
// represent both.
// case '~': return "&tilde;";
case '^': return "&circ;";
case '_': return "&lowbar;";
case '*': return "&ast;";
case '`': return "&grave;";
case '#': return "&num;";
case '[': return "&lsqb;";
case ']': return "&rsqb;";
case '{': return "&lcub;";
case '}': return "&rcub;";
case '<': return "&lt;";
case '>': return "&gt;";
case '\\': return "&bsol;";
case '|': return "&verbar;";
case '-': return "&hyphen;";
case '=': return "&equals;";
case '&': return "&amp;";
case ';': return "&semi;";
case '+': return "&plus;";
case ':': return "&colon;";
case '.': return "&period;";
case '"': return "&quot;";
case '\'': return "&apos;";
case '/': return "&sol;";
default: return {};
}
}

} // (anon)

AdocGenerator::
escape(OutputRef& os, std::string_view const str) const
AdocGenerator()
: HandlebarsGenerator("adoc", "adoc", "Asciidoc")
{
AdocEscape(os, str);
// Reserved characters that AsciiDoc treats specially in body text.
// Each one maps to its HTML named entity when one exists; the
// small set without a named entity (currently just `~`) falls
// back to the numeric form `&#NNN;` constructed from the
// character's code point.
static constexpr char reserved[] = R"(~^_*`#[]{}<>\|-=&;+:."\'/)";
for (char const c : reserved)
{
std::string_view const named = namedEntity(c);
if (!named.empty())
{
escapeMap_.set(c, named);
}
else
{
escapeMap_.set(
c,
std::format("&#{};", static_cast<int>(static_cast<unsigned char>(c))));
}
}
}

} // adoc
Expand Down
24 changes: 1 addition & 23 deletions src/lib/Gen/adoc/AdocGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,15 @@
#ifndef MRDOCS_LIB_GEN_ADOC_ADOCGENERATOR_HPP
#define MRDOCS_LIB_GEN_ADOC_ADOCGENERATOR_HPP

#include <mrdocs/Platform.hpp>
#include <lib/Gen/hbs/HandlebarsGenerator.hpp>
#include <mrdocs/Generator.hpp>

namespace mrdocs::adoc {

class AdocGenerator final
: public hbs::HandlebarsGenerator
{
public:
std::string_view
id() const noexcept override
{
return "adoc";
}

std::string_view
fileExtension() const noexcept override
{
return "adoc";
}


std::string_view
displayName() const noexcept override
{
return "Asciidoc";
}

void
escape(OutputRef& os, std::string_view str) const override;
AdocGenerator();
};

} // mrdocs::adoc
Expand Down
Loading
Loading