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,334 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
|
|
5
|
+
require_relative "error/diagram_type_error"
|
|
6
|
+
require_relative "error/pipeline_error"
|
|
7
|
+
require_relative "notation"
|
|
8
|
+
require_relative "notation/mermaid"
|
|
9
|
+
require_relative "theme/completion"
|
|
10
|
+
|
|
11
|
+
module Etassia
|
|
12
|
+
# Orchestrates the complete diagram rendering pipeline.
|
|
13
|
+
#
|
|
14
|
+
# The Engine class coordinates the parse → transform → layout → render
|
|
15
|
+
# pipeline for converting diagram source code into SVG output. Choosing the
|
|
16
|
+
# notation belongs to {Notation.resolve}, and detection and parsing to the
|
|
17
|
+
# notation itself (see {Notation::Mermaid}); the engine runs what the
|
|
18
|
+
# notation returns and manages error handling throughout the process.
|
|
19
|
+
#
|
|
20
|
+
# @example Render a flowchart
|
|
21
|
+
# engine = Etassia::Engine.new
|
|
22
|
+
# svg = engine.render("graph TD\nA-->B")
|
|
23
|
+
# puts svg
|
|
24
|
+
#
|
|
25
|
+
# @example Render with options
|
|
26
|
+
# engine = Etassia::Engine.new
|
|
27
|
+
# svg = engine.render(source, verbose: true)
|
|
28
|
+
class Engine
|
|
29
|
+
# @deprecated Use {Etassia::Notation::Mermaid::DIAGRAM_TYPE_PATTERNS}.
|
|
30
|
+
DIAGRAM_TYPE_PATTERNS = Notation::Mermaid::DIAGRAM_TYPE_PATTERNS
|
|
31
|
+
|
|
32
|
+
# @deprecated Use {Etassia::Notation::Mermaid::DIAGRAM_TYPE_KEYWORDS}.
|
|
33
|
+
DIAGRAM_TYPE_KEYWORDS = Notation::Mermaid::DIAGRAM_TYPE_KEYWORDS
|
|
34
|
+
|
|
35
|
+
attr_reader :verbose, :theme, :logger
|
|
36
|
+
|
|
37
|
+
# Creates a new Engine instance.
|
|
38
|
+
#
|
|
39
|
+
# @param verbose [Boolean] enable verbose output for debugging
|
|
40
|
+
# @param theme [String, Symbol, Theme, Hash, nil] theme specification
|
|
41
|
+
# @param today [Date, nil] reference date for diagrams that need one
|
|
42
|
+
# (gantt). Pin it to make rendering reproducible; nil uses the real
|
|
43
|
+
# date.
|
|
44
|
+
# @param notation [Symbol, String, nil] the notation to read sources
|
|
45
|
+
# with; nil lets each render pick one from its path and source
|
|
46
|
+
# @param logger [Logger, nil] destination for diagnostics. A host
|
|
47
|
+
# embedding Etassia and reading stdout as pure SVG cannot tolerate log
|
|
48
|
+
# lines landing on the same stream, so the default logs to $stderr
|
|
49
|
+
# instead; pass one in to redirect or format diagnostics your own way.
|
|
50
|
+
# @raise [PipelineError] if `notation` is invalid or not registered
|
|
51
|
+
#
|
|
52
|
+
# Theme loading parses attacker-supplied YAML, and it happens here,
|
|
53
|
+
# before `render` is ever called. The exhaustion rescue converts those
|
|
54
|
+
# VM-level failures into the public pipeline error contract.
|
|
55
|
+
def initialize(verbose: false, theme: nil, today: nil, logger: nil,
|
|
56
|
+
notation: nil)
|
|
57
|
+
@verbose = verbose
|
|
58
|
+
@notation_id = registered_id(notation)
|
|
59
|
+
@theme = load_theme(theme)
|
|
60
|
+
@today = today
|
|
61
|
+
@logger = logger || default_logger
|
|
62
|
+
rescue *EXHAUSTION_ERRORS => e
|
|
63
|
+
raise PipelineError, "Theme loading failed: #{e.message}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Renders diagram source code to SVG.
|
|
67
|
+
#
|
|
68
|
+
# @param source [String] diagram source code
|
|
69
|
+
# @param options [Hash] rendering options
|
|
70
|
+
# @option options [Boolean] :verbose enable verbose output
|
|
71
|
+
# @option options [String, Symbol, Theme, Hash, nil] :theme theme override
|
|
72
|
+
# @option options [Date, nil] :today reference date override
|
|
73
|
+
# @option options [Symbol, String, nil] :notation notation override
|
|
74
|
+
# @option options [String, nil] :path where the source came from; its
|
|
75
|
+
# extension picks the notation when none is given, and its directory
|
|
76
|
+
# is where a notation that reads files looks first
|
|
77
|
+
# @option options [String, nil] :base_dir that directory when the
|
|
78
|
+
# source has no file of its own (an inline block in a document)
|
|
79
|
+
# @option options [Array<String>, String, nil] :include_path further
|
|
80
|
+
# directories a notation may read files from
|
|
81
|
+
# @option options [Symbol] :layout_engine :grid (default) or :elk, which
|
|
82
|
+
# lays flowcharts out with elkrb and raises for any other diagram type
|
|
83
|
+
# @return [String] SVG XML string
|
|
84
|
+
# @raise [PipelineError] if `notation` is invalid or not registered
|
|
85
|
+
# @raise [DiagramTypeError] if diagram type cannot be detected
|
|
86
|
+
# @raise [Parser::ParseError] if the source fails to parse
|
|
87
|
+
# @raise [Layout::LayoutError] if the diagram fails its own
|
|
88
|
+
# validity check
|
|
89
|
+
# @raise [Renderer::RenderError] if rendering itself fails
|
|
90
|
+
# @raise [PipelineError] if a stage fails with no error class of its own
|
|
91
|
+
#
|
|
92
|
+
# Layer-specific Etassia errors propagate unchanged so the corpus harness
|
|
93
|
+
# keeps their stage. Exhaustion and notation-plugin failures are wrapped,
|
|
94
|
+
# without embedding backtraces in messages; Ruby retains each cause for
|
|
95
|
+
# diagnostics while batch rendering avoids accumulating huge strings.
|
|
96
|
+
def render(source, options = {})
|
|
97
|
+
render_pipeline(source, options)
|
|
98
|
+
rescue Error
|
|
99
|
+
raise
|
|
100
|
+
rescue *EXHAUSTION_ERRORS => e
|
|
101
|
+
raise PipelineError, "Rendering failed: #{e.message}"
|
|
102
|
+
rescue Notation::PluginFailure => e
|
|
103
|
+
raise PipelineError, "Rendering failed: #{describe_failure(e)}"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def default_logger
|
|
109
|
+
Logger.new($stderr).tap do |created_logger|
|
|
110
|
+
created_logger.formatter = proc do |_level, _time, _name, message|
|
|
111
|
+
"[Etassia::Engine] #{message}\n"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def render_pipeline(source, options)
|
|
117
|
+
@verbose = options[:verbose] if options.key?(:verbose)
|
|
118
|
+
theme, today, layout_engine = render_settings(options)
|
|
119
|
+
log "Starting render pipeline..."
|
|
120
|
+
notation = resolve_notation(source, options)
|
|
121
|
+
parsed = parse_source(notation, source, options)
|
|
122
|
+
layout_result = transform_diagram(
|
|
123
|
+
parsed.diagram, parsed.transform, today, theme,
|
|
124
|
+
**placement_options(parsed, options, layout_engine)
|
|
125
|
+
)
|
|
126
|
+
serialize(render_svg(layout_result, parsed.renderer, theme))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def placement_options(parsed, options, layout_engine)
|
|
130
|
+
source_layout = source_layout_engine(parsed, options)
|
|
131
|
+
if source_layout.nil?
|
|
132
|
+
return { layout_engine: layout_engine, source_layout: false }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
{ layout_engine: checked_layout_engine(source_layout),
|
|
136
|
+
source_layout: true }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def render_settings(options)
|
|
140
|
+
theme = options[:theme] ? load_theme(options[:theme]) : @theme
|
|
141
|
+
today = options.key?(:today) ? options[:today] : @today
|
|
142
|
+
layout_engine = checked_layout_engine(
|
|
143
|
+
options.fetch(:layout_engine, :grid),
|
|
144
|
+
)
|
|
145
|
+
[theme, today, layout_engine]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def resolve_notation(source, options)
|
|
149
|
+
explicit = case options[:notation]
|
|
150
|
+
when nil then @notation_id
|
|
151
|
+
else options[:notation]
|
|
152
|
+
end
|
|
153
|
+
Notation.resolve(
|
|
154
|
+
explicit: explicit,
|
|
155
|
+
path: options[:path],
|
|
156
|
+
source: source,
|
|
157
|
+
)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def serialize(document)
|
|
161
|
+
xml = document.to_xml
|
|
162
|
+
log "Render complete, #{xml.length} bytes"
|
|
163
|
+
xml
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# "Class: message", for an exception whose own #message may raise (an
|
|
167
|
+
# RSpec::Expectations::MultipleExpectationsNotMetError built without its
|
|
168
|
+
# aggregator does).
|
|
169
|
+
def describe_failure(error)
|
|
170
|
+
"#{error.class}: #{error.message}"
|
|
171
|
+
rescue Notation::PluginFailure
|
|
172
|
+
"#{error.class}: <message unavailable>"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# A notation declares the keywords it wants and gets only those:
|
|
176
|
+
# `logger:` (progress lines), `base_dir:` (where the source lives, for a
|
|
177
|
+
# notation that reads files beside it) and `include_path:` (further
|
|
178
|
+
# directories such a notation may read). One that declares none is
|
|
179
|
+
# called with the source alone.
|
|
180
|
+
def parse_source(notation, source, options)
|
|
181
|
+
context = {
|
|
182
|
+
logger: verbose ? logger : nil,
|
|
183
|
+
base_dir: base_dir_of(options),
|
|
184
|
+
include_path: options[:include_path],
|
|
185
|
+
}
|
|
186
|
+
wanted = notation.method(:parse).parameters.filter_map do |kind, name|
|
|
187
|
+
name if kind == :key
|
|
188
|
+
end
|
|
189
|
+
notation.parse(source, **context.slice(*wanted))
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# `:base_dir`, else the directory of `:path`.
|
|
193
|
+
def base_dir_of(options)
|
|
194
|
+
return options[:base_dir] if options[:base_dir]
|
|
195
|
+
return unless options[:path]
|
|
196
|
+
|
|
197
|
+
File.dirname(File.expand_path(options[:path]))
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# The registry's key for a validated notation, not the id the plugin
|
|
201
|
+
# answers later.
|
|
202
|
+
def registered_id(notation)
|
|
203
|
+
case notation
|
|
204
|
+
when nil
|
|
205
|
+
nil
|
|
206
|
+
else
|
|
207
|
+
Notation.fetch(notation)
|
|
208
|
+
case notation
|
|
209
|
+
when Symbol then notation
|
|
210
|
+
else String.instance_method(:to_sym).bind_call(notation)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Lays out the diagram model.
|
|
216
|
+
#
|
|
217
|
+
# @param diagram [Diagram::Base] diagram model
|
|
218
|
+
# @param transform_class [Class] layout class
|
|
219
|
+
# @param today [Date, nil] reference date, or nil for the real date
|
|
220
|
+
# @param theme [Theme] theme the layout may size text with
|
|
221
|
+
# @param placement [Hash] `:layout_engine` (:grid or :elk, default :grid)
|
|
222
|
+
# and `:source_layout` (true when the source chose the engine)
|
|
223
|
+
# @return [Layout::Scene, Layout::Legacy] a Scene, or a wrapped graph
|
|
224
|
+
def transform_diagram(diagram, transform_class, today, theme, **placement)
|
|
225
|
+
log "Transforming diagram to graph..."
|
|
226
|
+
layout = transform_class.new
|
|
227
|
+
choose_placement(layout, **placement)
|
|
228
|
+
result = layout.call(diagram, theme: theme, today: today)
|
|
229
|
+
log "Transform complete"
|
|
230
|
+
result
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def checked_layout_engine(name)
|
|
234
|
+
return name if %i[grid elk].include?(name)
|
|
235
|
+
|
|
236
|
+
raise PipelineError, "Unknown layout_engine: #{name.inspect}"
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def source_layout_engine(parsed, options)
|
|
240
|
+
parsed.layout_engine unless options.key?(:layout_engine)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def choose_placement(layout, layout_engine: :grid, source_layout: false)
|
|
244
|
+
return if layout_engine == :grid
|
|
245
|
+
|
|
246
|
+
unless layout.respond_to?(:placement=)
|
|
247
|
+
raise Layout::LayoutError,
|
|
248
|
+
"layout_engine :elk is not available for #{layout.class}"
|
|
249
|
+
end
|
|
250
|
+
layout.public_send(placement_setter(layout, source_layout), layout_engine)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def placement_setter(layout, source_layout)
|
|
254
|
+
if source_layout && layout.respond_to?(:source_placement=)
|
|
255
|
+
:source_placement=
|
|
256
|
+
else
|
|
257
|
+
:placement=
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Renders the layout result to an SVG document.
|
|
262
|
+
#
|
|
263
|
+
# @param layout_result [Object] output produced by the notation's layout
|
|
264
|
+
# transform
|
|
265
|
+
# @param renderer_class [Class] renderer class
|
|
266
|
+
# @param theme [Theme] theme to use for rendering
|
|
267
|
+
# @return [Svg::Document] SVG document
|
|
268
|
+
def render_svg(layout_result, renderer_class, theme)
|
|
269
|
+
log "Computing layout..."
|
|
270
|
+
log "Layout complete"
|
|
271
|
+
log "Rendering to SVG..."
|
|
272
|
+
renderer = renderer_class.new(theme: theme)
|
|
273
|
+
svg = renderer.render(layout_result)
|
|
274
|
+
log "SVG render complete"
|
|
275
|
+
svg
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Loads a theme from various specifications.
|
|
279
|
+
#
|
|
280
|
+
# @param theme_spec [String, Symbol, Theme, Hash, nil] theme specification
|
|
281
|
+
# @return [Theme] loaded theme
|
|
282
|
+
def load_theme(theme_spec)
|
|
283
|
+
Theme::Completion.call(resolve_theme_spec(theme_spec))
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def resolve_theme_spec(theme_spec)
|
|
287
|
+
return Theme::Registry.get(:default) if theme_spec.nil?
|
|
288
|
+
|
|
289
|
+
case theme_spec
|
|
290
|
+
when String then load_string_theme(theme_spec)
|
|
291
|
+
when Symbol then resolve_theme_name(theme_spec.to_s)
|
|
292
|
+
when Theme then theme_spec
|
|
293
|
+
when Hash then Theme.new(**theme_spec)
|
|
294
|
+
else Theme::Registry.get(:default)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def load_string_theme(theme_spec)
|
|
299
|
+
return Theme.load(theme_spec) if File.exist?(theme_spec)
|
|
300
|
+
|
|
301
|
+
resolve_theme_name(theme_spec)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Resolves a theme name against the registry, or raises -- an unknown
|
|
305
|
+
# name used to fall back to the default theme silently (exit 0, wrong
|
|
306
|
+
# theme drawn). A typo and an intentional `--theme default` looked
|
|
307
|
+
# identical to the caller.
|
|
308
|
+
#
|
|
309
|
+
# @param name [String] the requested theme name
|
|
310
|
+
# @return [Theme] the matching registered theme
|
|
311
|
+
# @raise [PipelineError] if no theme is registered under that name
|
|
312
|
+
def resolve_theme_name(name)
|
|
313
|
+
Theme::Registry.get(name.to_sym) || raise(
|
|
314
|
+
PipelineError,
|
|
315
|
+
"Unknown theme: #{name}. Valid themes: " \
|
|
316
|
+
"#{Theme::Registry.list.map(&:to_s).sort.join(', ')}",
|
|
317
|
+
)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Logs a diagnostic message at debug level, gated on @verbose. This
|
|
321
|
+
# never touches the logger's own `.level` -- an injected logger may be
|
|
322
|
+
# shared with (or owned by) the host embedding Etassia, and mutating its
|
|
323
|
+
# level as a side effect of construction/render either corrupts the
|
|
324
|
+
# host's own filtering or crashes outright for a duck-typed logger that
|
|
325
|
+
# doesn't implement `level=` (only `debug`/`info`/`warn`, the documented
|
|
326
|
+
# contract). A plain guard needs neither.
|
|
327
|
+
#
|
|
328
|
+
# @param message [String] message to log
|
|
329
|
+
# @return [void]
|
|
330
|
+
def log(message)
|
|
331
|
+
logger.debug(message) if verbose
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../error"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Layout
|
|
7
|
+
# Error raised during layout. A Etassia::Error so Engine#render
|
|
8
|
+
# can let it propagate unwrapped instead of collapsing it into
|
|
9
|
+
# PipelineError.
|
|
10
|
+
class LayoutError < Etassia::Error; end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../error"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
# Raised by {Etassia::Notation.register} when a plugin breaks the notation
|
|
7
|
+
# contract: a malformed member, a duplicate id, or an extension another
|
|
8
|
+
# notation already claims.
|
|
9
|
+
class NotationRegistrationError < Etassia::Error; end
|
|
10
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../error"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Parser
|
|
7
|
+
# Error raised during parsing. A Etassia::Error so Engine#render can let
|
|
8
|
+
# it propagate unwrapped instead of collapsing it into PipelineError.
|
|
9
|
+
class ParseError < Etassia::Error; end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../error"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Renderer
|
|
7
|
+
# Error raised during rendering. A Etassia::Error so Engine#render can
|
|
8
|
+
# let it propagate unwrapped instead of collapsing it into
|
|
9
|
+
# PipelineError.
|
|
10
|
+
class RenderError < Etassia::Error; end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../error"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module Parser
|
|
7
|
+
# A value the source spelled validly but the diagram type does not
|
|
8
|
+
# allow, such as a user journey score outside 1..5. Not a ParseError:
|
|
9
|
+
# the source parsed.
|
|
10
|
+
class ScoreError < Etassia::Error; end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Etassia
|
|
4
|
+
# Base class for every Etassia::Error subclass across the pipeline (parser,
|
|
5
|
+
# transform, renderer, engine). Its own file -- like version.rb -- so a
|
|
6
|
+
# component's base.rb can require_relative it directly and load standalone
|
|
7
|
+
# (`require "etassia/parser"` etc.) without first loading the whole
|
|
8
|
+
# lib/etassia.rb require chain.
|
|
9
|
+
class Error < StandardError; end
|
|
10
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Etassia
|
|
4
|
+
# Renders an exception for a `--verbose` reader, following the `cause`
|
|
5
|
+
# chain the engine deliberately leaves out of its messages.
|
|
6
|
+
#
|
|
7
|
+
# `Engine#render` raises `PipelineError` with `e.message` only, never
|
|
8
|
+
# `e.backtrace`. A real stack overflow's backtrace ran to 1,044,280 bytes
|
|
9
|
+
# for one measured bomb, and `BatchCommand` keeps every failure's message
|
|
10
|
+
# for the length of the run, so baking the trace into the string
|
|
11
|
+
# re-accumulated the very memory that guard exists to bound. Raising
|
|
12
|
+
# inside the rescue chains the original on as `cause`, so nothing is lost
|
|
13
|
+
# — it is simply one `.cause` away instead of inside every `#message`.
|
|
14
|
+
#
|
|
15
|
+
# Reading it back is this module's job. Without it `--verbose` shows a
|
|
16
|
+
# trace that starts at the re-raise in `engine.rb` and omits the parser
|
|
17
|
+
# frames that say what actually went wrong.
|
|
18
|
+
module ErrorReport
|
|
19
|
+
# How many frames of a CAUSE's backtrace to print.
|
|
20
|
+
#
|
|
21
|
+
# The top-level error's own trace is printed whole, because a wrapper
|
|
22
|
+
# raised at a known line is short by construction. A cause is not: the
|
|
23
|
+
# exhaustion path is exactly where a trace runs to six figures of
|
|
24
|
+
# frames, and `--verbose` must stay readable on the failure it was most
|
|
25
|
+
# needed for. The innermost frames are the ones that name the fault, so
|
|
26
|
+
# the head of the trace is the part worth keeping.
|
|
27
|
+
CAUSE_FRAME_LIMIT = 50
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# Every cause below ERROR, deepest last, each with its class, message
|
|
32
|
+
# and a bounded head of its backtrace.
|
|
33
|
+
#
|
|
34
|
+
# @param error [Exception]
|
|
35
|
+
# @return [String] empty when ERROR has no cause
|
|
36
|
+
def cause_diagnostics(error)
|
|
37
|
+
causes(error).map { |cause| one_cause(cause) }.join("\n")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param error [Exception]
|
|
41
|
+
# @return [Array<Exception>] the cause chain, nearest first
|
|
42
|
+
def causes(error)
|
|
43
|
+
chain = []
|
|
44
|
+
seen = [error.object_id]
|
|
45
|
+
# A `cause` cycle is not reachable through `raise` today, but this
|
|
46
|
+
# walks user-supplied exceptions and a loop here would hang the CLI
|
|
47
|
+
# on the one code path whose whole purpose is surviving a bad input.
|
|
48
|
+
while (error = error.cause) && !seen.include?(error.object_id)
|
|
49
|
+
seen << error.object_id
|
|
50
|
+
chain << error
|
|
51
|
+
end
|
|
52
|
+
chain
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param cause [Exception]
|
|
56
|
+
# @return [String]
|
|
57
|
+
def one_cause(cause)
|
|
58
|
+
# `backtrace` is nil when the VM fails an allocation before it can
|
|
59
|
+
# build one, so verbose output must not assume there is a trace.
|
|
60
|
+
frames = cause.backtrace || []
|
|
61
|
+
shown = frames.first(CAUSE_FRAME_LIMIT)
|
|
62
|
+
omitted = frames.size - shown.size
|
|
63
|
+
|
|
64
|
+
lines = ["Caused by: #{cause.class}: #{cause.message}", *shown]
|
|
65
|
+
lines << "... #{omitted} more frames" if omitted.positive?
|
|
66
|
+
lines.join("\n")
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "item"
|
|
4
|
+
require_relative "integrity"
|
|
5
|
+
require_relative "dimension"
|
|
6
|
+
require_relative "series"
|
|
7
|
+
require_relative "data_value"
|
|
8
|
+
|
|
9
|
+
module Etassia
|
|
10
|
+
module IR
|
|
11
|
+
class Data < Item
|
|
12
|
+
attribute :dimensions, Dimension, collection: true, default: -> { [] }
|
|
13
|
+
attribute :series, Series, collection: true, default: -> { [] }
|
|
14
|
+
attribute :values, DataValue, collection: true, default: -> { [] }
|
|
15
|
+
attribute :items, Item, collection: true, default: -> { [] }
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def semantic_errors
|
|
20
|
+
super +
|
|
21
|
+
Integrity.unique_id_errors([self] + members) +
|
|
22
|
+
Integrity.parent_errors(members) +
|
|
23
|
+
reference_errors
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def members
|
|
27
|
+
dimensions + series + values + items
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def reference_errors
|
|
31
|
+
Integrity.reference_errors(
|
|
32
|
+
values,
|
|
33
|
+
dimensions: dimensions,
|
|
34
|
+
series: series,
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "item"
|
|
4
|
+
require_relative "scalar"
|
|
5
|
+
|
|
6
|
+
module Etassia
|
|
7
|
+
module IR
|
|
8
|
+
class DataValue < Item
|
|
9
|
+
attribute :dimension_id, :string
|
|
10
|
+
attribute :series_id, :string
|
|
11
|
+
attribute :value, Scalar
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def semantic_errors
|
|
16
|
+
super + reference_errors + value_errors
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def reference_errors
|
|
20
|
+
references = { dimension_id: dimension_id, series_id: series_id }
|
|
21
|
+
references.filter_map do |name, reference|
|
|
22
|
+
next unless reference == ""
|
|
23
|
+
|
|
24
|
+
validation_error("#{name} must be nonempty when present")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def value_errors
|
|
29
|
+
return [] if value&.valid?
|
|
30
|
+
|
|
31
|
+
[validation_error("value must be a valid Scalar")]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "item"
|
|
4
|
+
|
|
5
|
+
module Etassia
|
|
6
|
+
module IR
|
|
7
|
+
class Edge < Item
|
|
8
|
+
attribute :source_id, :string
|
|
9
|
+
attribute :target_id, :string
|
|
10
|
+
attribute :minimum_rank_span, :integer
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def semantic_errors
|
|
15
|
+
super.concat(missing_id_errors, rank_span_errors)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def missing_id_errors
|
|
19
|
+
{ "source_id" => source_id, "target_id" => target_id }
|
|
20
|
+
.filter_map do |name, value|
|
|
21
|
+
next unless value.nil? || value.empty?
|
|
22
|
+
|
|
23
|
+
validation_error("#{name} must be nonempty")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def rank_span_errors
|
|
28
|
+
return [] unless minimum_rank_span && !minimum_rank_span.positive?
|
|
29
|
+
|
|
30
|
+
[validation_error("minimum_rank_span must be a positive integer")]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "item"
|
|
4
|
+
require_relative "integrity"
|
|
5
|
+
require_relative "node"
|
|
6
|
+
require_relative "edge"
|
|
7
|
+
|
|
8
|
+
module Etassia
|
|
9
|
+
module IR
|
|
10
|
+
class Graph < Item
|
|
11
|
+
attribute :nodes, Node, collection: true, default: -> { [] }
|
|
12
|
+
attribute :edges, Edge, collection: true, default: -> { [] }
|
|
13
|
+
|
|
14
|
+
def items
|
|
15
|
+
nodes + edges
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def semantic_errors
|
|
21
|
+
super +
|
|
22
|
+
Integrity.unique_id_errors([self] + items) +
|
|
23
|
+
Integrity.parent_errors(items, parents: nodes) +
|
|
24
|
+
Integrity.endpoint_errors(edges, endpoints: nodes)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|