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,419 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "base"
|
|
5
|
+
require_relative "containment"
|
|
6
|
+
|
|
7
|
+
module Etassia
|
|
8
|
+
module Diagram
|
|
9
|
+
# Represents a flowchart node.
|
|
10
|
+
#
|
|
11
|
+
# A node has an identifier, label text, and a shape type that
|
|
12
|
+
# determines how it should be rendered visually.
|
|
13
|
+
class FlowchartNode < Lutaml::Model::Serializable
|
|
14
|
+
# Unique identifier for the node
|
|
15
|
+
attribute :id, :string
|
|
16
|
+
|
|
17
|
+
# Display text/label for the node
|
|
18
|
+
attribute :label, :string
|
|
19
|
+
|
|
20
|
+
# Shape type: :rect, :rounded, :stadium, :subroutine, :cylindrical,
|
|
21
|
+
# :circle, :asymmetric, :rhombus, :hexagon, :parallelogram,
|
|
22
|
+
# :parallelogram_alt, :trapezoid, :trapezoid_alt, :double_circle
|
|
23
|
+
attribute :shape, :string
|
|
24
|
+
|
|
25
|
+
# Optional classes/styles
|
|
26
|
+
attribute :classes, :string
|
|
27
|
+
attribute :fill, :string
|
|
28
|
+
attribute :stroke, :string
|
|
29
|
+
|
|
30
|
+
PAINT_KEYWORDS = %w[
|
|
31
|
+
none currentcolor transparent aliceblue antiquewhite aqua aquamarine
|
|
32
|
+
azure beige bisque black blanchedalmond blue blueviolet brown burlywood
|
|
33
|
+
cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson
|
|
34
|
+
cyan darkblue darkcyan darkgoldenrod darkgray darkgrey darkgreen
|
|
35
|
+
darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred
|
|
36
|
+
darksalmon darkseagreen darkslateblue darkslategray darkslategrey
|
|
37
|
+
darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue
|
|
38
|
+
firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold
|
|
39
|
+
goldenrod gray grey green greenyellow honeydew hotpink indianred indigo
|
|
40
|
+
ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue
|
|
41
|
+
lightcoral lightcyan lightgoldenrodyellow lightgray lightgrey lightgreen
|
|
42
|
+
lightpink lightsalmon lightseagreen lightskyblue lightslategray
|
|
43
|
+
lightslategrey lightsteelblue lightyellow lime limegreen linen magenta
|
|
44
|
+
maroon mediumaquamarine mediumblue mediumorchid mediumpurple
|
|
45
|
+
mediumseagreen mediumslateblue mediumspringgreen mediumturquoise
|
|
46
|
+
mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite
|
|
47
|
+
navy oldlace olive olivedrab orange orangered orchid palegoldenrod
|
|
48
|
+
palegreen paleturquoise palevioletred papayawhip peachpuff peru pink
|
|
49
|
+
plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown
|
|
50
|
+
salmon sandybrown seagreen seashell sienna silver skyblue slateblue
|
|
51
|
+
slategray slategrey snow springgreen steelblue tan teal thistle tomato
|
|
52
|
+
turquoise violet wheat white whitesmoke yellow yellowgreen
|
|
53
|
+
].freeze
|
|
54
|
+
HEX_PAINT = /\A#(?:[0-9a-f]{3}|[0-9a-f]{6})\z/i
|
|
55
|
+
RGB_COMPONENT = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)%?/
|
|
56
|
+
RGB_PAINT = /\Argb\(\s*#{RGB_COMPONENT}\s*,
|
|
57
|
+
\s*#{RGB_COMPONENT}\s*,\s*#{RGB_COMPONENT}\s*\)\z/ix
|
|
58
|
+
private_constant :PAINT_KEYWORDS, :HEX_PAINT, :RGB_COMPONENT, :RGB_PAINT
|
|
59
|
+
|
|
60
|
+
# Invalid CSS declarations leave the earlier paint in force. Keep the
|
|
61
|
+
# supported opaque color forms separate from permissive parser tails.
|
|
62
|
+
def self.paint_value(value)
|
|
63
|
+
paint = value.to_s.strip
|
|
64
|
+
return paint if PAINT_KEYWORDS.include?(paint.downcase)
|
|
65
|
+
return paint if HEX_PAINT.match?(paint) || RGB_PAINT.match?(paint)
|
|
66
|
+
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Initialize with default shape
|
|
71
|
+
def initialize(*args)
|
|
72
|
+
super
|
|
73
|
+
self.shape ||= "rect"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Validates the node has required attributes.
|
|
77
|
+
#
|
|
78
|
+
# @return [Boolean] true if node is valid
|
|
79
|
+
def valid?
|
|
80
|
+
!id.nil? && !id.empty? && !label.nil?
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Represents a flowchart edge (connection between nodes).
|
|
85
|
+
#
|
|
86
|
+
# An edge connects a source node to a target node, with optional
|
|
87
|
+
# label text and arrow styling.
|
|
88
|
+
class FlowchartEdge < Lutaml::Model::Serializable
|
|
89
|
+
# Source node identifier
|
|
90
|
+
attribute :source_id, :string
|
|
91
|
+
|
|
92
|
+
# Target node identifier
|
|
93
|
+
attribute :target_id, :string
|
|
94
|
+
|
|
95
|
+
# Optional edge label
|
|
96
|
+
attribute :label, :string
|
|
97
|
+
|
|
98
|
+
# Arrow type: the head part, optionally prefixed by the line's
|
|
99
|
+
# weight. The head part is `line` for none, or `arrow`, `cross` or
|
|
100
|
+
# `circle`; a `_both` suffix marks the head as drawn at both ends.
|
|
101
|
+
# Weights are `thick_` and `dotted_`. `invisible` carries neither.
|
|
102
|
+
attribute :arrow_type, :string
|
|
103
|
+
|
|
104
|
+
# Minimum number of layout ranks crossed by an explicitly long link.
|
|
105
|
+
# nil is the ordinary one-rank Mermaid default.
|
|
106
|
+
attribute :minimum_rank_span, :integer
|
|
107
|
+
|
|
108
|
+
# Initialize with default arrow type
|
|
109
|
+
def initialize(*args)
|
|
110
|
+
super
|
|
111
|
+
self.arrow_type ||= "arrow"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Validates the edge has required attributes.
|
|
115
|
+
#
|
|
116
|
+
# @return [Boolean] true if edge is valid
|
|
117
|
+
def valid?
|
|
118
|
+
!source_id.nil? && !source_id.empty? &&
|
|
119
|
+
!target_id.nil? && !target_id.empty?
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# A subgraph groups nodes under a titled box. mermaid draws it as a
|
|
124
|
+
# cluster painted behind the edges and nodes it contains.
|
|
125
|
+
#
|
|
126
|
+
# Nodes and edges stay in the diagram's own flat collections — a
|
|
127
|
+
# subgraph names its members rather than owning them, so an edge
|
|
128
|
+
# crossing a boundary needs no special case.
|
|
129
|
+
class FlowchartSubgraph < Lutaml::Model::Serializable
|
|
130
|
+
# Identifier, as written or generated by mermaid
|
|
131
|
+
attribute :id, :string
|
|
132
|
+
|
|
133
|
+
# The label mermaid draws, resolved by the transform because the
|
|
134
|
+
# rule depends on how the title was written. Often absent: read
|
|
135
|
+
# `title`, which falls back to the id, so `subgraph s` reads "s".
|
|
136
|
+
attribute :declared_title, :string
|
|
137
|
+
|
|
138
|
+
# Enclosing subgraph's id, nil at the top level
|
|
139
|
+
attribute :parent_id, :string
|
|
140
|
+
|
|
141
|
+
# Ids of the nodes declared directly inside this subgraph
|
|
142
|
+
attribute :node_ids, :string, collection: true, default: -> { [] }
|
|
143
|
+
|
|
144
|
+
# Ids of the subgraphs declared directly inside this subgraph
|
|
145
|
+
attribute :child_ids, :string, collection: true, default: -> { [] }
|
|
146
|
+
|
|
147
|
+
# `direction` written inside the box, which turns its contents
|
|
148
|
+
# independently of the diagram's own direction. nil when unwritten.
|
|
149
|
+
#
|
|
150
|
+
# Read by nothing yet, so it changes nothing on the page. The
|
|
151
|
+
# fallback grid ignores layout options entirely, and the diagram's
|
|
152
|
+
# OWN `direction` is dropped the same way: `flowchart LR` puts its
|
|
153
|
+
# nodes exactly where `flowchart TD` does. Both start working
|
|
154
|
+
# together when the real layout engine lands. Keeping the value
|
|
155
|
+
# here means the source is not thrown away in the meantime.
|
|
156
|
+
attribute :direction, :string
|
|
157
|
+
|
|
158
|
+
# A method rather than a constructor default: the id is usually
|
|
159
|
+
# assigned after construction, so a fallback baked into initialize
|
|
160
|
+
# would have already seen nil and stuck with it.
|
|
161
|
+
#
|
|
162
|
+
# @return [String] the label to draw on the cluster
|
|
163
|
+
def title
|
|
164
|
+
declared_title.nil? || declared_title.empty? ? id : declared_title
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# mermaid draws no cluster for a subgraph holding nothing, even
|
|
168
|
+
# though it accepts the source.
|
|
169
|
+
#
|
|
170
|
+
# @return [Boolean] true when there is a box worth drawing
|
|
171
|
+
def drawable?
|
|
172
|
+
!node_ids.empty? || !child_ids.empty?
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Validates the subgraph names itself.
|
|
176
|
+
#
|
|
177
|
+
# Everything downstream keys off the id: the layout hangs children
|
|
178
|
+
# on it, the renderer writes it into the cluster's group id, and an
|
|
179
|
+
# edge end that names a box finds it by id. A box with no id draws
|
|
180
|
+
# a cluster nobody can reach, so it is refused here instead.
|
|
181
|
+
#
|
|
182
|
+
# @return [Boolean] true if the subgraph is valid
|
|
183
|
+
def valid?
|
|
184
|
+
!id.nil? && !id.empty?
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Flowchart diagram model.
|
|
189
|
+
#
|
|
190
|
+
# Represents a complete flowchart with nodes and edges. Flowcharts
|
|
191
|
+
# support various node shapes and edge types to create flow diagrams,
|
|
192
|
+
# decision trees, and process flows.
|
|
193
|
+
#
|
|
194
|
+
# @example Creating a simple flowchart
|
|
195
|
+
# flowchart = Flowchart.new(direction: 'TD')
|
|
196
|
+
# flowchart.nodes << FlowchartNode.new(
|
|
197
|
+
# id: 'A',
|
|
198
|
+
# label: 'Start',
|
|
199
|
+
# shape: 'stadium'
|
|
200
|
+
# )
|
|
201
|
+
# flowchart.nodes << FlowchartNode.new(
|
|
202
|
+
# id: 'B',
|
|
203
|
+
# label: 'Process',
|
|
204
|
+
# shape: 'rect'
|
|
205
|
+
# )
|
|
206
|
+
# flowchart.edges << FlowchartEdge.new(
|
|
207
|
+
# source_id: 'A',
|
|
208
|
+
# target_id: 'B',
|
|
209
|
+
# arrow_type: 'arrow'
|
|
210
|
+
# )
|
|
211
|
+
class Flowchart < Base
|
|
212
|
+
# Collection of nodes in the flowchart
|
|
213
|
+
attribute :nodes, FlowchartNode, collection: true, default: -> { [] }
|
|
214
|
+
|
|
215
|
+
# Collection of edges connecting nodes
|
|
216
|
+
attribute :edges, FlowchartEdge, collection: true, default: -> { [] }
|
|
217
|
+
|
|
218
|
+
# Subgraphs, flat and in declaration order. Nesting is expressed by
|
|
219
|
+
# `parent_id` rather than by containment, so a lookup never has to
|
|
220
|
+
# walk a tree.
|
|
221
|
+
attribute :subgraphs, FlowchartSubgraph, collection: true,
|
|
222
|
+
default: -> { [] }
|
|
223
|
+
|
|
224
|
+
# Returns the diagram type identifier.
|
|
225
|
+
#
|
|
226
|
+
# @return [Symbol] :flowchart
|
|
227
|
+
def diagram_type
|
|
228
|
+
:flowchart
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# Validates the flowchart structure.
|
|
232
|
+
#
|
|
233
|
+
# A flowchart is valid if:
|
|
234
|
+
# - `nodes` is set (mermaid draws a source with none at all, but an
|
|
235
|
+
# explicit `nil` here is a caller bug, not a real diagram)
|
|
236
|
+
# - No box is its own ancestor
|
|
237
|
+
# - A flowchart with no nodes is valid only if it also declares no
|
|
238
|
+
# subgraph: mermaid draws a bare `graph TD` as an empty canvas, but
|
|
239
|
+
# draws a declared-and-empty subgraph (`subgraph s\nend`) as a
|
|
240
|
+
# fallback node this model has no way to represent, so that shape
|
|
241
|
+
# is refused instead of silently dropped
|
|
242
|
+
# - All nodes are valid
|
|
243
|
+
# - All edges are valid
|
|
244
|
+
# - All subgraphs are valid
|
|
245
|
+
# - Every member a box names is in the diagram
|
|
246
|
+
# - `parent_id` and `child_ids` tell the same story
|
|
247
|
+
# - Every edge end names a node, or a subgraph that gets drawn
|
|
248
|
+
#
|
|
249
|
+
# @return [Boolean] true if flowchart is valid
|
|
250
|
+
def valid?
|
|
251
|
+
return false if nodes.nil?
|
|
252
|
+
|
|
253
|
+
boxes = subgraphs || []
|
|
254
|
+
structure_valid?(boxes) && references_resolve?(boxes)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Finds a node by its identifier.
|
|
258
|
+
#
|
|
259
|
+
# @param id [String] the node identifier to find
|
|
260
|
+
# @return [FlowchartNode, nil] the node or nil if not found
|
|
261
|
+
def find_node(id)
|
|
262
|
+
nodes.find { |n| n.id == id }
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Finds all edges originating from a specific node.
|
|
266
|
+
#
|
|
267
|
+
# @param node_id [String] the source node identifier
|
|
268
|
+
# @return [Array<FlowchartEdge>] edges from the node
|
|
269
|
+
def edges_from(node_id)
|
|
270
|
+
edges.select { |e| e.source_id == node_id }
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# Finds all edges targeting a specific node.
|
|
274
|
+
#
|
|
275
|
+
# @param node_id [String] the target node identifier
|
|
276
|
+
# @return [Array<FlowchartEdge>] edges to the node
|
|
277
|
+
def edges_to(node_id)
|
|
278
|
+
edges.select { |e| e.target_id == node_id }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
private
|
|
282
|
+
|
|
283
|
+
def structure_valid?(boxes)
|
|
284
|
+
!parent_cycle?(boxes) && collections_valid?(boxes) &&
|
|
285
|
+
containment_valid?(boxes)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def collections_valid?(boxes)
|
|
289
|
+
nodes.all?(&:valid?) && valid_collection?(edges) &&
|
|
290
|
+
boxes.all?(&:valid?)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def containment_valid?(boxes)
|
|
294
|
+
members_named?(boxes, nodes) && nesting_agrees?(boxes)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def valid_collection?(items)
|
|
298
|
+
items.nil? || items.all?(&:valid?)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# An edge may name a subgraph rather than a node: mermaid joins
|
|
302
|
+
# the cluster boxes and draws no node for either end. Only a box
|
|
303
|
+
# that gets drawn is carried into the layout and can be reached.
|
|
304
|
+
def references_resolve?(boxes)
|
|
305
|
+
drawn_box_ids = drawable_box_ids(boxes)
|
|
306
|
+
return false if only_undrawable_boxes?(boxes, drawn_box_ids)
|
|
307
|
+
|
|
308
|
+
edge_references_resolve?(nodes.map(&:id) + drawn_box_ids)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def drawable_box_ids(boxes)
|
|
312
|
+
boxes.filter_map { |box| box.id if box.drawable? }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def only_undrawable_boxes?(boxes, drawn_box_ids)
|
|
316
|
+
boxes.any? && nodes.empty? && drawn_box_ids.empty?
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def edge_references_resolve?(known)
|
|
320
|
+
edges.nil? || edges.all? do |edge|
|
|
321
|
+
known.include?(edge.source_id) && known.include?(edge.target_id)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# A box names its members rather than owning them, so a name that
|
|
326
|
+
# matches nothing leaves the box holding an empty seat: the box
|
|
327
|
+
# counts as drawable, the layout sizes it around no contents, and
|
|
328
|
+
# the picture shows a cluster with nothing in it.
|
|
329
|
+
#
|
|
330
|
+
# A member may name a node or another box. An empty subgraph stays
|
|
331
|
+
# a plain node in mermaid, so both spellings come out of a parse.
|
|
332
|
+
#
|
|
333
|
+
# @param boxes [Array<FlowchartSubgraph>] the diagram's subgraphs
|
|
334
|
+
# @param drawn_nodes [Array<FlowchartNode>] the diagram's nodes
|
|
335
|
+
# @return [Boolean] true when every named member is present
|
|
336
|
+
def members_named?(boxes, drawn_nodes)
|
|
337
|
+
# A hash rather than an array scan: one box can hold thousands of
|
|
338
|
+
# members, and asking an array for each of them is quadratic.
|
|
339
|
+
known = {}
|
|
340
|
+
drawn_nodes.each { |node| known[node.id] = true }
|
|
341
|
+
boxes.each { |box| known[box.id] = true }
|
|
342
|
+
|
|
343
|
+
boxes.all? do |box|
|
|
344
|
+
box.node_ids.all? { |member_id| known.key?(member_id) }
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# `parent_id` and `child_ids` say the same thing from two ends, and
|
|
349
|
+
# the drawing believes both. The transform hangs a box off its
|
|
350
|
+
# `parent_id`, while `drawable?` counts `child_ids` — so a box
|
|
351
|
+
# listed as a child but pointing nowhere is drawn twice, and one
|
|
352
|
+
# pointing at a parent that does not list it stops the parent from
|
|
353
|
+
# being drawn at all. Nothing keeps the two in step on a model
|
|
354
|
+
# somebody builds by hand, so a model that argues with itself is
|
|
355
|
+
# refused here rather than drawn wrong.
|
|
356
|
+
#
|
|
357
|
+
# A parent nobody declared is not a disagreement: the transform
|
|
358
|
+
# puts such a box at the top level on purpose.
|
|
359
|
+
#
|
|
360
|
+
# Ids are looked up as groups, not one apiece, because a source may
|
|
361
|
+
# declare the same box twice. Only the first object carries the
|
|
362
|
+
# nesting; the second is an empty repeat of the same name.
|
|
363
|
+
#
|
|
364
|
+
# @param boxes [Array<FlowchartSubgraph>] the diagram's subgraphs
|
|
365
|
+
# @return [Boolean] true when both directions agree
|
|
366
|
+
def nesting_agrees?(boxes)
|
|
367
|
+
holders = boxes.group_by(&:id)
|
|
368
|
+
|
|
369
|
+
boxes.all? do |box|
|
|
370
|
+
named_by_parent?(holders, box) && children_name_back?(holders, box)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def named_by_parent?(holders, box)
|
|
375
|
+
parents = holders[box.parent_id]
|
|
376
|
+
|
|
377
|
+
parents.nil? ||
|
|
378
|
+
parents.any? { |parent| parent.child_ids.include?(box.id) }
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def children_name_back?(holders, box)
|
|
382
|
+
box.child_ids.all? do |child_id|
|
|
383
|
+
holders.fetch(child_id, []).any? { |child| child.parent_id == box.id }
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# A box cannot be its own ancestor. The layout hangs each box off
|
|
388
|
+
# its parent, so a ring of them hangs off itself: not one of the
|
|
389
|
+
# boxes in the ring is ever placed, while their nodes still count
|
|
390
|
+
# as spoken for and so are left out of the loose pile too. Two
|
|
391
|
+
# boxes parented to each other lose everything they hold, and so
|
|
392
|
+
# does a box naming itself. Boxes outside the ring still draw,
|
|
393
|
+
# which is why the model has to refuse this rather than let a
|
|
394
|
+
# half-empty picture through.
|
|
395
|
+
#
|
|
396
|
+
# The parser cannot build one, so this only ever fires on a model
|
|
397
|
+
# somebody assembled by hand. Every parent edge the transform can
|
|
398
|
+
# set — a reference it claimed, or a nested declaration — is also
|
|
399
|
+
# an edge in the containment graph it walks BEFORE any of this,
|
|
400
|
+
# so the parent graph is a subset of one already proven acyclic.
|
|
401
|
+
#
|
|
402
|
+
# Every box contributes its parent, rather than the last one for a
|
|
403
|
+
# given id winning, because a duplicated id means the layout can
|
|
404
|
+
# follow either edge and a loop through either one is real.
|
|
405
|
+
#
|
|
406
|
+
# @param boxes [Array<FlowchartSubgraph>] the subgraphs to test
|
|
407
|
+
# @return [Boolean] true when some box is its own ancestor
|
|
408
|
+
def parent_cycle?(boxes)
|
|
409
|
+
graph = boxes.each_with_object({}) do |box, acc|
|
|
410
|
+
next if box.parent_id.nil?
|
|
411
|
+
|
|
412
|
+
acc[box.id] = acc.fetch(box.id, []) | [box.parent_id]
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
!Containment.looping_pair(graph).nil?
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../markdown_text"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Diagram
|
|
7
|
+
# Mermaid draws a flowchart label without the syntax that wrote it: the
|
|
8
|
+
# quote or markdown-string delimiters around it, a leading `fa:fa-x`
|
|
9
|
+
# icon, HTML tags, and the doubling of a backslash.
|
|
10
|
+
module FlowchartLabelText
|
|
11
|
+
QUOTED = /\A"(.*)"\z/m
|
|
12
|
+
MARKDOWN = /\A`(.*)`\z/m
|
|
13
|
+
ICON = /\bfa[bklrs]?:fa-[\w-]+\s*/
|
|
14
|
+
BREAK = %r{<br\s*/?>}i
|
|
15
|
+
LINE_BREAK = Regexp.union(BREAK, /\n/)
|
|
16
|
+
TAG = %r{</?[a-zA-Z][^>]*>}
|
|
17
|
+
DOUBLED_BACKSLASH = "\\\\"
|
|
18
|
+
ESCAPED_LINE_BREAK = "\\n"
|
|
19
|
+
|
|
20
|
+
# @param text [String, nil] label text as written in the source
|
|
21
|
+
# @return [String, nil] the text as mermaid draws it
|
|
22
|
+
def self.display(text)
|
|
23
|
+
return text if text.nil?
|
|
24
|
+
|
|
25
|
+
lines(text).join(" ").strip
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# @param text [String, nil] label text as written in the source
|
|
29
|
+
# @return [Array<String>] the lines mermaid draws, one for each `<br>`
|
|
30
|
+
# or newline; one empty line for no text
|
|
31
|
+
def self.lines(text)
|
|
32
|
+
shown = visible_source(text.to_s)
|
|
33
|
+
markdown = shown[MARKDOWN, 1]
|
|
34
|
+
return markdown_lines(markdown) if markdown
|
|
35
|
+
|
|
36
|
+
parts = shown.split(LINE_BREAK, -1)
|
|
37
|
+
lines = parts.map { |line| tidy(line) }
|
|
38
|
+
lines.empty? ? [""] : lines
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.visible_source(text)
|
|
42
|
+
shown = text.strip
|
|
43
|
+
quoted = shown.match(QUOTED)
|
|
44
|
+
return shown unless quoted
|
|
45
|
+
|
|
46
|
+
quoted[1].gsub(ESCAPED_LINE_BREAK, "\n")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.markdown_lines(text)
|
|
50
|
+
MarkdownText.parse_lines(text.gsub(BREAK, "\n")).map do |runs|
|
|
51
|
+
tidy(runs.map(&:text).join)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.tidy(text)
|
|
56
|
+
shown = text.gsub(ICON, "").gsub(TAG, "")
|
|
57
|
+
shown.gsub(DOUBLED_BACKSLASH, "\\").gsub(/[[:space:]]+/, " ").strip
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private_class_method :visible_source, :markdown_lines, :tidy
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "base"
|
|
5
|
+
|
|
6
|
+
module Etassia
|
|
7
|
+
module Diagram
|
|
8
|
+
# Gantt chart task
|
|
9
|
+
class GanttTask < Lutaml::Model::Serializable
|
|
10
|
+
# Filled in by the transform once `after_task`/`until_task` resolve. Not
|
|
11
|
+
# attributes: they are derived, and reopening the class from the
|
|
12
|
+
# transform to add them put a second definition in that file.
|
|
13
|
+
attr_accessor :calculated_start, :calculated_end
|
|
14
|
+
|
|
15
|
+
attribute :description, :string
|
|
16
|
+
attribute :id, :string
|
|
17
|
+
attribute :start_date, :string
|
|
18
|
+
attribute :end_date, :string
|
|
19
|
+
attribute :duration, :string
|
|
20
|
+
attribute :after_task, :string
|
|
21
|
+
attribute :until_task, :string
|
|
22
|
+
attribute :tags, :string, collection: true
|
|
23
|
+
attribute :click_href, :string
|
|
24
|
+
attribute :click_callback, :string
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
27
|
+
super
|
|
28
|
+
@tags ||= []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def done?
|
|
32
|
+
tags.include?("done")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def active?
|
|
36
|
+
tags.include?("active")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def critical?
|
|
40
|
+
tags.include?("crit")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def milestone?
|
|
44
|
+
tags.include?("milestone")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Gantt chart section grouping
|
|
49
|
+
class GanttSection < Lutaml::Model::Serializable
|
|
50
|
+
attribute :name, :string
|
|
51
|
+
attribute :tasks, GanttTask, collection: true
|
|
52
|
+
|
|
53
|
+
def initialize(name = nil)
|
|
54
|
+
super()
|
|
55
|
+
@name = name
|
|
56
|
+
@tasks ||= []
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Gantt chart diagram model
|
|
61
|
+
class Gantt < Base
|
|
62
|
+
attribute :title, :string
|
|
63
|
+
attribute :date_format, :string, default: -> { "YYYY-MM-DD" }
|
|
64
|
+
attribute :axis_format, :string
|
|
65
|
+
attribute :tick_interval, :string
|
|
66
|
+
attribute :excludes, :string, collection: true
|
|
67
|
+
attribute :weekend, :string
|
|
68
|
+
attribute :inclusive_end_dates, :boolean, default: -> { false }
|
|
69
|
+
attribute :today_marker, :string
|
|
70
|
+
attribute :sections, GanttSection, collection: true
|
|
71
|
+
|
|
72
|
+
def initialize
|
|
73
|
+
super
|
|
74
|
+
@sections ||= []
|
|
75
|
+
@excludes ||= []
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns the diagram type identifier.
|
|
79
|
+
#
|
|
80
|
+
# @return [Symbol] :gantt
|
|
81
|
+
def diagram_type
|
|
82
|
+
:gantt
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Gantt charts have no validation rules yet. See TODO.foundation's
|
|
86
|
+
# corpus burndown for real validation; this is deliberately trivial.
|
|
87
|
+
#
|
|
88
|
+
# @return [Boolean] true
|
|
89
|
+
def valid?
|
|
90
|
+
true
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cgi"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Diagram
|
|
7
|
+
# Mermaid writes a generic as `List~T~` and draws it as `List<T>`.
|
|
8
|
+
module GenericText
|
|
9
|
+
PAIR = /~([^~]+)~/
|
|
10
|
+
|
|
11
|
+
# @param text [String] source text holding `~T~` pairs
|
|
12
|
+
# @return [String] the text with each pair drawn as `<T>`
|
|
13
|
+
def self.display(text)
|
|
14
|
+
shown = text
|
|
15
|
+
shown = shown.gsub(PAIR, '<\1>') while shown.match?(PAIR)
|
|
16
|
+
shown
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Like {display}, for member text: a leading `~` is the package
|
|
20
|
+
# visibility mark and not the start of a pair, and an HTML entity such
|
|
21
|
+
# as `<` is drawn as the character it names.
|
|
22
|
+
def self.display_member(text)
|
|
23
|
+
text = CGI.unescapeHTML(text)
|
|
24
|
+
return display(text) unless text.start_with?("~")
|
|
25
|
+
|
|
26
|
+
"~#{display(text[1..])}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "base"
|
|
5
|
+
|
|
6
|
+
module Etassia
|
|
7
|
+
module Diagram
|
|
8
|
+
# Represents a Git Graph diagram
|
|
9
|
+
class GitGraph < Base
|
|
10
|
+
# Represents a commit in the git graph
|
|
11
|
+
class Commit < Lutaml::Model::Serializable
|
|
12
|
+
attribute :id, :string
|
|
13
|
+
attribute :message, :string
|
|
14
|
+
attribute :type, :string, default: -> { "NORMAL" }
|
|
15
|
+
attribute :tag, :string
|
|
16
|
+
attribute :tags, :string, collection: true, default: -> { [] }
|
|
17
|
+
attribute :branch_name, :string
|
|
18
|
+
attribute :parent_ids, :string, collection: true, default: -> { [] }
|
|
19
|
+
attribute :is_merge, :boolean, default: -> { false }
|
|
20
|
+
attribute :merge_branch, :string
|
|
21
|
+
attribute :is_cherry_pick, :boolean, default: -> { false }
|
|
22
|
+
attribute :cherry_pick_parent, :string
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Represents a branch in the git graph
|
|
26
|
+
class Branch < Lutaml::Model::Serializable
|
|
27
|
+
attribute :name, :string
|
|
28
|
+
attribute :order, :integer
|
|
29
|
+
attribute :parent_branch, :string
|
|
30
|
+
attribute :created_at_commit, :string
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# "LR" (default), "TB" or "BT": the direction time runs in.
|
|
34
|
+
attribute :orientation, :string, default: -> { "LR" }
|
|
35
|
+
attribute :main_branch_name, :string, default: -> { "main" }
|
|
36
|
+
attribute :acc_title, :string
|
|
37
|
+
attribute :acc_description, :string
|
|
38
|
+
attribute :commits, Commit, collection: true, default: -> { [] }
|
|
39
|
+
attribute :branches, Branch, collection: true, default: -> { [] }
|
|
40
|
+
|
|
41
|
+
# Returns the diagram type identifier.
|
|
42
|
+
#
|
|
43
|
+
# @return [Symbol] :git_graph
|
|
44
|
+
def diagram_type
|
|
45
|
+
:git_graph
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Git graphs have no validation rules yet. See TODO.foundation's
|
|
49
|
+
# corpus burndown for real validation; this is deliberately trivial.
|
|
50
|
+
#
|
|
51
|
+
# @return [Boolean] true
|
|
52
|
+
def valid?
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
require_relative "base"
|
|
5
|
+
|
|
6
|
+
module Etassia
|
|
7
|
+
module Diagram
|
|
8
|
+
# Info diagram model.
|
|
9
|
+
#
|
|
10
|
+
# Represents a simple informational diagram that displays a message
|
|
11
|
+
# or status information. Info diagrams are typically used to show
|
|
12
|
+
# system information, help text, or status messages.
|
|
13
|
+
#
|
|
14
|
+
# @example Creating an info diagram
|
|
15
|
+
# info = Info.new
|
|
16
|
+
# info.show_info = true
|
|
17
|
+
class Info < Base
|
|
18
|
+
# Whether to show additional info
|
|
19
|
+
attribute :show_info, :boolean, default: -> { false }
|
|
20
|
+
|
|
21
|
+
# Returns the diagram type identifier.
|
|
22
|
+
#
|
|
23
|
+
# @return [Symbol] :info
|
|
24
|
+
def diagram_type
|
|
25
|
+
:info
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Validates the info diagram structure.
|
|
29
|
+
#
|
|
30
|
+
# Info diagrams are always valid as they have no required content.
|
|
31
|
+
#
|
|
32
|
+
# @return [Boolean] true
|
|
33
|
+
def valid?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|