///|
/// Multi-kind entry points preserve the sequence-only API.
pub(all) enum ParsedDiagram {
Sequence(@ast.Diagram)
Swimlane(@swimlane_ast.Diagram)
} derive(Eq, Debug)
///|
pub(all) enum DiagramTree {
Sequence(@cst.Node)
Swimlane(@swimlane_cst.Node)
Unsupported(String)
} derive(Eq, Debug)
///|
pub fn DiagramTree::text(self : DiagramTree) -> String {
match self {
Sequence(tree) => tree.text()
Swimlane(tree) => tree.text()
Unsupported(source) => source
}
}
///|
pub struct DiagramReadResult {
tree : DiagramTree
ast : ParsedDiagram?
diagnostics : ReadOnlyArray[@diagrams.Diagnostic]
} derive(Eq, Debug)
///|
pub struct DiagramPrintResult {
output : String?
diagnostics : ReadOnlyArray[@diagrams.Diagnostic]
} derive(Eq, Debug)
///|
pub fn read_diagram(
source : String,
limits~ : @swimlane_syntax.Limits = @swimlane_syntax.Limits::new(),
) -> DiagramReadResult {
if source.length() > limits.source {
return {
tree: Unsupported(source),
ast: None,
diagnostics: [
@diagrams.Diagnostic::error(
"swimlane/source-limit", "Source limit exceeded",
),
],
}
}
let mut front = false
let mut directive = false
for line in source.split("\n") {
let mut text = @swimlane_syntax.trim_space(line.to_owned())
if !directive {
if text == "---" {
front = !front
continue
}
if front || text.is_empty() {
continue
}
}
// A directive consumes only through its closing delimiter. Keep scanning
// the suffix, which may contain another directive or the diagram header.
let mut remainder = text[:]
while directive || remainder.has_prefix("%%{") {
directive = true
guard remainder.find("}%%") is Some(close) else { break }
directive = false
remainder = remainder[close + 3:]
let mut whitespace = 0
while whitespace < remainder.length() &&
@swimlane_syntax.is_space(remainder.at(whitespace).to_int()) {
whitespace += 1
}
remainder = remainder[whitespace:]
}
if directive {
continue
}
text = remainder.to_owned()
if text.is_empty() {
continue
}
if text.has_prefix("%%") {
continue
}
if text.has_prefix("swimlane-beta") &&
(
text.length() == 13 ||
@swimlane_syntax.is_space(text.at(13).to_int()) ||
text.at(13).to_int() == 59
) {
let result = @swimlane_syntax.read(source, limits~)
return {
tree: Swimlane(result.tree),
ast: result.ast.map(ast => Swimlane(ast)),
diagnostics: result.diagnostics,
}
}
if text.has_prefix("sequenceDiagram") {
let result = read(source)
return {
tree: Sequence(result.tree),
ast: result.ast.map(ast => Sequence(ast)),
diagnostics: result.diagnostics,
}
}
break
}
{
tree: Unsupported(source),
ast: None,
diagnostics: [
@diagrams.Diagnostic::error(
"mermaid/unsupported-diagram", "Expected sequenceDiagram or swimlane-beta",
),
],
}
}
///|
pub fn print_diagram(
diagram : ParsedDiagram,
limits~ : @swimlane_syntax.Limits = @swimlane_syntax.Limits::new(),
) -> DiagramPrintResult {
match diagram {
Sequence(ast) => {
let output = print(ast)
if output.length() > limits.output {
{
output: None,
diagnostics: [
@diagrams.Diagnostic::error(
"mermaid/print-limit", "Output limit exceeded",
),
],
}
} else {
{ output: Some(output), diagnostics: [], }
}
}
Swimlane(ast) => {
let result = @swimlane_printer.print(ast, limits~)
{ output: result.output, diagnostics: result.diagnostics, }
}
}
}
///|
pub fn to_swimlane(
diagram : @swimlane_ast.Diagram,
limits~ : @swimlane_syntax.Limits = @swimlane_syntax.Limits::new(),
id~ : String = "swimlane",
) -> @swimlane_conversion.Conversion {
@swimlane_conversion.to_swimlane(diagram, limits~, id~)
}
///|
pub extend ParsedDiagram with Eq::{equal, not_equal}
///|
pub extend ParsedDiagram with @debug.Debug::{to_repr}
///|
pub extend DiagramTree with Eq::{equal, not_equal}
///|
pub extend DiagramTree with @debug.Debug::{to_repr}
///|
pub extend DiagramReadResult with Eq::{equal, not_equal}
///|
pub extend DiagramReadResult with @debug.Debug::{to_repr}
///|
pub extend DiagramPrintResult with Eq::{equal, not_equal}
///|
pub extend DiagramPrintResult with @debug.Debug::{to_repr}
///|
/// Existing sequence-only inventories retain their original meaning.
pub let swimlane_diagnostic_codes : ReadOnlyArray[String] = @swimlane_syntax.diagnostic_codes
///|
pub let swimlane_conversion_diagnostic_codes : ReadOnlyArray[String] = @swimlane_conversion.diagnostic_codes