use crate::detect::DetectorFn;
use crate::diagram::{
BuiltInDiagramSemanticParser, BuiltInRenderSemanticParser, RenderSemanticModel,
RenderSemanticParseOutput,
};
use crate::{
EditorSemanticFacts, Error, MermaidConfig, ParseControl, ParseControlResult, ParseMetadata,
Result,
};
use serde::Serialize;
use serde_json::Value;
use std::sync::OnceLock;
pub(crate) type CombinedSemanticParser = fn(
code: &str,
meta: &ParseMetadata,
control: &ParseControl,
) -> ParseControlResult<CombinedSemanticParse>;
pub(crate) struct CombinedSemanticParse {
model: Result<Value>,
editor_facts: EditorSemanticFacts,
}
pub(crate) struct CombinedSemanticFailure {
error: Box<Error>,
editor_facts: Box<EditorSemanticFacts>,
recovery_parser: Option<&'static str>,
}
impl CombinedSemanticFailure {
pub(crate) fn new(error: Error, editor_facts: EditorSemanticFacts) -> Self {
Self {
error: Box::new(error),
editor_facts: Box::new(editor_facts),
recovery_parser: None,
}
}
pub(crate) fn parser_recovery(
parser: &'static str,
error: Error,
editor_facts: EditorSemanticFacts,
) -> Self {
Self {
error: Box::new(error),
editor_facts: Box::new(editor_facts),
recovery_parser: Some(parser),
}
}
pub(crate) fn replace_family_lexemes(&mut self, batch: crate::editor::EditorLexemeBatchResult) {
self.editor_facts.replace_family_lexemes(batch);
}
pub(crate) fn into_parts(mut self) -> (Error, EditorSemanticFacts) {
if let Some(parser) = self.recovery_parser.take() {
let (message, span) = match self.error.as_ref() {
Error::DiagramParse { diagnostic, .. } => {
(diagnostic.message().to_string(), diagnostic.span())
}
error => (error.to_string(), None),
};
self.editor_facts.mark_recovered_from_parse_error(
format!("{parser} parser recovered after parse error: {message}"),
span,
);
}
(*self.error, *self.editor_facts)
}
pub(crate) fn into_error(self) -> Error {
*self.error
}
}
#[cfg(test)]
mod combined_semantic_failure_tests {
use super::*;
use crate::{EditorSemanticDiagnosticKind, ParseDiagnosticSpanKind, SourceSpan};
#[test]
fn parser_recovery_preserves_the_strict_error_and_exact_editor_diagnostic() {
let span = SourceSpan::new(17, 29);
let failure = CombinedSemanticFailure::parser_recovery(
"quadrant chart",
Error::diagram_parse_exact("quadrantChart", "expected point coordinates", span),
EditorSemanticFacts::new(),
);
let (error, facts) = failure.into_parts();
let Error::DiagramParse {
diagram_type,
diagnostic,
} = error
else {
panic!("expected diagram parse error");
};
assert_eq!(diagram_type, "quadrantChart");
assert_eq!(diagnostic.message(), "expected point coordinates");
assert_eq!(diagnostic.span(), Some(span));
assert_eq!(diagnostic.span_kind(), ParseDiagnosticSpanKind::Exact);
assert_eq!(facts.diagnostics.len(), 1);
assert_eq!(
facts.diagnostics[0].message,
"quadrant chart parser recovered after parse error: expected point coordinates"
);
assert_eq!(facts.diagnostics[0].span, Some(span));
assert_eq!(
facts.diagnostics[0].kind,
EditorSemanticDiagnosticKind::ParserRecovery
);
}
}
impl CombinedSemanticParse {
pub(crate) fn from_construction<S, F>(
construction: std::result::Result<S, F>,
success: impl FnOnce(S) -> (Result<Value>, EditorSemanticFacts),
failure: impl FnOnce(F) -> (Error, EditorSemanticFacts),
) -> Self {
match construction {
Ok(source) => {
let (model, editor_facts) = success(source);
Self {
model,
editor_facts,
}
}
Err(parse_failure) => {
let (error, editor_facts) = failure(parse_failure);
Self {
model: Err(error),
editor_facts,
}
}
}
}
pub(crate) fn into_parts(self) -> (Result<Value>, EditorSemanticFacts) {
(self.model, self.editor_facts)
}
}
#[cfg(test)]
pub(crate) mod test_support {
use super::{CombinedSemanticParse, CombinedSemanticParser};
use crate::{EditorSemanticFacts, Error, ParseControl, ParseControlResult, ParseMetadata};
use serde_json::Value;
pub(crate) fn into_result(
parsed: ParseControlResult<CombinedSemanticParse>,
) -> std::result::Result<(Value, EditorSemanticFacts), Error> {
let (model, editor_facts) = parsed
.expect("a private parse control cannot be cancelled")
.into_parts();
model.map(|model| (model, editor_facts))
}
pub(crate) fn editor_facts(
parser: CombinedSemanticParser,
code: &str,
meta: &ParseMetadata,
) -> EditorSemanticFacts {
parser(code, meta, &ParseControl::new())
.expect("a private parse control cannot be cancelled")
.into_parts()
.1
}
}
#[derive(Clone, Copy)]
pub(crate) struct DetectorFact {
pub(crate) id: &'static str,
pub(crate) detector: DetectorFn,
}
#[derive(Clone, Copy)]
pub(crate) struct SemanticParserFact {
pub(crate) id: &'static str,
pub(crate) parser: BuiltInDiagramSemanticParser,
}
#[derive(Clone, Copy)]
pub(crate) struct RenderParserFact {
pub(crate) id: &'static str,
pub(crate) metadata_id: Option<&'static str>,
pub(crate) model_kind: &'static str,
pub(crate) parser: BuiltInRenderSemanticParser,
}
#[derive(Clone, Copy)]
pub(crate) struct CombinedParserFact {
pub(crate) id: &'static str,
pub(crate) parser: CombinedSemanticParser,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DiagramHeaderFact {
pub diagram_type: &'static str,
pub label: &'static str,
pub detail: &'static str,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[non_exhaustive]
pub struct DiagramFamilyCapability {
pub diagram_type: &'static str,
pub logical_family_kind: &'static str,
pub metadata_id: Option<&'static str>,
pub render_model_kind: Option<&'static str>,
pub has_detector: bool,
pub has_semantic_parser: bool,
pub has_editor_parser: bool,
pub has_combined_parser: bool,
pub has_render_parser: bool,
pub has_header: bool,
pub config_namespace: Option<&'static str>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)]
#[serde(transparent)]
pub struct DiagramFamilyId(&'static str);
impl DiagramFamilyId {
pub fn as_str(self) -> &'static str {
self.0
}
}
struct FamilyCatalogProjection {
detector_facts: Vec<DetectorFact>,
semantic_parser_facts: Vec<SemanticParserFact>,
render_parser_facts: Vec<RenderParserFact>,
combined_parser_facts: Vec<CombinedParserFact>,
supported_diagram_metadata_ids: Vec<&'static str>,
diagram_header_facts: Vec<DiagramHeaderFact>,
diagram_family_capabilities: Vec<DiagramFamilyCapability>,
}
impl FamilyCatalogProjection {
fn build() -> Self {
let mut detector_facts = Vec::<(u16, DetectorFact)>::new();
let mut semantic_parser_facts = Vec::<(u16, SemanticParserFact)>::new();
let mut render_parser_facts = Vec::<(u16, RenderParserFact)>::new();
let mut combined_parser_facts = Vec::<(u16, CombinedParserFact)>::new();
let mut metadata_facts = Vec::<(u16, &'static str)>::new();
let mut diagram_header_facts = Vec::<(u16, DiagramHeaderFact)>::new();
let mut diagram_family_capabilities = Vec::<(u16, DiagramFamilyCapability)>::new();
for (family, variant) in variants() {
if let Some(ordered) = variant.detector {
detector_facts.push((
ordered.order,
DetectorFact {
id: variant.id,
detector: ordered.value,
},
));
}
if let Some(ordered) = variant.semantic {
semantic_parser_facts.push((
ordered.order,
SemanticParserFact {
id: variant.id,
parser: ordered.value,
},
));
}
if let Some(ordered) = variant.typed_render {
render_parser_facts.push((
ordered.order,
RenderParserFact {
id: variant.id,
metadata_id: variant.metadata.map(|metadata| metadata.id),
model_kind: variant
.render_model_kind
.expect("typed render variants declare their model kind"),
parser: ordered.value,
},
));
}
if let Some(ordered) = variant.combined {
combined_parser_facts.push((
ordered.order,
CombinedParserFact {
id: variant.id,
parser: ordered.value,
},
));
}
if let Some((order, id)) = variant
.metadata
.and_then(|metadata| metadata.order.map(|order| (order, metadata.id)))
{
metadata_facts.push((order, id));
}
for header in variant.headers {
diagram_header_facts.push((
header.order,
DiagramHeaderFact {
diagram_type: variant.id,
label: header.label,
detail: header.detail,
},
));
}
diagram_family_capabilities.push((
variant.catalog_order,
DiagramFamilyCapability {
diagram_type: variant.id,
logical_family_kind: family.logical_kind,
metadata_id: variant.metadata.map(|metadata| metadata.id),
render_model_kind: variant.render_model_kind,
has_detector: variant.detector.is_some(),
has_semantic_parser: variant.semantic.is_some(),
has_editor_parser: variant.combined.is_some(),
has_combined_parser: variant.combined.is_some(),
has_render_parser: variant.typed_render.is_some(),
has_header: !variant.headers.is_empty(),
config_namespace: family.config.map(|config| config.namespace),
},
));
}
let detector_facts = ordered_values(detector_facts);
let semantic_parser_facts = ordered_values(semantic_parser_facts);
let render_parser_facts = ordered_values(render_parser_facts);
let combined_parser_facts = ordered_values(combined_parser_facts);
let metadata_facts = ordered_values(metadata_facts);
let diagram_header_facts = ordered_values(diagram_header_facts);
let diagram_family_capabilities = ordered_values(diagram_family_capabilities);
let supported_diagram_metadata_ids = metadata_facts
.into_iter()
.filter(|metadata_id| {
render_parser_facts
.iter()
.any(|fact| fact.metadata_id == Some(*metadata_id))
})
.collect();
Self {
detector_facts,
semantic_parser_facts,
render_parser_facts,
combined_parser_facts,
supported_diagram_metadata_ids,
diagram_header_facts,
diagram_family_capabilities,
}
}
}
fn ordered_values<T>(mut values: Vec<(u16, T)>) -> Vec<T> {
values.sort_by_key(|(order, _)| *order);
values.into_iter().map(|(_, value)| value).collect()
}
fn family_catalog_projection() -> &'static FamilyCatalogProjection {
static CATALOG: OnceLock<FamilyCatalogProjection> = OnceLock::new();
CATALOG.get_or_init(FamilyCatalogProjection::build)
}
pub(crate) fn detector_facts() -> &'static [DetectorFact] {
family_catalog_projection().detector_facts.as_slice()
}
pub(crate) fn semantic_parser_facts() -> &'static [SemanticParserFact] {
family_catalog_projection().semantic_parser_facts.as_slice()
}
pub(crate) fn render_parser_facts() -> &'static [RenderParserFact] {
family_catalog_projection().render_parser_facts.as_slice()
}
pub(crate) fn combined_parser_facts() -> &'static [CombinedParserFact] {
family_catalog_projection().combined_parser_facts.as_slice()
}
pub(crate) fn combined_parser(diagram_type: &str) -> Option<CombinedSemanticParser> {
combined_parser_facts()
.iter()
.find_map(|fact| (fact.id == diagram_type).then_some(fact.parser))
}
pub(crate) fn supported_diagram_metadata_ids() -> &'static [&'static str] {
family_catalog_projection()
.supported_diagram_metadata_ids
.as_slice()
}
pub(crate) fn diagram_header_facts() -> &'static [DiagramHeaderFact] {
family_catalog_projection().diagram_header_facts.as_slice()
}
pub(crate) fn diagram_family_capabilities() -> &'static [DiagramFamilyCapability] {
family_catalog_projection()
.diagram_family_capabilities
.as_slice()
}
pub(crate) fn is_builtin_diagram_type(diagram_type: &str) -> bool {
find_variant(diagram_type).is_some()
}
pub(crate) fn render_model_kind_supports_diagram_type(
model_kind: &'static str,
diagram_type: &str,
) -> bool {
render_parser_facts()
.iter()
.any(|fact| fact.id == diagram_type && fact.model_kind == model_kind)
}
pub fn diagram_type_family_kind(diagram_type: &str) -> Option<&'static str> {
diagram_type_family_id(diagram_type).map(DiagramFamilyId::as_str)
}
pub fn diagram_type_metadata_id(diagram_type: &str) -> Option<&'static str> {
find_variant(diagram_type).and_then(|(_, variant)| variant.metadata.map(|metadata| metadata.id))
}
pub(crate) fn diagram_type_family_id(diagram_type: &str) -> Option<DiagramFamilyId> {
find_variant(diagram_type).map(|(family, _)| DiagramFamilyId(family.logical_kind))
}
pub fn diagram_type_render_model_kind(diagram_type: &str) -> Option<&'static str> {
find_variant(diagram_type).and_then(|(_, variant)| variant.render_model_kind)
}
pub(crate) fn apply_diagram_type_config_effects(
diagram_type: &str,
user_config: &MermaidConfig,
effective_config: &mut MermaidConfig,
) {
let (effect, default_effect) = find_variant(diagram_type)
.map(|(_, variant)| (variant.known_type_effect, variant.default_effect))
.unwrap_or((KnownTypeEffect::None, DefaultEffect::None));
match effect {
KnownTypeEffect::None => {}
KnownTypeEffect::ForceElk => {
effective_config.set_value("layout", Value::String("elk".to_string()));
}
KnownTypeEffect::RendererSelectsElk(config_path) => {
if effective_config.get_str(config_path) == Some("elk") {
effective_config.set_value("layout", Value::String("elk".to_string()));
}
}
}
match default_effect {
DefaultEffect::None => {}
DefaultEffect::SwimlaneLayout if user_config.get_str("layout").is_none() => {
effective_config.set_value("layout", Value::String("swimlane".to_string()));
}
DefaultEffect::SwimlaneLayout => {}
}
}
macro_rules! render_parser {
($fn_name:ident, $parser:path, $variant:path) => {
fn $fn_name(code: &str, meta: &ParseMetadata) -> Result<RenderSemanticParseOutput> {
$parser(code, meta)
.map($variant)
.map(RenderSemanticParseOutput::new)
}
};
}
render_parser!(
render_error,
crate::diagrams::error_diagram::parse_error_model_for_render,
RenderSemanticModel::Error
);
render_parser!(
render_mindmap,
crate::diagrams::mindmap::parse_mindmap_model_for_render,
RenderSemanticModel::Mindmap
);
render_parser!(
render_state,
crate::diagrams::state::parse_state_model_for_render,
RenderSemanticModel::State
);
render_parser!(
render_zenuml,
crate::diagrams::zenuml::parse_zenuml_model_for_render,
RenderSemanticModel::Zenuml
);
render_parser!(
render_sequence,
crate::diagrams::sequence::parse_sequence_model_for_render,
RenderSemanticModel::Sequence
);
fn render_flowchart(code: &str, meta: &ParseMetadata) -> Result<RenderSemanticParseOutput> {
let (model, label_sources) =
crate::diagrams::flowchart::parse_flowchart_model_with_render_context(code, meta)?;
Ok(RenderSemanticParseOutput::flowchart(model, label_sources))
}
render_parser!(
render_class,
crate::diagrams::class::parse_class_typed,
RenderSemanticModel::Class
);
render_parser!(
render_c4,
crate::diagrams::c4::parse_c4_model_for_render,
RenderSemanticModel::C4
);
render_parser!(
render_cynefin,
crate::diagrams::cynefin::parse_cynefin_model_for_render,
RenderSemanticModel::Cynefin
);
render_parser!(
render_railroad,
crate::diagrams::railroad::parse_railroad_model_for_render,
RenderSemanticModel::Railroad
);
render_parser!(
render_railroad_ebnf,
crate::diagrams::railroad::parse_railroad_ebnf_model_for_render,
RenderSemanticModel::Railroad
);
render_parser!(
render_railroad_abnf,
crate::diagrams::railroad::parse_railroad_abnf_model_for_render,
RenderSemanticModel::Railroad
);
render_parser!(
render_railroad_peg,
crate::diagrams::railroad::parse_railroad_peg_model_for_render,
RenderSemanticModel::Railroad
);
render_parser!(
render_architecture,
crate::diagrams::architecture::parse_architecture_model_for_render,
RenderSemanticModel::Architecture
);
render_parser!(
render_kanban,
crate::diagrams::kanban::parse_kanban_model_for_render,
RenderSemanticModel::Kanban
);
render_parser!(
render_gantt,
crate::diagrams::gantt::parse_gantt_model_for_render,
RenderSemanticModel::Gantt
);
render_parser!(
render_pie,
crate::diagrams::pie::parse_pie_model_for_render,
RenderSemanticModel::Pie
);
render_parser!(
render_packet,
crate::diagrams::packet::parse_packet_model_for_render,
RenderSemanticModel::Packet
);
render_parser!(
render_timeline,
crate::diagrams::timeline::parse_timeline_model_for_render,
RenderSemanticModel::Timeline
);
render_parser!(
render_journey,
crate::diagrams::journey::parse_journey_model_for_render,
RenderSemanticModel::Journey
);
render_parser!(
render_requirement,
crate::diagrams::requirement::parse_requirement_model_for_render,
RenderSemanticModel::Requirement
);
render_parser!(
render_sankey,
crate::diagrams::sankey::parse_sankey_model_for_render,
RenderSemanticModel::Sankey
);
render_parser!(
render_radar,
crate::diagrams::radar::parse_radar_model_for_render,
RenderSemanticModel::Radar
);
render_parser!(
render_info,
crate::diagrams::info::parse_info_model_for_render,
RenderSemanticModel::Info
);
render_parser!(
render_treemap,
crate::diagrams::treemap::parse_treemap_model_for_render,
RenderSemanticModel::Treemap
);
render_parser!(
render_block,
crate::diagrams::block::parse_block_model_for_render,
RenderSemanticModel::Block
);
render_parser!(
render_er,
crate::diagrams::er::parse_er_model_for_render,
RenderSemanticModel::Er
);
render_parser!(
render_quadrant_chart,
crate::diagrams::quadrant_chart::parse_quadrant_chart_model_for_render,
RenderSemanticModel::QuadrantChart
);
render_parser!(
render_xychart,
crate::diagrams::xychart::parse_xychart_model_for_render,
RenderSemanticModel::XyChart
);
render_parser!(
render_git_graph,
crate::diagrams::git_graph::parse_git_graph_model_for_render,
RenderSemanticModel::GitGraph
);
render_parser!(
render_tree_view,
crate::diagrams::tree_view::parse_tree_view_model_for_render,
RenderSemanticModel::TreeView
);
render_parser!(
render_ishikawa,
crate::diagrams::ishikawa::parse_ishikawa_model_for_render,
RenderSemanticModel::Ishikawa
);
render_parser!(
render_eventmodeling,
crate::diagrams::eventmodeling::parse_eventmodeling_model_for_render,
RenderSemanticModel::EventModeling
);
render_parser!(
render_venn,
crate::diagrams::venn::parse_venn_model_for_render,
RenderSemanticModel::Venn
);
render_parser!(
render_wardley,
crate::diagrams::wardley::parse_wardley_model_for_render,
RenderSemanticModel::Wardley
);
#[derive(Clone, Copy)]
struct Ordered<T> {
order: u16,
value: T,
}
const fn ordered<T>(order: u16, value: T) -> Ordered<T> {
Ordered { order, value }
}
#[derive(Clone, Copy)]
struct MetadataDefinition {
id: &'static str,
order: Option<u16>,
}
const fn metadata(id: &'static str, order: Option<u16>) -> MetadataDefinition {
MetadataDefinition { id, order }
}
#[derive(Clone, Copy)]
struct HeaderDefinition {
order: u16,
label: &'static str,
detail: &'static str,
}
const fn header(order: u16, label: &'static str, detail: &'static str) -> HeaderDefinition {
HeaderDefinition {
order,
label,
detail,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum KnownTypeEffect {
None,
ForceElk,
RendererSelectsElk(&'static str),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DefaultEffect {
None,
SwimlaneLayout,
}
#[derive(Clone, Copy)]
struct FamilyVariantDefinition {
id: &'static str,
catalog_order: u16,
detector: Option<Ordered<DetectorFn>>,
semantic: Option<Ordered<BuiltInDiagramSemanticParser>>,
combined: Option<Ordered<CombinedSemanticParser>>,
typed_render: Option<Ordered<BuiltInRenderSemanticParser>>,
render_model_kind: Option<&'static str>,
metadata: Option<MetadataDefinition>,
headers: &'static [HeaderDefinition],
frontmatter_alias_order: Option<u16>,
known_type_effect: KnownTypeEffect,
default_effect: DefaultEffect,
}
#[derive(Clone, Copy)]
struct FamilyConfigDefinition {
namespace: &'static str,
frontmatter_order: u16,
}
#[derive(Clone, Copy)]
struct DiagramFamilyDefinition {
logical_kind: &'static str,
config: Option<FamilyConfigDefinition>,
variants: &'static [FamilyVariantDefinition],
}
macro_rules! variant {
(
id: $id:literal,
catalog_order: $catalog_order:literal,
detector: $detector:expr,
semantic: $semantic:expr,
combined: $combined:expr,
typed: $typed:expr,
render_kind: $render_kind:expr,
metadata: $metadata:expr,
headers: $headers:expr,
config_alias_order: $config_alias_order:expr,
known_effect: $known_effect:expr,
default_effect: $default_effect:expr $(,)?
) => {
FamilyVariantDefinition {
id: $id,
catalog_order: $catalog_order,
detector: $detector,
semantic: $semantic,
combined: $combined,
typed_render: $typed,
render_model_kind: $render_kind,
metadata: $metadata,
headers: $headers,
frontmatter_alias_order: $config_alias_order,
known_type_effect: $known_effect,
default_effect: $default_effect,
}
};
}
fn variants() -> impl Iterator<
Item = (
&'static DiagramFamilyDefinition,
&'static FamilyVariantDefinition,
),
> {
FAMILY_CATALOG
.iter()
.flat_map(|family| family.variants.iter().map(move |variant| (family, variant)))
}
fn find_variant(
diagram_type: &str,
) -> Option<(
&'static DiagramFamilyDefinition,
&'static FamilyVariantDefinition,
)> {
FAMILY_CATALOG.iter().find_map(|family| {
family
.variants
.iter()
.find(|variant| variant.id == diagram_type)
.map(|variant| (family, variant))
})
}
#[derive(Clone, Copy)]
pub(crate) struct FrontmatterConfigAliasFact {
pub(crate) source: &'static str,
pub(crate) namespace: &'static str,
}
pub(crate) fn frontmatter_config_aliases() -> &'static [FrontmatterConfigAliasFact] {
static FACTS: OnceLock<Vec<FrontmatterConfigAliasFact>> = OnceLock::new();
FACTS
.get_or_init(|| {
let mut facts: Vec<_> = FAMILY_CATALOG
.iter()
.flat_map(|family| {
family.variants.iter().filter_map(move |variant| {
variant.frontmatter_alias_order.map(|order| {
let namespace = family
.config
.expect("config aliases require a family namespace")
.namespace;
(
order,
FrontmatterConfigAliasFact {
source: variant.id,
namespace,
},
)
})
})
})
.collect();
facts.sort_by_key(|(order, _)| *order);
facts.into_iter().map(|(_, fact)| fact).collect()
})
.as_slice()
}
pub(crate) fn frontmatter_config_namespaces() -> &'static [&'static str] {
static NAMESPACES: OnceLock<Vec<&'static str>> = OnceLock::new();
NAMESPACES
.get_or_init(|| {
let mut namespaces: Vec<_> = FAMILY_CATALOG
.iter()
.filter_map(|family| {
family
.config
.map(|config| (config.frontmatter_order, config.namespace))
})
.collect();
namespaces.sort_by_key(|(order, _)| *order);
namespaces
.into_iter()
.map(|(_, namespace)| namespace)
.collect()
})
.as_slice()
}
pub(crate) fn config_namespace_for_diagram_type(diagram_type: &str) -> Option<&'static str> {
find_variant(diagram_type).and_then(|(family, _)| family.config.map(|config| config.namespace))
}
const FLOWCHART_HEADERS: &[HeaderDefinition] = &[
header(0, "flowchart TD", "flowchart header"),
header(1, "graph TD", "flowchart alias"),
];
const SEQUENCE_HEADERS: &[HeaderDefinition] = &[header(2, "sequenceDiagram", "sequence header")];
const SWIMLANE_HEADERS: &[HeaderDefinition] = &[header(3, "swimlane-beta", "swimlane header")];
const CLASS_HEADERS: &[HeaderDefinition] = &[
header(4, "classDiagram", "class header"),
header(5, "classDiagram-v2", "class header"),
];
const STATE_HEADERS: &[HeaderDefinition] = &[
header(6, "stateDiagram-v2", "state header"),
header(7, "stateDiagram", "legacy state header"),
];
const ER_HEADERS: &[HeaderDefinition] = &[header(8, "erDiagram", "er header")];
const GANTT_HEADERS: &[HeaderDefinition] = &[header(9, "gantt", "gantt header")];
const MINDMAP_HEADERS: &[HeaderDefinition] = &[header(10, "mindmap", "mindmap header")];
const INFO_HEADERS: &[HeaderDefinition] = &[header(11, "info", "info header")];
const JOURNEY_HEADERS: &[HeaderDefinition] = &[header(12, "journey", "journey header")];
const TIMELINE_HEADERS: &[HeaderDefinition] = &[header(13, "timeline", "timeline header")];
const GIT_GRAPH_HEADERS: &[HeaderDefinition] = &[header(14, "gitGraph", "git graph header")];
const PIE_HEADERS: &[HeaderDefinition] = &[header(15, "pie", "pie header")];
const REQUIREMENT_HEADERS: &[HeaderDefinition] =
&[header(16, "requirementDiagram", "requirement header")];
const SANKEY_HEADERS: &[HeaderDefinition] = &[header(17, "sankey", "sankey header")];
const PACKET_HEADERS: &[HeaderDefinition] = &[
header(18, "packet", "packet header"),
header(19, "packet-beta", "packet beta header"),
];
const XYCHART_HEADERS: &[HeaderDefinition] = &[
header(20, "xychart", "xychart header"),
header(21, "xychart-beta", "xychart beta header"),
];
const TREE_VIEW_HEADERS: &[HeaderDefinition] = &[header(22, "treeView-beta", "tree view header")];
const ISHIKAWA_HEADERS: &[HeaderDefinition] = &[header(23, "ishikawa-beta", "ishikawa header")];
const EVENTMODELING_HEADERS: &[HeaderDefinition] =
&[header(24, "eventmodeling", "event modeling header")];
const QUADRANT_HEADERS: &[HeaderDefinition] =
&[header(25, "quadrantChart", "quadrant chart header")];
const VENN_HEADERS: &[HeaderDefinition] = &[header(26, "venn-beta", "venn header")];
const ZENUML_HEADERS: &[HeaderDefinition] = &[header(27, "zenuml", "zenuml header")];
const C4_HEADERS: &[HeaderDefinition] = &[
header(28, "C4Context", "c4 context header"),
header(29, "C4Container", "c4 container header"),
header(30, "C4Component", "c4 component header"),
header(31, "C4Dynamic", "c4 dynamic header"),
header(32, "C4Deployment", "c4 deployment header"),
];
const KANBAN_HEADERS: &[HeaderDefinition] = &[header(33, "kanban", "kanban header")];
const ARCHITECTURE_HEADERS: &[HeaderDefinition] =
&[header(34, "architecture-beta", "architecture header")];
const BLOCK_HEADERS: &[HeaderDefinition] = &[header(35, "block-beta", "block header")];
const RADAR_HEADERS: &[HeaderDefinition] = &[header(36, "radar-beta", "radar header")];
const TREEMAP_HEADERS: &[HeaderDefinition] = &[header(37, "treemap-beta", "treemap header")];
const RAILROAD_HEADERS: &[HeaderDefinition] = &[header(38, "railroad-beta", "railroad header")];
const RAILROAD_EBNF_HEADERS: &[HeaderDefinition] =
&[header(39, "railroad-ebnf-beta", "railroad ebnf header")];
const RAILROAD_ABNF_HEADERS: &[HeaderDefinition] =
&[header(40, "railroad-abnf-beta", "railroad abnf header")];
const RAILROAD_PEG_HEADERS: &[HeaderDefinition] =
&[header(41, "railroad-peg-beta", "railroad peg header")];
const WARDLEY_HEADERS: &[HeaderDefinition] = &[header(42, "wardley-beta", "wardley header")];
const CYNEFIN_HEADERS: &[HeaderDefinition] = &[header(43, "cynefin-beta", "cynefin header")];
const FLOWCHART_ELK_HEADERS: &[HeaderDefinition] =
&[header(44, "flowchart-elk TD", "elk flowchart header")];
const ERROR_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "error",
catalog_order: 0,
detector: Some(ordered(0, crate::detect::detector_error)),
semantic: Some(ordered(0, crate::diagrams::error_diagram::parse_error)),
combined: None,
typed: Some(ordered(38, render_error)),
render_kind: Some("error"),
metadata: None,
headers: &[],
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const FLOWCHART_VARIANTS: &[FamilyVariantDefinition] = &[
variant! {
id: "flowchart-elk",
catalog_order: 2,
detector: Some(ordered(2, crate::detect::detector_flowchart_elk)),
semantic: Some(ordered(3, crate::diagrams::flowchart::parse_flowchart)),
combined: Some(ordered(2, crate::diagrams::flowchart::parse_flowchart_json_and_editor_facts)),
typed: Some(ordered(7, render_flowchart)),
render_kind: Some("flowchart"),
metadata: Some(metadata("flowchart", None)),
headers: FLOWCHART_ELK_HEADERS,
config_alias_order: Some(3),
known_effect: KnownTypeEffect::ForceElk,
default_effect: DefaultEffect::None,
},
variant! {
id: "flowchart-v2",
catalog_order: 17,
detector: Some(ordered(17, crate::detect::detector_flowchart_v2)),
semantic: Some(ordered(1, crate::diagrams::flowchart::parse_flowchart)),
combined: Some(ordered(0, crate::diagrams::flowchart::parse_flowchart_json_and_editor_facts)),
typed: Some(ordered(5, render_flowchart)),
render_kind: Some("flowchart"),
metadata: Some(metadata("flowchart", Some(7))),
headers: FLOWCHART_HEADERS,
config_alias_order: Some(2),
known_effect: KnownTypeEffect::RendererSelectsElk("flowchart.defaultRenderer"),
default_effect: DefaultEffect::None,
},
variant! {
id: "flowchart",
catalog_order: 18,
detector: Some(ordered(18, crate::detect::detector_flowchart_dagre_d3_graph)),
semantic: Some(ordered(2, crate::diagrams::flowchart::parse_flowchart)),
combined: Some(ordered(1, crate::diagrams::flowchart::parse_flowchart_json_and_editor_facts)),
typed: Some(ordered(6, render_flowchart)),
render_kind: Some("flowchart"),
metadata: Some(metadata("flowchart", None)),
headers: &[],
config_alias_order: None,
known_effect: KnownTypeEffect::RendererSelectsElk("flowchart.defaultRenderer"),
default_effect: DefaultEffect::None,
},
];
const SWIMLANE_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "swimlane",
catalog_order: 16,
detector: Some(ordered(16, crate::detect::detector_swimlane)),
semantic: Some(ordered(9, crate::diagrams::flowchart::parse_flowchart)),
combined: Some(ordered(3, crate::diagrams::flowchart::parse_flowchart_json_and_editor_facts)),
typed: Some(ordered(39, render_flowchart)),
render_kind: Some("flowchart"),
metadata: Some(metadata("swimlane", Some(27))),
headers: SWIMLANE_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::SwimlaneLayout,
}];
const MINDMAP_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "mindmap",
catalog_order: 3,
detector: Some(ordered(3, crate::detect::detector_mindmap)),
semantic: Some(ordered(22, crate::diagrams::mindmap::parse_mindmap)),
combined: Some(ordered(5, crate::diagrams::mindmap::parse_mindmap_json_and_editor_facts)),
typed: Some(ordered(0, render_mindmap)),
render_kind: Some("mindmap"),
metadata: Some(metadata("mindmap", Some(14))),
headers: MINDMAP_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const ARCHITECTURE_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "architecture",
catalog_order: 4,
detector: Some(ordered(4, crate::detect::detector_architecture)),
semantic: Some(ordered(27, crate::diagrams::architecture::parse_architecture)),
combined: Some(ordered(4, crate::diagrams::architecture::parse_architecture_json_and_editor_facts)),
typed: Some(ordered(16, render_architecture)),
render_kind: Some("architecture"),
metadata: Some(metadata("architecture", Some(0))),
headers: ARCHITECTURE_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const ZENUML_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "zenuml",
catalog_order: 5,
detector: Some(ordered(5, crate::detect::detector_zenuml)),
semantic: Some(ordered(15, crate::diagrams::zenuml::parse_zenuml)),
combined: Some(ordered(36, crate::diagrams::zenuml::parse_zenuml_json_and_editor_facts)),
typed: Some(ordered(3, render_zenuml)),
render_kind: Some("zenuml"),
metadata: Some(metadata("zenuml", Some(34))),
headers: ZENUML_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const SEQUENCE_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "sequence",
catalog_order: 15,
detector: Some(ordered(15, crate::detect::detector_sequence)),
semantic: Some(ordered(8, crate::diagrams::sequence::parse_sequence)),
combined: Some(ordered(19, crate::diagrams::sequence::parse_sequence_json_and_editor_facts)),
typed: Some(ordered(4, render_sequence)),
render_kind: Some("sequence"),
metadata: Some(metadata("sequence", Some(25))),
headers: SEQUENCE_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const C4_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "c4",
catalog_order: 6,
detector: Some(ordered(6, crate::detect::detector_c4)),
semantic: Some(ordered(6, crate::diagrams::c4::parse_c4)),
combined: Some(ordered(28, crate::diagrams::c4::parse_c4_json_and_editor_facts)),
typed: Some(ordered(10, render_c4)),
render_kind: Some("c4"),
metadata: Some(metadata("c4", Some(2))),
headers: C4_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const KANBAN_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "kanban",
catalog_order: 7,
detector: Some(ordered(7, crate::detect::detector_kanban)),
semantic: Some(ordered(26, crate::diagrams::kanban::parse_kanban)),
combined: Some(ordered(29, crate::diagrams::kanban::parse_kanban_json_and_editor_facts)),
typed: Some(ordered(17, render_kanban)),
render_kind: Some("kanban"),
metadata: Some(metadata("kanban", Some(13))),
headers: KANBAN_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const CLASS_VARIANTS: &[FamilyVariantDefinition] = &[
variant! {
id: "classDiagram",
catalog_order: 8,
detector: Some(ordered(8, crate::detect::detector_class_v2)),
semantic: Some(ordered(16, crate::diagrams::class::parse_class)),
combined: Some(ordered(20, crate::diagrams::class::parse_class_json_and_editor_facts)),
typed: Some(ordered(8, render_class)),
render_kind: Some("class"),
metadata: Some(metadata("class", Some(3))),
headers: CLASS_HEADERS,
config_alias_order: Some(0),
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "class",
catalog_order: 9,
detector: Some(ordered(9, crate::detect::detector_class_dagre_d3)),
semantic: Some(ordered(17, crate::diagrams::class::parse_class)),
combined: Some(ordered(21, crate::diagrams::class::parse_class_json_and_editor_facts)),
typed: Some(ordered(9, render_class)),
render_kind: Some("class"),
metadata: Some(metadata("class", None)),
headers: &[],
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
];
const ER_VARIANTS: &[FamilyVariantDefinition] = &[
variant! {
id: "er",
catalog_order: 10,
detector: Some(ordered(10, crate::detect::detector_er)),
semantic: Some(ordered(18, crate::diagrams::er::parse_er)),
combined: Some(ordered(17, crate::diagrams::er::parse_er_json_and_editor_facts)),
typed: Some(ordered(29, render_er)),
render_kind: Some("er"),
metadata: Some(metadata("er", Some(5))),
headers: ER_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "erDiagram",
catalog_order: 41,
detector: None,
semantic: Some(ordered(19, crate::diagrams::er::parse_er)),
combined: Some(ordered(18, crate::diagrams::er::parse_er_json_and_editor_facts)),
typed: Some(ordered(30, render_er)),
render_kind: Some("er"),
metadata: Some(metadata("er", None)),
headers: &[],
config_alias_order: Some(1),
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
];
const GANTT_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "gantt",
catalog_order: 11,
detector: Some(ordered(11, crate::detect::detector_gantt)),
semantic: Some(ordered(23, crate::diagrams::gantt::parse_gantt)),
combined: Some(ordered(30, crate::diagrams::gantt::parse_gantt_json_and_editor_facts)),
typed: Some(ordered(18, render_gantt)),
render_kind: Some("gantt"),
metadata: Some(metadata("gantt", Some(8))),
headers: GANTT_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const INFO_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "info",
catalog_order: 12,
detector: Some(ordered(12, crate::detect::detector_info)),
semantic: Some(ordered(4, crate::diagrams::info::parse_info)),
combined: Some(ordered(10, crate::diagrams::info::parse_info_json_and_editor_facts)),
typed: Some(ordered(26, render_info)),
render_kind: Some("info"),
metadata: Some(metadata("info", Some(10))),
headers: INFO_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const PIE_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "pie",
catalog_order: 13,
detector: Some(ordered(13, crate::detect::detector_pie)),
semantic: Some(ordered(5, crate::diagrams::pie::parse_pie)),
combined: Some(ordered(11, crate::diagrams::pie::parse_pie_json_and_editor_facts)),
typed: Some(ordered(19, render_pie)),
render_kind: Some("pie"),
metadata: Some(metadata("pie", Some(16))),
headers: PIE_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const REQUIREMENT_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "requirement",
catalog_order: 14,
detector: Some(ordered(14, crate::detect::detector_requirement)),
semantic: Some(ordered(7, crate::diagrams::requirement::parse_requirement)),
combined: Some(ordered(31, crate::diagrams::requirement::parse_requirement_json_and_editor_facts)),
typed: Some(ordered(23, render_requirement)),
render_kind: Some("requirement"),
metadata: Some(metadata("requirement", Some(23))),
headers: REQUIREMENT_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const TIMELINE_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "timeline",
catalog_order: 19,
detector: Some(ordered(19, crate::detect::detector_timeline)),
semantic: Some(ordered(24, crate::diagrams::timeline::parse_timeline)),
combined: Some(ordered(32, crate::diagrams::timeline::parse_timeline_json_and_editor_facts)),
typed: Some(ordered(21, render_timeline)),
render_kind: Some("timeline"),
metadata: Some(metadata("timeline", Some(28))),
headers: TIMELINE_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const GIT_GRAPH_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "gitGraph",
catalog_order: 20,
detector: Some(ordered(20, crate::detect::detector_git_graph)),
semantic: Some(ordered(29, crate::diagrams::git_graph::parse_git_graph)),
combined: Some(ordered(15, crate::diagrams::git_graph::parse_git_graph_json_and_editor_facts)),
typed: Some(ordered(33, render_git_graph)),
render_kind: Some("gitGraph"),
metadata: Some(metadata("gitgraph", Some(9))),
headers: GIT_GRAPH_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const STATE_VARIANTS: &[FamilyVariantDefinition] = &[
variant! {
id: "stateDiagram",
catalog_order: 21,
detector: Some(ordered(21, crate::detect::detector_state_v2)),
semantic: Some(ordered(20, crate::diagrams::state::parse_state)),
combined: Some(ordered(26, crate::diagrams::state::parse_state_json_and_editor_facts)),
typed: Some(ordered(1, render_state)),
render_kind: Some("state"),
metadata: Some(metadata("state", Some(26))),
headers: STATE_HEADERS,
config_alias_order: Some(4),
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "state",
catalog_order: 22,
detector: Some(ordered(22, crate::detect::detector_state_dagre_d3)),
semantic: Some(ordered(21, crate::diagrams::state::parse_state)),
combined: Some(ordered(27, crate::diagrams::state::parse_state_json_and_editor_facts)),
typed: Some(ordered(2, render_state)),
render_kind: Some("state"),
metadata: Some(metadata("state", None)),
headers: &[],
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
];
const JOURNEY_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "journey",
catalog_order: 23,
detector: Some(ordered(23, crate::detect::detector_journey)),
semantic: Some(ordered(25, crate::diagrams::journey::parse_journey)),
combined: Some(ordered(33, crate::diagrams::journey::parse_journey_json_and_editor_facts)),
typed: Some(ordered(22, render_journey)),
render_kind: Some("journey"),
metadata: Some(metadata("journey", Some(12))),
headers: JOURNEY_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const QUADRANT_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "quadrantChart",
catalog_order: 24,
detector: Some(ordered(24, crate::detect::detector_quadrant)),
semantic: Some(ordered(30, crate::diagrams::quadrant_chart::parse_quadrant_chart)),
combined: Some(ordered(34, crate::diagrams::quadrant_chart::parse_quadrant_chart_json_and_editor_facts)),
typed: Some(ordered(31, render_quadrant_chart)),
render_kind: Some("quadrantChart"),
metadata: Some(metadata("quadrantchart", Some(17))),
headers: QUADRANT_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const SANKEY_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "sankey",
catalog_order: 25,
detector: Some(ordered(25, crate::detect::detector_sankey)),
semantic: Some(ordered(38, crate::diagrams::sankey::parse_sankey)),
combined: Some(ordered(16, crate::diagrams::sankey::parse_sankey_json_and_editor_facts)),
typed: Some(ordered(24, render_sankey)),
render_kind: Some("sankey"),
metadata: Some(metadata("sankey", Some(24))),
headers: SANKEY_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const PACKET_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "packet",
catalog_order: 26,
detector: Some(ordered(26, crate::detect::detector_packet)),
semantic: Some(ordered(31, crate::diagrams::packet::parse_packet)),
combined: Some(ordered(12, crate::diagrams::packet::parse_packet_json_and_editor_facts)),
typed: Some(ordered(20, render_packet)),
render_kind: Some("packet"),
metadata: Some(metadata("packet", Some(15))),
headers: PACKET_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const XYCHART_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "xychart",
catalog_order: 27,
detector: Some(ordered(27, crate::detect::detector_xychart)),
semantic: Some(ordered(39, crate::diagrams::xychart::parse_xychart)),
combined: Some(ordered(38, crate::diagrams::xychart::parse_xychart_json_and_editor_facts)),
typed: Some(ordered(32, render_xychart)),
render_kind: Some("xychart"),
metadata: Some(metadata("xychart", Some(33))),
headers: XYCHART_HEADERS,
config_alias_order: Some(5),
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const BLOCK_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "block",
catalog_order: 28,
detector: Some(ordered(28, crate::detect::detector_block)),
semantic: Some(ordered(28, crate::diagrams::block::parse_block)),
combined: Some(ordered(37, crate::diagrams::block::parse_block_json_and_editor_facts)),
typed: Some(ordered(28, render_block)),
render_kind: Some("block"),
metadata: Some(metadata("block", Some(1))),
headers: BLOCK_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const EVENTMODELING_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "eventmodeling",
catalog_order: 29,
detector: Some(ordered(29, crate::detect::detector_eventmodeling)),
semantic: Some(ordered(35, crate::diagrams::eventmodeling::parse_eventmodeling)),
combined: Some(ordered(22, crate::diagrams::eventmodeling::parse_eventmodeling_json_and_editor_facts)),
typed: Some(ordered(36, render_eventmodeling)),
render_kind: Some("eventmodeling"),
metadata: Some(metadata("eventmodeling", Some(6))),
headers: EVENTMODELING_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const TREE_VIEW_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "treeView",
catalog_order: 30,
detector: Some(ordered(30, crate::detect::detector_tree_view)),
semantic: Some(ordered(33, crate::diagrams::tree_view::parse_tree_view)),
combined: Some(ordered(23, crate::diagrams::tree_view::parse_tree_view_json_and_editor_facts)),
typed: Some(ordered(34, render_tree_view)),
render_kind: Some("treeView"),
metadata: Some(metadata("treeView", Some(29))),
headers: TREE_VIEW_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const RADAR_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "radar",
catalog_order: 31,
detector: Some(ordered(31, crate::detect::detector_radar)),
semantic: Some(ordered(32, crate::diagrams::radar::parse_radar)),
combined: Some(ordered(14, crate::diagrams::radar::parse_radar_json_and_editor_facts)),
typed: Some(ordered(25, render_radar)),
render_kind: Some("radar"),
metadata: Some(metadata("radar", Some(18))),
headers: RADAR_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const ISHIKAWA_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "ishikawa",
catalog_order: 32,
detector: Some(ordered(32, crate::detect::detector_ishikawa)),
semantic: Some(ordered(34, crate::diagrams::ishikawa::parse_ishikawa)),
combined: Some(ordered(24, crate::diagrams::ishikawa::parse_ishikawa_json_and_editor_facts)),
typed: Some(ordered(35, render_ishikawa)),
render_kind: Some("ishikawa"),
metadata: Some(metadata("ishikawa", Some(11))),
headers: ISHIKAWA_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const TREEMAP_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "treemap",
catalog_order: 33,
detector: Some(ordered(33, crate::detect::detector_treemap)),
semantic: Some(ordered(36, crate::diagrams::treemap::parse_treemap)),
combined: Some(ordered(25, crate::diagrams::treemap::parse_treemap_json_and_editor_facts)),
typed: Some(ordered(27, render_treemap)),
render_kind: Some("treemap"),
metadata: Some(metadata("treemap", Some(30))),
headers: TREEMAP_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const RAILROAD_VARIANTS: &[FamilyVariantDefinition] = &[
variant! {
id: "railroad",
catalog_order: 34,
detector: Some(ordered(34, crate::detect::detector_railroad)),
semantic: Some(ordered(11, crate::diagrams::railroad::parse_railroad)),
combined: Some(ordered(6, crate::diagrams::railroad::parse_railroad_json_and_editor_facts)),
typed: Some(ordered(12, render_railroad)),
render_kind: Some("railroad"),
metadata: Some(metadata("railroad", Some(19))),
headers: RAILROAD_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "railroadEbnf",
catalog_order: 35,
detector: Some(ordered(35, crate::detect::detector_railroad_ebnf)),
semantic: Some(ordered(12, crate::diagrams::railroad::parse_railroad_ebnf)),
combined: Some(ordered(7, crate::diagrams::railroad::parse_railroad_ebnf_json_and_editor_facts)),
typed: Some(ordered(13, render_railroad_ebnf)),
render_kind: Some("railroad"),
metadata: Some(metadata("railroadEbnf", Some(21))),
headers: RAILROAD_EBNF_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "railroadAbnf",
catalog_order: 36,
detector: Some(ordered(36, crate::detect::detector_railroad_abnf)),
semantic: Some(ordered(13, crate::diagrams::railroad::parse_railroad_abnf)),
combined: Some(ordered(8, crate::diagrams::railroad::parse_railroad_abnf_json_and_editor_facts)),
typed: Some(ordered(14, render_railroad_abnf)),
render_kind: Some("railroad"),
metadata: Some(metadata("railroadAbnf", Some(20))),
headers: RAILROAD_ABNF_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
variant! {
id: "railroadPeg",
catalog_order: 37,
detector: Some(ordered(37, crate::detect::detector_railroad_peg)),
semantic: Some(ordered(14, crate::diagrams::railroad::parse_railroad_peg)),
combined: Some(ordered(9, crate::diagrams::railroad::parse_railroad_peg_json_and_editor_facts)),
typed: Some(ordered(15, render_railroad_peg)),
render_kind: Some("railroad"),
metadata: Some(metadata("railroadPeg", Some(22))),
headers: RAILROAD_PEG_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
},
];
const VENN_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "venn",
catalog_order: 38,
detector: Some(ordered(38, crate::detect::detector_venn)),
semantic: Some(ordered(37, crate::diagrams::venn::parse_venn)),
combined: Some(ordered(35, crate::diagrams::venn::parse_venn_json_and_editor_facts)),
typed: Some(ordered(37, render_venn)),
render_kind: Some("venn"),
metadata: Some(metadata("venn", Some(31))),
headers: VENN_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const WARDLEY_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "wardley",
catalog_order: 39,
detector: Some(ordered(39, crate::detect::detector_wardley)),
semantic: Some(ordered(40, crate::diagrams::wardley::parse_wardley)),
combined: Some(ordered(39, crate::diagrams::wardley::parse_wardley_json_and_editor_facts)),
typed: Some(ordered(40, render_wardley)),
render_kind: Some("wardley"),
metadata: Some(metadata("wardley", Some(32))),
headers: WARDLEY_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const CYNEFIN_VARIANTS: &[FamilyVariantDefinition] = &[variant! {
id: "cynefin",
catalog_order: 40,
detector: Some(ordered(40, crate::detect::detector_cynefin)),
semantic: Some(ordered(10, crate::diagrams::cynefin::parse_cynefin)),
combined: Some(ordered(13, crate::diagrams::cynefin::parse_cynefin_json_and_editor_facts)),
typed: Some(ordered(11, render_cynefin)),
render_kind: Some("cynefin"),
metadata: Some(metadata("cynefin", Some(4))),
headers: CYNEFIN_HEADERS,
config_alias_order: None,
known_effect: KnownTypeEffect::None,
default_effect: DefaultEffect::None,
}];
const FAMILY_CATALOG: &[DiagramFamilyDefinition] = &[
DiagramFamilyDefinition {
logical_kind: "error",
config: None,
variants: ERROR_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "flowchart",
config: Some(FamilyConfigDefinition {
namespace: "flowchart",
frontmatter_order: 7,
}),
variants: FLOWCHART_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "swimlane",
config: Some(FamilyConfigDefinition {
namespace: "swimlane",
frontmatter_order: 23,
}),
variants: SWIMLANE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "mindmap",
config: Some(FamilyConfigDefinition {
namespace: "mindmap",
frontmatter_order: 13,
}),
variants: MINDMAP_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "architecture",
config: Some(FamilyConfigDefinition {
namespace: "architecture",
frontmatter_order: 0,
}),
variants: ARCHITECTURE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "zenuml",
config: Some(FamilyConfigDefinition {
namespace: "zenuml",
frontmatter_order: 30,
}),
variants: ZENUML_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "sequence",
config: Some(FamilyConfigDefinition {
namespace: "sequence",
frontmatter_order: 21,
}),
variants: SEQUENCE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "c4",
config: Some(FamilyConfigDefinition {
namespace: "c4",
frontmatter_order: 2,
}),
variants: C4_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "kanban",
config: Some(FamilyConfigDefinition {
namespace: "kanban",
frontmatter_order: 12,
}),
variants: KANBAN_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "class",
config: Some(FamilyConfigDefinition {
namespace: "class",
frontmatter_order: 3,
}),
variants: CLASS_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "er",
config: Some(FamilyConfigDefinition {
namespace: "er",
frontmatter_order: 5,
}),
variants: ER_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "gantt",
config: Some(FamilyConfigDefinition {
namespace: "gantt",
frontmatter_order: 8,
}),
variants: GANTT_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "info",
config: None,
variants: INFO_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "pie",
config: Some(FamilyConfigDefinition {
namespace: "pie",
frontmatter_order: 15,
}),
variants: PIE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "requirement",
config: Some(FamilyConfigDefinition {
namespace: "requirement",
frontmatter_order: 19,
}),
variants: REQUIREMENT_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "timeline",
config: Some(FamilyConfigDefinition {
namespace: "timeline",
frontmatter_order: 24,
}),
variants: TIMELINE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "gitGraph",
config: Some(FamilyConfigDefinition {
namespace: "gitGraph",
frontmatter_order: 9,
}),
variants: GIT_GRAPH_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "state",
config: Some(FamilyConfigDefinition {
namespace: "state",
frontmatter_order: 22,
}),
variants: STATE_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "journey",
config: Some(FamilyConfigDefinition {
namespace: "journey",
frontmatter_order: 11,
}),
variants: JOURNEY_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "quadrantChart",
config: Some(FamilyConfigDefinition {
namespace: "quadrantChart",
frontmatter_order: 16,
}),
variants: QUADRANT_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "sankey",
config: Some(FamilyConfigDefinition {
namespace: "sankey",
frontmatter_order: 20,
}),
variants: SANKEY_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "packet",
config: Some(FamilyConfigDefinition {
namespace: "packet",
frontmatter_order: 14,
}),
variants: PACKET_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "xychart",
config: Some(FamilyConfigDefinition {
namespace: "xyChart",
frontmatter_order: 29,
}),
variants: XYCHART_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "block",
config: Some(FamilyConfigDefinition {
namespace: "block",
frontmatter_order: 1,
}),
variants: BLOCK_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "eventmodeling",
config: Some(FamilyConfigDefinition {
namespace: "eventmodeling",
frontmatter_order: 6,
}),
variants: EVENTMODELING_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "treeView",
config: Some(FamilyConfigDefinition {
namespace: "treeView",
frontmatter_order: 25,
}),
variants: TREE_VIEW_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "radar",
config: Some(FamilyConfigDefinition {
namespace: "radar",
frontmatter_order: 17,
}),
variants: RADAR_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "ishikawa",
config: Some(FamilyConfigDefinition {
namespace: "ishikawa",
frontmatter_order: 10,
}),
variants: ISHIKAWA_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "treemap",
config: Some(FamilyConfigDefinition {
namespace: "treemap",
frontmatter_order: 26,
}),
variants: TREEMAP_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "railroad",
config: Some(FamilyConfigDefinition {
namespace: "railroad",
frontmatter_order: 18,
}),
variants: RAILROAD_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "venn",
config: Some(FamilyConfigDefinition {
namespace: "venn",
frontmatter_order: 27,
}),
variants: VENN_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "wardley",
config: Some(FamilyConfigDefinition {
namespace: "wardley-beta",
frontmatter_order: 28,
}),
variants: WARDLEY_VARIANTS,
},
DiagramFamilyDefinition {
logical_kind: "cynefin",
config: Some(FamilyConfigDefinition {
namespace: "cynefin",
frontmatter_order: 4,
}),
variants: CYNEFIN_VARIANTS,
},
];
#[cfg(test)]
mod catalog_tests {
use super::*;
use std::collections::BTreeSet;
#[test]
fn public_metadata_ids_are_catalog_owned_instead_of_derived_from_family_names() {
assert_eq!(diagram_type_metadata_id("flowchart-v2"), Some("flowchart"));
assert_eq!(diagram_type_metadata_id("gitGraph"), Some("gitgraph"));
assert_eq!(
diagram_type_metadata_id("quadrantChart"),
Some("quadrantchart")
);
assert_eq!(diagram_type_metadata_id("treeView"), Some("treeView"));
}
#[test]
fn catalog_ids_orders_and_family_policy_are_internally_consistent() {
let mut ids = BTreeSet::new();
let mut catalog_orders = BTreeSet::new();
let mut detector_orders = BTreeSet::new();
let mut semantic_orders = BTreeSet::new();
let mut combined_orders = BTreeSet::new();
let mut render_orders = BTreeSet::new();
let mut metadata_orders = BTreeSet::new();
let mut header_orders = BTreeSet::new();
for family in FAMILY_CATALOG {
for variant in family.variants {
assert_ne!(variant.id, "---", "frontmatter guard is not a family");
assert!(
ids.insert(variant.id),
"duplicate catalog id {}",
variant.id
);
assert!(
catalog_orders.insert(variant.catalog_order),
"duplicate catalog order {}",
variant.catalog_order
);
assert_eq!(
variant.typed_render.is_some(),
variant.render_model_kind.is_some(),
"{} typed parser and render kind must be declared together",
variant.id
);
assert!(
variant.metadata.is_none() || variant.typed_render.is_some(),
"{} metadata requires a typed render parser",
variant.id
);
assert!(
variant.combined.is_none() || variant.semantic.is_some(),
"{} combined parsing requires a semantic adapter",
variant.id
);
if let Some(fact) = variant.detector {
assert!(detector_orders.insert(fact.order));
}
if let Some(fact) = variant.semantic {
assert!(semantic_orders.insert(fact.order));
}
if let Some(fact) = variant.combined {
assert!(combined_orders.insert(fact.order));
}
if let Some(fact) = variant.typed_render {
assert!(render_orders.insert(fact.order));
}
if let Some(order) = variant.metadata.and_then(|metadata| metadata.order) {
assert!(metadata_orders.insert(order));
}
for fact in variant.headers {
assert!(header_orders.insert(fact.order));
}
}
}
let config_orders = FAMILY_CATALOG
.iter()
.filter_map(|family| family.config.map(|config| config.frontmatter_order))
.collect::<BTreeSet<_>>();
let config_count = FAMILY_CATALOG
.iter()
.filter(|family| family.config.is_some())
.count();
assert_eq!(config_orders.len(), config_count);
assert_eq!(ids.len(), diagram_family_capabilities().len());
}
}