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.
Files changed (727) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +140 -0
  3. data/LICENSE +25 -0
  4. data/README.adoc +436 -0
  5. data/exe/etassia +7 -0
  6. data/lib/etassia/cli.rb +187 -0
  7. data/lib/etassia/commands/batch.rb +210 -0
  8. data/lib/etassia/commands/notation_loader.rb +22 -0
  9. data/lib/etassia/commands/render.rb +98 -0
  10. data/lib/etassia/commands/types.rb +33 -0
  11. data/lib/etassia/commands/version.rb +24 -0
  12. data/lib/etassia/corpus_type_names.rb +52 -0
  13. data/lib/etassia/diagram/architecture.rb +108 -0
  14. data/lib/etassia/diagram/base.rb +61 -0
  15. data/lib/etassia/diagram/block.rb +102 -0
  16. data/lib/etassia/diagram/c4.rb +337 -0
  17. data/lib/etassia/diagram/class_diagram.rb +466 -0
  18. data/lib/etassia/diagram/class_namespace.rb +17 -0
  19. data/lib/etassia/diagram/class_note.rb +17 -0
  20. data/lib/etassia/diagram/containment.rb +107 -0
  21. data/lib/etassia/diagram/er_diagram.rb +317 -0
  22. data/lib/etassia/diagram/error.rb +38 -0
  23. data/lib/etassia/diagram/flowchart.rb +419 -0
  24. data/lib/etassia/diagram/flowchart_label_text.rb +63 -0
  25. data/lib/etassia/diagram/gantt.rb +94 -0
  26. data/lib/etassia/diagram/generic_text.rb +30 -0
  27. data/lib/etassia/diagram/git_graph.rb +57 -0
  28. data/lib/etassia/diagram/info.rb +38 -0
  29. data/lib/etassia/diagram/kanban.rb +198 -0
  30. data/lib/etassia/diagram/mindmap.rb +71 -0
  31. data/lib/etassia/diagram/packet.rb +93 -0
  32. data/lib/etassia/diagram/pie.rb +115 -0
  33. data/lib/etassia/diagram/quadrant.rb +135 -0
  34. data/lib/etassia/diagram/radar.rb +65 -0
  35. data/lib/etassia/diagram/requirement.rb +168 -0
  36. data/lib/etassia/diagram/sankey.rb +217 -0
  37. data/lib/etassia/diagram/sequence.rb +299 -0
  38. data/lib/etassia/diagram/sequence_box.rb +18 -0
  39. data/lib/etassia/diagram/sequence_frame.rb +37 -0
  40. data/lib/etassia/diagram/sequence_frame_section.rb +23 -0
  41. data/lib/etassia/diagram/sequence_text.rb +69 -0
  42. data/lib/etassia/diagram/sequence_wrap.rb +23 -0
  43. data/lib/etassia/diagram/state_diagram.rb +282 -0
  44. data/lib/etassia/diagram/timeline.rb +183 -0
  45. data/lib/etassia/diagram/treemap.rb +95 -0
  46. data/lib/etassia/diagram/user_journey.rb +153 -0
  47. data/lib/etassia/diagram/xy_chart.rb +90 -0
  48. data/lib/etassia/diagram.rb +8 -0
  49. data/lib/etassia/diagram_registry.rb +34 -0
  50. data/lib/etassia/engine.rb +334 -0
  51. data/lib/etassia/error/diagram_type_error.rb +10 -0
  52. data/lib/etassia/error/layout_error.rb +12 -0
  53. data/lib/etassia/error/notation_registration_error.rb +10 -0
  54. data/lib/etassia/error/parse_error.rb +11 -0
  55. data/lib/etassia/error/pipeline_error.rb +10 -0
  56. data/lib/etassia/error/render_error.rb +12 -0
  57. data/lib/etassia/error/score_error.rb +12 -0
  58. data/lib/etassia/error.rb +10 -0
  59. data/lib/etassia/error_report.rb +69 -0
  60. data/lib/etassia/ir/data.rb +39 -0
  61. data/lib/etassia/ir/data_value.rb +35 -0
  62. data/lib/etassia/ir/dimension.rb +10 -0
  63. data/lib/etassia/ir/edge.rb +34 -0
  64. data/lib/etassia/ir/graph.rb +28 -0
  65. data/lib/etassia/ir/integrity.rb +80 -0
  66. data/lib/etassia/ir/item.rb +46 -0
  67. data/lib/etassia/ir/model.rb +56 -0
  68. data/lib/etassia/ir/node.rb +10 -0
  69. data/lib/etassia/ir/placement.rb +47 -0
  70. data/lib/etassia/ir/prepositioned.rb +25 -0
  71. data/lib/etassia/ir/prepositioned_item.rb +26 -0
  72. data/lib/etassia/ir/property_set.rb +43 -0
  73. data/lib/etassia/ir/scalar.rb +25 -0
  74. data/lib/etassia/ir/series.rb +10 -0
  75. data/lib/etassia/ir.rb +17 -0
  76. data/lib/etassia/js_math.rb +511 -0
  77. data/lib/etassia/js_number.rb +64 -0
  78. data/lib/etassia/layout/architecture.rb +1472 -0
  79. data/lib/etassia/layout/base.rb +276 -0
  80. data/lib/etassia/layout/block.rb +738 -0
  81. data/lib/etassia/layout/c4.rb +876 -0
  82. data/lib/etassia/layout/c4_boundary_metrics.rb +35 -0
  83. data/lib/etassia/layout/c4_bounds.rb +106 -0
  84. data/lib/etassia/layout/c4_intersection.rb +77 -0
  85. data/lib/etassia/layout/c4_placement.rb +135 -0
  86. data/lib/etassia/layout/c4_shape_metrics.rb +97 -0
  87. data/lib/etassia/layout/c4_shape_outline.rb +67 -0
  88. data/lib/etassia/layout/c4_stereotype.rb +30 -0
  89. data/lib/etassia/layout/c4_text.rb +54 -0
  90. data/lib/etassia/layout/class_cell_placement.rb +148 -0
  91. data/lib/etassia/layout/class_diagram.rb +1116 -0
  92. data/lib/etassia/layout/class_diagram_namespaces.rb +26 -0
  93. data/lib/etassia/layout/class_diagram_notes.rb +26 -0
  94. data/lib/etassia/layout/class_name_advances.rb +31 -0
  95. data/lib/etassia/layout/class_namespace_box.rb +21 -0
  96. data/lib/etassia/layout/class_namespace_nodes.rb +197 -0
  97. data/lib/etassia/layout/class_namespace_placement.rb +71 -0
  98. data/lib/etassia/layout/class_note.rb +44 -0
  99. data/lib/etassia/layout/class_note_nodes.rb +84 -0
  100. data/lib/etassia/layout/elk_notices.rb +48 -0
  101. data/lib/etassia/layout/elk_placement.rb +197 -0
  102. data/lib/etassia/layout/er_diagram.rb +1002 -0
  103. data/lib/etassia/layout/er_diagram_adjacency.rb +20 -0
  104. data/lib/etassia/layout/er_diagram_alignment.rb +72 -0
  105. data/lib/etassia/layout/er_diagram_compaction.rb +85 -0
  106. data/lib/etassia/layout/er_diagram_conflicts.rb +70 -0
  107. data/lib/etassia/layout/er_diagram_coordinates.rb +104 -0
  108. data/lib/etassia/layout/er_diagram_entity_size.rb +82 -0
  109. data/lib/etassia/layout/er_diagram_layering.rb +109 -0
  110. data/lib/etassia/layout/er_diagram_ordering.rb +143 -0
  111. data/lib/etassia/layout/er_diagram_placement.rb +163 -0
  112. data/lib/etassia/layout/er_diagram_placement_node.rb +22 -0
  113. data/lib/etassia/layout/error.rb +133 -0
  114. data/lib/etassia/layout/flowchart/brandes_koepf.rb +208 -0
  115. data/lib/etassia/layout/flowchart/cluster_reach.rb +70 -0
  116. data/lib/etassia/layout/flowchart/component_packing.rb +129 -0
  117. data/lib/etassia/layout/flowchart/directed_placement.rb +428 -0
  118. data/lib/etassia/layout/flowchart/edge_chains.rb +111 -0
  119. data/lib/etassia/layout/flowchart/edge_order.rb +34 -0
  120. data/lib/etassia/layout/flowchart/edge_router.rb +533 -0
  121. data/lib/etassia/layout/flowchart/label_backdrop_geometry.rb +62 -0
  122. data/lib/etassia/layout/flowchart/layer_spacing.rb +85 -0
  123. data/lib/etassia/layout/flowchart/level_edges.rb +74 -0
  124. data/lib/etassia/layout/flowchart/level_frame.rb +47 -0
  125. data/lib/etassia/layout/flowchart/minimum_rank_spacing.rb +74 -0
  126. data/lib/etassia/layout/flowchart/row_centering.rb +229 -0
  127. data/lib/etassia/layout/flowchart.rb +1290 -0
  128. data/lib/etassia/layout/gantt.rb +814 -0
  129. data/lib/etassia/layout/gantt_duration.rb +49 -0
  130. data/lib/etassia/layout/gantt_exclusions.rb +74 -0
  131. data/lib/etassia/layout/gantt_ticks.rb +165 -0
  132. data/lib/etassia/layout/git_graph.rb +1075 -0
  133. data/lib/etassia/layout/grid.rb +165 -0
  134. data/lib/etassia/layout/info.rb +113 -0
  135. data/lib/etassia/layout/kanban.rb +452 -0
  136. data/lib/etassia/layout/kanban_card_text.rb +95 -0
  137. data/lib/etassia/layout/mindmap.rb +425 -0
  138. data/lib/etassia/layout/mindmap_cose.rb +81 -0
  139. data/lib/etassia/layout/mindmap_cose_body.rb +93 -0
  140. data/lib/etassia/layout/mindmap_cose_geometry.rb +190 -0
  141. data/lib/etassia/layout/mindmap_cose_grid.rb +96 -0
  142. data/lib/etassia/layout/mindmap_cose_link.rb +42 -0
  143. data/lib/etassia/layout/mindmap_cose_relaxation.rb +166 -0
  144. data/lib/etassia/layout/mindmap_cose_seed.rb +93 -0
  145. data/lib/etassia/layout/mindmap_cose_wedge.rb +37 -0
  146. data/lib/etassia/layout/mindmap_node_size.rb +130 -0
  147. data/lib/etassia/layout/packet.rb +285 -0
  148. data/lib/etassia/layout/pie.rb +305 -0
  149. data/lib/etassia/layout/pie_legend.rb +64 -0
  150. data/lib/etassia/layout/pie_legend_entry.rb +21 -0
  151. data/lib/etassia/layout/quadrant.rb +402 -0
  152. data/lib/etassia/layout/radar.rb +442 -0
  153. data/lib/etassia/layout/requirement.rb +765 -0
  154. data/lib/etassia/layout/sankey.rb +501 -0
  155. data/lib/etassia/layout/scene.rb +18 -0
  156. data/lib/etassia/layout/sequence/actor_gaps.rb +151 -0
  157. data/lib/etassia/layout/sequence/box_shape.rb +23 -0
  158. data/lib/etassia/layout/sequence/creations.rb +73 -0
  159. data/lib/etassia/layout/sequence/frame_divider.rb +22 -0
  160. data/lib/etassia/layout/sequence/frame_placement.rb +424 -0
  161. data/lib/etassia/layout/sequence/frame_reader.rb +75 -0
  162. data/lib/etassia/layout/sequence/frame_shape.rb +45 -0
  163. data/lib/etassia/layout/sequence/geometry.rb +24 -0
  164. data/lib/etassia/layout/sequence/message_rows.rb +165 -0
  165. data/lib/etassia/layout/sequence/note.rb +16 -0
  166. data/lib/etassia/layout/sequence/note_box.rb +114 -0
  167. data/lib/etassia/layout/sequence/note_placement.rb +223 -0
  168. data/lib/etassia/layout/sequence/text_width.rb +69 -0
  169. data/lib/etassia/layout/sequence/text_wrap.rb +93 -0
  170. data/lib/etassia/layout/sequence.rb +936 -0
  171. data/lib/etassia/layout/state_diagram.rb +1277 -0
  172. data/lib/etassia/layout/timeline.rb +165 -0
  173. data/lib/etassia/layout/timeline_card.rb +142 -0
  174. data/lib/etassia/layout/timeline_flow.rb +164 -0
  175. data/lib/etassia/layout/timeline_line.rb +33 -0
  176. data/lib/etassia/layout/timeline_rounding.rb +19 -0
  177. data/lib/etassia/layout/timeline_text.rb +105 -0
  178. data/lib/etassia/layout/treemap.rb +303 -0
  179. data/lib/etassia/layout/treemap_placement.rb +52 -0
  180. data/lib/etassia/layout/treemap_squarify.rb +108 -0
  181. data/lib/etassia/layout/user_journey.rb +300 -0
  182. data/lib/etassia/layout/user_journey_face.rb +33 -0
  183. data/lib/etassia/layout/user_journey_face_geometry.rb +80 -0
  184. data/lib/etassia/layout/user_journey_geometry.rb +336 -0
  185. data/lib/etassia/layout/user_journey_legend.rb +84 -0
  186. data/lib/etassia/layout/xy_chart.rb +620 -0
  187. data/lib/etassia/layout.rb +19 -0
  188. data/lib/etassia/lint_debt_scoreboard.rb +219 -0
  189. data/lib/etassia/markdown_text/emphasis_simulator.rb +373 -0
  190. data/lib/etassia/markdown_text.rb +393 -0
  191. data/lib/etassia/notation/builtin.rb +39 -0
  192. data/lib/etassia/notation/entry.rb +15 -0
  193. data/lib/etassia/notation/mermaid/class_diagram_config.rb +42 -0
  194. data/lib/etassia/notation/mermaid/git_graph_config.rb +46 -0
  195. data/lib/etassia/notation/mermaid/ir_adapter.rb +27 -0
  196. data/lib/etassia/notation/mermaid/ir_adapters/architecture.rb +196 -0
  197. data/lib/etassia/notation/mermaid/ir_adapters/block.rb +138 -0
  198. data/lib/etassia/notation/mermaid/ir_adapters/c4.rb +258 -0
  199. data/lib/etassia/notation/mermaid/ir_adapters/class_diagram.rb +257 -0
  200. data/lib/etassia/notation/mermaid/ir_adapters/er_diagram.rb +220 -0
  201. data/lib/etassia/notation/mermaid/ir_adapters/error.rb +32 -0
  202. data/lib/etassia/notation/mermaid/ir_adapters/flowchart.rb +208 -0
  203. data/lib/etassia/notation/mermaid/ir_adapters/gantt.rb +236 -0
  204. data/lib/etassia/notation/mermaid/ir_adapters/git_graph.rb +186 -0
  205. data/lib/etassia/notation/mermaid/ir_adapters/info.rb +34 -0
  206. data/lib/etassia/notation/mermaid/ir_adapters/kanban.rb +110 -0
  207. data/lib/etassia/notation/mermaid/ir_adapters/mindmap.rb +76 -0
  208. data/lib/etassia/notation/mermaid/ir_adapters/packet.rb +51 -0
  209. data/lib/etassia/notation/mermaid/ir_adapters/pie.rb +71 -0
  210. data/lib/etassia/notation/mermaid/ir_adapters/quadrant.rb +116 -0
  211. data/lib/etassia/notation/mermaid/ir_adapters/radar.rb +142 -0
  212. data/lib/etassia/notation/mermaid/ir_adapters/requirement.rb +237 -0
  213. data/lib/etassia/notation/mermaid/ir_adapters/sankey.rb +74 -0
  214. data/lib/etassia/notation/mermaid/ir_adapters/sequence.rb +304 -0
  215. data/lib/etassia/notation/mermaid/ir_adapters/state_diagram.rb +225 -0
  216. data/lib/etassia/notation/mermaid/ir_adapters/timeline.rb +93 -0
  217. data/lib/etassia/notation/mermaid/ir_adapters/treemap.rb +143 -0
  218. data/lib/etassia/notation/mermaid/ir_adapters/user_journey.rb +127 -0
  219. data/lib/etassia/notation/mermaid/ir_adapters/xychart.rb +131 -0
  220. data/lib/etassia/notation/mermaid.rb +399 -0
  221. data/lib/etassia/notation/parsed.rb +31 -0
  222. data/lib/etassia/notation/plantuml/activity/arrow_head.rb +45 -0
  223. data/lib/etassia/notation/plantuml/activity/arrow_style.rb +53 -0
  224. data/lib/etassia/notation/plantuml/activity/bar_columns.rb +75 -0
  225. data/lib/etassia/notation/plantuml/activity/box.rb +60 -0
  226. data/lib/etassia/notation/plantuml/activity/builder.rb +77 -0
  227. data/lib/etassia/notation/plantuml/activity/canvas.rb +117 -0
  228. data/lib/etassia/notation/plantuml/activity/column_centres.rb +151 -0
  229. data/lib/etassia/notation/plantuml/activity/columns.rb +224 -0
  230. data/lib/etassia/notation/plantuml/activity/diagram.rb +35 -0
  231. data/lib/etassia/notation/plantuml/activity/edge.rb +35 -0
  232. data/lib/etassia/notation/plantuml/activity/edge_marks.rb +68 -0
  233. data/lib/etassia/notation/plantuml/activity/exits.rb +61 -0
  234. data/lib/etassia/notation/plantuml/activity/frame_marks.rb +116 -0
  235. data/lib/etassia/notation/plantuml/activity/lane_steps.rb +82 -0
  236. data/lib/etassia/notation/plantuml/activity/lane_titles.rb +46 -0
  237. data/lib/etassia/notation/plantuml/activity/layout.rb +50 -0
  238. data/lib/etassia/notation/plantuml/activity/legacy_parser.rb +181 -0
  239. data/lib/etassia/notation/plantuml/activity/legacy_row_gaps.rb +65 -0
  240. data/lib/etassia/notation/plantuml/activity/mark.rb +23 -0
  241. data/lib/etassia/notation/plantuml/activity/marks.rb +62 -0
  242. data/lib/etassia/notation/plantuml/activity/metrics.rb +169 -0
  243. data/lib/etassia/notation/plantuml/activity/new_parser/blocks.rb +166 -0
  244. data/lib/etassia/notation/plantuml/activity/new_parser.rb +177 -0
  245. data/lib/etassia/notation/plantuml/activity/node.rb +50 -0
  246. data/lib/etassia/notation/plantuml/activity/node_marks.rb +174 -0
  247. data/lib/etassia/notation/plantuml/activity/note.rb +27 -0
  248. data/lib/etassia/notation/plantuml/activity/parser.rb +51 -0
  249. data/lib/etassia/notation/plantuml/activity/placement.rb +327 -0
  250. data/lib/etassia/notation/plantuml/activity/ranking.rb +142 -0
  251. data/lib/etassia/notation/plantuml/activity/reach.rb +58 -0
  252. data/lib/etassia/notation/plantuml/activity/renderer.rb +220 -0
  253. data/lib/etassia/notation/plantuml/activity/route.rb +22 -0
  254. data/lib/etassia/notation/plantuml/activity/router.rb +308 -0
  255. data/lib/etassia/notation/plantuml/activity/row_gaps.rb +105 -0
  256. data/lib/etassia/notation/plantuml/activity/row_spread.rb +59 -0
  257. data/lib/etassia/notation/plantuml/activity/scene.rb +20 -0
  258. data/lib/etassia/notation/plantuml/activity/text.rb +36 -0
  259. data/lib/etassia/notation/plantuml/activity.rb +50 -0
  260. data/lib/etassia/notation/plantuml/arrow.rb +135 -0
  261. data/lib/etassia/notation/plantuml/caption.rb +50 -0
  262. data/lib/etassia/notation/plantuml/caption_layout.rb +97 -0
  263. data/lib/etassia/notation/plantuml/caption_rows.rb +67 -0
  264. data/lib/etassia/notation/plantuml/class_header.rb +178 -0
  265. data/lib/etassia/notation/plantuml/class_name.rb +51 -0
  266. data/lib/etassia/notation/plantuml/component.rb +37 -0
  267. data/lib/etassia/notation/plantuml/creole.rb +278 -0
  268. data/lib/etassia/notation/plantuml/creole_icons.rb +33 -0
  269. data/lib/etassia/notation/plantuml/diagram.rb +60 -0
  270. data/lib/etassia/notation/plantuml/diagram_builder.rb +442 -0
  271. data/lib/etassia/notation/plantuml/diagram_name.rb +51 -0
  272. data/lib/etassia/notation/plantuml/directives.rb +33 -0
  273. data/lib/etassia/notation/plantuml/drawing/box.rb +28 -0
  274. data/lib/etassia/notation/plantuml/drawing/face.rb +39 -0
  275. data/lib/etassia/notation/plantuml/drawing/pen.rb +105 -0
  276. data/lib/etassia/notation/plantuml/drawing/renderer.rb +36 -0
  277. data/lib/etassia/notation/plantuml/drawing/scene.rb +28 -0
  278. data/lib/etassia/notation/plantuml/drawing.rb +19 -0
  279. data/lib/etassia/notation/plantuml/ebnf/blocks.rb +272 -0
  280. data/lib/etassia/notation/plantuml/ebnf/layout.rb +117 -0
  281. data/lib/etassia/notation/plantuml/ebnf/model.rb +22 -0
  282. data/lib/etassia/notation/plantuml/ebnf/reader.rb +131 -0
  283. data/lib/etassia/notation/plantuml/ebnf.rb +34 -0
  284. data/lib/etassia/notation/plantuml/end_texts.rb +78 -0
  285. data/lib/etassia/notation/plantuml/entity.rb +54 -0
  286. data/lib/etassia/notation/plantuml/further.rb +38 -0
  287. data/lib/etassia/notation/plantuml/gantt/layout.rb +269 -0
  288. data/lib/etassia/notation/plantuml/gantt/reader.rb +210 -0
  289. data/lib/etassia/notation/plantuml/gantt/renderer.rb +81 -0
  290. data/lib/etassia/notation/plantuml/gantt.rb +34 -0
  291. data/lib/etassia/notation/plantuml/include/blocks.rb +66 -0
  292. data/lib/etassia/notation/plantuml/include/finder.rb +61 -0
  293. data/lib/etassia/notation/plantuml/include.rb +78 -0
  294. data/lib/etassia/notation/plantuml/ir_adapter/annotations.rb +40 -0
  295. data/lib/etassia/notation/plantuml/ir_adapter/links.rb +91 -0
  296. data/lib/etassia/notation/plantuml/ir_adapter/sink.rb +49 -0
  297. data/lib/etassia/notation/plantuml/ir_adapter/structure.rb +86 -0
  298. data/lib/etassia/notation/plantuml/ir_adapter.rb +32 -0
  299. data/lib/etassia/notation/plantuml/ir_reader/annotations.rb +51 -0
  300. data/lib/etassia/notation/plantuml/ir_reader/index.rb +49 -0
  301. data/lib/etassia/notation/plantuml/ir_reader/links.rb +133 -0
  302. data/lib/etassia/notation/plantuml/ir_reader/structure.rb +83 -0
  303. data/lib/etassia/notation/plantuml/ir_reader.rb +42 -0
  304. data/lib/etassia/notation/plantuml/junction.rb +20 -0
  305. data/lib/etassia/notation/plantuml/klass.rb +41 -0
  306. data/lib/etassia/notation/plantuml/label_clearance.rb +67 -0
  307. data/lib/etassia/notation/plantuml/layout.rb +2806 -0
  308. data/lib/etassia/notation/plantuml/member.rb +37 -0
  309. data/lib/etassia/notation/plantuml/member_icon.rb +87 -0
  310. data/lib/etassia/notation/plantuml/member_icon_elements.rb +91 -0
  311. data/lib/etassia/notation/plantuml/member_pitch.rb +76 -0
  312. data/lib/etassia/notation/plantuml/member_rule.rb +48 -0
  313. data/lib/etassia/notation/plantuml/network/grid.rb +170 -0
  314. data/lib/etassia/notation/plantuml/network/layout.rb +158 -0
  315. data/lib/etassia/notation/plantuml/network/model.rb +22 -0
  316. data/lib/etassia/notation/plantuml/network/placement.rb +64 -0
  317. data/lib/etassia/notation/plantuml/network/reader.rb +126 -0
  318. data/lib/etassia/notation/plantuml/network/shapes.rb +109 -0
  319. data/lib/etassia/notation/plantuml/network.rb +37 -0
  320. data/lib/etassia/notation/plantuml/node_graph/archimate.rb +49 -0
  321. data/lib/etassia/notation/plantuml/node_graph/box_reader.rb +86 -0
  322. data/lib/etassia/notation/plantuml/node_graph/cloud.rb +73 -0
  323. data/lib/etassia/notation/plantuml/node_graph/crows_foot.rb +85 -0
  324. data/lib/etassia/notation/plantuml/node_graph/curve.rb +66 -0
  325. data/lib/etassia/notation/plantuml/node_graph/data_reader.rb +77 -0
  326. data/lib/etassia/notation/plantuml/node_graph/data_shape.rb +39 -0
  327. data/lib/etassia/notation/plantuml/node_graph/detour.rb +98 -0
  328. data/lib/etassia/notation/plantuml/node_graph/edge.rb +26 -0
  329. data/lib/etassia/notation/plantuml/node_graph/entity_metrics.rb +49 -0
  330. data/lib/etassia/notation/plantuml/node_graph/entity_reader.rb +65 -0
  331. data/lib/etassia/notation/plantuml/node_graph/entity_shape.rb +111 -0
  332. data/lib/etassia/notation/plantuml/node_graph/figures.rb +92 -0
  333. data/lib/etassia/notation/plantuml/node_graph/frame_ports.rb +73 -0
  334. data/lib/etassia/notation/plantuml/node_graph/graph.rb +40 -0
  335. data/lib/etassia/notation/plantuml/node_graph/heads.rb +89 -0
  336. data/lib/etassia/notation/plantuml/node_graph/label_fan.rb +76 -0
  337. data/lib/etassia/notation/plantuml/node_graph/label_placer.rb +310 -0
  338. data/lib/etassia/notation/plantuml/node_graph/label_waypoint.rb +47 -0
  339. data/lib/etassia/notation/plantuml/node_graph/layout.rb +293 -0
  340. data/lib/etassia/notation/plantuml/node_graph/link.rb +78 -0
  341. data/lib/etassia/notation/plantuml/node_graph/macros.rb +39 -0
  342. data/lib/etassia/notation/plantuml/node_graph/metrics.rb +113 -0
  343. data/lib/etassia/notation/plantuml/node_graph/node.rb +44 -0
  344. data/lib/etassia/notation/plantuml/node_graph/note_tail.rb +58 -0
  345. data/lib/etassia/notation/plantuml/node_graph/packer.rb +126 -0
  346. data/lib/etassia/notation/plantuml/node_graph/parser.rb +309 -0
  347. data/lib/etassia/notation/plantuml/node_graph/paths.rb +48 -0
  348. data/lib/etassia/notation/plantuml/node_graph/ranking.rb +231 -0
  349. data/lib/etassia/notation/plantuml/node_graph/reader.rb +53 -0
  350. data/lib/etassia/notation/plantuml/node_graph/references.rb +38 -0
  351. data/lib/etassia/notation/plantuml/node_graph/renderer.rb +160 -0
  352. data/lib/etassia/notation/plantuml/node_graph/scene.rb +22 -0
  353. data/lib/etassia/notation/plantuml/node_graph/shapes.rb +302 -0
  354. data/lib/etassia/notation/plantuml/node_graph/skipped_ranks.rb +61 -0
  355. data/lib/etassia/notation/plantuml/node_graph/tab.rb +68 -0
  356. data/lib/etassia/notation/plantuml/node_graph/usecase_ellipse.rb +100 -0
  357. data/lib/etassia/notation/plantuml/node_graph.rb +38 -0
  358. data/lib/etassia/notation/plantuml/note.rb +27 -0
  359. data/lib/etassia/notation/plantuml/note_layout.rb +257 -0
  360. data/lib/etassia/notation/plantuml/note_outline.rb +68 -0
  361. data/lib/etassia/notation/plantuml/objects/map_rows.rb +46 -0
  362. data/lib/etassia/notation/plantuml/objects/reader.rb +208 -0
  363. data/lib/etassia/notation/plantuml/objects.rb +39 -0
  364. data/lib/etassia/notation/plantuml/package.rb +45 -0
  365. data/lib/etassia/notation/plantuml/package_color.rb +32 -0
  366. data/lib/etassia/notation/plantuml/package_frames.rb +178 -0
  367. data/lib/etassia/notation/plantuml/parser.rb +622 -0
  368. data/lib/etassia/notation/plantuml/portion_visibility.rb +91 -0
  369. data/lib/etassia/notation/plantuml/qualified_association_layout.rb +332 -0
  370. data/lib/etassia/notation/plantuml/qualifier_box.rb +78 -0
  371. data/lib/etassia/notation/plantuml/rank_chain.rb +527 -0
  372. data/lib/etassia/notation/plantuml/rank_hierarchy.rb +347 -0
  373. data/lib/etassia/notation/plantuml/relation.rb +103 -0
  374. data/lib/etassia/notation/plantuml/relation_label_separator.rb +199 -0
  375. data/lib/etassia/notation/plantuml/relation_path_points.rb +84 -0
  376. data/lib/etassia/notation/plantuml/renderer.rb +490 -0
  377. data/lib/etassia/notation/plantuml/scene.rb +134 -0
  378. data/lib/etassia/notation/plantuml/segment_box.rb +85 -0
  379. data/lib/etassia/notation/plantuml/sequence/activation.rb +28 -0
  380. data/lib/etassia/notation/plantuml/sequence/appearance.rb +71 -0
  381. data/lib/etassia/notation/plantuml/sequence/arrow_end.rb +23 -0
  382. data/lib/etassia/notation/plantuml/sequence/arrow_marks.rb +111 -0
  383. data/lib/etassia/notation/plantuml/sequence/arrow_style.rb +42 -0
  384. data/lib/etassia/notation/plantuml/sequence/arrow_syntax.rb +122 -0
  385. data/lib/etassia/notation/plantuml/sequence/bar_tracker.rb +59 -0
  386. data/lib/etassia/notation/plantuml/sequence/box.rb +23 -0
  387. data/lib/etassia/notation/plantuml/sequence/chrome.rb +60 -0
  388. data/lib/etassia/notation/plantuml/sequence/chrome_rows.rb +184 -0
  389. data/lib/etassia/notation/plantuml/sequence/create.rb +34 -0
  390. data/lib/etassia/notation/plantuml/sequence/delay.rb +19 -0
  391. data/lib/etassia/notation/plantuml/sequence/destroy.rb +20 -0
  392. data/lib/etassia/notation/plantuml/sequence/diagram.rb +86 -0
  393. data/lib/etassia/notation/plantuml/sequence/divider.rb +19 -0
  394. data/lib/etassia/notation/plantuml/sequence/edge.rb +53 -0
  395. data/lib/etassia/notation/plantuml/sequence/embedded.rb +77 -0
  396. data/lib/etassia/notation/plantuml/sequence/fill.rb +56 -0
  397. data/lib/etassia/notation/plantuml/sequence/fragment.rb +28 -0
  398. data/lib/etassia/notation/plantuml/sequence/fragment_shape.rb +138 -0
  399. data/lib/etassia/notation/plantuml/sequence/head_style.rb +43 -0
  400. data/lib/etassia/notation/plantuml/sequence/ir_adapter/blocks.rb +73 -0
  401. data/lib/etassia/notation/plantuml/sequence/ir_adapter/fills.rb +24 -0
  402. data/lib/etassia/notation/plantuml/sequence/ir_adapter/items.rb +48 -0
  403. data/lib/etassia/notation/plantuml/sequence/ir_adapter/messages.rb +62 -0
  404. data/lib/etassia/notation/plantuml/sequence/ir_adapter/participants.rb +42 -0
  405. data/lib/etassia/notation/plantuml/sequence/ir_adapter/settings.rb +54 -0
  406. data/lib/etassia/notation/plantuml/sequence/ir_adapter.rb +38 -0
  407. data/lib/etassia/notation/plantuml/sequence/ir_reader/blocks.rb +77 -0
  408. data/lib/etassia/notation/plantuml/sequence/ir_reader/fills.rb +27 -0
  409. data/lib/etassia/notation/plantuml/sequence/ir_reader/index.rb +36 -0
  410. data/lib/etassia/notation/plantuml/sequence/ir_reader/items.rb +35 -0
  411. data/lib/etassia/notation/plantuml/sequence/ir_reader/messages.rb +70 -0
  412. data/lib/etassia/notation/plantuml/sequence/ir_reader/participants.rb +42 -0
  413. data/lib/etassia/notation/plantuml/sequence/ir_reader/settings.rb +74 -0
  414. data/lib/etassia/notation/plantuml/sequence/ir_reader.rb +38 -0
  415. data/lib/etassia/notation/plantuml/sequence/keyword_defaults.rb +28 -0
  416. data/lib/etassia/notation/plantuml/sequence/layout.rb +1567 -0
  417. data/lib/etassia/notation/plantuml/sequence/message.rb +97 -0
  418. data/lib/etassia/notation/plantuml/sequence/message_wrap.rb +77 -0
  419. data/lib/etassia/notation/plantuml/sequence/note.rb +61 -0
  420. data/lib/etassia/notation/plantuml/sequence/note_fill.rb +35 -0
  421. data/lib/etassia/notation/plantuml/sequence/note_geometry.rb +126 -0
  422. data/lib/etassia/notation/plantuml/sequence/note_shape.rb +51 -0
  423. data/lib/etassia/notation/plantuml/sequence/numbered_label.rb +57 -0
  424. data/lib/etassia/notation/plantuml/sequence/numbering.rb +49 -0
  425. data/lib/etassia/notation/plantuml/sequence/outline.rb +204 -0
  426. data/lib/etassia/notation/plantuml/sequence/page_break.rb +17 -0
  427. data/lib/etassia/notation/plantuml/sequence/paint.rb +79 -0
  428. data/lib/etassia/notation/plantuml/sequence/parallel_message.rb +19 -0
  429. data/lib/etassia/notation/plantuml/sequence/parser.rb +844 -0
  430. data/lib/etassia/notation/plantuml/sequence/participant.rb +27 -0
  431. data/lib/etassia/notation/plantuml/sequence/picture.rb +29 -0
  432. data/lib/etassia/notation/plantuml/sequence/ref.rb +24 -0
  433. data/lib/etassia/notation/plantuml/sequence/ref_shape.rb +74 -0
  434. data/lib/etassia/notation/plantuml/sequence/refusals.rb +47 -0
  435. data/lib/etassia/notation/plantuml/sequence/renderer.rb +501 -0
  436. data/lib/etassia/notation/plantuml/sequence/scene.rb +200 -0
  437. data/lib/etassia/notation/plantuml/sequence/skin.rb +76 -0
  438. data/lib/etassia/notation/plantuml/sequence/spacing.rb +28 -0
  439. data/lib/etassia/notation/plantuml/sequence/style.rb +151 -0
  440. data/lib/etassia/notation/plantuml/sequence/tab_size.rb +42 -0
  441. data/lib/etassia/notation/plantuml/sequence/walker.rb +1190 -0
  442. data/lib/etassia/notation/plantuml/sequence.rb +47 -0
  443. data/lib/etassia/notation/plantuml/source_lines.rb +33 -0
  444. data/lib/etassia/notation/plantuml/state/axis_solver.rb +272 -0
  445. data/lib/etassia/notation/plantuml/state/cluster_padding.rb +75 -0
  446. data/lib/etassia/notation/plantuml/state/curve.rb +73 -0
  447. data/lib/etassia/notation/plantuml/state/dot_axis.rb +248 -0
  448. data/lib/etassia/notation/plantuml/state/extent.rb +42 -0
  449. data/lib/etassia/notation/plantuml/state/hierarchy.rb +355 -0
  450. data/lib/etassia/notation/plantuml/state/label_clearance.rb +148 -0
  451. data/lib/etassia/notation/plantuml/state/label_reach.rb +139 -0
  452. data/lib/etassia/notation/plantuml/state/layout.rb +173 -0
  453. data/lib/etassia/notation/plantuml/state/level_edges.rb +113 -0
  454. data/lib/etassia/notation/plantuml/state/look.rb +36 -0
  455. data/lib/etassia/notation/plantuml/state/note_shape.rb +73 -0
  456. data/lib/etassia/notation/plantuml/state/plane.rb +85 -0
  457. data/lib/etassia/notation/plantuml/state/ranking.rb +181 -0
  458. data/lib/etassia/notation/plantuml/state/reader.rb +310 -0
  459. data/lib/etassia/notation/plantuml/state/renderer.rb +253 -0
  460. data/lib/etassia/notation/plantuml/state/route_detour.rb +115 -0
  461. data/lib/etassia/notation/plantuml/state/route_geometry.rb +186 -0
  462. data/lib/etassia/notation/plantuml/state/routes.rb +196 -0
  463. data/lib/etassia/notation/plantuml/state/row.rb +88 -0
  464. data/lib/etassia/notation/plantuml/state/rows.rb +50 -0
  465. data/lib/etassia/notation/plantuml/state/stretch.rb +71 -0
  466. data/lib/etassia/notation/plantuml/state.rb +62 -0
  467. data/lib/etassia/notation/plantuml/stereotype_head.rb +58 -0
  468. data/lib/etassia/notation/plantuml/style/bound.rb +34 -0
  469. data/lib/etassia/notation/plantuml/style/colour.rb +41 -0
  470. data/lib/etassia/notation/plantuml/style/colour_names.rb +89 -0
  471. data/lib/etassia/notation/plantuml/style/defaults.rb +33 -0
  472. data/lib/etassia/notation/plantuml/style/inline.rb +56 -0
  473. data/lib/etassia/notation/plantuml/style/reader.rb +242 -0
  474. data/lib/etassia/notation/plantuml/style/sheet.rb +103 -0
  475. data/lib/etassia/notation/plantuml/style.rb +32 -0
  476. data/lib/etassia/notation/plantuml/style_reader.rb +160 -0
  477. data/lib/etassia/notation/plantuml/style_sheet.rb +27 -0
  478. data/lib/etassia/notation/plantuml/styled_relation_curve.rb +71 -0
  479. data/lib/etassia/notation/plantuml/timing/arrows.rb +81 -0
  480. data/lib/etassia/notation/plantuml/timing/axis.rb +100 -0
  481. data/lib/etassia/notation/plantuml/timing/layout.rb +172 -0
  482. data/lib/etassia/notation/plantuml/timing/model.rb +34 -0
  483. data/lib/etassia/notation/plantuml/timing/reader.rb +173 -0
  484. data/lib/etassia/notation/plantuml/timing/signals.rb +328 -0
  485. data/lib/etassia/notation/plantuml/timing.rb +38 -0
  486. data/lib/etassia/notation/plantuml/tree/layout.rb +276 -0
  487. data/lib/etassia/notation/plantuml/tree/mindmap_layout.rb +157 -0
  488. data/lib/etassia/notation/plantuml/tree/reader.rb +186 -0
  489. data/lib/etassia/notation/plantuml/tree/renderer.rb +67 -0
  490. data/lib/etassia/notation/plantuml/tree/role.rb +57 -0
  491. data/lib/etassia/notation/plantuml/tree/rules.rb +156 -0
  492. data/lib/etassia/notation/plantuml/tree/wbs_layout.rb +164 -0
  493. data/lib/etassia/notation/plantuml/tree.rb +41 -0
  494. data/lib/etassia/notation/plantuml/unsupported_construct_error.rb +39 -0
  495. data/lib/etassia/notation/plantuml/unsupported_constructs.rb +103 -0
  496. data/lib/etassia/notation/plantuml/usecase.rb +36 -0
  497. data/lib/etassia/notation/plantuml.rb +132 -0
  498. data/lib/etassia/notation/plantuml_data/boxes/frames.rb +101 -0
  499. data/lib/etassia/notation/plantuml_data/boxes/graph_layout.rb +348 -0
  500. data/lib/etassia/notation/plantuml_data/boxes/heads.rb +65 -0
  501. data/lib/etassia/notation/plantuml_data/boxes/highlights.rb +70 -0
  502. data/lib/etassia/notation/plantuml_data/boxes/inline_rows.rb +99 -0
  503. data/lib/etassia/notation/plantuml_data/boxes/json_reader.rb +24 -0
  504. data/lib/etassia/notation/plantuml_data/boxes/link_text.rb +94 -0
  505. data/lib/etassia/notation/plantuml_data/boxes/marks.rb +76 -0
  506. data/lib/etassia/notation/plantuml_data/boxes/ornaments.rb +130 -0
  507. data/lib/etassia/notation/plantuml_data/boxes/renderer.rb +95 -0
  508. data/lib/etassia/notation/plantuml_data/boxes/row_alignment.rb +58 -0
  509. data/lib/etassia/notation/plantuml_data/boxes/row_bend.rb +43 -0
  510. data/lib/etassia/notation/plantuml_data/boxes/scene.rb +27 -0
  511. data/lib/etassia/notation/plantuml_data/boxes/table.rb +56 -0
  512. data/lib/etassia/notation/plantuml_data/boxes/table_box.rb +355 -0
  513. data/lib/etassia/notation/plantuml_data/boxes/text.rb +101 -0
  514. data/lib/etassia/notation/plantuml_data/boxes/tree_builder.rb +82 -0
  515. data/lib/etassia/notation/plantuml_data/boxes/tree_layout.rb +82 -0
  516. data/lib/etassia/notation/plantuml_data/boxes/yaml_reader.rb +105 -0
  517. data/lib/etassia/notation/plantuml_data/openiconic.LICENSE +6 -0
  518. data/lib/etassia/notation/plantuml_data/openiconic.json +1 -0
  519. data/lib/etassia/notation/plantuml_data.rb +84 -0
  520. data/lib/etassia/notation/plantuml_salt/block.rb +80 -0
  521. data/lib/etassia/notation/plantuml_salt/box.rb +30 -0
  522. data/lib/etassia/notation/plantuml_salt/font_metrics.rb +28 -0
  523. data/lib/etassia/notation/plantuml_salt/grid_marks.rb +66 -0
  524. data/lib/etassia/notation/plantuml_salt/group_marks.rb +77 -0
  525. data/lib/etassia/notation/plantuml_salt/layout.rb +206 -0
  526. data/lib/etassia/notation/plantuml_salt/mark.rb +36 -0
  527. data/lib/etassia/notation/plantuml_salt/markup.rb +57 -0
  528. data/lib/etassia/notation/plantuml_salt/parser.rb +239 -0
  529. data/lib/etassia/notation/plantuml_salt/renderer.rb +138 -0
  530. data/lib/etassia/notation/plantuml_salt/row.rb +19 -0
  531. data/lib/etassia/notation/plantuml_salt/run.rb +34 -0
  532. data/lib/etassia/notation/plantuml_salt/scene.rb +23 -0
  533. data/lib/etassia/notation/plantuml_salt/scroll_marks.rb +94 -0
  534. data/lib/etassia/notation/plantuml_salt/tab_marks.rb +74 -0
  535. data/lib/etassia/notation/plantuml_salt/tree_marks.rb +127 -0
  536. data/lib/etassia/notation/plantuml_salt/widget.rb +40 -0
  537. data/lib/etassia/notation/plantuml_salt/widget_marks.rb +319 -0
  538. data/lib/etassia/notation/plantuml_salt.rb +66 -0
  539. data/lib/etassia/notation/plugin_failure.rb +42 -0
  540. data/lib/etassia/notation.rb +289 -0
  541. data/lib/etassia/parser/architecture.rb +25 -0
  542. data/lib/etassia/parser/atoms/delimited_run.rb +82 -0
  543. data/lib/etassia/parser/atoms/greedy_run.rb +116 -0
  544. data/lib/etassia/parser/atoms/joined.rb +47 -0
  545. data/lib/etassia/parser/atoms/trimmed_run.rb +47 -0
  546. data/lib/etassia/parser/base.rb +258 -0
  547. data/lib/etassia/parser/block.rb +32 -0
  548. data/lib/etassia/parser/builders/architecture.rb +135 -0
  549. data/lib/etassia/parser/builders/block.rb +288 -0
  550. data/lib/etassia/parser/builders/c4.rb +275 -0
  551. data/lib/etassia/parser/builders/capture_string.rb +17 -0
  552. data/lib/etassia/parser/builders/class_diagram.rb +539 -0
  553. data/lib/etassia/parser/builders/er_diagram.rb +308 -0
  554. data/lib/etassia/parser/builders/error.rb +51 -0
  555. data/lib/etassia/parser/builders/flowchart.rb +1150 -0
  556. data/lib/etassia/parser/builders/gantt.rb +267 -0
  557. data/lib/etassia/parser/builders/git_graph.rb +301 -0
  558. data/lib/etassia/parser/builders/info.rb +57 -0
  559. data/lib/etassia/parser/builders/kanban.rb +411 -0
  560. data/lib/etassia/parser/builders/mindmap.rb +271 -0
  561. data/lib/etassia/parser/builders/packet.rb +85 -0
  562. data/lib/etassia/parser/builders/pie.rb +105 -0
  563. data/lib/etassia/parser/builders/quadrant.rb +165 -0
  564. data/lib/etassia/parser/builders/radar.rb +157 -0
  565. data/lib/etassia/parser/builders/requirement.rb +230 -0
  566. data/lib/etassia/parser/builders/sankey.rb +142 -0
  567. data/lib/etassia/parser/builders/sequence.rb +431 -0
  568. data/lib/etassia/parser/builders/sequence_blocks.rb +117 -0
  569. data/lib/etassia/parser/builders/sequence_box_title.rb +57 -0
  570. data/lib/etassia/parser/builders/state_diagram.rb +364 -0
  571. data/lib/etassia/parser/builders/timeline.rb +133 -0
  572. data/lib/etassia/parser/builders/treemap.rb +138 -0
  573. data/lib/etassia/parser/builders/xy_chart.rb +148 -0
  574. data/lib/etassia/parser/c4.rb +37 -0
  575. data/lib/etassia/parser/class_diagram.rb +58 -0
  576. data/lib/etassia/parser/class_namespaces.rb +62 -0
  577. data/lib/etassia/parser/class_notes.rb +54 -0
  578. data/lib/etassia/parser/er_diagram.rb +28 -0
  579. data/lib/etassia/parser/error.rb +30 -0
  580. data/lib/etassia/parser/flowchart.rb +87 -0
  581. data/lib/etassia/parser/gantt.rb +43 -0
  582. data/lib/etassia/parser/git_graph.rb +106 -0
  583. data/lib/etassia/parser/grammars/architecture.rb +165 -0
  584. data/lib/etassia/parser/grammars/block.rb +190 -0
  585. data/lib/etassia/parser/grammars/c4.rb +229 -0
  586. data/lib/etassia/parser/grammars/class_diagram.rb +606 -0
  587. data/lib/etassia/parser/grammars/common.rb +107 -0
  588. data/lib/etassia/parser/grammars/er_diagram.rb +232 -0
  589. data/lib/etassia/parser/grammars/error.rb +32 -0
  590. data/lib/etassia/parser/grammars/flowchart.rb +1722 -0
  591. data/lib/etassia/parser/grammars/gantt.rb +198 -0
  592. data/lib/etassia/parser/grammars/git_graph.rb +234 -0
  593. data/lib/etassia/parser/grammars/info.rb +53 -0
  594. data/lib/etassia/parser/grammars/kanban.rb +417 -0
  595. data/lib/etassia/parser/grammars/mermaid_unicode_text.rb +108 -0
  596. data/lib/etassia/parser/grammars/mindmap.rb +220 -0
  597. data/lib/etassia/parser/grammars/packet.rb +71 -0
  598. data/lib/etassia/parser/grammars/pie.rb +128 -0
  599. data/lib/etassia/parser/grammars/quadrant.rb +202 -0
  600. data/lib/etassia/parser/grammars/radar.rb +158 -0
  601. data/lib/etassia/parser/grammars/requirement.rb +258 -0
  602. data/lib/etassia/parser/grammars/sankey.rb +104 -0
  603. data/lib/etassia/parser/grammars/sequence.rb +940 -0
  604. data/lib/etassia/parser/grammars/state_diagram.rb +382 -0
  605. data/lib/etassia/parser/grammars/timeline.rb +153 -0
  606. data/lib/etassia/parser/grammars/treemap.rb +122 -0
  607. data/lib/etassia/parser/grammars/xy_chart.rb +119 -0
  608. data/lib/etassia/parser/info.rb +32 -0
  609. data/lib/etassia/parser/kanban.rb +131 -0
  610. data/lib/etassia/parser/mermaid_shapes.rb +106 -0
  611. data/lib/etassia/parser/metadata_yaml.rb +452 -0
  612. data/lib/etassia/parser/mindmap.rb +92 -0
  613. data/lib/etassia/parser/native/builders/architecture.rb +103 -0
  614. data/lib/etassia/parser/native/builders/block.rb +68 -0
  615. data/lib/etassia/parser/native/builders/c4.rb +16 -0
  616. data/lib/etassia/parser/native/builders/class_diagram.rb +63 -0
  617. data/lib/etassia/parser/native/builders/er_diagram.rb +47 -0
  618. data/lib/etassia/parser/native/builders/flowchart.rb +58 -0
  619. data/lib/etassia/parser/native/builders/gantt.rb +35 -0
  620. data/lib/etassia/parser/native/builders/gitgraph.rb +35 -0
  621. data/lib/etassia/parser/native/builders/info.rb +30 -0
  622. data/lib/etassia/parser/native/builders/kanban.rb +37 -0
  623. data/lib/etassia/parser/native/builders/mindmap.rb +26 -0
  624. data/lib/etassia/parser/native/builders/packet.rb +63 -0
  625. data/lib/etassia/parser/native/builders/pie.rb +82 -0
  626. data/lib/etassia/parser/native/builders/quadrant.rb +27 -0
  627. data/lib/etassia/parser/native/builders/radar.rb +84 -0
  628. data/lib/etassia/parser/native/builders/requirement.rb +25 -0
  629. data/lib/etassia/parser/native/builders/sankey.rb +18 -0
  630. data/lib/etassia/parser/native/builders/sequence.rb +48 -0
  631. data/lib/etassia/parser/native/builders/state_diagram.rb +61 -0
  632. data/lib/etassia/parser/native/builders/timeline.rb +46 -0
  633. data/lib/etassia/parser/native/builders/treemap.rb +60 -0
  634. data/lib/etassia/parser/native/builders/user_journey.rb +83 -0
  635. data/lib/etassia/parser/native/builders/xy_chart.rb +94 -0
  636. data/lib/etassia/parser/native/declined.rb +12 -0
  637. data/lib/etassia/parser/native/mermaid.json +1 -0
  638. data/lib/etassia/parser/native/text.rb +31 -0
  639. data/lib/etassia/parser/native.rb +99 -0
  640. data/lib/etassia/parser/packet.rb +56 -0
  641. data/lib/etassia/parser/pie.rb +32 -0
  642. data/lib/etassia/parser/quadrant.rb +77 -0
  643. data/lib/etassia/parser/radar.rb +99 -0
  644. data/lib/etassia/parser/requirement.rb +32 -0
  645. data/lib/etassia/parser/sankey.rb +47 -0
  646. data/lib/etassia/parser/sequence.rb +34 -0
  647. data/lib/etassia/parser/state_diagram.rb +29 -0
  648. data/lib/etassia/parser/timeline.rb +40 -0
  649. data/lib/etassia/parser/treemap.rb +25 -0
  650. data/lib/etassia/parser/user_journey.rb +253 -0
  651. data/lib/etassia/parser/xy_chart.rb +98 -0
  652. data/lib/etassia/parser.rb +18 -0
  653. data/lib/etassia/renderer/architecture.rb +232 -0
  654. data/lib/etassia/renderer/architecture_edge_router.rb +379 -0
  655. data/lib/etassia/renderer/base.rb +295 -0
  656. data/lib/etassia/renderer/block.rb +157 -0
  657. data/lib/etassia/renderer/c4.rb +294 -0
  658. data/lib/etassia/renderer/class_diagram.rb +671 -0
  659. data/lib/etassia/renderer/er_diagram.rb +842 -0
  660. data/lib/etassia/renderer/error.rb +131 -0
  661. data/lib/etassia/renderer/flowchart.rb +315 -0
  662. data/lib/etassia/renderer/gantt.rb +177 -0
  663. data/lib/etassia/renderer/git_graph.rb +224 -0
  664. data/lib/etassia/renderer/info.rb +59 -0
  665. data/lib/etassia/renderer/kanban.rb +157 -0
  666. data/lib/etassia/renderer/line_break_text.rb +56 -0
  667. data/lib/etassia/renderer/markdown_text.rb +106 -0
  668. data/lib/etassia/renderer/mindmap.rb +290 -0
  669. data/lib/etassia/renderer/packet.rb +87 -0
  670. data/lib/etassia/renderer/pie.rb +113 -0
  671. data/lib/etassia/renderer/quadrant.rb +189 -0
  672. data/lib/etassia/renderer/radar.rb +191 -0
  673. data/lib/etassia/renderer/requirement.rb +209 -0
  674. data/lib/etassia/renderer/sankey.rb +114 -0
  675. data/lib/etassia/renderer/sequence/frame_drawing.rb +169 -0
  676. data/lib/etassia/renderer/sequence/note_drawing.rb +69 -0
  677. data/lib/etassia/renderer/sequence.rb +490 -0
  678. data/lib/etassia/renderer/state_diagram.rb +202 -0
  679. data/lib/etassia/renderer/timeline.rb +134 -0
  680. data/lib/etassia/renderer/timeline_palette.rb +18 -0
  681. data/lib/etassia/renderer/treemap/section_total.rb +33 -0
  682. data/lib/etassia/renderer/treemap.rb +128 -0
  683. data/lib/etassia/renderer/user_journey.rb +209 -0
  684. data/lib/etassia/renderer/xy_chart.rb +180 -0
  685. data/lib/etassia/renderer.rb +22 -0
  686. data/lib/etassia/runtime.rb +125 -0
  687. data/lib/etassia/source/frontmatter.rb +501 -0
  688. data/lib/etassia/source.rb +224 -0
  689. data/lib/etassia/svg/arrowhead.rb +205 -0
  690. data/lib/etassia/svg/circle.rb +19 -0
  691. data/lib/etassia/svg/document.rb +106 -0
  692. data/lib/etassia/svg/element.rb +209 -0
  693. data/lib/etassia/svg/ellipse.rb +23 -0
  694. data/lib/etassia/svg/escaping.rb +149 -0
  695. data/lib/etassia/svg/group.rb +64 -0
  696. data/lib/etassia/svg/line.rb +21 -0
  697. data/lib/etassia/svg/numbers.rb +53 -0
  698. data/lib/etassia/svg/path.rb +67 -0
  699. data/lib/etassia/svg/path_geometry.rb +378 -0
  700. data/lib/etassia/svg/polygon.rb +25 -0
  701. data/lib/etassia/svg/polyline.rb +28 -0
  702. data/lib/etassia/svg/rect.rb +34 -0
  703. data/lib/etassia/svg/style.rb +50 -0
  704. data/lib/etassia/svg/text.rb +181 -0
  705. data/lib/etassia/svg/tspan.rb +48 -0
  706. data/lib/etassia/svg.rb +38 -0
  707. data/lib/etassia/text_measurement/arial_advances.rb +122 -0
  708. data/lib/etassia/text_measurement/dejavu_advances.rb +111 -0
  709. data/lib/etassia/text_measurement/times_advances.rb +64 -0
  710. data/lib/etassia/text_measurement/trebuchet_advances.rb +53 -0
  711. data/lib/etassia/text_measurement/trebuchet_kerning.rb +29 -0
  712. data/lib/etassia/text_measurement.rb +198 -0
  713. data/lib/etassia/theme/builtin/dark.yml +229 -0
  714. data/lib/etassia/theme/builtin/default.yml +239 -0
  715. data/lib/etassia/theme/builtin/high_contrast.yml +231 -0
  716. data/lib/etassia/theme/builtin/light.yml +229 -0
  717. data/lib/etassia/theme/color_palette.rb +97 -0
  718. data/lib/etassia/theme/completion.rb +50 -0
  719. data/lib/etassia/theme/effect_styles.rb +34 -0
  720. data/lib/etassia/theme/registry.rb +45 -0
  721. data/lib/etassia/theme/shape_styles.rb +34 -0
  722. data/lib/etassia/theme/spacing_config.rb +30 -0
  723. data/lib/etassia/theme/typography.rb +40 -0
  724. data/lib/etassia/theme.rb +73 -0
  725. data/lib/etassia/version.rb +5 -0
  726. data/lib/etassia.rb +40 -0
  727. metadata +865 -0
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Etassia
4
+ module Notation
5
+ module PlantUML
6
+ # Reads a relation glyph such as `<|--`, `o-down-`, `*.r.>` or `..>`.
7
+ #
8
+ # A glyph is an optional marker, a body of dashes or dots (a dot makes
9
+ # the line dashed) that may carry a direction word between two runs,
10
+ # and an optional marker. The direction word is kept as `:up`, `:down`,
11
+ # `:left` or `:right` for the layout; a one-character body such as
12
+ # `->` or `.>` lays out like `:right`. The body's length, its dashes
13
+ # and dots, sets how many ranks the relation spans.
14
+ module Arrow
15
+ extend self
16
+
17
+ LEFT_MARKER = '(?:<\||<|o|\*|\+)'
18
+ RIGHT_MARKER = '(?:\|>|>|o|\*|\+)'
19
+ # A bare `o` or `*` after the body only ends it before a space or a
20
+ # quote; otherwise it starts the class name (`A --oB`).
21
+ RIGHT_IN_LINE = '(?:\|>|>|(?:o|\*|\+)(?=[ \t"]))'
22
+ # A bracketed style (`-[#red,dashed,thickness=2]->`) stands in for
23
+ # the dashes; its words after the colour set the line's dashing.
24
+ BRACKET = '-\[[^\]]*\]-*'
25
+ BODY = "(?:[-.]+(?:(?:up|down|left|right|u|d|l|r)[-.]+)?" \
26
+ "|#{BRACKET})".freeze
27
+
28
+ # Matches one glyph; embed it, then call {parse} on the match.
29
+ PATTERN = "(#{LEFT_MARKER}?#{BODY}#{RIGHT_IN_LINE}?)".freeze
30
+
31
+ GLYPH = /\A(#{LEFT_MARKER})?(#{BODY})(#{RIGHT_MARKER})?\z/o
32
+ PLAIN = /\A(?:-->|<--|->|<-)\z/
33
+ KINDS = { "|" => :extension, "o" => :aggregation,
34
+ "*" => :composition, "+" => :nesting }.freeze
35
+ PLAIN_HEADS = %w[< >].freeze
36
+ DIRECTIONS = { "u" => :up, "d" => :down, "l" => :left,
37
+ "r" => :right }.freeze
38
+ DASHING = /\b(?:dashed|dotted)\b/i
39
+ private_constant :BRACKET, :DASHING, :LEFT_MARKER, :RIGHT_MARKER,
40
+ :RIGHT_IN_LINE, :BODY, :GLYPH, :PLAIN, :KINDS,
41
+ :PLAIN_HEADS, :DIRECTIONS
42
+
43
+ # @return [Hash, nil] `:markers` (side to kind, left first), `:dashed`,
44
+ # `:kind` and `:head` (:left, :right, or :both with a nil kind when
45
+ # both ends carry a marker), `:direction` (nil without a word),
46
+ # `:length` (the body's dashes and dots) and `:plain` (a bare
47
+ # association
48
+ # arrow, which a sequence diagram also has); nil for `<->`, which
49
+ # a sequence diagram also has and which is not drawn here
50
+ def parse(glyph)
51
+ match = GLYPH.match(glyph)
52
+ left, body, right = match.captures
53
+ return if plain_heads?(left, right)
54
+
55
+ details(glyph, left, body, right)
56
+ end
57
+
58
+ private
59
+
60
+ def plain_heads?(left, right)
61
+ [left, right].all? { |end_| PLAIN_HEADS.include?(end_) }
62
+ end
63
+
64
+ def details(glyph, left, body, right)
65
+ style = body[/\[([^\]]*)\]/, 1]
66
+ body = body.sub(/\[[^\]]*\]/, "") if style
67
+ dashed = body.include?(".") || DASHING.match?(style.to_s)
68
+ markers = markers_of(left, right, dashed)
69
+ { markers: markers, dashed: dashed, head: head_of(markers),
70
+ kind: single_kind(markers, dashed), plain: PLAIN.match?(glyph),
71
+ direction: direction_of(body), length: body.count("-.") }
72
+ .merge(stroke_of(style.to_s))
73
+ end
74
+
75
+ def markers_of(left, right, dashed)
76
+ { left: left, right: right }.compact
77
+ .transform_values { |marker| kind_of(marker, dashed) }
78
+ end
79
+
80
+ # The bracket's colour, thickness and dotted flag; absent keys mean
81
+ # the theme's own line. Of comma-separated colours the last wins, as
82
+ # in the JAR; of a `#red;#green` pair the first.
83
+ def stroke_of(style)
84
+ words = style.split(/[,;]/).map(&:strip)
85
+ { color: color_of(style),
86
+ width: thickness_of(words),
87
+ dotted: words.any? { |word| word.casecmp?("dotted") } }
88
+ end
89
+
90
+ def color_of(style)
91
+ style.split(",").filter_map do |group|
92
+ group.split(";").first.to_s.strip[/\A#(\w+)\z/, 1]
93
+ end.last
94
+ end
95
+
96
+ def thickness_of(words)
97
+ width = words.filter_map { |word| word[/\Athickness=(\d+)/, 1] }
98
+ .first.to_i
99
+ width if width.positive?
100
+ end
101
+
102
+ def direction_of(body)
103
+ word = body[/[a-z]+/]
104
+ return DIRECTIONS[word[0]] if word
105
+
106
+ :right if body.size == 1
107
+ end
108
+
109
+ def single_kind(markers, dashed)
110
+ return line_kind(dashed) if markers.empty?
111
+
112
+ markers.values.first if markers.size == 1
113
+ end
114
+
115
+ def kind_of(marker, dashed)
116
+ shape = marker.delete("<>")
117
+ return line_kind(dashed) if shape.empty?
118
+ return dashed ? :implementation : :extension if shape == "|"
119
+
120
+ KINDS.fetch(shape)
121
+ end
122
+
123
+ def line_kind(dashed)
124
+ dashed ? :dependency : :association
125
+ end
126
+
127
+ def head_of(markers)
128
+ return :both if markers.size == 2
129
+
130
+ markers.keys.first
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Etassia
4
+ module Notation
5
+ module PlantUML
6
+ # One of the five statements PlantUML draws around a diagram: its
7
+ # `kind` is :title, :header, :footer, :caption or :legend and `text`
8
+ # the one plain line written after the word.
9
+ class Caption
10
+ KINDS = %i[title header footer caption legend].freeze
11
+
12
+ # A text this notation can draw as written: no creole or HTML markup,
13
+ # no escape sequence, and none of the alignment words PlantUML reads
14
+ # after `legend`, which open a block.
15
+ PLAIN = /\A[[:alnum:]][[:alnum:] .,:;!?()'-]*\z/
16
+ ARROW_START = /\A\S*(?:--|\.\.|->|<-)/
17
+ ALIGNMENT = /\A(?:left|right|center|top|bottom)\z/i
18
+ LINE = /\A(#{KINDS.join('|')})[ \t]+(.+)\z/io
19
+ private_constant :PLAIN, :ARROW_START, :ALIGNMENT, :LINE
20
+
21
+ # @param text [String] one stripped source line
22
+ # @return [Caption, nil] nil when the line is not a caption this
23
+ # notation draws: another statement, a block form, or markup
24
+ def self.read(text)
25
+ match = LINE.match(text)
26
+ return unless match
27
+
28
+ body = match[2].strip
29
+ return unless PLAIN.match?(body) && !ARROW_START.match?(body)
30
+ return if match[1].casecmp?("legend") && ALIGNMENT.match?(body)
31
+
32
+ new(match[1].downcase.to_sym, body)
33
+ end
34
+
35
+ # @return [Boolean] whether one line of a block is plain text
36
+ def self.plain?(text)
37
+ PLAIN.match?(text) && !ARROW_START.match?(text)
38
+ end
39
+
40
+ attr_reader :kind, :text
41
+
42
+ def initialize(kind, text)
43
+ @kind = kind
44
+ @text = text
45
+ freeze
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "caption_rows"
4
+ require_relative "scene"
5
+
6
+ module Etassia
7
+ module Notation
8
+ module PlantUML
9
+ # Places a diagram's captions around an already laid out Scene: header
10
+ # and title above it, legend, caption and footer below it, each on its
11
+ # own row. The content keeps its coordinates and moves as a whole by
12
+ # the Scene's `content_x` and `content_y`.
13
+ class CaptionLayout
14
+ PADDING = 5.0
15
+ SMALL = %i[header footer].freeze
16
+ SMALL_SIZE = 10.0
17
+ LEGEND_FILL = "#DDDDDD"
18
+ SMALL_COLOUR = "#888888"
19
+ private_constant :PADDING, :SMALL, :SMALL_SIZE, :LEGEND_FILL,
20
+ :SMALL_COLOUR
21
+
22
+ # @param diagram [Diagram]
23
+ # @param normal_size [Float] the font size of a title, caption or
24
+ # legend that the style does not set
25
+ # @param measure [#call] width of a text given the text and its size
26
+ def initialize(diagram, normal_size:, measure:)
27
+ @diagram = diagram
28
+ @normal_size = normal_size
29
+ @measure = measure
30
+ end
31
+
32
+ # @param scene [Scene] the content, freshly built: it is resized and
33
+ # given the panels in place
34
+ # @return [Scene] the same Scene, as large as content and captions
35
+ def dress(scene)
36
+ panels = sized_panels
37
+ return scene if panels.empty? && @diagram.style.background.nil?
38
+
39
+ width = canvas_width(scene, panels)
40
+ settle(scene, width, CaptionRows.new(panels, width, scene.height))
41
+ scene.background = @diagram.style.background
42
+ scene
43
+ end
44
+
45
+ private
46
+
47
+ # The old width is read before it is replaced.
48
+ def settle(scene, width, rows)
49
+ scene.content_x = (width - scene.width) / 2
50
+ scene.content_y = rows.content_y
51
+ scene.width = width
52
+ scene.height = rows.bottom_edge
53
+ scene.panels = rows.panels
54
+ end
55
+
56
+ def canvas_width(scene, panels)
57
+ widest = panels.map(&:width).max.to_f
58
+ [scene.width, widest + (CaptionRows::GAP * 2)].max
59
+ end
60
+
61
+ def sized_panels
62
+ @diagram.captions.map { |caption| panel(caption) }
63
+ end
64
+
65
+ def panel(caption)
66
+ kind = caption.kind
67
+ rule = @diagram.style.rule(kind)
68
+ size = size_of(kind, rule)
69
+ Scene::Panel.new(
70
+ id: "caption-#{kind}", kind: kind.to_s, font_size: size,
71
+ content: caption.text, **extent_of(caption.text, size),
72
+ **look_of(kind, rule)
73
+ )
74
+ end
75
+
76
+ def extent_of(text, size)
77
+ { width: @measure.call(text, size) + (PADDING * 2),
78
+ height: (size * 1.2) + (PADDING * 2) }
79
+ end
80
+
81
+ def look_of(kind, rule)
82
+ { bordered: kind == :legend, bold: kind == :title,
83
+ fill: rule[:background] || (LEGEND_FILL if kind == :legend),
84
+ colour: rule[:colour] || (SMALL_COLOUR if SMALL.include?(kind)) }
85
+ end
86
+
87
+ def size_of(kind, rule)
88
+ (rule[:size] || default_size(kind)).to_f
89
+ end
90
+
91
+ def default_size(kind)
92
+ SMALL.include?(kind) ? SMALL_SIZE : @normal_size
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Etassia
4
+ module Notation
5
+ module PlantUML
6
+ # Stacks sized caption panels into the rows above and below the
7
+ # diagram content: header and title above it, legend, caption and
8
+ # footer below it, each kind on its own row.
9
+ class CaptionRows
10
+ GAP = 10.0
11
+ TOP = %i[header title].freeze
12
+ BOTTOM = %i[legend caption footer].freeze
13
+ private_constant :TOP, :BOTTOM
14
+
15
+ # @param panels [Array<Scene::Panel>] sized, not yet positioned
16
+ # @param width [Float] the width of the whole picture
17
+ # @param content_height [Float] the height of the diagram content
18
+ def initialize(panels, width, content_height)
19
+ @panels = panels
20
+ @width = width
21
+ @top = stack(TOP, GAP)
22
+ @content_y = @top.empty? ? 0.0 : @top.last.y + @top.last.height
23
+ @below = @content_y + content_height
24
+ @bottom = stack(BOTTOM, @below)
25
+ end
26
+
27
+ # @return [Float] where the diagram content starts
28
+ attr_reader :content_y
29
+
30
+ # @return [Array<Scene::Panel>] every panel, positioned
31
+ def panels
32
+ @top + @bottom
33
+ end
34
+
35
+ # @return [Float] the height of the whole picture
36
+ def bottom_edge
37
+ @bottom.empty? ? @below : @bottom.last.y + @bottom.last.height + GAP
38
+ end
39
+
40
+ private
41
+
42
+ # Stacks the kinds in `order` that are present, top to bottom from
43
+ # `start`, and returns them positioned.
44
+ def stack(order, start)
45
+ cursor = start
46
+ order.filter_map do |kind|
47
+ panel = @panels.find { |item| item.kind == kind.to_s }
48
+ next unless panel
49
+
50
+ positioned = at(panel, cursor)
51
+ cursor += panel.height + GAP
52
+ positioned
53
+ end
54
+ end
55
+
56
+ def at(panel, top)
57
+ left = (@width - panel.width) / 2
58
+ left = @width - GAP - panel.width if panel.kind == "header"
59
+ panel.tap do |item|
60
+ item.x = left
61
+ item.y = top
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "scene"
4
+
5
+ module Etassia
6
+ module Notation
7
+ module PlantUML
8
+ # What PlantUML draws in a class box's header beyond its name: the
9
+ # circled letter (C for a class, A for an abstract class, I for an
10
+ # interface, E for an enum, @ for an annotation) and, in a class
11
+ # with no members, the two rules of its empty compartments. Placed
12
+ # after layout, from the final box geometry, so it never changes a
13
+ # size.
14
+ module ClassHeader
15
+ extend self
16
+
17
+ Glyph = Struct.new(:fill, :outline)
18
+
19
+ RADIUS = 11.0
20
+ # Offsets from the class name's baseline and from the start of the
21
+ # circle-and-name block, measured against PlantUML 1.2026.6.
22
+ CENTRE_ABOVE_BASELINE = 5.291
23
+ NAME_GAP = 3.0
24
+ # An empty class is 48 high: its field and method compartments end
25
+ # 32 and 40 below the top.
26
+ EMPTY_HEIGHT = 48.0
27
+ EMPTY_RULES = [32.0, 40.0].freeze
28
+ BLOCK_SHIFT = 0.5
29
+ # Outlines are relative to the circle's centre.
30
+ GLYPHS = {
31
+ class: Glyph.new(
32
+ "#ADD1B2",
33
+ %w[M2.4731,6.1431 Q1.8921,6.4419 1.2529,6.5913 Q0.6138,6.7407
34
+ -0.0918,6.7407 Q-2.5986,6.7407 -3.9185,5.0889
35
+ Q-5.2383,3.437 -5.2383,0.3159 Q-5.2383,-2.8135
36
+ -3.9185,-4.4653 Q-2.5986,-6.1172 -0.0918,-6.1172
37
+ Q0.6138,-6.1172 1.2612,-5.9678 Q1.9087,-5.8184
38
+ 2.4731,-5.5195 L2.4731,-2.7969 Q1.8423,-3.3779
39
+ 1.2488,-3.6477 Q0.6553,-3.9175 0.0244,-3.9175
40
+ Q-1.3203,-3.9175 -2.0051,-2.8508 Q-2.6899,-1.7842
41
+ -2.6899,0.3159 Q-2.6899,2.4077 -2.0051,3.4744
42
+ Q-1.3203,4.541 0.0244,4.541 Q0.6553,4.541 1.2488,4.2712
43
+ Q1.8423,4.0015 2.4731,3.4204 Z].join(" "),
44
+ ),
45
+ abstract: Glyph.new(
46
+ "#A9DCDF",
47
+ %w[M-0.1367,-4.6519 L-1.2905,0.4199 L1.0254,0.4199 Z
48
+ M-1.6309,-6.8931 L1.3657,-6.8931 L4.7109,5.5 L2.2622,5.5
49
+ L1.4985,2.437 L-1.7803,2.437 L-2.5273,5.5
50
+ L-4.9761,5.5 Z].join(" "),
51
+ ),
52
+ interface: Glyph.new(
53
+ "#B4A7E5",
54
+ %w[M-3.5723,-3.7349 L-3.5723,-5.8931 L3.8071,-5.8931
55
+ L3.8071,-3.7349 L1.3418,-3.7349 L1.3418,4.3418
56
+ L3.8071,4.3418 L3.8071,6.5 L-3.5723,6.5 L-3.5723,4.3418
57
+ L-1.1069,4.3418 L-1.1069,-3.7349 Z].join(" "),
58
+ ),
59
+ enum: Glyph.new(
60
+ "#EB937F",
61
+ %w[M3.6143,6.5 L-4.1055,6.5 L-4.1055,-5.8931 L3.6143,-5.8931
62
+ L3.6143,-3.7349 L-1.6567,-3.7349 L-1.6567,-1.062
63
+ L3.1162,-1.062 L3.1162,1.0962 L-1.6567,1.0962
64
+ L-1.6567,4.3418 L3.6143,4.3418 Z].join(" "),
65
+ ),
66
+ annotation: Glyph.new(
67
+ "#E3664A",
68
+ %w[M2.5767,0.2261 Q2.5767,-0.7119 2.1533,-1.2432
69
+ Q1.73,-1.7744 0.9912,-1.7744 Q0.2524,-1.7744
70
+ -0.1667,-1.2432 Q-0.5859,-0.7119 -0.5859,0.2261
71
+ Q-0.5859,1.1724 -0.1667,1.7036 Q0.2524,2.2349
72
+ 0.9912,2.2349 Q1.73,2.2349 2.1533,1.7036 Q2.5767,1.1724
73
+ 2.5767,0.2261 Z M4.1206,3.6294 L2.4937,3.6294
74
+ L2.4937,2.9487 Q2.1782,3.3887 1.7507,3.592 Q1.3232,3.7954
75
+ 0.7256,3.7954 Q-0.6357,3.7954 -1.47,2.8159 Q-2.3042,1.8364
76
+ -2.3042,0.2261 Q-2.3042,-1.376 -1.4741,-2.3513
77
+ Q-0.644,-3.3267 0.7256,-3.3267 Q1.3149,-3.3267
78
+ 1.7632,-3.1233 Q2.2114,-2.9199 2.4937,-2.5298
79
+ L2.4937,-2.8701 Q2.4937,-3.999 1.8752,-4.6133
80
+ Q1.2568,-5.2275 0.1113,-5.2275 Q-1.6152,-5.2275
81
+ -2.7068,-3.7085 Q-3.7983,-2.1895 -3.7983,0.2427
82
+ Q-3.7983,2.791 -2.5366,4.2976 Q-1.2749,5.8042
83
+ 0.8252,5.8042 Q1.4893,5.8042 2.1118,5.6091 Q2.7344,5.4141
84
+ 3.3071,5.0239 L4.0708,6.4849 Q3.3984,6.9414 2.6057,7.1697
85
+ Q1.813,7.3979 0.9082,7.3979 Q-1.9971,7.3979 -3.7236,5.4639
86
+ Q-5.4502,3.5298 -5.4502,0.2427 Q-5.4502,-2.9697
87
+ -3.8979,-4.8997 Q-2.3457,-6.8296 0.2109,-6.8296
88
+ Q2.0205,-6.8296 3.0706,-5.738 Q4.1206,-4.6465
89
+ 4.1206,-2.7622 Z].join(" "),
90
+ ),
91
+ }.freeze
92
+ private_constant :GLYPHS, :CENTRE_ABOVE_BASELINE, :NAME_GAP,
93
+ :BLOCK_SHIFT,
94
+ :EMPTY_HEIGHT, :EMPTY_RULES
95
+
96
+ # @param diagram [Diagram]
97
+ # @param scene [Scene] class boxes already placed
98
+ # @param measure [#call] width of a text given the text
99
+ # @return [Scene] the same scene, its class boxes dressed
100
+ def apply(diagram, scene, measure)
101
+ kinds = spot_kinds(diagram)
102
+ scene.boxes.select { |box| box.kind == "class" }.each do |box|
103
+ place(box, kinds[box.id], measure)
104
+ rule_empty_compartments(box)
105
+ end
106
+ scene
107
+ end
108
+
109
+ # @return [Glyph, nil] the colour and outline of a kind's circle
110
+ def glyph(kind)
111
+ GLYPHS[kind]
112
+ end
113
+
114
+ # @return [Boolean] whether `hide circle` is in force
115
+ def circles_hidden?(diagram)
116
+ diagram.directives.any? do |line|
117
+ line.match?(/\Ahide[ \t]+circle\z/i)
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ # Class name to kind, empty when `hide circle` is in force.
124
+ def spot_kinds(diagram)
125
+ return {} if circles_hidden?(diagram)
126
+
127
+ diagram.classes.to_h { |klass| [klass.name, klass.kind] }
128
+ end
129
+
130
+ def rule_empty_compartments(box)
131
+ return unless empty?(box)
132
+
133
+ EMPTY_RULES.each { |offset| box.separators << rule_at(box, offset) }
134
+ end
135
+
136
+ def rule_at(box, offset)
137
+ y = box.y + offset
138
+ Scene::Segment.new(x1: box.x, y1: y, x2: box.x + box.width, y2: y)
139
+ end
140
+
141
+ def empty?(box)
142
+ box.separators.empty? &&
143
+ (box.height - EMPTY_HEIGHT).abs < 0.01 &&
144
+ box.texts.all? { |text| text.role == "class_name" }
145
+ end
146
+
147
+ # The circle and the name sit side by side, centred on the box.
148
+ def place(box, kind, measure)
149
+ name = sole_name(box)
150
+ return unless name && GLYPHS.key?(kind) && box.spot.nil?
151
+
152
+ left = name.x - (block_width(name, measure) / 2) + BLOCK_SHIFT
153
+ box.spot = spot_at(kind, left, name.y)
154
+ start_after_spot(name, left)
155
+ end
156
+
157
+ def start_after_spot(name, left)
158
+ name.x = left + (2 * RADIUS) + NAME_GAP
159
+ name.anchor = "start"
160
+ end
161
+
162
+ def sole_name(box)
163
+ names = box.texts.select { |text| text.role == "class_name" }
164
+ names.first if names.one?
165
+ end
166
+
167
+ def spot_at(kind, left, baseline)
168
+ Scene::Spot.new(kind: kind.to_s, cx: left + RADIUS,
169
+ cy: baseline - CENTRE_ABOVE_BASELINE)
170
+ end
171
+
172
+ def block_width(name, measure)
173
+ (2 * RADIUS) + NAME_GAP + measure.call(name.content)
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Etassia
4
+ module Notation
5
+ module PlantUML
6
+ # The text PlantUML draws for a class named in quotes. The part after
7
+ # the last dot is the class; the parts before it are its namespaces.
8
+ #
9
+ # `\n`, `\r` and `\l` end a line, `\t` is a gap and `\\` is one
10
+ # backslash. Any other backslash stays as written. `\uXXXX` is also
11
+ # read by PlantUML and is not read here, so {escapes?} lets a caller
12
+ # refuse it.
13
+ module ClassName
14
+ extend self
15
+
16
+ LINE_BREAKS = %w[n r l].freeze
17
+ GAP = "\u00A0" * 4
18
+ EMPTY_LINE = "\u00A0"
19
+ private_constant :LINE_BREAKS, :GAP, :EMPTY_LINE
20
+
21
+ # @return [Boolean] true when `name` holds a `\u` escape
22
+ def escapes?(name)
23
+ name.include?("\\u")
24
+ end
25
+
26
+ # @return [Array<String>] the namespaces, outermost first
27
+ def namespaces(name)
28
+ name.split(".", -1)[0...-1]
29
+ end
30
+
31
+ # @return [Array<String>] the drawn lines of the class itself; a
32
+ # blank line is a non-breaking space so it keeps its height
33
+ def lines(name)
34
+ text = name.split(".", -1).last.gsub(/\\(.)/m) { unescape($1) }
35
+ text.split("\n", -1).map do |line|
36
+ line.strip.then { |kept| kept.empty? ? EMPTY_LINE : kept }
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def unescape(char)
43
+ return "\n" if LINE_BREAKS.include?(char)
44
+ return GAP if char == "t"
45
+
46
+ char == "\\" ? "\\" : "\\#{char}"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "node_graph"
4
+
5
+ module Etassia
6
+ module Notation
7
+ module PlantUML
8
+ # The PlantUML component and basic deployment diagram: components,
9
+ # interfaces and deployment nodes. Dispatched to from {PlantUML.parse}.
10
+ module Component
11
+ extend self
12
+
13
+ # Lines only a component or deployment diagram has. `package`,
14
+ # `database` and `interface` are not here: classes and sequences use
15
+ # them too.
16
+ MARKER = /\A(?:\[[^\]]+\]|component\s|portin\s|portout\s|\(\)\s|
17
+ (?:node|cloud|file|folder|frame|storage|artifact|card|
18
+ rectangle|archimate)\s)/xi
19
+ private_constant :MARKER
20
+
21
+ # @return [Boolean] whether the source reads as a component diagram
22
+ def component?(source)
23
+ lines = NodeGraph.lines_of(source)
24
+ lines.none? { |line| NodeGraph::FOREIGN.match?(line) } &&
25
+ lines.any? { |line| MARKER.match?(line) }
26
+ end
27
+
28
+ # @return [Notation::Parsed]
29
+ def parse(source)
30
+ NodeGraph.parsed(source, type: :component_diagram,
31
+ direction: :top_to_bottom,
32
+ default_kind: :interface)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end