etassia 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +140 -0
- data/LICENSE +25 -0
- data/README.adoc +436 -0
- data/exe/etassia +7 -0
- data/lib/etassia/cli.rb +187 -0
- data/lib/etassia/commands/batch.rb +210 -0
- data/lib/etassia/commands/notation_loader.rb +22 -0
- data/lib/etassia/commands/render.rb +98 -0
- data/lib/etassia/commands/types.rb +33 -0
- data/lib/etassia/commands/version.rb +24 -0
- data/lib/etassia/corpus_type_names.rb +52 -0
- data/lib/etassia/diagram/architecture.rb +108 -0
- data/lib/etassia/diagram/base.rb +61 -0
- data/lib/etassia/diagram/block.rb +102 -0
- data/lib/etassia/diagram/c4.rb +337 -0
- data/lib/etassia/diagram/class_diagram.rb +466 -0
- data/lib/etassia/diagram/class_namespace.rb +17 -0
- data/lib/etassia/diagram/class_note.rb +17 -0
- data/lib/etassia/diagram/containment.rb +107 -0
- data/lib/etassia/diagram/er_diagram.rb +317 -0
- data/lib/etassia/diagram/error.rb +38 -0
- data/lib/etassia/diagram/flowchart.rb +419 -0
- data/lib/etassia/diagram/flowchart_label_text.rb +63 -0
- data/lib/etassia/diagram/gantt.rb +94 -0
- data/lib/etassia/diagram/generic_text.rb +30 -0
- data/lib/etassia/diagram/git_graph.rb +57 -0
- data/lib/etassia/diagram/info.rb +38 -0
- data/lib/etassia/diagram/kanban.rb +198 -0
- data/lib/etassia/diagram/mindmap.rb +71 -0
- data/lib/etassia/diagram/packet.rb +93 -0
- data/lib/etassia/diagram/pie.rb +115 -0
- data/lib/etassia/diagram/quadrant.rb +135 -0
- data/lib/etassia/diagram/radar.rb +65 -0
- data/lib/etassia/diagram/requirement.rb +168 -0
- data/lib/etassia/diagram/sankey.rb +217 -0
- data/lib/etassia/diagram/sequence.rb +299 -0
- data/lib/etassia/diagram/sequence_box.rb +18 -0
- data/lib/etassia/diagram/sequence_frame.rb +37 -0
- data/lib/etassia/diagram/sequence_frame_section.rb +23 -0
- data/lib/etassia/diagram/sequence_text.rb +69 -0
- data/lib/etassia/diagram/sequence_wrap.rb +23 -0
- data/lib/etassia/diagram/state_diagram.rb +282 -0
- data/lib/etassia/diagram/timeline.rb +183 -0
- data/lib/etassia/diagram/treemap.rb +95 -0
- data/lib/etassia/diagram/user_journey.rb +153 -0
- data/lib/etassia/diagram/xy_chart.rb +90 -0
- data/lib/etassia/diagram.rb +8 -0
- data/lib/etassia/diagram_registry.rb +34 -0
- data/lib/etassia/engine.rb +334 -0
- data/lib/etassia/error/diagram_type_error.rb +10 -0
- data/lib/etassia/error/layout_error.rb +12 -0
- data/lib/etassia/error/notation_registration_error.rb +10 -0
- data/lib/etassia/error/parse_error.rb +11 -0
- data/lib/etassia/error/pipeline_error.rb +10 -0
- data/lib/etassia/error/render_error.rb +12 -0
- data/lib/etassia/error/score_error.rb +12 -0
- data/lib/etassia/error.rb +10 -0
- data/lib/etassia/error_report.rb +69 -0
- data/lib/etassia/ir/data.rb +39 -0
- data/lib/etassia/ir/data_value.rb +35 -0
- data/lib/etassia/ir/dimension.rb +10 -0
- data/lib/etassia/ir/edge.rb +34 -0
- data/lib/etassia/ir/graph.rb +28 -0
- data/lib/etassia/ir/integrity.rb +80 -0
- data/lib/etassia/ir/item.rb +46 -0
- data/lib/etassia/ir/model.rb +56 -0
- data/lib/etassia/ir/node.rb +10 -0
- data/lib/etassia/ir/placement.rb +47 -0
- data/lib/etassia/ir/prepositioned.rb +25 -0
- data/lib/etassia/ir/prepositioned_item.rb +26 -0
- data/lib/etassia/ir/property_set.rb +43 -0
- data/lib/etassia/ir/scalar.rb +25 -0
- data/lib/etassia/ir/series.rb +10 -0
- data/lib/etassia/ir.rb +17 -0
- data/lib/etassia/js_math.rb +511 -0
- data/lib/etassia/js_number.rb +64 -0
- data/lib/etassia/layout/architecture.rb +1472 -0
- data/lib/etassia/layout/base.rb +276 -0
- data/lib/etassia/layout/block.rb +738 -0
- data/lib/etassia/layout/c4.rb +876 -0
- data/lib/etassia/layout/c4_boundary_metrics.rb +35 -0
- data/lib/etassia/layout/c4_bounds.rb +106 -0
- data/lib/etassia/layout/c4_intersection.rb +77 -0
- data/lib/etassia/layout/c4_placement.rb +135 -0
- data/lib/etassia/layout/c4_shape_metrics.rb +97 -0
- data/lib/etassia/layout/c4_shape_outline.rb +67 -0
- data/lib/etassia/layout/c4_stereotype.rb +30 -0
- data/lib/etassia/layout/c4_text.rb +54 -0
- data/lib/etassia/layout/class_cell_placement.rb +148 -0
- data/lib/etassia/layout/class_diagram.rb +1116 -0
- data/lib/etassia/layout/class_diagram_namespaces.rb +26 -0
- data/lib/etassia/layout/class_diagram_notes.rb +26 -0
- data/lib/etassia/layout/class_name_advances.rb +31 -0
- data/lib/etassia/layout/class_namespace_box.rb +21 -0
- data/lib/etassia/layout/class_namespace_nodes.rb +197 -0
- data/lib/etassia/layout/class_namespace_placement.rb +71 -0
- data/lib/etassia/layout/class_note.rb +44 -0
- data/lib/etassia/layout/class_note_nodes.rb +84 -0
- data/lib/etassia/layout/elk_notices.rb +48 -0
- data/lib/etassia/layout/elk_placement.rb +197 -0
- data/lib/etassia/layout/er_diagram.rb +1002 -0
- data/lib/etassia/layout/er_diagram_adjacency.rb +20 -0
- data/lib/etassia/layout/er_diagram_alignment.rb +72 -0
- data/lib/etassia/layout/er_diagram_compaction.rb +85 -0
- data/lib/etassia/layout/er_diagram_conflicts.rb +70 -0
- data/lib/etassia/layout/er_diagram_coordinates.rb +104 -0
- data/lib/etassia/layout/er_diagram_entity_size.rb +82 -0
- data/lib/etassia/layout/er_diagram_layering.rb +109 -0
- data/lib/etassia/layout/er_diagram_ordering.rb +143 -0
- data/lib/etassia/layout/er_diagram_placement.rb +163 -0
- data/lib/etassia/layout/er_diagram_placement_node.rb +22 -0
- data/lib/etassia/layout/error.rb +133 -0
- data/lib/etassia/layout/flowchart/brandes_koepf.rb +208 -0
- data/lib/etassia/layout/flowchart/cluster_reach.rb +70 -0
- data/lib/etassia/layout/flowchart/component_packing.rb +129 -0
- data/lib/etassia/layout/flowchart/directed_placement.rb +428 -0
- data/lib/etassia/layout/flowchart/edge_chains.rb +111 -0
- data/lib/etassia/layout/flowchart/edge_order.rb +34 -0
- data/lib/etassia/layout/flowchart/edge_router.rb +533 -0
- data/lib/etassia/layout/flowchart/label_backdrop_geometry.rb +62 -0
- data/lib/etassia/layout/flowchart/layer_spacing.rb +85 -0
- data/lib/etassia/layout/flowchart/level_edges.rb +74 -0
- data/lib/etassia/layout/flowchart/level_frame.rb +47 -0
- data/lib/etassia/layout/flowchart/minimum_rank_spacing.rb +74 -0
- data/lib/etassia/layout/flowchart/row_centering.rb +229 -0
- data/lib/etassia/layout/flowchart.rb +1290 -0
- data/lib/etassia/layout/gantt.rb +814 -0
- data/lib/etassia/layout/gantt_duration.rb +49 -0
- data/lib/etassia/layout/gantt_exclusions.rb +74 -0
- data/lib/etassia/layout/gantt_ticks.rb +165 -0
- data/lib/etassia/layout/git_graph.rb +1075 -0
- data/lib/etassia/layout/grid.rb +165 -0
- data/lib/etassia/layout/info.rb +113 -0
- data/lib/etassia/layout/kanban.rb +452 -0
- data/lib/etassia/layout/kanban_card_text.rb +95 -0
- data/lib/etassia/layout/mindmap.rb +425 -0
- data/lib/etassia/layout/mindmap_cose.rb +81 -0
- data/lib/etassia/layout/mindmap_cose_body.rb +93 -0
- data/lib/etassia/layout/mindmap_cose_geometry.rb +190 -0
- data/lib/etassia/layout/mindmap_cose_grid.rb +96 -0
- data/lib/etassia/layout/mindmap_cose_link.rb +42 -0
- data/lib/etassia/layout/mindmap_cose_relaxation.rb +166 -0
- data/lib/etassia/layout/mindmap_cose_seed.rb +93 -0
- data/lib/etassia/layout/mindmap_cose_wedge.rb +37 -0
- data/lib/etassia/layout/mindmap_node_size.rb +130 -0
- data/lib/etassia/layout/packet.rb +285 -0
- data/lib/etassia/layout/pie.rb +305 -0
- data/lib/etassia/layout/pie_legend.rb +64 -0
- data/lib/etassia/layout/pie_legend_entry.rb +21 -0
- data/lib/etassia/layout/quadrant.rb +402 -0
- data/lib/etassia/layout/radar.rb +442 -0
- data/lib/etassia/layout/requirement.rb +765 -0
- data/lib/etassia/layout/sankey.rb +501 -0
- data/lib/etassia/layout/scene.rb +18 -0
- data/lib/etassia/layout/sequence/actor_gaps.rb +151 -0
- data/lib/etassia/layout/sequence/box_shape.rb +23 -0
- data/lib/etassia/layout/sequence/creations.rb +73 -0
- data/lib/etassia/layout/sequence/frame_divider.rb +22 -0
- data/lib/etassia/layout/sequence/frame_placement.rb +424 -0
- data/lib/etassia/layout/sequence/frame_reader.rb +75 -0
- data/lib/etassia/layout/sequence/frame_shape.rb +45 -0
- data/lib/etassia/layout/sequence/geometry.rb +24 -0
- data/lib/etassia/layout/sequence/message_rows.rb +165 -0
- data/lib/etassia/layout/sequence/note.rb +16 -0
- data/lib/etassia/layout/sequence/note_box.rb +114 -0
- data/lib/etassia/layout/sequence/note_placement.rb +223 -0
- data/lib/etassia/layout/sequence/text_width.rb +69 -0
- data/lib/etassia/layout/sequence/text_wrap.rb +93 -0
- data/lib/etassia/layout/sequence.rb +936 -0
- data/lib/etassia/layout/state_diagram.rb +1277 -0
- data/lib/etassia/layout/timeline.rb +165 -0
- data/lib/etassia/layout/timeline_card.rb +142 -0
- data/lib/etassia/layout/timeline_flow.rb +164 -0
- data/lib/etassia/layout/timeline_line.rb +33 -0
- data/lib/etassia/layout/timeline_rounding.rb +19 -0
- data/lib/etassia/layout/timeline_text.rb +105 -0
- data/lib/etassia/layout/treemap.rb +303 -0
- data/lib/etassia/layout/treemap_placement.rb +52 -0
- data/lib/etassia/layout/treemap_squarify.rb +108 -0
- data/lib/etassia/layout/user_journey.rb +300 -0
- data/lib/etassia/layout/user_journey_face.rb +33 -0
- data/lib/etassia/layout/user_journey_face_geometry.rb +80 -0
- data/lib/etassia/layout/user_journey_geometry.rb +336 -0
- data/lib/etassia/layout/user_journey_legend.rb +84 -0
- data/lib/etassia/layout/xy_chart.rb +620 -0
- data/lib/etassia/layout.rb +19 -0
- data/lib/etassia/lint_debt_scoreboard.rb +219 -0
- data/lib/etassia/markdown_text/emphasis_simulator.rb +373 -0
- data/lib/etassia/markdown_text.rb +393 -0
- data/lib/etassia/notation/builtin.rb +39 -0
- data/lib/etassia/notation/entry.rb +15 -0
- data/lib/etassia/notation/mermaid/class_diagram_config.rb +42 -0
- data/lib/etassia/notation/mermaid/git_graph_config.rb +46 -0
- data/lib/etassia/notation/mermaid/ir_adapter.rb +27 -0
- data/lib/etassia/notation/mermaid/ir_adapters/architecture.rb +196 -0
- data/lib/etassia/notation/mermaid/ir_adapters/block.rb +138 -0
- data/lib/etassia/notation/mermaid/ir_adapters/c4.rb +258 -0
- data/lib/etassia/notation/mermaid/ir_adapters/class_diagram.rb +257 -0
- data/lib/etassia/notation/mermaid/ir_adapters/er_diagram.rb +220 -0
- data/lib/etassia/notation/mermaid/ir_adapters/error.rb +32 -0
- data/lib/etassia/notation/mermaid/ir_adapters/flowchart.rb +208 -0
- data/lib/etassia/notation/mermaid/ir_adapters/gantt.rb +236 -0
- data/lib/etassia/notation/mermaid/ir_adapters/git_graph.rb +186 -0
- data/lib/etassia/notation/mermaid/ir_adapters/info.rb +34 -0
- data/lib/etassia/notation/mermaid/ir_adapters/kanban.rb +110 -0
- data/lib/etassia/notation/mermaid/ir_adapters/mindmap.rb +76 -0
- data/lib/etassia/notation/mermaid/ir_adapters/packet.rb +51 -0
- data/lib/etassia/notation/mermaid/ir_adapters/pie.rb +71 -0
- data/lib/etassia/notation/mermaid/ir_adapters/quadrant.rb +116 -0
- data/lib/etassia/notation/mermaid/ir_adapters/radar.rb +142 -0
- data/lib/etassia/notation/mermaid/ir_adapters/requirement.rb +237 -0
- data/lib/etassia/notation/mermaid/ir_adapters/sankey.rb +74 -0
- data/lib/etassia/notation/mermaid/ir_adapters/sequence.rb +304 -0
- data/lib/etassia/notation/mermaid/ir_adapters/state_diagram.rb +225 -0
- data/lib/etassia/notation/mermaid/ir_adapters/timeline.rb +93 -0
- data/lib/etassia/notation/mermaid/ir_adapters/treemap.rb +143 -0
- data/lib/etassia/notation/mermaid/ir_adapters/user_journey.rb +127 -0
- data/lib/etassia/notation/mermaid/ir_adapters/xychart.rb +131 -0
- data/lib/etassia/notation/mermaid.rb +399 -0
- data/lib/etassia/notation/parsed.rb +31 -0
- data/lib/etassia/notation/plantuml/activity/arrow_head.rb +45 -0
- data/lib/etassia/notation/plantuml/activity/arrow_style.rb +53 -0
- data/lib/etassia/notation/plantuml/activity/bar_columns.rb +75 -0
- data/lib/etassia/notation/plantuml/activity/box.rb +60 -0
- data/lib/etassia/notation/plantuml/activity/builder.rb +77 -0
- data/lib/etassia/notation/plantuml/activity/canvas.rb +117 -0
- data/lib/etassia/notation/plantuml/activity/column_centres.rb +151 -0
- data/lib/etassia/notation/plantuml/activity/columns.rb +224 -0
- data/lib/etassia/notation/plantuml/activity/diagram.rb +35 -0
- data/lib/etassia/notation/plantuml/activity/edge.rb +35 -0
- data/lib/etassia/notation/plantuml/activity/edge_marks.rb +68 -0
- data/lib/etassia/notation/plantuml/activity/exits.rb +61 -0
- data/lib/etassia/notation/plantuml/activity/frame_marks.rb +116 -0
- data/lib/etassia/notation/plantuml/activity/lane_steps.rb +82 -0
- data/lib/etassia/notation/plantuml/activity/lane_titles.rb +46 -0
- data/lib/etassia/notation/plantuml/activity/layout.rb +50 -0
- data/lib/etassia/notation/plantuml/activity/legacy_parser.rb +181 -0
- data/lib/etassia/notation/plantuml/activity/legacy_row_gaps.rb +65 -0
- data/lib/etassia/notation/plantuml/activity/mark.rb +23 -0
- data/lib/etassia/notation/plantuml/activity/marks.rb +62 -0
- data/lib/etassia/notation/plantuml/activity/metrics.rb +169 -0
- data/lib/etassia/notation/plantuml/activity/new_parser/blocks.rb +166 -0
- data/lib/etassia/notation/plantuml/activity/new_parser.rb +177 -0
- data/lib/etassia/notation/plantuml/activity/node.rb +50 -0
- data/lib/etassia/notation/plantuml/activity/node_marks.rb +174 -0
- data/lib/etassia/notation/plantuml/activity/note.rb +27 -0
- data/lib/etassia/notation/plantuml/activity/parser.rb +51 -0
- data/lib/etassia/notation/plantuml/activity/placement.rb +327 -0
- data/lib/etassia/notation/plantuml/activity/ranking.rb +142 -0
- data/lib/etassia/notation/plantuml/activity/reach.rb +58 -0
- data/lib/etassia/notation/plantuml/activity/renderer.rb +220 -0
- data/lib/etassia/notation/plantuml/activity/route.rb +22 -0
- data/lib/etassia/notation/plantuml/activity/router.rb +308 -0
- data/lib/etassia/notation/plantuml/activity/row_gaps.rb +105 -0
- data/lib/etassia/notation/plantuml/activity/row_spread.rb +59 -0
- data/lib/etassia/notation/plantuml/activity/scene.rb +20 -0
- data/lib/etassia/notation/plantuml/activity/text.rb +36 -0
- data/lib/etassia/notation/plantuml/activity.rb +50 -0
- data/lib/etassia/notation/plantuml/arrow.rb +135 -0
- data/lib/etassia/notation/plantuml/caption.rb +50 -0
- data/lib/etassia/notation/plantuml/caption_layout.rb +97 -0
- data/lib/etassia/notation/plantuml/caption_rows.rb +67 -0
- data/lib/etassia/notation/plantuml/class_header.rb +178 -0
- data/lib/etassia/notation/plantuml/class_name.rb +51 -0
- data/lib/etassia/notation/plantuml/component.rb +37 -0
- data/lib/etassia/notation/plantuml/creole.rb +278 -0
- data/lib/etassia/notation/plantuml/creole_icons.rb +33 -0
- data/lib/etassia/notation/plantuml/diagram.rb +60 -0
- data/lib/etassia/notation/plantuml/diagram_builder.rb +442 -0
- data/lib/etassia/notation/plantuml/diagram_name.rb +51 -0
- data/lib/etassia/notation/plantuml/directives.rb +33 -0
- data/lib/etassia/notation/plantuml/drawing/box.rb +28 -0
- data/lib/etassia/notation/plantuml/drawing/face.rb +39 -0
- data/lib/etassia/notation/plantuml/drawing/pen.rb +105 -0
- data/lib/etassia/notation/plantuml/drawing/renderer.rb +36 -0
- data/lib/etassia/notation/plantuml/drawing/scene.rb +28 -0
- data/lib/etassia/notation/plantuml/drawing.rb +19 -0
- data/lib/etassia/notation/plantuml/ebnf/blocks.rb +272 -0
- data/lib/etassia/notation/plantuml/ebnf/layout.rb +117 -0
- data/lib/etassia/notation/plantuml/ebnf/model.rb +22 -0
- data/lib/etassia/notation/plantuml/ebnf/reader.rb +131 -0
- data/lib/etassia/notation/plantuml/ebnf.rb +34 -0
- data/lib/etassia/notation/plantuml/end_texts.rb +78 -0
- data/lib/etassia/notation/plantuml/entity.rb +54 -0
- data/lib/etassia/notation/plantuml/further.rb +38 -0
- data/lib/etassia/notation/plantuml/gantt/layout.rb +269 -0
- data/lib/etassia/notation/plantuml/gantt/reader.rb +210 -0
- data/lib/etassia/notation/plantuml/gantt/renderer.rb +81 -0
- data/lib/etassia/notation/plantuml/gantt.rb +34 -0
- data/lib/etassia/notation/plantuml/include/blocks.rb +66 -0
- data/lib/etassia/notation/plantuml/include/finder.rb +61 -0
- data/lib/etassia/notation/plantuml/include.rb +78 -0
- data/lib/etassia/notation/plantuml/ir_adapter/annotations.rb +40 -0
- data/lib/etassia/notation/plantuml/ir_adapter/links.rb +91 -0
- data/lib/etassia/notation/plantuml/ir_adapter/sink.rb +49 -0
- data/lib/etassia/notation/plantuml/ir_adapter/structure.rb +86 -0
- data/lib/etassia/notation/plantuml/ir_adapter.rb +32 -0
- data/lib/etassia/notation/plantuml/ir_reader/annotations.rb +51 -0
- data/lib/etassia/notation/plantuml/ir_reader/index.rb +49 -0
- data/lib/etassia/notation/plantuml/ir_reader/links.rb +133 -0
- data/lib/etassia/notation/plantuml/ir_reader/structure.rb +83 -0
- data/lib/etassia/notation/plantuml/ir_reader.rb +42 -0
- data/lib/etassia/notation/plantuml/junction.rb +20 -0
- data/lib/etassia/notation/plantuml/klass.rb +41 -0
- data/lib/etassia/notation/plantuml/label_clearance.rb +67 -0
- data/lib/etassia/notation/plantuml/layout.rb +2806 -0
- data/lib/etassia/notation/plantuml/member.rb +37 -0
- data/lib/etassia/notation/plantuml/member_icon.rb +87 -0
- data/lib/etassia/notation/plantuml/member_icon_elements.rb +91 -0
- data/lib/etassia/notation/plantuml/member_pitch.rb +76 -0
- data/lib/etassia/notation/plantuml/member_rule.rb +48 -0
- data/lib/etassia/notation/plantuml/network/grid.rb +170 -0
- data/lib/etassia/notation/plantuml/network/layout.rb +158 -0
- data/lib/etassia/notation/plantuml/network/model.rb +22 -0
- data/lib/etassia/notation/plantuml/network/placement.rb +64 -0
- data/lib/etassia/notation/plantuml/network/reader.rb +126 -0
- data/lib/etassia/notation/plantuml/network/shapes.rb +109 -0
- data/lib/etassia/notation/plantuml/network.rb +37 -0
- data/lib/etassia/notation/plantuml/node_graph/archimate.rb +49 -0
- data/lib/etassia/notation/plantuml/node_graph/box_reader.rb +86 -0
- data/lib/etassia/notation/plantuml/node_graph/cloud.rb +73 -0
- data/lib/etassia/notation/plantuml/node_graph/crows_foot.rb +85 -0
- data/lib/etassia/notation/plantuml/node_graph/curve.rb +66 -0
- data/lib/etassia/notation/plantuml/node_graph/data_reader.rb +77 -0
- data/lib/etassia/notation/plantuml/node_graph/data_shape.rb +39 -0
- data/lib/etassia/notation/plantuml/node_graph/detour.rb +98 -0
- data/lib/etassia/notation/plantuml/node_graph/edge.rb +26 -0
- data/lib/etassia/notation/plantuml/node_graph/entity_metrics.rb +49 -0
- data/lib/etassia/notation/plantuml/node_graph/entity_reader.rb +65 -0
- data/lib/etassia/notation/plantuml/node_graph/entity_shape.rb +111 -0
- data/lib/etassia/notation/plantuml/node_graph/figures.rb +92 -0
- data/lib/etassia/notation/plantuml/node_graph/frame_ports.rb +73 -0
- data/lib/etassia/notation/plantuml/node_graph/graph.rb +40 -0
- data/lib/etassia/notation/plantuml/node_graph/heads.rb +89 -0
- data/lib/etassia/notation/plantuml/node_graph/label_fan.rb +76 -0
- data/lib/etassia/notation/plantuml/node_graph/label_placer.rb +310 -0
- data/lib/etassia/notation/plantuml/node_graph/label_waypoint.rb +47 -0
- data/lib/etassia/notation/plantuml/node_graph/layout.rb +293 -0
- data/lib/etassia/notation/plantuml/node_graph/link.rb +78 -0
- data/lib/etassia/notation/plantuml/node_graph/macros.rb +39 -0
- data/lib/etassia/notation/plantuml/node_graph/metrics.rb +113 -0
- data/lib/etassia/notation/plantuml/node_graph/node.rb +44 -0
- data/lib/etassia/notation/plantuml/node_graph/note_tail.rb +58 -0
- data/lib/etassia/notation/plantuml/node_graph/packer.rb +126 -0
- data/lib/etassia/notation/plantuml/node_graph/parser.rb +309 -0
- data/lib/etassia/notation/plantuml/node_graph/paths.rb +48 -0
- data/lib/etassia/notation/plantuml/node_graph/ranking.rb +231 -0
- data/lib/etassia/notation/plantuml/node_graph/reader.rb +53 -0
- data/lib/etassia/notation/plantuml/node_graph/references.rb +38 -0
- data/lib/etassia/notation/plantuml/node_graph/renderer.rb +160 -0
- data/lib/etassia/notation/plantuml/node_graph/scene.rb +22 -0
- data/lib/etassia/notation/plantuml/node_graph/shapes.rb +302 -0
- data/lib/etassia/notation/plantuml/node_graph/skipped_ranks.rb +61 -0
- data/lib/etassia/notation/plantuml/node_graph/tab.rb +68 -0
- data/lib/etassia/notation/plantuml/node_graph/usecase_ellipse.rb +100 -0
- data/lib/etassia/notation/plantuml/node_graph.rb +38 -0
- data/lib/etassia/notation/plantuml/note.rb +27 -0
- data/lib/etassia/notation/plantuml/note_layout.rb +257 -0
- data/lib/etassia/notation/plantuml/note_outline.rb +68 -0
- data/lib/etassia/notation/plantuml/objects/map_rows.rb +46 -0
- data/lib/etassia/notation/plantuml/objects/reader.rb +208 -0
- data/lib/etassia/notation/plantuml/objects.rb +39 -0
- data/lib/etassia/notation/plantuml/package.rb +45 -0
- data/lib/etassia/notation/plantuml/package_color.rb +32 -0
- data/lib/etassia/notation/plantuml/package_frames.rb +178 -0
- data/lib/etassia/notation/plantuml/parser.rb +622 -0
- data/lib/etassia/notation/plantuml/portion_visibility.rb +91 -0
- data/lib/etassia/notation/plantuml/qualified_association_layout.rb +332 -0
- data/lib/etassia/notation/plantuml/qualifier_box.rb +78 -0
- data/lib/etassia/notation/plantuml/rank_chain.rb +527 -0
- data/lib/etassia/notation/plantuml/rank_hierarchy.rb +347 -0
- data/lib/etassia/notation/plantuml/relation.rb +103 -0
- data/lib/etassia/notation/plantuml/relation_label_separator.rb +199 -0
- data/lib/etassia/notation/plantuml/relation_path_points.rb +84 -0
- data/lib/etassia/notation/plantuml/renderer.rb +490 -0
- data/lib/etassia/notation/plantuml/scene.rb +134 -0
- data/lib/etassia/notation/plantuml/segment_box.rb +85 -0
- data/lib/etassia/notation/plantuml/sequence/activation.rb +28 -0
- data/lib/etassia/notation/plantuml/sequence/appearance.rb +71 -0
- data/lib/etassia/notation/plantuml/sequence/arrow_end.rb +23 -0
- data/lib/etassia/notation/plantuml/sequence/arrow_marks.rb +111 -0
- data/lib/etassia/notation/plantuml/sequence/arrow_style.rb +42 -0
- data/lib/etassia/notation/plantuml/sequence/arrow_syntax.rb +122 -0
- data/lib/etassia/notation/plantuml/sequence/bar_tracker.rb +59 -0
- data/lib/etassia/notation/plantuml/sequence/box.rb +23 -0
- data/lib/etassia/notation/plantuml/sequence/chrome.rb +60 -0
- data/lib/etassia/notation/plantuml/sequence/chrome_rows.rb +184 -0
- data/lib/etassia/notation/plantuml/sequence/create.rb +34 -0
- data/lib/etassia/notation/plantuml/sequence/delay.rb +19 -0
- data/lib/etassia/notation/plantuml/sequence/destroy.rb +20 -0
- data/lib/etassia/notation/plantuml/sequence/diagram.rb +86 -0
- data/lib/etassia/notation/plantuml/sequence/divider.rb +19 -0
- data/lib/etassia/notation/plantuml/sequence/edge.rb +53 -0
- data/lib/etassia/notation/plantuml/sequence/embedded.rb +77 -0
- data/lib/etassia/notation/plantuml/sequence/fill.rb +56 -0
- data/lib/etassia/notation/plantuml/sequence/fragment.rb +28 -0
- data/lib/etassia/notation/plantuml/sequence/fragment_shape.rb +138 -0
- data/lib/etassia/notation/plantuml/sequence/head_style.rb +43 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/blocks.rb +73 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/fills.rb +24 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/items.rb +48 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/messages.rb +62 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/participants.rb +42 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter/settings.rb +54 -0
- data/lib/etassia/notation/plantuml/sequence/ir_adapter.rb +38 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/blocks.rb +77 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/fills.rb +27 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/index.rb +36 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/items.rb +35 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/messages.rb +70 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/participants.rb +42 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader/settings.rb +74 -0
- data/lib/etassia/notation/plantuml/sequence/ir_reader.rb +38 -0
- data/lib/etassia/notation/plantuml/sequence/keyword_defaults.rb +28 -0
- data/lib/etassia/notation/plantuml/sequence/layout.rb +1567 -0
- data/lib/etassia/notation/plantuml/sequence/message.rb +97 -0
- data/lib/etassia/notation/plantuml/sequence/message_wrap.rb +77 -0
- data/lib/etassia/notation/plantuml/sequence/note.rb +61 -0
- data/lib/etassia/notation/plantuml/sequence/note_fill.rb +35 -0
- data/lib/etassia/notation/plantuml/sequence/note_geometry.rb +126 -0
- data/lib/etassia/notation/plantuml/sequence/note_shape.rb +51 -0
- data/lib/etassia/notation/plantuml/sequence/numbered_label.rb +57 -0
- data/lib/etassia/notation/plantuml/sequence/numbering.rb +49 -0
- data/lib/etassia/notation/plantuml/sequence/outline.rb +204 -0
- data/lib/etassia/notation/plantuml/sequence/page_break.rb +17 -0
- data/lib/etassia/notation/plantuml/sequence/paint.rb +79 -0
- data/lib/etassia/notation/plantuml/sequence/parallel_message.rb +19 -0
- data/lib/etassia/notation/plantuml/sequence/parser.rb +844 -0
- data/lib/etassia/notation/plantuml/sequence/participant.rb +27 -0
- data/lib/etassia/notation/plantuml/sequence/picture.rb +29 -0
- data/lib/etassia/notation/plantuml/sequence/ref.rb +24 -0
- data/lib/etassia/notation/plantuml/sequence/ref_shape.rb +74 -0
- data/lib/etassia/notation/plantuml/sequence/refusals.rb +47 -0
- data/lib/etassia/notation/plantuml/sequence/renderer.rb +501 -0
- data/lib/etassia/notation/plantuml/sequence/scene.rb +200 -0
- data/lib/etassia/notation/plantuml/sequence/skin.rb +76 -0
- data/lib/etassia/notation/plantuml/sequence/spacing.rb +28 -0
- data/lib/etassia/notation/plantuml/sequence/style.rb +151 -0
- data/lib/etassia/notation/plantuml/sequence/tab_size.rb +42 -0
- data/lib/etassia/notation/plantuml/sequence/walker.rb +1190 -0
- data/lib/etassia/notation/plantuml/sequence.rb +47 -0
- data/lib/etassia/notation/plantuml/source_lines.rb +33 -0
- data/lib/etassia/notation/plantuml/state/axis_solver.rb +272 -0
- data/lib/etassia/notation/plantuml/state/cluster_padding.rb +75 -0
- data/lib/etassia/notation/plantuml/state/curve.rb +73 -0
- data/lib/etassia/notation/plantuml/state/dot_axis.rb +248 -0
- data/lib/etassia/notation/plantuml/state/extent.rb +42 -0
- data/lib/etassia/notation/plantuml/state/hierarchy.rb +355 -0
- data/lib/etassia/notation/plantuml/state/label_clearance.rb +148 -0
- data/lib/etassia/notation/plantuml/state/label_reach.rb +139 -0
- data/lib/etassia/notation/plantuml/state/layout.rb +173 -0
- data/lib/etassia/notation/plantuml/state/level_edges.rb +113 -0
- data/lib/etassia/notation/plantuml/state/look.rb +36 -0
- data/lib/etassia/notation/plantuml/state/note_shape.rb +73 -0
- data/lib/etassia/notation/plantuml/state/plane.rb +85 -0
- data/lib/etassia/notation/plantuml/state/ranking.rb +181 -0
- data/lib/etassia/notation/plantuml/state/reader.rb +310 -0
- data/lib/etassia/notation/plantuml/state/renderer.rb +253 -0
- data/lib/etassia/notation/plantuml/state/route_detour.rb +115 -0
- data/lib/etassia/notation/plantuml/state/route_geometry.rb +186 -0
- data/lib/etassia/notation/plantuml/state/routes.rb +196 -0
- data/lib/etassia/notation/plantuml/state/row.rb +88 -0
- data/lib/etassia/notation/plantuml/state/rows.rb +50 -0
- data/lib/etassia/notation/plantuml/state/stretch.rb +71 -0
- data/lib/etassia/notation/plantuml/state.rb +62 -0
- data/lib/etassia/notation/plantuml/stereotype_head.rb +58 -0
- data/lib/etassia/notation/plantuml/style/bound.rb +34 -0
- data/lib/etassia/notation/plantuml/style/colour.rb +41 -0
- data/lib/etassia/notation/plantuml/style/colour_names.rb +89 -0
- data/lib/etassia/notation/plantuml/style/defaults.rb +33 -0
- data/lib/etassia/notation/plantuml/style/inline.rb +56 -0
- data/lib/etassia/notation/plantuml/style/reader.rb +242 -0
- data/lib/etassia/notation/plantuml/style/sheet.rb +103 -0
- data/lib/etassia/notation/plantuml/style.rb +32 -0
- data/lib/etassia/notation/plantuml/style_reader.rb +160 -0
- data/lib/etassia/notation/plantuml/style_sheet.rb +27 -0
- data/lib/etassia/notation/plantuml/styled_relation_curve.rb +71 -0
- data/lib/etassia/notation/plantuml/timing/arrows.rb +81 -0
- data/lib/etassia/notation/plantuml/timing/axis.rb +100 -0
- data/lib/etassia/notation/plantuml/timing/layout.rb +172 -0
- data/lib/etassia/notation/plantuml/timing/model.rb +34 -0
- data/lib/etassia/notation/plantuml/timing/reader.rb +173 -0
- data/lib/etassia/notation/plantuml/timing/signals.rb +328 -0
- data/lib/etassia/notation/plantuml/timing.rb +38 -0
- data/lib/etassia/notation/plantuml/tree/layout.rb +276 -0
- data/lib/etassia/notation/plantuml/tree/mindmap_layout.rb +157 -0
- data/lib/etassia/notation/plantuml/tree/reader.rb +186 -0
- data/lib/etassia/notation/plantuml/tree/renderer.rb +67 -0
- data/lib/etassia/notation/plantuml/tree/role.rb +57 -0
- data/lib/etassia/notation/plantuml/tree/rules.rb +156 -0
- data/lib/etassia/notation/plantuml/tree/wbs_layout.rb +164 -0
- data/lib/etassia/notation/plantuml/tree.rb +41 -0
- data/lib/etassia/notation/plantuml/unsupported_construct_error.rb +39 -0
- data/lib/etassia/notation/plantuml/unsupported_constructs.rb +103 -0
- data/lib/etassia/notation/plantuml/usecase.rb +36 -0
- data/lib/etassia/notation/plantuml.rb +132 -0
- data/lib/etassia/notation/plantuml_data/boxes/frames.rb +101 -0
- data/lib/etassia/notation/plantuml_data/boxes/graph_layout.rb +348 -0
- data/lib/etassia/notation/plantuml_data/boxes/heads.rb +65 -0
- data/lib/etassia/notation/plantuml_data/boxes/highlights.rb +70 -0
- data/lib/etassia/notation/plantuml_data/boxes/inline_rows.rb +99 -0
- data/lib/etassia/notation/plantuml_data/boxes/json_reader.rb +24 -0
- data/lib/etassia/notation/plantuml_data/boxes/link_text.rb +94 -0
- data/lib/etassia/notation/plantuml_data/boxes/marks.rb +76 -0
- data/lib/etassia/notation/plantuml_data/boxes/ornaments.rb +130 -0
- data/lib/etassia/notation/plantuml_data/boxes/renderer.rb +95 -0
- data/lib/etassia/notation/plantuml_data/boxes/row_alignment.rb +58 -0
- data/lib/etassia/notation/plantuml_data/boxes/row_bend.rb +43 -0
- data/lib/etassia/notation/plantuml_data/boxes/scene.rb +27 -0
- data/lib/etassia/notation/plantuml_data/boxes/table.rb +56 -0
- data/lib/etassia/notation/plantuml_data/boxes/table_box.rb +355 -0
- data/lib/etassia/notation/plantuml_data/boxes/text.rb +101 -0
- data/lib/etassia/notation/plantuml_data/boxes/tree_builder.rb +82 -0
- data/lib/etassia/notation/plantuml_data/boxes/tree_layout.rb +82 -0
- data/lib/etassia/notation/plantuml_data/boxes/yaml_reader.rb +105 -0
- data/lib/etassia/notation/plantuml_data/openiconic.LICENSE +6 -0
- data/lib/etassia/notation/plantuml_data/openiconic.json +1 -0
- data/lib/etassia/notation/plantuml_data.rb +84 -0
- data/lib/etassia/notation/plantuml_salt/block.rb +80 -0
- data/lib/etassia/notation/plantuml_salt/box.rb +30 -0
- data/lib/etassia/notation/plantuml_salt/font_metrics.rb +28 -0
- data/lib/etassia/notation/plantuml_salt/grid_marks.rb +66 -0
- data/lib/etassia/notation/plantuml_salt/group_marks.rb +77 -0
- data/lib/etassia/notation/plantuml_salt/layout.rb +206 -0
- data/lib/etassia/notation/plantuml_salt/mark.rb +36 -0
- data/lib/etassia/notation/plantuml_salt/markup.rb +57 -0
- data/lib/etassia/notation/plantuml_salt/parser.rb +239 -0
- data/lib/etassia/notation/plantuml_salt/renderer.rb +138 -0
- data/lib/etassia/notation/plantuml_salt/row.rb +19 -0
- data/lib/etassia/notation/plantuml_salt/run.rb +34 -0
- data/lib/etassia/notation/plantuml_salt/scene.rb +23 -0
- data/lib/etassia/notation/plantuml_salt/scroll_marks.rb +94 -0
- data/lib/etassia/notation/plantuml_salt/tab_marks.rb +74 -0
- data/lib/etassia/notation/plantuml_salt/tree_marks.rb +127 -0
- data/lib/etassia/notation/plantuml_salt/widget.rb +40 -0
- data/lib/etassia/notation/plantuml_salt/widget_marks.rb +319 -0
- data/lib/etassia/notation/plantuml_salt.rb +66 -0
- data/lib/etassia/notation/plugin_failure.rb +42 -0
- data/lib/etassia/notation.rb +289 -0
- data/lib/etassia/parser/architecture.rb +25 -0
- data/lib/etassia/parser/atoms/delimited_run.rb +82 -0
- data/lib/etassia/parser/atoms/greedy_run.rb +116 -0
- data/lib/etassia/parser/atoms/joined.rb +47 -0
- data/lib/etassia/parser/atoms/trimmed_run.rb +47 -0
- data/lib/etassia/parser/base.rb +258 -0
- data/lib/etassia/parser/block.rb +32 -0
- data/lib/etassia/parser/builders/architecture.rb +135 -0
- data/lib/etassia/parser/builders/block.rb +288 -0
- data/lib/etassia/parser/builders/c4.rb +275 -0
- data/lib/etassia/parser/builders/capture_string.rb +17 -0
- data/lib/etassia/parser/builders/class_diagram.rb +539 -0
- data/lib/etassia/parser/builders/er_diagram.rb +308 -0
- data/lib/etassia/parser/builders/error.rb +51 -0
- data/lib/etassia/parser/builders/flowchart.rb +1150 -0
- data/lib/etassia/parser/builders/gantt.rb +267 -0
- data/lib/etassia/parser/builders/git_graph.rb +301 -0
- data/lib/etassia/parser/builders/info.rb +57 -0
- data/lib/etassia/parser/builders/kanban.rb +411 -0
- data/lib/etassia/parser/builders/mindmap.rb +271 -0
- data/lib/etassia/parser/builders/packet.rb +85 -0
- data/lib/etassia/parser/builders/pie.rb +105 -0
- data/lib/etassia/parser/builders/quadrant.rb +165 -0
- data/lib/etassia/parser/builders/radar.rb +157 -0
- data/lib/etassia/parser/builders/requirement.rb +230 -0
- data/lib/etassia/parser/builders/sankey.rb +142 -0
- data/lib/etassia/parser/builders/sequence.rb +431 -0
- data/lib/etassia/parser/builders/sequence_blocks.rb +117 -0
- data/lib/etassia/parser/builders/sequence_box_title.rb +57 -0
- data/lib/etassia/parser/builders/state_diagram.rb +364 -0
- data/lib/etassia/parser/builders/timeline.rb +133 -0
- data/lib/etassia/parser/builders/treemap.rb +138 -0
- data/lib/etassia/parser/builders/xy_chart.rb +148 -0
- data/lib/etassia/parser/c4.rb +37 -0
- data/lib/etassia/parser/class_diagram.rb +58 -0
- data/lib/etassia/parser/class_namespaces.rb +62 -0
- data/lib/etassia/parser/class_notes.rb +54 -0
- data/lib/etassia/parser/er_diagram.rb +28 -0
- data/lib/etassia/parser/error.rb +30 -0
- data/lib/etassia/parser/flowchart.rb +87 -0
- data/lib/etassia/parser/gantt.rb +43 -0
- data/lib/etassia/parser/git_graph.rb +106 -0
- data/lib/etassia/parser/grammars/architecture.rb +165 -0
- data/lib/etassia/parser/grammars/block.rb +190 -0
- data/lib/etassia/parser/grammars/c4.rb +229 -0
- data/lib/etassia/parser/grammars/class_diagram.rb +606 -0
- data/lib/etassia/parser/grammars/common.rb +107 -0
- data/lib/etassia/parser/grammars/er_diagram.rb +232 -0
- data/lib/etassia/parser/grammars/error.rb +32 -0
- data/lib/etassia/parser/grammars/flowchart.rb +1722 -0
- data/lib/etassia/parser/grammars/gantt.rb +198 -0
- data/lib/etassia/parser/grammars/git_graph.rb +234 -0
- data/lib/etassia/parser/grammars/info.rb +53 -0
- data/lib/etassia/parser/grammars/kanban.rb +417 -0
- data/lib/etassia/parser/grammars/mermaid_unicode_text.rb +108 -0
- data/lib/etassia/parser/grammars/mindmap.rb +220 -0
- data/lib/etassia/parser/grammars/packet.rb +71 -0
- data/lib/etassia/parser/grammars/pie.rb +128 -0
- data/lib/etassia/parser/grammars/quadrant.rb +202 -0
- data/lib/etassia/parser/grammars/radar.rb +158 -0
- data/lib/etassia/parser/grammars/requirement.rb +258 -0
- data/lib/etassia/parser/grammars/sankey.rb +104 -0
- data/lib/etassia/parser/grammars/sequence.rb +940 -0
- data/lib/etassia/parser/grammars/state_diagram.rb +382 -0
- data/lib/etassia/parser/grammars/timeline.rb +153 -0
- data/lib/etassia/parser/grammars/treemap.rb +122 -0
- data/lib/etassia/parser/grammars/xy_chart.rb +119 -0
- data/lib/etassia/parser/info.rb +32 -0
- data/lib/etassia/parser/kanban.rb +131 -0
- data/lib/etassia/parser/mermaid_shapes.rb +106 -0
- data/lib/etassia/parser/metadata_yaml.rb +452 -0
- data/lib/etassia/parser/mindmap.rb +92 -0
- data/lib/etassia/parser/native/builders/architecture.rb +103 -0
- data/lib/etassia/parser/native/builders/block.rb +68 -0
- data/lib/etassia/parser/native/builders/c4.rb +16 -0
- data/lib/etassia/parser/native/builders/class_diagram.rb +63 -0
- data/lib/etassia/parser/native/builders/er_diagram.rb +47 -0
- data/lib/etassia/parser/native/builders/flowchart.rb +58 -0
- data/lib/etassia/parser/native/builders/gantt.rb +35 -0
- data/lib/etassia/parser/native/builders/gitgraph.rb +35 -0
- data/lib/etassia/parser/native/builders/info.rb +30 -0
- data/lib/etassia/parser/native/builders/kanban.rb +37 -0
- data/lib/etassia/parser/native/builders/mindmap.rb +26 -0
- data/lib/etassia/parser/native/builders/packet.rb +63 -0
- data/lib/etassia/parser/native/builders/pie.rb +82 -0
- data/lib/etassia/parser/native/builders/quadrant.rb +27 -0
- data/lib/etassia/parser/native/builders/radar.rb +84 -0
- data/lib/etassia/parser/native/builders/requirement.rb +25 -0
- data/lib/etassia/parser/native/builders/sankey.rb +18 -0
- data/lib/etassia/parser/native/builders/sequence.rb +48 -0
- data/lib/etassia/parser/native/builders/state_diagram.rb +61 -0
- data/lib/etassia/parser/native/builders/timeline.rb +46 -0
- data/lib/etassia/parser/native/builders/treemap.rb +60 -0
- data/lib/etassia/parser/native/builders/user_journey.rb +83 -0
- data/lib/etassia/parser/native/builders/xy_chart.rb +94 -0
- data/lib/etassia/parser/native/declined.rb +12 -0
- data/lib/etassia/parser/native/mermaid.json +1 -0
- data/lib/etassia/parser/native/text.rb +31 -0
- data/lib/etassia/parser/native.rb +99 -0
- data/lib/etassia/parser/packet.rb +56 -0
- data/lib/etassia/parser/pie.rb +32 -0
- data/lib/etassia/parser/quadrant.rb +77 -0
- data/lib/etassia/parser/radar.rb +99 -0
- data/lib/etassia/parser/requirement.rb +32 -0
- data/lib/etassia/parser/sankey.rb +47 -0
- data/lib/etassia/parser/sequence.rb +34 -0
- data/lib/etassia/parser/state_diagram.rb +29 -0
- data/lib/etassia/parser/timeline.rb +40 -0
- data/lib/etassia/parser/treemap.rb +25 -0
- data/lib/etassia/parser/user_journey.rb +253 -0
- data/lib/etassia/parser/xy_chart.rb +98 -0
- data/lib/etassia/parser.rb +18 -0
- data/lib/etassia/renderer/architecture.rb +232 -0
- data/lib/etassia/renderer/architecture_edge_router.rb +379 -0
- data/lib/etassia/renderer/base.rb +295 -0
- data/lib/etassia/renderer/block.rb +157 -0
- data/lib/etassia/renderer/c4.rb +294 -0
- data/lib/etassia/renderer/class_diagram.rb +671 -0
- data/lib/etassia/renderer/er_diagram.rb +842 -0
- data/lib/etassia/renderer/error.rb +131 -0
- data/lib/etassia/renderer/flowchart.rb +315 -0
- data/lib/etassia/renderer/gantt.rb +177 -0
- data/lib/etassia/renderer/git_graph.rb +224 -0
- data/lib/etassia/renderer/info.rb +59 -0
- data/lib/etassia/renderer/kanban.rb +157 -0
- data/lib/etassia/renderer/line_break_text.rb +56 -0
- data/lib/etassia/renderer/markdown_text.rb +106 -0
- data/lib/etassia/renderer/mindmap.rb +290 -0
- data/lib/etassia/renderer/packet.rb +87 -0
- data/lib/etassia/renderer/pie.rb +113 -0
- data/lib/etassia/renderer/quadrant.rb +189 -0
- data/lib/etassia/renderer/radar.rb +191 -0
- data/lib/etassia/renderer/requirement.rb +209 -0
- data/lib/etassia/renderer/sankey.rb +114 -0
- data/lib/etassia/renderer/sequence/frame_drawing.rb +169 -0
- data/lib/etassia/renderer/sequence/note_drawing.rb +69 -0
- data/lib/etassia/renderer/sequence.rb +490 -0
- data/lib/etassia/renderer/state_diagram.rb +202 -0
- data/lib/etassia/renderer/timeline.rb +134 -0
- data/lib/etassia/renderer/timeline_palette.rb +18 -0
- data/lib/etassia/renderer/treemap/section_total.rb +33 -0
- data/lib/etassia/renderer/treemap.rb +128 -0
- data/lib/etassia/renderer/user_journey.rb +209 -0
- data/lib/etassia/renderer/xy_chart.rb +180 -0
- data/lib/etassia/renderer.rb +22 -0
- data/lib/etassia/runtime.rb +125 -0
- data/lib/etassia/source/frontmatter.rb +501 -0
- data/lib/etassia/source.rb +224 -0
- data/lib/etassia/svg/arrowhead.rb +205 -0
- data/lib/etassia/svg/circle.rb +19 -0
- data/lib/etassia/svg/document.rb +106 -0
- data/lib/etassia/svg/element.rb +209 -0
- data/lib/etassia/svg/ellipse.rb +23 -0
- data/lib/etassia/svg/escaping.rb +149 -0
- data/lib/etassia/svg/group.rb +64 -0
- data/lib/etassia/svg/line.rb +21 -0
- data/lib/etassia/svg/numbers.rb +53 -0
- data/lib/etassia/svg/path.rb +67 -0
- data/lib/etassia/svg/path_geometry.rb +378 -0
- data/lib/etassia/svg/polygon.rb +25 -0
- data/lib/etassia/svg/polyline.rb +28 -0
- data/lib/etassia/svg/rect.rb +34 -0
- data/lib/etassia/svg/style.rb +50 -0
- data/lib/etassia/svg/text.rb +181 -0
- data/lib/etassia/svg/tspan.rb +48 -0
- data/lib/etassia/svg.rb +38 -0
- data/lib/etassia/text_measurement/arial_advances.rb +122 -0
- data/lib/etassia/text_measurement/dejavu_advances.rb +111 -0
- data/lib/etassia/text_measurement/times_advances.rb +64 -0
- data/lib/etassia/text_measurement/trebuchet_advances.rb +53 -0
- data/lib/etassia/text_measurement/trebuchet_kerning.rb +29 -0
- data/lib/etassia/text_measurement.rb +198 -0
- data/lib/etassia/theme/builtin/dark.yml +229 -0
- data/lib/etassia/theme/builtin/default.yml +239 -0
- data/lib/etassia/theme/builtin/high_contrast.yml +231 -0
- data/lib/etassia/theme/builtin/light.yml +229 -0
- data/lib/etassia/theme/color_palette.rb +97 -0
- data/lib/etassia/theme/completion.rb +50 -0
- data/lib/etassia/theme/effect_styles.rb +34 -0
- data/lib/etassia/theme/registry.rb +45 -0
- data/lib/etassia/theme/shape_styles.rb +34 -0
- data/lib/etassia/theme/spacing_config.rb +30 -0
- data/lib/etassia/theme/typography.rb +40 -0
- data/lib/etassia/theme.rb +73 -0
- data/lib/etassia/version.rb +5 -0
- data/lib/etassia.rb +40 -0
- metadata +865 -0
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "common"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Parser
|
|
7
|
+
module Grammars
|
|
8
|
+
# Parslet grammar for sequence diagrams.
|
|
9
|
+
#
|
|
10
|
+
# Handles all sequence diagram syntax including participants, messages,
|
|
11
|
+
# notes, activations, and control structures. The grammar properly handles
|
|
12
|
+
# complex arrow patterns with activation modifiers that cannot be parsed
|
|
13
|
+
# correctly by regex-based lexers.
|
|
14
|
+
class Sequence < Common
|
|
15
|
+
root(:diagram)
|
|
16
|
+
|
|
17
|
+
# Main diagram structure
|
|
18
|
+
rule(:diagram) do
|
|
19
|
+
ws? >>
|
|
20
|
+
header >>
|
|
21
|
+
ws? >>
|
|
22
|
+
statements.maybe >>
|
|
23
|
+
ws?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
rule(:header) do
|
|
27
|
+
str("sequenceDiagram").as(:header) >> semicolon.maybe >> ws?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# A `;`-terminated statement can be followed by another bare `;`
|
|
31
|
+
# with nothing between them (`m;;m2`): the first `;` already ends
|
|
32
|
+
# the statement via `content_boundary`, and mermaid treats the
|
|
33
|
+
# second as an empty no-op statement rather than a syntax error
|
|
34
|
+
# (measured against mermaid 11.16.1: `Alice->>Bob: m;;Alice->>Bob:
|
|
35
|
+
# m2` gives 2 messages). Without this, `statements`' `repeat(1)`
|
|
36
|
+
# has nowhere to put that second `;` — no rule in `statement`
|
|
37
|
+
# starts on one — and the whole diagram fails to parse. Swallowing
|
|
38
|
+
# any run of extra `;`s after each statement mirrors that, the
|
|
39
|
+
# same way `ws?` already swallows blank space between statements.
|
|
40
|
+
rule(:statements) do
|
|
41
|
+
(statement >> ws? >> (semicolon >> ws?).repeat).repeat(1)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
rule(:statement) do
|
|
45
|
+
comment_statement |
|
|
46
|
+
hash_comment_statement |
|
|
47
|
+
metadata_statement |
|
|
48
|
+
create_statement |
|
|
49
|
+
destroy_statement |
|
|
50
|
+
links_statement |
|
|
51
|
+
participant_declaration |
|
|
52
|
+
actor_declaration |
|
|
53
|
+
note_statement |
|
|
54
|
+
box_statement |
|
|
55
|
+
activation_command |
|
|
56
|
+
deactivation_command |
|
|
57
|
+
control_structure |
|
|
58
|
+
message
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# A line starting with a bare `%` (not opening `%{`) is a whole-line
|
|
62
|
+
# comment to mermaid, contributing zero statements — mermaid's own
|
|
63
|
+
# comment rule takes priority over its actor rule at the start of a
|
|
64
|
+
# statement, so a leading `%` swallows the rest of the line whatever
|
|
65
|
+
# punctuation follows it. `message_actor_lead` already refuses to let
|
|
66
|
+
# a message actor START with a bare `%` (`mermaid_token_opener`,
|
|
67
|
+
# below), so it agrees such a line is never a message — but until
|
|
68
|
+
# this rule it had no statement to fall back to, so the whole
|
|
69
|
+
# diagram failed instead of skipping one line.
|
|
70
|
+
#
|
|
71
|
+
# No `.as(...)` in this rule. `root` is `diagram`, which always pairs
|
|
72
|
+
# `statements` with `header.as(:header)`, and Parslet drops an
|
|
73
|
+
# unnamed match when composing it alongside a named one rather than
|
|
74
|
+
# handing it up as an array entry — verified by parsing the real
|
|
75
|
+
# `diagram` root, not this rule in isolation (calling `statements`
|
|
76
|
+
# directly returns a bare `Parslet::Slice`, a code path the parser
|
|
77
|
+
# never actually takes): `g.parse("sequenceDiagram\n%c\nA->>B: m\n")`
|
|
78
|
+
# comes back `[{header: ...}, {from: "A", ...}]`, two entries, not
|
|
79
|
+
# three — the comment line leaves nothing behind for
|
|
80
|
+
# `Builders::Sequence`'s `is_a?(Hash)` guards in
|
|
81
|
+
# `apply`/`process_statements` to skip. Those guards are real and
|
|
82
|
+
# matter for other rules; they simply never see this one.
|
|
83
|
+
#
|
|
84
|
+
# A comment line does not swallow the statement after it
|
|
85
|
+
# (`%c\nA->>B: m\n` still yields participants `A`, `B`). A line
|
|
86
|
+
# starting `%%` also parses to zero participants, matching mermaid,
|
|
87
|
+
# but NOT through this rule — `diagram`'s own `ws?` right after
|
|
88
|
+
# `header` already consumes it via `common.rb`'s `comment` rule
|
|
89
|
+
# (`%%` to end of line) before `statements` ever gets a chance to
|
|
90
|
+
# try this one. Do not read that case as evidence for this rule.
|
|
91
|
+
rule(:comment_statement) do
|
|
92
|
+
str("%") >> str("{").absent? >>
|
|
93
|
+
(line_end.absent? >> any).repeat >> line_end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# `title`, `accTitle`, `accDescr` and `autonumber` are recognised so
|
|
97
|
+
# the diagram parses, and contribute no statement: like
|
|
98
|
+
# `comment_statement`, no `.as(...)`. The title, accessibility text
|
|
99
|
+
# and message numbering are not drawn. Each rule must end at
|
|
100
|
+
# `line_end` or `content_boundary` (which also accepts `;`), which
|
|
101
|
+
# keeps `autonumber->>B: m` and `title->>B: m` ordinary messages.
|
|
102
|
+
rule(:metadata_statement) do
|
|
103
|
+
title_statement | acc_title_statement | acc_descr_block |
|
|
104
|
+
acc_descr_statement | autonumber_statement
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
rule(:title_statement) do
|
|
108
|
+
str("title") >> ((colon >> space?) | space.repeat(1)) >>
|
|
109
|
+
match['^#;\n'].repeat >> content_boundary
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
rule(:acc_title_statement) do
|
|
113
|
+
str("accTitle") >> space? >> colon >> rest_of_line
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
rule(:acc_descr_statement) do
|
|
117
|
+
str("accDescr") >> space? >> colon >> rest_of_line
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
rule(:acc_descr_block) do
|
|
121
|
+
str("accDescr") >> space? >> lbrace >>
|
|
122
|
+
(rbrace.absent? >> any).repeat >> rbrace >> content_boundary
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
rule(:autonumber_statement) do
|
|
126
|
+
str("autonumber") >>
|
|
127
|
+
(space.repeat(1) >> (str("off") | numbering)).maybe >>
|
|
128
|
+
content_boundary
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Mermaid's NUM is digits with up to two decimals, or a leading-dot
|
|
132
|
+
# decimal.
|
|
133
|
+
rule(:number) do
|
|
134
|
+
(
|
|
135
|
+
match["0-9"].repeat(1) >>
|
|
136
|
+
(str(".") >> match["0-9"].repeat(1, 2)).maybe
|
|
137
|
+
) |
|
|
138
|
+
(str(".") >> match["0-9"].repeat(1, 2))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
rule(:numbering) do
|
|
142
|
+
number >> (space.repeat(1) >> number).maybe
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# A `#` comment runs to the physical line end, `;` included —
|
|
146
|
+
# shared by every `content_boundary` caller below.
|
|
147
|
+
rule(:trailing_comment) do
|
|
148
|
+
(space? >> str("#") >> match['^\n'].repeat).maybe
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# The boundary a `;`-aware text capture (`text_run` below) yields
|
|
152
|
+
# to: an optional trailing `#` comment, then a line end or an
|
|
153
|
+
# inline `;`. The bare `\r` + eof arm exists because `text_run`
|
|
154
|
+
# stops at every `\r`; only direct `Parser::Sequence#parse` calls
|
|
155
|
+
# reach it, since `Source#normalize` rewrites `\r\n?` first.
|
|
156
|
+
rule(:content_boundary) do
|
|
157
|
+
trailing_comment >> (line_end | semicolon | (str("\r") >> eof))
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# A whole-line `#...` comment left behind once a label capture
|
|
161
|
+
# stops at an inline `;` (`alt -:<>,;# comment` splits into a
|
|
162
|
+
# label ending at the `;` and this bare comment line — only
|
|
163
|
+
# `alt`/`par` opening labels are `;`-aware; `loop`'s is not).
|
|
164
|
+
# Mirrors `comment_statement` above: no `.as(...)`, contributes
|
|
165
|
+
# zero statements. `char_ref.absent?` keeps a genuine character
|
|
166
|
+
# reference (`#9829;`) from ever being misread as the start of a
|
|
167
|
+
# comment line here.
|
|
168
|
+
rule(:hash_comment_statement) do
|
|
169
|
+
char_ref.absent? >> hash_char >>
|
|
170
|
+
(line_end.absent? >> any).repeat >> line_end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# mermaid encodes `/#\w+;/g` globally before its lexer ever runs
|
|
174
|
+
# (see the grammar's design doc for the full citation); this is
|
|
175
|
+
# the regex-equivalent grammar rule, needed wherever a `;`-aware
|
|
176
|
+
# boundary would otherwise split a character reference in half.
|
|
177
|
+
rule(:char_ref) do
|
|
178
|
+
hash_char >> match["a-zA-Z0-9_"].repeat(1) >> semicolon
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# A `;`-aware text capture: a character reference is consumed
|
|
182
|
+
# whole, so its own `;` is never mistaken for a separator. Also
|
|
183
|
+
# stops at a bare `#`, leaving it for `content_boundary`'s
|
|
184
|
+
# trailing-comment consumption — a `#` opens a comment that runs to
|
|
185
|
+
# the physical line end, `;` included.
|
|
186
|
+
#
|
|
187
|
+
# `match['^;\n\r#']` is a bulk fast path: one native scan per run
|
|
188
|
+
# instead of one Parslet alternation per character. It keeps
|
|
189
|
+
# trailing spaces before the boundary inside the run rather than
|
|
190
|
+
# excluding them; every caller either strips via `extract_text` or
|
|
191
|
+
# never reads the label (`alt`/`par`), so that difference is moot.
|
|
192
|
+
rule(:text_run) do
|
|
193
|
+
(char_ref | match['^;\n\r#'].repeat(1)).repeat
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Runs to the physical line end: testing `line_end` at every
|
|
197
|
+
# character rescans an interior whitespace run each time.
|
|
198
|
+
rule(:rest_of_line) do
|
|
199
|
+
match['^\n'].repeat >> line_end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# An actor name is a bounded run of text, not a programming
|
|
203
|
+
# identifier: mermaid accepts spaces, parentheses, dashes, `=` and
|
|
204
|
+
# a leading digit (`Alice ()`, `Alice-in-Wonderland`, `1`).
|
|
205
|
+
#
|
|
206
|
+
# `actor_stop` names every boundary an actor name yields to. It
|
|
207
|
+
# includes `arrow_base` rather than `arrow` because the activation
|
|
208
|
+
# suffix is `.maybe`, so the two are equivalent as a boundary and
|
|
209
|
+
# `arrow_base` says what is meant. `%%` is required even though a
|
|
210
|
+
# bare `%` stays name material: `line_end` lets every statement
|
|
211
|
+
# carry a trailing comment, so an actor name has to yield to `%%`
|
|
212
|
+
# or `participant Alice %% who` would swallow the comment into the
|
|
213
|
+
# id. `alias_keyword` needs surrounding whitespace so it splits
|
|
214
|
+
# `participant 1 as text` at the keyword without eating a name like
|
|
215
|
+
# `Cast Away` (`t A` is not ` as `). `@{` (never a bare `@`) is the
|
|
216
|
+
# shape-metadata opener.
|
|
217
|
+
rule(:alias_keyword) { space.repeat(1) >> str("as") >> space.repeat(1) }
|
|
218
|
+
|
|
219
|
+
rule(:actor_stop) do
|
|
220
|
+
arrow_base | colon | comma | semicolon | str("%%") |
|
|
221
|
+
alias_keyword | str("@{") | newline
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# `+` and `<` are never `actor_name` material (used by note/activate/
|
|
225
|
+
# deactivate references) — they would collide with the activation
|
|
226
|
+
# suffix (`A->>+B`) or an arrow spelling (`<<->>`). This does NOT
|
|
227
|
+
# generalise to a `participant`/`actor` DECLARATION: a declaration
|
|
228
|
+
# has no arrow to collide with, and mermaid accepts `participant
|
|
229
|
+
# A+B` outright (id "A+B") — see `declaration_stop` below, which
|
|
230
|
+
# bans `<>` but deliberately not `+`. Measured against mermaid
|
|
231
|
+
# 11.16.1's own parser directly; a stale version of this comment
|
|
232
|
+
# once claimed `participant A+B` was rejected too.
|
|
233
|
+
#
|
|
234
|
+
# A dash is consumed unless the very next thing is another dash or
|
|
235
|
+
# the start of a genuine arrow — that is the only real ambiguity a
|
|
236
|
+
# trailing dash creates (`A--->B` must not read as actor `A-` plus
|
|
237
|
+
# arrow `-->`). `newline` is deliberately absent from this set,
|
|
238
|
+
# unlike the general `actor_stop` gate above: a trailing dash at
|
|
239
|
+
# end-of-statement is exactly as legal as one at end-of-file (both
|
|
240
|
+
# already work — `participant A-` at EOF gives `"A-"`), and mmdc
|
|
241
|
+
# accepts `participant A-` followed by more statements the same
|
|
242
|
+
# way. The general gate still stops an ordinary character at a
|
|
243
|
+
# newline, so a name still cannot span multiple lines.
|
|
244
|
+
# `>` joins `<` as never `actor_name` material, matching the same
|
|
245
|
+
# fix applied to `message_actor_char` — it was missing here too.
|
|
246
|
+
# Measured against mermaid 11.16.1 directly: `activate A>B`,
|
|
247
|
+
# `deactivate A>B` and `Note over A>B: n` all raise on mermaid;
|
|
248
|
+
# base created actor `"A>B"` for all three, reading straight past
|
|
249
|
+
# the `>`. Round-2 Codex finding, in scope: same missing exclusion
|
|
250
|
+
# as the message-actor fix, just in the sibling rule that serves
|
|
251
|
+
# activation and note references instead of messages.
|
|
252
|
+
rule(:actor_char) do
|
|
253
|
+
actor_stop.absent? >>
|
|
254
|
+
(match["^+<>-"] |
|
|
255
|
+
(str("-") >>
|
|
256
|
+
(str("-") | arrow_base | colon | comma | semicolon |
|
|
257
|
+
str("%%") | alias_keyword | str("@{")).absent?))
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# An arrow-tail character cannot open a name: `A->)B` is a bad
|
|
261
|
+
# arrow, not a message into an actor called `)B`. `/` joins the
|
|
262
|
+
# same set — it opens three reversed-arrow spellings (`/|-`,
|
|
263
|
+
# `/|--`, `//-`, `//--`), so `A->>/B` is a bad arrow rather than a
|
|
264
|
+
# message to `/B`; measured, mermaid rejects it there while
|
|
265
|
+
# accepting `/` elsewhere in a name.
|
|
266
|
+
rule(:actor_lead) { match[")|>/"].absent? >> actor_char }
|
|
267
|
+
|
|
268
|
+
# A character reference is one unit, so its own `;` does not end
|
|
269
|
+
# the name (`Note over A#65;: n`, `activate A#65;`).
|
|
270
|
+
rule(:actor_name) do
|
|
271
|
+
(char_ref | actor_lead) >> (char_ref | actor_char).repeat
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# `actor_name` above is shared by every OTHER actor reference
|
|
275
|
+
# (notes, activate/deactivate) and stays untouched. Declarations
|
|
276
|
+
# and message endpoints get their own rules below: mermaid's real
|
|
277
|
+
# grammar treats the two very differently, and forcing one token
|
|
278
|
+
# to cover both is what created phantom actors and rejected valid
|
|
279
|
+
# input in three places at once (measured against mermaid
|
|
280
|
+
# 11.16.1's own parser and lexer directly).
|
|
281
|
+
#
|
|
282
|
+
# A declaration has no arrow next to it, so there is nothing for
|
|
283
|
+
# a `+`, a `-` run, or a leading `/` to be ambiguous with —
|
|
284
|
+
# `actor_char`'s bans on those exist only to protect a message's
|
|
285
|
+
# arrow and activation-suffix syntax. Measured: `participant
|
|
286
|
+
# A+B`, `participant /B`, `participant )B`, `participant |B` and
|
|
287
|
+
# `participant A--B` all succeed with those literal ids; only `<`
|
|
288
|
+
# and `>` are ever rejected.
|
|
289
|
+
# Bare `@` is banned outright, not just the `@{` shape-metadata
|
|
290
|
+
# opener — measured against mermaid 11.16.1: `participant A@B`
|
|
291
|
+
# raises `Expecting 'ACTOR', got 'INVALID'`. Banning only `@{`
|
|
292
|
+
# left a bare `@` as ordinary id material, which mermaid never
|
|
293
|
+
# accepts (`shape_metadata` below still matches `@{...}` right
|
|
294
|
+
# after this stop point when metadata is actually present).
|
|
295
|
+
# `#` is NOT here: mermaid only rejects a LEADING `#`
|
|
296
|
+
# (`declaration_lead`/`declaration_word_lead` below), and lets it
|
|
297
|
+
# through everywhere else in an id — measured against mermaid
|
|
298
|
+
# 11.16.1, `participant A#B` gives id "A#B".
|
|
299
|
+
rule(:declaration_stop) do
|
|
300
|
+
match["<>"] | colon | comma | semicolon | str("%%") |
|
|
301
|
+
str("@") | newline
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
rule(:declaration_char) { declaration_stop.absent? >> any }
|
|
305
|
+
|
|
306
|
+
# The first character of an id is the only place `#` is ever
|
|
307
|
+
# banned — measured against mermaid 11.16.1: `participant #B`
|
|
308
|
+
# raises, `participant A#B` does not. `char_ref` is tried first so
|
|
309
|
+
# a leading `#9829;` reference is consumed whole rather than
|
|
310
|
+
# rejected by the ban.
|
|
311
|
+
# Shared by `declaration_lead` and `declaration_word_lead` below —
|
|
312
|
+
# both are "char_ref, else a plain character not banned by a
|
|
313
|
+
# leading `#`", differing only in which character rule bounds the
|
|
314
|
+
# plain branch. A private method, not `rule()`: Parslet's `rule()`
|
|
315
|
+
# macro memoizes a fixed zero-argument atom and can't take one.
|
|
316
|
+
def hash_free_lead(char_rule)
|
|
317
|
+
char_ref | (hash_char.absent? >> char_rule)
|
|
318
|
+
end
|
|
319
|
+
private :hash_free_lead
|
|
320
|
+
|
|
321
|
+
rule(:declaration_lead) { hash_free_lead(declaration_char) }
|
|
322
|
+
|
|
323
|
+
# The `as`-alias split only fires when the id BEFORE it has no
|
|
324
|
+
# embedded whitespace — mermaid's own ID-then-AS lexer rule
|
|
325
|
+
# (`[^<>:\n,;@\s]+(?=\s+as\s)`) excludes whitespace from that id
|
|
326
|
+
# entirely. When the id DOES contain whitespace, `as` is not a
|
|
327
|
+
# keyword boundary and the whole thing — "as" included — stays one
|
|
328
|
+
# id. Measured against mermaid 11.16.1 directly:
|
|
329
|
+
# `participant A as C` -> id "A", label "C" (alias applies)
|
|
330
|
+
# `participant A B as C` -> id "A B as C", no label at all
|
|
331
|
+
# `declaration_word_char` is deliberately narrower than
|
|
332
|
+
# `declaration_char` (it also excludes whitespace) so the
|
|
333
|
+
# lookahead below only fires on a whitespace-free run, exactly
|
|
334
|
+
# matching that lexer rule.
|
|
335
|
+
rule(:declaration_word_char) do
|
|
336
|
+
(declaration_stop | space).absent? >> any
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
rule(:declaration_word_lead) { hash_free_lead(declaration_word_char) }
|
|
340
|
+
|
|
341
|
+
# Each branch's lead unit bans a leading bare `#`; the repeated
|
|
342
|
+
# tail does not, so a `#` past the first character stays ordinary
|
|
343
|
+
# id material. Both also gain a `char_ref` alternative ahead of
|
|
344
|
+
# their plain character rule, so a `#9829;` run is consumed as one
|
|
345
|
+
# atomic unit. Without it in the alias branch specifically,
|
|
346
|
+
# `#9829;B as Heart` falls through to the fallback branch and
|
|
347
|
+
# swallows the whole thing as an id with no label.
|
|
348
|
+
rule(:declaration_name) do
|
|
349
|
+
(declaration_word_lead >> (char_ref | declaration_word_char).repeat >>
|
|
350
|
+
alias_keyword.present?) |
|
|
351
|
+
(declaration_lead >> (char_ref | declaration_char).repeat)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# A message endpoint sits next to an arrow, so it keeps
|
|
355
|
+
# `actor_char`'s arrow-safety, but two of its restrictions are
|
|
356
|
+
# wrong for a message specifically:
|
|
357
|
+
#
|
|
358
|
+
# - `alias_keyword` must NOT stop a message name. Measured: `A as
|
|
359
|
+
# Z->>B: m` and `A->>B as Z: m` both parse in mermaid with `as`
|
|
360
|
+
# as ordinary text — ` as ` only splits id from label inside a
|
|
361
|
+
# `participant`/`actor` statement, never inside a message.
|
|
362
|
+
# - `(` and `)` must stop a message name instead of joining it.
|
|
363
|
+
# Unlike a declaration's literal `Alice ()`, a `()` touching a
|
|
364
|
+
# message endpoint is mermaid's own central-connection
|
|
365
|
+
# decoration (jison terminal `()`, `LINETYPE.CENTRAL_CONNECTION`
|
|
366
|
+
# /`_REVERSE`/`_DUAL`) and never becomes part of the actor's
|
|
367
|
+
# identity: `A ()->>B: m` and `A->>() B: m` both resolve to the
|
|
368
|
+
# two declared actors `A`/`B`, not to phantom actors `A ()` /
|
|
369
|
+
# `() B`.
|
|
370
|
+
# `#` is NOT here, matching `declaration_stop`: mermaid only
|
|
371
|
+
# rejects a LEADING `#` on a message endpoint, not one mid-name —
|
|
372
|
+
# measured, `A->>B#C: m` gives recipient "B#C". The leading ban
|
|
373
|
+
# lives in `message_actor_lead_char` below instead, so it applies
|
|
374
|
+
# only to the first character, not to every character that
|
|
375
|
+
# follows this rule via `message_actor_char`.
|
|
376
|
+
rule(:message_actor_stop) do
|
|
377
|
+
arrow_base | colon | comma | semicolon | str("%%") |
|
|
378
|
+
str("@{") | lparen | rparen | newline
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# FOUR rounds of patching this rule each found a new gap, and the
|
|
382
|
+
# fourth (a differential fuzz against mermaid, 10,568 generated
|
|
383
|
+
# inputs, all 1,939 etassia-accepted ones cross-checked in Chrome
|
|
384
|
+
# — this grammar's own hand-written approximations had exhausted
|
|
385
|
+
# every gate we already had) found two more, both the SAME shape
|
|
386
|
+
# as the first three: a HAND-DERIVED stand-in for a piece of
|
|
387
|
+
# mermaid's real regex, each stand-in accurate on the cases it
|
|
388
|
+
# was checked against and wrong on one it wasn't. The fix each
|
|
389
|
+
# time was to stop deriving and start copying:
|
|
390
|
+
#
|
|
391
|
+
# - The regex has TWO SEPARATE things where this rule had
|
|
392
|
+
# conflated them into one per-character check: an ENTRY
|
|
393
|
+
# lookahead, evaluated ONCE at the position of the triggering
|
|
394
|
+
# dash, and a TAIL character class, evaluated per character
|
|
395
|
+
# while consuming the run that follows. Round 3's version
|
|
396
|
+
# re-ran a stop-check (including `arrow_base` and etassia's own
|
|
397
|
+
# `%%`/`@{` extensions) at EVERY tail character, which is not
|
|
398
|
+
# what the real regex does — its tail class
|
|
399
|
+
# (`[^\+<\->\->:\n,;]`) is a flat set with no arrow-awareness
|
|
400
|
+
# at all. Measured: `B->>A-(%%C: m` — mermaid consumes the
|
|
401
|
+
# embedded `%%` as ordinary tail material and sends message
|
|
402
|
+
# "m"; the per-character recheck stopped there instead,
|
|
403
|
+
# producing recipient "A-(" and an EMPTY message. Same root
|
|
404
|
+
# cause exposed `A-(//-B: m`: mermaid reads the whole
|
|
405
|
+
# "A-(//-B" as one actor and rejects the missing arrow; the
|
|
406
|
+
# recheck matched `arrow_base`'s reversed-arrow spelling
|
|
407
|
+
# mid-tail and stopped there instead, letting `->>` parse as a
|
|
408
|
+
# real arrow it should never have reached.
|
|
409
|
+
# `message_actor_continuation_tail_char` below is now the
|
|
410
|
+
# regex's OWN flat class, ported directly rather than built
|
|
411
|
+
# from etassia's existing rule references.
|
|
412
|
+
# - The entry lookahead itself was still incomplete: `arrow_base`
|
|
413
|
+
# (independently verified, unchanged across all four rounds)
|
|
414
|
+
# covers every COMPLETE arrow spelling, but mermaid's lookahead
|
|
415
|
+
# ALSO independently bans a bare `-/` and a bare `-\` even when
|
|
416
|
+
# nothing arrow-shaped ever follows — measured directly against
|
|
417
|
+
# the compiled lookahead: `"A-/ZZZ"` and `"A-\ZZZ"` both stop
|
|
418
|
+
# at `"A"`, same as `"A--ZZZ"`, while `"A-fooZZZ"`,
|
|
419
|
+
# `"A-(ZZZ"` and `"A-%ZZZ"` all continue past it. No
|
|
420
|
+
# `arrow_base` alternative is exactly "-/" or "-\" — every
|
|
421
|
+
# slash/backslash spelling in `reversed_arrow` needs a THIRD
|
|
422
|
+
# character etassia already covers, or a fourth like `-//`
|
|
423
|
+
# which `solid_arrow` already has. `-/` and `-\` alone were
|
|
424
|
+
# simply missing, so `B->>A-/(): m` and `B->>A-\(): m` fused
|
|
425
|
+
# the guard character into the identity instead of refusing.
|
|
426
|
+
# `message_actor_continuation_entry_stop` below adds exactly
|
|
427
|
+
# those two, verified empirically against every candidate
|
|
428
|
+
# prefix the compiled lookahead actually protects, not
|
|
429
|
+
# re-derived from the regex source text a second time (that is
|
|
430
|
+
# how `-/` was missed the first time — hand-reading nested
|
|
431
|
+
# backslash escapes in a 200-character alternation).
|
|
432
|
+
rule(:message_actor_continuation_entry_stop) do
|
|
433
|
+
arrow_base | str("--") | str("-/") | str("-\\")
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# The regex's own tail class, `[^\+<\->\->:\n,;]`, transliterated
|
|
437
|
+
# directly: excludes only `+ < - > : \n , ;`. No arrow-awareness,
|
|
438
|
+
# no `%%`/`@{` — those are etassia's OWN extensions for comments
|
|
439
|
+
# and shape metadata, real everywhere ELSE in this grammar, but
|
|
440
|
+
# never part of mermaid's ACTOR token and specifically NOT part
|
|
441
|
+
# of an already-open fusion tail (finding 1's `%%` case above).
|
|
442
|
+
# `\r` sits alongside `\n` because etassia's own `newline` rule
|
|
443
|
+
# (used elsewhere) accepts CRLF; excluding both characters
|
|
444
|
+
# individually gives the same boundary a rule-based check would,
|
|
445
|
+
# without needing a rule reference inside a character class.
|
|
446
|
+
rule(:message_actor_continuation_tail_char) do
|
|
447
|
+
match["^+<>:\n\r,;-"]
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
rule(:message_actor_continuation) do
|
|
451
|
+
message_actor_continuation_entry_stop.absent? >> str("-") >>
|
|
452
|
+
message_actor_continuation_tail_char.repeat(1)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# CORRECTED (round 5): the EOF case this comment used to justify
|
|
456
|
+
# keeping this branch no longer reaches a successful parse at all —
|
|
457
|
+
# `A->>B-` at true end of file now raises (spec: "rejects a
|
|
458
|
+
# trailing dash recipient at true end of file"), because THIS diff
|
|
459
|
+
# makes `message_text` mandatory. `message_actor_stop` never
|
|
460
|
+
# matches at true EOF, so the branch still consumes the trailing
|
|
461
|
+
# dash, but nothing is left to satisfy the now-required `: text`.
|
|
462
|
+
# Whether that makes the branch fully unreachable was not
|
|
463
|
+
# re-derived here — removing it is a separate, unverified change
|
|
464
|
+
# from the four rules this diff scopes; left in place rather than
|
|
465
|
+
# deleted on an unverified claim.
|
|
466
|
+
# A dash followed by `/` or `\` ends the name, as it does for a
|
|
467
|
+
# continuation: `A->>B-/C: m` and `A->>B-\C: m` are rejected.
|
|
468
|
+
rule(:message_actor_char) do
|
|
469
|
+
message_actor_stop.absent? >>
|
|
470
|
+
(match["^+<>()-"] |
|
|
471
|
+
(str("-") >>
|
|
472
|
+
(str("-") | str("/") | str("\\") | message_actor_stop).absent?))
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# `>` joins `<` as never message-actor material, in any position —
|
|
476
|
+
# not just leading. Measured: `A->>B>C: m` raises on mermaid
|
|
477
|
+
# (`got 'INVALID'`); base only excluded `>` from the immediate
|
|
478
|
+
# arrow-tail set below, not from `message_actor_char`, so it kept
|
|
479
|
+
# reading past an interior `>` and merged `B>C` into one actor.
|
|
480
|
+
#
|
|
481
|
+
# `\` joins the arrow-tail set for the same reason `/` is already
|
|
482
|
+
# there: a name cannot OPEN with it, because it also opens the
|
|
483
|
+
# reversed-arrow spellings (`\|-`, `\|--`, `\\-`, `\\--`).
|
|
484
|
+
# Measured: `A->>\B: m` raises on mermaid (`got 'INVALID'`); base
|
|
485
|
+
# accepted it and rendered actor `"\\B"`.
|
|
486
|
+
#
|
|
487
|
+
# `|` does NOT join this set: no arrow spelling starts with a bare
|
|
488
|
+
# `|` (the pipe-bearing spellings — `-|/`, `-|\`, `--|/`, `--|\` —
|
|
489
|
+
# all need a leading dash first, which `message_actor_lead` already
|
|
490
|
+
# never consumes). Measured against mermaid 11.16.1: `A-->|: m` and
|
|
491
|
+
# `A-x|: m` both give recipient `"|"` verbatim; a leading pipe is
|
|
492
|
+
# ordinary actor-name material, not a collision to protect against.
|
|
493
|
+
#
|
|
494
|
+
# The LEAD-only character rule for point 1 above: the plain
|
|
495
|
+
# character class only, deliberately WITHOUT `message_actor_char`'s
|
|
496
|
+
# dash branch, so a message actor name can never open with `-` —
|
|
497
|
+
# neither `-foo`, `-B`, `-()`, nor `- ()`. `hash_char.absent?` bans
|
|
498
|
+
# a LEADING bare `#` only — `message_actor_stop` no longer does,
|
|
499
|
+
# so a `#` past the first character stays ordinary name material
|
|
500
|
+
# (measured, `A->>B#C: m` gives recipient "B#C").
|
|
501
|
+
rule(:message_actor_lead_char) do
|
|
502
|
+
message_actor_stop.absent? >> hash_char.absent? >> match["^+<>()-"]
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
# `char_ref` is tried first so a name can OPEN with a character
|
|
506
|
+
# reference (`links #9829;B: {}`) — the reference is consumed
|
|
507
|
+
# whole, before `message_actor_lead_char`'s `#` ban would otherwise
|
|
508
|
+
# stop the plain branch at its very first character.
|
|
509
|
+
rule(:message_actor_lead) do
|
|
510
|
+
char_ref |
|
|
511
|
+
(match[")>/\\\\"].absent? >> mermaid_token_opener.absent? >>
|
|
512
|
+
message_actor_lead_char)
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
# Where mermaid's lexer starts a token, two of its rules run before
|
|
516
|
+
# its actor rule and take the text instead, so a message endpoint
|
|
517
|
+
# can never start with either:
|
|
518
|
+
#
|
|
519
|
+
# - `%` not opening `%{`: the rest of the line is a comment.
|
|
520
|
+
# `A->>%B: m` is rejected; `A->>%{x: m` is not.
|
|
521
|
+
# - a number followed by a space or newline: it is read as a
|
|
522
|
+
# number, not a name. `A->>8 : m` and `1 ->> 2: m` are rejected;
|
|
523
|
+
# `A->>8: m` and `A->>1.555 : m` (three decimals) are not.
|
|
524
|
+
#
|
|
525
|
+
# A `%%` right after an endpoint's first character needs no rule
|
|
526
|
+
# here: `%%` already ends the name, and the comment it opens leaves
|
|
527
|
+
# the message without its required `: text`.
|
|
528
|
+
rule(:mermaid_token_opener) do
|
|
529
|
+
(str("%") >> str("{").absent?) |
|
|
530
|
+
(lexed_number >> match[" \n"])
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
rule(:lexed_number) do
|
|
534
|
+
(match["0-9"].repeat(1) >>
|
|
535
|
+
(str(".") >> match["0-9"].repeat(1, 2)).maybe) |
|
|
536
|
+
(str(".") >> match["0-9"].repeat(1, 2))
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
# `message_actor_continuation` is tried only in the repeat below —
|
|
540
|
+
# never as part of `message_actor_lead` above — which combined
|
|
541
|
+
# with the lead using `message_actor_lead_char` (not
|
|
542
|
+
# `message_actor_char`) is what makes an empty prefix before a
|
|
543
|
+
# dash-fusion unreachable from either direction. Tried before the
|
|
544
|
+
# plain `message_actor_char` branch since it is the more specific
|
|
545
|
+
# case and Parslet alternation is first-match.
|
|
546
|
+
rule(:message_actor_name) do
|
|
547
|
+
message_actor_lead >> message_actor_run.repeat >>
|
|
548
|
+
message_actor_slash_fusion.maybe
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
rule(:message_actor_run) do
|
|
552
|
+
char_ref | message_actor_continuation |
|
|
553
|
+
(match["/\\\\"].absent? >> message_actor_char)
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
# Mermaid tests for a `/` or `\` arrow (`\|-`, `\\-`, ...) only
|
|
557
|
+
# where its name token ends or begins a run, which for these
|
|
558
|
+
# characters means the FIRST one in the name. A first one that
|
|
559
|
+
# opens no arrow joins the name and its flat tail, so a later
|
|
560
|
+
# spelling is name text: `Alice \\|- John: m` has no arrow and is
|
|
561
|
+
# rejected (oracle: sequencediagram_spec-97601112).
|
|
562
|
+
rule(:message_actor_slash_fusion) do
|
|
563
|
+
reversed_arrow.absent? >> match["/\\\\"] >>
|
|
564
|
+
(char_ref | message_actor_continuation |
|
|
565
|
+
(message_actor_fused_stop.absent? >> match["^+<>()-"])).repeat
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
rule(:message_actor_fused_stop) do
|
|
569
|
+
colon | comma | semicolon | str("%%") | str("@{") | lparen |
|
|
570
|
+
rparen | newline
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
# The decoration is parsed and discarded, not modeled — Etassia
|
|
574
|
+
# does not draw the central-connection marker, so only the
|
|
575
|
+
# phantom-actor bug needs closing here. No embedded whitespace
|
|
576
|
+
# rule of its own: the message rule wraps it in `space?` on both
|
|
577
|
+
# sides, matching jison's `()` token lexing in the
|
|
578
|
+
# whitespace-skipping INITIAL state (`A()->>B` and `A ()->>B`
|
|
579
|
+
# are both legal).
|
|
580
|
+
rule(:central_connection) { str("()") }
|
|
581
|
+
|
|
582
|
+
# Shape metadata (`@{"type":"boundary"}`) is captured whole as
|
|
583
|
+
# `:shape_metadata`; the builder reads only its `type`. It is not
|
|
584
|
+
# validated as JSON — a nested `{...}` on one line still ends
|
|
585
|
+
# the payload at its first `}` (no corpus case has one). Bounded
|
|
586
|
+
# to one line — `newline.absent?` is load-bearing, not tidiness:
|
|
587
|
+
# an unclosed `@{` would otherwise scan into a later statement's
|
|
588
|
+
# closing brace and silently discard everything between, rather
|
|
589
|
+
# than raising. `repeat(1)`, not `repeat`: mermaid rejects an
|
|
590
|
+
# empty `@{}`, so the payload must not be empty either.
|
|
591
|
+
rule(:shape_metadata) do
|
|
592
|
+
str("@{") >>
|
|
593
|
+
(str("}").absent? >> newline.absent? >> any).repeat(1) >>
|
|
594
|
+
str("}")
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# Participant declarations. `keyword` and `id`/`label` are shared
|
|
598
|
+
# by the plain declarations below and by `create_statement`, so
|
|
599
|
+
# `create participant Carl` inherits `declaration_name`'s char-ref
|
|
600
|
+
# fix for free the same way a bare `participant Carl` does — a
|
|
601
|
+
# private method, not `rule()`, since only the TERMINATOR differs
|
|
602
|
+
# between the two callers (see `create_statement`'s comment).
|
|
603
|
+
def declaration_body(keyword)
|
|
604
|
+
declaration_keyword(keyword) >> declaration_identity >>
|
|
605
|
+
declaration_label.maybe
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
def declaration_keyword(keyword)
|
|
609
|
+
str(keyword) >> space.repeat(1)
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def declaration_identity
|
|
613
|
+
declaration_name.as(:id) >>
|
|
614
|
+
shape_metadata.as(:shape_metadata).maybe >> space?
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def declaration_label
|
|
618
|
+
str("as") >> space.repeat(1) >> label.as(:label)
|
|
619
|
+
end
|
|
620
|
+
private :declaration_body, :declaration_keyword,
|
|
621
|
+
:declaration_identity, :declaration_label
|
|
622
|
+
|
|
623
|
+
# Ends at `content_boundary`, not `line_end` — a declaration can be
|
|
624
|
+
# followed by another statement on the same line after a `;`, and
|
|
625
|
+
# `line_end` only accepts one right before a newline. Measured
|
|
626
|
+
# against mermaid 11.16.1: `participant A;participant B;A->>B: m`
|
|
627
|
+
# gives 2 participants, 1 message; `line_end` alone rejected it
|
|
628
|
+
# outright, since it has nowhere to put the text still left after
|
|
629
|
+
# its own leading `;`.
|
|
630
|
+
rule(:participant_declaration) do
|
|
631
|
+
declaration_body("participant") >> content_boundary.as(:participant)
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
rule(:actor_declaration) do
|
|
635
|
+
declaration_body("actor") >> content_boundary.as(:actor)
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
# `.as(:create)` is required: the builder's lifecycle check (see
|
|
639
|
+
# `Builders::Sequence`) branches on this key to register the
|
|
640
|
+
# pending create; without it a `create` is silently unchecked.
|
|
641
|
+
# Same `content_boundary` terminator as the two plain declarations
|
|
642
|
+
# above, for the same inline-`;` reason. Measured against mermaid
|
|
643
|
+
# 11.16.1: `create participant B;A->>B: m` gives 2 participants,
|
|
644
|
+
# 1 message.
|
|
645
|
+
rule(:create_statement) do
|
|
646
|
+
str("create").as(:create) >> space.repeat(1) >>
|
|
647
|
+
(
|
|
648
|
+
(declaration_body("participant") >>
|
|
649
|
+
content_boundary.as(:participant)) |
|
|
650
|
+
(declaration_body("actor") >> content_boundary.as(:actor))
|
|
651
|
+
)
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
# Draws no destroy marker (etassia's existing "not modeled" stance
|
|
655
|
+
# on decorative constructs) — `.as(:destroy)` still captures the
|
|
656
|
+
# target id because the lifecycle check needs it to register the
|
|
657
|
+
# pending destroy against the very next message.
|
|
658
|
+
#
|
|
659
|
+
# Ends at `content_boundary` for the same inline-`;` reason as
|
|
660
|
+
# `create_statement` above: `destroy B;A->>B: m` gives 2
|
|
661
|
+
# participants, 1 message on mermaid 11.16.1; `line_end` alone
|
|
662
|
+
# rejected it.
|
|
663
|
+
rule(:destroy_statement) do
|
|
664
|
+
str("destroy") >> space.repeat(1) >>
|
|
665
|
+
declaration_name.as(:destroy) >> content_boundary
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
# Target uses `message_actor_name`, not `declaration_name` like
|
|
669
|
+
# `participant`/`actor`/`destroy` — don't "fix" that; its bans on
|
|
670
|
+
# `()`/`#`/leading dash come from `message_actor_stop`/
|
|
671
|
+
# `message_actor_lead_char`. `.as(:links)` looks unread but isn't:
|
|
672
|
+
# the builder uses it to call `ensure_participant`. Payload is
|
|
673
|
+
# unvalidated JSON, like `shape_metadata`, and stops at
|
|
674
|
+
# `content_boundary` (not `rest_of_line`) so an inline `;` always
|
|
675
|
+
# yields the following message instead of swallowing it.
|
|
676
|
+
rule(:links_statement) do
|
|
677
|
+
str("links") >> space.repeat(1) >>
|
|
678
|
+
message_actor_name.as(:links) >> colon >> text_run >>
|
|
679
|
+
content_boundary
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
# Messages with arrows (order matters: longest patterns first)
|
|
683
|
+
rule(:message) do
|
|
684
|
+
message_actor_name.as(:from) >> space? >>
|
|
685
|
+
message_signal.as(:arrow) >> space? >>
|
|
686
|
+
message_actor_name.as(:to) >> space? >>
|
|
687
|
+
message_text.as(:text) >>
|
|
688
|
+
content_boundary
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
# A central-connection decoration and an activation suffix never
|
|
692
|
+
# coexist on the same message — measured against mermaid 11.16.1
|
|
693
|
+
# directly: `A->>+()B`, `A->>()+B`, `A()->>+B`, `A<<->>+()B` and
|
|
694
|
+
# `A<<->>()+B` all raise ("Expecting 'ACTOR'"/"'+'"/"'-'"),
|
|
695
|
+
# whichever side carries the decoration and whichever carries the
|
|
696
|
+
# suffix. `A-()->>+B` only looks like a counterexample: there the
|
|
697
|
+
# `()` is fused into the FROM actor's own identity by
|
|
698
|
+
# `message_actor_paren_unit` above, so no real central connection
|
|
699
|
+
# reaches this rule at all, and the plain third branch below
|
|
700
|
+
# applies instead.
|
|
701
|
+
#
|
|
702
|
+
# A branch with `()` present therefore uses `arrow_base` alone —
|
|
703
|
+
# no `activation_suffix` component exists to try. Parslet
|
|
704
|
+
# alternation is first-match, so the connection branches are tried
|
|
705
|
+
# before the plain one; `central_connection` stays uncaptured
|
|
706
|
+
# here, same as before this rule existed — it is parsed and
|
|
707
|
+
# discarded either way.
|
|
708
|
+
rule(:message_signal) do
|
|
709
|
+
(central_connection >> space? >> arrow_base.as(:arrow_base) >>
|
|
710
|
+
space? >> central_connection.maybe) |
|
|
711
|
+
(arrow_base.as(:arrow_base) >> space? >> central_connection) |
|
|
712
|
+
arrow
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
# Arrow types including activation modifiers
|
|
716
|
+
# Critical: These must be tried in order from longest to shortest
|
|
717
|
+
rule(:arrow) do
|
|
718
|
+
arrow_base.as(:arrow_base) >> activation_suffix.maybe.as(:activation)
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
# Every spelling mmdc 11.12.0 renders, and only those. Half and
|
|
722
|
+
# stick heads come in a reversed spelling too, which puts the marker
|
|
723
|
+
# on the source end: `A//-B` and `A-//B` draw the same head at
|
|
724
|
+
# opposite ends of the line.
|
|
725
|
+
#
|
|
726
|
+
# `->|` and `-->|` are NOT arrows. mmdc reads `A->|B` as `->` into
|
|
727
|
+
# an actor named `|B`, so treating the pipe as part of the arrow
|
|
728
|
+
# named the wrong participant.
|
|
729
|
+
#
|
|
730
|
+
# Parslet alternation is first-match, so a genuine prefix pair has
|
|
731
|
+
# to be listed longest-first: `-->` before `-->>` would swallow it,
|
|
732
|
+
# and so would `//-` before `//--`. Nothing else here shadows —
|
|
733
|
+
# no solid arrow's second character is a dash, so the families are
|
|
734
|
+
# order-independent between themselves.
|
|
735
|
+
rule(:arrow_base) do
|
|
736
|
+
str("<<-->>") | str("<<->>") |
|
|
737
|
+
dotted_arrow | solid_arrow | reversed_arrow
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
rule(:dotted_arrow) do
|
|
741
|
+
str("-->>") | str("--|/") | str("--|\\") | str("--//") |
|
|
742
|
+
str("--\\\\") | str("--x") | str("--X") | str("--)") | str("-->")
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
rule(:solid_arrow) do
|
|
746
|
+
str("->>") | str("-|/") | str("-|\\") | str("-//") |
|
|
747
|
+
str("-\\\\") | str("-x") | str("-X") | str("-)") | str("->")
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
rule(:reversed_arrow) do
|
|
751
|
+
str("/|--") | str("/|-") | str('\\|--') | str('\\|-') |
|
|
752
|
+
str("//--") | str("//-") | str('\\\\--') | str('\\\\-')
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
rule(:activation_suffix) { space? >> match["+-"] }
|
|
756
|
+
|
|
757
|
+
rule(:message_text) do
|
|
758
|
+
colon >> space? >>
|
|
759
|
+
text_run.as(:message_text)
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
# Notes
|
|
763
|
+
rule(:note_statement) do
|
|
764
|
+
(str("note") | str("Note")) >> space.repeat(1) >>
|
|
765
|
+
note_position.as(:position) >> space.repeat(1) >>
|
|
766
|
+
note_participants.as(:participants) >> space? >>
|
|
767
|
+
colon >> space? >>
|
|
768
|
+
text_run.as(:note_text) >>
|
|
769
|
+
content_boundary
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
rule(:note_position) do
|
|
773
|
+
(str("left") >> space.repeat(1) >> str("of")).as(:left_of) |
|
|
774
|
+
(str("right") >> space.repeat(1) >> str("of")).as(:right_of) |
|
|
775
|
+
str("over").as(:over)
|
|
776
|
+
end
|
|
777
|
+
|
|
778
|
+
rule(:note_participants) do
|
|
779
|
+
actor_name.as(:participant) >>
|
|
780
|
+
(space? >> comma >> space? >>
|
|
781
|
+
actor_name.as(:participant)).repeat
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
# Activation/Deactivation commands. Widened to `actor_name` for
|
|
785
|
+
# construct completeness: an actor name is one construct, and
|
|
786
|
+
# leaving these two sites on `identifier` would make
|
|
787
|
+
# `participant 1` parse while `activate 1` failed on the very same
|
|
788
|
+
# actor.
|
|
789
|
+
rule(:activation_command) do
|
|
790
|
+
str("activate") >> space.repeat(1) >>
|
|
791
|
+
actor_name.as(:activate) >>
|
|
792
|
+
line_end
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
rule(:deactivation_command) do
|
|
796
|
+
str("deactivate") >> space.repeat(1) >>
|
|
797
|
+
actor_name.as(:deactivate) >>
|
|
798
|
+
line_end
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
# Box grouping
|
|
802
|
+
rule(:box_statement) do
|
|
803
|
+
str("box") >> space.repeat(1) >>
|
|
804
|
+
text_run.as(:box_label) >> content_boundary >>
|
|
805
|
+
ws? >>
|
|
806
|
+
statements.as(:box_statements) >>
|
|
807
|
+
ws? >>
|
|
808
|
+
str("end") >> line_end
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
# Control structures
|
|
812
|
+
rule(:control_structure) do
|
|
813
|
+
loop_structure |
|
|
814
|
+
alt_structure |
|
|
815
|
+
opt_structure |
|
|
816
|
+
rect_structure |
|
|
817
|
+
par_structure |
|
|
818
|
+
critical_structure |
|
|
819
|
+
break_structure
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
rule(:loop_structure) do
|
|
823
|
+
str("loop") >> space? >>
|
|
824
|
+
text_run.as(:loop_label) >> content_boundary >>
|
|
825
|
+
ws? >>
|
|
826
|
+
statements.as(:loop_statements) >>
|
|
827
|
+
ws? >>
|
|
828
|
+
str("end") >> line_end
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
# Every block-opening/continuation label (this one through
|
|
832
|
+
# `break_label`) must use `text_run`, never its own end-of-line
|
|
833
|
+
# scan: mermaid's real lexer tokenizes all of them — `loop`, `alt`,
|
|
834
|
+
# `else`, `opt`, `par`, `and`, `critical`, `option`, `break`, `box`
|
|
835
|
+
# — through one shared state whose label rule stops at `;`. `rect`
|
|
836
|
+
# is a separate rule, see `rect_structure`.
|
|
837
|
+
rule(:alt_structure) do
|
|
838
|
+
str("alt") >> space? >>
|
|
839
|
+
text_run.as(:alt_label) >> content_boundary >>
|
|
840
|
+
ws? >>
|
|
841
|
+
statements.as(:alt_statements) >>
|
|
842
|
+
ws? >>
|
|
843
|
+
(
|
|
844
|
+
str("else") >> space? >>
|
|
845
|
+
text_run.as(:else_label) >> content_boundary >>
|
|
846
|
+
ws? >>
|
|
847
|
+
statements.as(:else_statements) >>
|
|
848
|
+
ws?
|
|
849
|
+
).repeat.as(:else_blocks) >>
|
|
850
|
+
str("end") >> line_end
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
# `match['a-zA-Z0-9_'].absent?` after the literal `opt` is a real
|
|
854
|
+
# word-boundary guard, not just a bare literal: without it, this
|
|
855
|
+
# rule matches `opt` as a PREFIX of `option` (case 041's
|
|
856
|
+
# `option Network timeout` line inside a `critical` block was
|
|
857
|
+
# misread as a nested `opt` with label `"ion Network timeout"`,
|
|
858
|
+
# consuming the real closing `end` and breaking the whole parse).
|
|
859
|
+
# Verified mermaid also rejects a glued `optFoo`.
|
|
860
|
+
rule(:opt_structure) do
|
|
861
|
+
str("opt") >> match["a-zA-Z0-9_"].absent? >> space? >>
|
|
862
|
+
text_run.as(:opt_label) >> content_boundary >>
|
|
863
|
+
ws? >>
|
|
864
|
+
statements.as(:opt_statements) >>
|
|
865
|
+
ws? >>
|
|
866
|
+
str("end") >> line_end
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
# `rect <colour>` highlights the statements it wraps. The colour is
|
|
870
|
+
# parsed like any block label and dropped, as for `opt`, `loop` and
|
|
871
|
+
# the other frames: only the statements inside are kept.
|
|
872
|
+
rule(:rect_structure) do
|
|
873
|
+
str("rect") >> match["a-zA-Z0-9_"].absent? >> space? >>
|
|
874
|
+
text_run.as(:rect_label) >> content_boundary >>
|
|
875
|
+
ws? >>
|
|
876
|
+
statements.as(:rect_statements) >>
|
|
877
|
+
ws? >>
|
|
878
|
+
str("end") >> line_end
|
|
879
|
+
end
|
|
880
|
+
|
|
881
|
+
rule(:par_structure) do
|
|
882
|
+
str("par") >> space? >>
|
|
883
|
+
text_run.as(:par_label) >> content_boundary >>
|
|
884
|
+
ws? >>
|
|
885
|
+
statements.as(:par_statements) >>
|
|
886
|
+
ws? >>
|
|
887
|
+
(
|
|
888
|
+
str("and") >> space? >>
|
|
889
|
+
text_run.as(:and_label) >> content_boundary >>
|
|
890
|
+
ws? >>
|
|
891
|
+
statements.as(:and_statements) >>
|
|
892
|
+
ws?
|
|
893
|
+
).repeat.as(:and_blocks) >>
|
|
894
|
+
str("end") >> line_end
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
rule(:critical_structure) do
|
|
898
|
+
str("critical") >> space? >>
|
|
899
|
+
text_run.as(:critical_label) >> content_boundary >>
|
|
900
|
+
ws? >>
|
|
901
|
+
statements.as(:critical_statements) >>
|
|
902
|
+
ws? >>
|
|
903
|
+
(
|
|
904
|
+
str("option") >> space? >>
|
|
905
|
+
text_run.as(:option_label) >> content_boundary >>
|
|
906
|
+
ws? >>
|
|
907
|
+
statements.as(:option_statements) >>
|
|
908
|
+
ws?
|
|
909
|
+
).repeat.as(:option_blocks) >>
|
|
910
|
+
str("end") >> line_end
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
rule(:break_structure) do
|
|
914
|
+
str("break") >> space? >>
|
|
915
|
+
text_run.as(:break_label) >> content_boundary >>
|
|
916
|
+
ws? >>
|
|
917
|
+
statements.as(:break_statements) >>
|
|
918
|
+
ws? >>
|
|
919
|
+
str("end") >> line_end
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
# mmdc keeps the quotes of `as "x"` in the label (measured, see
|
|
923
|
+
# spec/etassia/parser/sequence_alias_quotes_spec.rb), so a quoted
|
|
924
|
+
# alias is ordinary text, never a `string`.
|
|
925
|
+
rule(:label) { unquoted_label }
|
|
926
|
+
|
|
927
|
+
# Only caller is `declaration_body`'s alias branch, shared by
|
|
928
|
+
# `participant`/`actor`/`create`. Stops at an inline `;` for the
|
|
929
|
+
# same reason `declaration_body`'s own terminator does below —
|
|
930
|
+
# without it, `participant B as Bee;A->>B: m` reads the whole
|
|
931
|
+
# `;A->>B: m` into the label instead of leaving it for the next
|
|
932
|
+
# statement. Measured against mermaid 11.16.1: `B` gets label
|
|
933
|
+
# "Bee", and `A->>B: m` parses as a separate message.
|
|
934
|
+
rule(:unquoted_label) do
|
|
935
|
+
(char_ref | (line_end.absent? >> semicolon.absent? >> any)).repeat(1)
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
end
|
|
939
|
+
end
|
|
940
|
+
end
|