Fixed mermaid verbatim directives handling
This commit is contained in:
@@ -33,6 +33,11 @@ generator::generator(diagram_config &config, diagram_model &model)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generator::generate_diagram_type(std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
ostr << "classDiagram\n";
|
||||||
|
}
|
||||||
|
|
||||||
void generator::generate_alias(
|
void generator::generate_alias(
|
||||||
const common::model::element &c, std::ostream &ostr) const
|
const common::model::element &c, std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
@@ -696,8 +701,6 @@ void generator::generate_relationships(
|
|||||||
|
|
||||||
void generator::generate_diagram(std::ostream &ostr) const
|
void generator::generate_diagram(std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
ostr << "classDiagram\n";
|
|
||||||
|
|
||||||
generate_top_level_elements(ostr);
|
generate_top_level_elements(ostr);
|
||||||
|
|
||||||
generate_groups(ostr);
|
generate_groups(ostr);
|
||||||
|
|||||||
@@ -79,6 +79,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void generate_diagram(std::ostream &ostr) const override;
|
void generate_diagram(std::ostream &ostr) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate the diagram type
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
*/
|
||||||
|
void generate_diagram_type(std::ostream &ostr) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief In a nested diagram, generate the top level elements.
|
* @brief In a nested diagram, generate the top level elements.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -107,6 +107,16 @@ public:
|
|||||||
void generate_mermaid_directives(
|
void generate_mermaid_directives(
|
||||||
std::ostream &ostr, const std::vector<std::string> &directives) const;
|
std::ostream &ostr, const std::vector<std::string> &directives) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate the diagram type
|
||||||
|
*
|
||||||
|
* This method must be overriden for each diagram type (e.g. it renders
|
||||||
|
* a single line `classDiagram` for Mermaid class diagrams.
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
*/
|
||||||
|
virtual void generate_diagram_type(std::ostream &ostr) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate diagram notes
|
* @brief Generate diagram notes
|
||||||
*
|
*
|
||||||
@@ -228,13 +238,13 @@ void generator<C, D>::generate(std::ostream &ostr) const
|
|||||||
|
|
||||||
update_context();
|
update_context();
|
||||||
|
|
||||||
// generate_mermaid_diagram_type(ostr, config);
|
generate_diagram_type(ostr);
|
||||||
|
|
||||||
generate_mermaid_directives(ostr, config.puml().before);
|
generate_mermaid_directives(ostr, config.mermaid().before);
|
||||||
|
|
||||||
generate_diagram(ostr);
|
generate_diagram(ostr);
|
||||||
|
|
||||||
generate_mermaid_directives(ostr, config.puml().after);
|
generate_mermaid_directives(ostr, config.mermaid().after);
|
||||||
|
|
||||||
generate_metadata(ostr);
|
generate_metadata(ostr);
|
||||||
}
|
}
|
||||||
@@ -304,6 +314,61 @@ template <typename C, typename D>
|
|||||||
void generator<C, D>::generate_mermaid_directives(
|
void generator<C, D>::generate_mermaid_directives(
|
||||||
std::ostream &ostr, const std::vector<std::string> &directives) const
|
std::ostream &ostr, const std::vector<std::string> &directives) const
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const auto &config = generators::generator<C, D>::config();
|
||||||
|
const auto &model = generators::generator<C, D>::model();
|
||||||
|
|
||||||
|
using common::model::namespace_;
|
||||||
|
|
||||||
|
for (const auto &d : directives) {
|
||||||
|
try {
|
||||||
|
// Render the directive with template engine first
|
||||||
|
std::string directive{env().render(std::string_view{d}, context())};
|
||||||
|
|
||||||
|
// Now search for alias `@A()` directives in the text
|
||||||
|
// (this is deprecated)
|
||||||
|
std::tuple<std::string, size_t, size_t> alias_match;
|
||||||
|
while (util::find_element_alias(directive, alias_match)) {
|
||||||
|
const auto full_name =
|
||||||
|
config.using_namespace() | std::get<0>(alias_match);
|
||||||
|
auto element_opt = model.get(full_name.to_string());
|
||||||
|
|
||||||
|
if (element_opt)
|
||||||
|
directive.replace(std::get<1>(alias_match),
|
||||||
|
std::get<2>(alias_match), element_opt.value().alias());
|
||||||
|
else {
|
||||||
|
LOG_ERROR("Cannot find clang-uml alias for element {}",
|
||||||
|
full_name.to_string());
|
||||||
|
directive.replace(std::get<1>(alias_match),
|
||||||
|
std::get<2>(alias_match), "UNKNOWN_ALIAS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ostr << indent(1) << directive << '\n';
|
||||||
|
}
|
||||||
|
catch (const clanguml::error::uml_alias_missing &e) {
|
||||||
|
LOG_ERROR(
|
||||||
|
"Failed to render MermaidJS directive due to unresolvable "
|
||||||
|
"alias: {}",
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
catch (const inja::json::parse_error &e) {
|
||||||
|
LOG_ERROR("Failed to parse Jinja template: {}", d);
|
||||||
|
}
|
||||||
|
catch (const inja::json::exception &e) {
|
||||||
|
LOG_ERROR("Failed to render MermaidJS directive: \n{}\n due to: {}",
|
||||||
|
d, e.what());
|
||||||
|
}
|
||||||
|
catch (const std::regex_error &e) {
|
||||||
|
LOG_ERROR("Failed to render MermaidJS directive: \n{}\n due to "
|
||||||
|
"std::regex_error: {}",
|
||||||
|
d, e.what());
|
||||||
|
}
|
||||||
|
catch (const std::exception &e) {
|
||||||
|
LOG_ERROR("Failed to render PlantUML directive: \n{}\n due to: {}",
|
||||||
|
d, e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename D>
|
template <typename C, typename D>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ using clanguml::config::include_diagram;
|
|||||||
using clanguml::config::layout_hint;
|
using clanguml::config::layout_hint;
|
||||||
using clanguml::config::location_t;
|
using clanguml::config::location_t;
|
||||||
using clanguml::config::member_order_t;
|
using clanguml::config::member_order_t;
|
||||||
|
using clanguml::config::mermaid;
|
||||||
using clanguml::config::method_arguments;
|
using clanguml::config::method_arguments;
|
||||||
using clanguml::config::method_type;
|
using clanguml::config::method_type;
|
||||||
using clanguml::config::package_diagram;
|
using clanguml::config::package_diagram;
|
||||||
@@ -389,6 +390,18 @@ template <> struct convert<plantuml> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct convert<mermaid> {
|
||||||
|
static bool decode(const Node &node, mermaid &rhs)
|
||||||
|
{
|
||||||
|
if (node["before"])
|
||||||
|
rhs.before = node["before"].as<decltype(rhs.before)>();
|
||||||
|
|
||||||
|
if (node["after"])
|
||||||
|
rhs.after = node["after"].as<decltype(rhs.after)>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct convert<string_or_regex> {
|
template <> struct convert<string_or_regex> {
|
||||||
static bool decode(const Node &node, string_or_regex &rhs)
|
static bool decode(const Node &node, string_or_regex &rhs)
|
||||||
{
|
{
|
||||||
@@ -531,6 +544,7 @@ template <typename T> bool decode_diagram(const Node &node, T &rhs)
|
|||||||
get_option(node, rhs.include);
|
get_option(node, rhs.include);
|
||||||
get_option(node, rhs.exclude);
|
get_option(node, rhs.exclude);
|
||||||
get_option(node, rhs.puml);
|
get_option(node, rhs.puml);
|
||||||
|
get_option(node, rhs.mermaid);
|
||||||
get_option(node, rhs.git);
|
get_option(node, rhs.git);
|
||||||
get_option(node, rhs.generate_links);
|
get_option(node, rhs.generate_links);
|
||||||
get_option(node, rhs.type_aliases);
|
get_option(node, rhs.type_aliases);
|
||||||
@@ -762,6 +776,7 @@ template <> struct convert<config> {
|
|||||||
get_option(node, rhs.remove_compile_flags);
|
get_option(node, rhs.remove_compile_flags);
|
||||||
get_option(node, rhs.include_relations_also_as_members);
|
get_option(node, rhs.include_relations_also_as_members);
|
||||||
get_option(node, rhs.puml);
|
get_option(node, rhs.puml);
|
||||||
|
get_option(node, rhs.mermaid);
|
||||||
get_option(node, rhs.generate_method_arguments);
|
get_option(node, rhs.generate_method_arguments);
|
||||||
get_option(node, rhs.generate_packages);
|
get_option(node, rhs.generate_packages);
|
||||||
get_option(node, rhs.package_type);
|
get_option(node, rhs.package_type);
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ generator::generator(diagram_config &config, diagram_model &model)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generator::generate_diagram_type(std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
ostr << "flowchart\n";
|
||||||
|
}
|
||||||
|
|
||||||
void generator::generate_relationships(
|
void generator::generate_relationships(
|
||||||
const source_file &f, std::ostream &ostr) const
|
const source_file &f, std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
@@ -114,8 +119,6 @@ void generator::generate_notes(
|
|||||||
|
|
||||||
void generator::generate_diagram(std::ostream &ostr) const
|
void generator::generate_diagram(std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
ostr << "flowchart\n";
|
|
||||||
|
|
||||||
// Generate files and folders
|
// Generate files and folders
|
||||||
util::for_each(model(), [this, &ostr](const auto &f) {
|
util::for_each(model(), [this, &ostr](const auto &f) {
|
||||||
generate(dynamic_cast<source_file &>(*f), ostr);
|
generate(dynamic_cast<source_file &>(*f), ostr);
|
||||||
|
|||||||
@@ -64,6 +64,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void generate_diagram(std::ostream &ostr) const override;
|
void generate_diagram(std::ostream &ostr) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate the diagram type
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
*/
|
||||||
|
void generate_diagram_type(std::ostream &ostr) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate relationships originating from source_file `f`
|
* @brief Generate relationships originating from source_file `f`
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ generator::generator(diagram_config &config, diagram_model &model)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generator::generate_diagram_type(std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
ostr << "flowchart\n";
|
||||||
|
}
|
||||||
|
|
||||||
void generator::generate_relationships(
|
void generator::generate_relationships(
|
||||||
const package &p, std::ostream &ostr) const
|
const package &p, std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
@@ -144,8 +149,6 @@ void generator::generate_notes(
|
|||||||
|
|
||||||
void generator::generate_diagram(std::ostream &ostr) const
|
void generator::generate_diagram(std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
ostr << "flowchart\n";
|
|
||||||
|
|
||||||
for (const auto &p : model()) {
|
for (const auto &p : model()) {
|
||||||
auto &pkg = dynamic_cast<package &>(*p);
|
auto &pkg = dynamic_cast<package &>(*p);
|
||||||
if (model().should_include(pkg)) {
|
if (model().should_include(pkg)) {
|
||||||
|
|||||||
@@ -66,6 +66,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void generate_diagram(std::ostream &ostr) const override;
|
void generate_diagram(std::ostream &ostr) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate the diagram type
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
*/
|
||||||
|
void generate_diagram_type(std::ostream &ostr) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate relationships originating from package `p`
|
* @brief Generate relationships originating from package `p`
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ generator::generator(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generator::generate_diagram_type(std::ostream &ostr) const
|
||||||
|
{
|
||||||
|
ostr << "sequenceDiagram\n";
|
||||||
|
}
|
||||||
|
|
||||||
void generator::generate_call(const message &m, std::ostream &ostr) const
|
void generator::generate_call(const message &m, std::ostream &ostr) const
|
||||||
{
|
{
|
||||||
const auto &from = model().get_participant<model::participant>(m.from());
|
const auto &from = model().get_participant<model::participant>(m.from());
|
||||||
@@ -389,8 +394,6 @@ void generator::generate_diagram(std::ostream &ostr) const
|
|||||||
{
|
{
|
||||||
model().print();
|
model().print();
|
||||||
|
|
||||||
ostr << "sequenceDiagram\n";
|
|
||||||
|
|
||||||
if (config().participants_order.has_value) {
|
if (config().participants_order.has_value) {
|
||||||
for (const auto &p : config().participants_order()) {
|
for (const auto &p : config().participants_order()) {
|
||||||
LOG_DBG("Pregenerating participant {}", p);
|
LOG_DBG("Pregenerating participant {}", p);
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void generate_diagram(std::ostream &ostr) const override;
|
void generate_diagram(std::ostream &ostr) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate the diagram type
|
||||||
|
*
|
||||||
|
* @param ostr Output stream
|
||||||
|
*/
|
||||||
|
void generate_diagram_type(std::ostream &ostr) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate sequence diagram message.
|
* @brief Generate sequence diagram message.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -96,4 +96,10 @@ TEST_CASE("t20006", "[test-case][sequence]")
|
|||||||
|
|
||||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_sequence_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -121,4 +121,10 @@ TEST_CASE("t20012", "[test-case][sequence]")
|
|||||||
|
|
||||||
save_json(config.output_directory(), diagram->name + ".json", j);
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_sequence_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,3 +18,15 @@ diagrams:
|
|||||||
- 'class "Boo" as C_002'
|
- 'class "Boo" as C_002'
|
||||||
- 'class C_002 {'
|
- 'class C_002 {'
|
||||||
- '}'
|
- '}'
|
||||||
|
mermaid:
|
||||||
|
before:
|
||||||
|
- 'class C_001["Foo"]'
|
||||||
|
- 'class C_001 {'
|
||||||
|
- ' +int value'
|
||||||
|
- '}'
|
||||||
|
- 'C_001 <|-- ArrayList'
|
||||||
|
- 'note for C_001 "This is a very important class."'
|
||||||
|
- 'note "This is a\nfloating note"'
|
||||||
|
- 'class C_002["Boo"]'
|
||||||
|
- 'class C_002 {'
|
||||||
|
- '}'
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ TEST_CASE("t90000", "[test-case][config]")
|
|||||||
|
|
||||||
REQUIRE(model->name() == "t90000_class");
|
REQUIRE(model->name() == "t90000_class");
|
||||||
|
|
||||||
|
{
|
||||||
auto puml = generate_class_puml(diagram, *model);
|
auto puml = generate_class_puml(diagram, *model);
|
||||||
AliasMatcher _A(puml);
|
AliasMatcher _A(puml);
|
||||||
|
|
||||||
@@ -37,3 +38,18 @@ TEST_CASE("t90000", "[test-case][config]")
|
|||||||
|
|
||||||
save_puml(config.output_directory(), diagram->name + ".puml", puml);
|
save_puml(config.output_directory(), diagram->name + ".puml", puml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto j = generate_class_json(diagram, *model);
|
||||||
|
|
||||||
|
using namespace json;
|
||||||
|
|
||||||
|
save_json(config.output_directory(), diagram->name + ".json", j);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto mmd = generate_class_mermaid(diagram, *model);
|
||||||
|
|
||||||
|
save_mermaid(config.output_directory(), diagram->name + ".mmd", mmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -282,7 +282,6 @@ void save_puml(const std::string &path, const std::string &filename,
|
|||||||
const std::string &puml)
|
const std::string &puml)
|
||||||
{
|
{
|
||||||
std::filesystem::path p{path};
|
std::filesystem::path p{path};
|
||||||
p /= "puml";
|
|
||||||
p /= filename;
|
p /= filename;
|
||||||
save_diagram(p, puml);
|
save_diagram(p, puml);
|
||||||
}
|
}
|
||||||
@@ -291,7 +290,6 @@ void save_json(const std::string &path, const std::string &filename,
|
|||||||
const nlohmann::json &j)
|
const nlohmann::json &j)
|
||||||
{
|
{
|
||||||
std::filesystem::path p{path};
|
std::filesystem::path p{path};
|
||||||
p /= "json";
|
|
||||||
p /= filename;
|
p /= filename;
|
||||||
save_diagram(p, j);
|
save_diagram(p, j);
|
||||||
}
|
}
|
||||||
@@ -300,7 +298,6 @@ void save_mermaid(const std::string &path, const std::string &filename,
|
|||||||
const std::string &mmd)
|
const std::string &mmd)
|
||||||
{
|
{
|
||||||
std::filesystem::path p{path};
|
std::filesystem::path p{path};
|
||||||
p /= "mermaid";
|
|
||||||
p /= filename;
|
p /= filename;
|
||||||
save_diagram(p, mmd);
|
save_diagram(p, mmd);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user