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,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require_relative "element"
5
+
6
+ module Etassia
7
+ module Svg
8
+ # SVG Tspan element <tspan>
9
+ #
10
+ # One styled run inside a <text> element: a bold or italic word, or the
11
+ # start of a new line after a hard line break. Only the attributes a
12
+ # markdown run actually needs — position resets (`x`, `y`) and per-run
13
+ # styling (`font-weight`, `font-style`, and for creole runs `font-family`,
14
+ # `font-size` and `text-decoration`; `fill` is a base attribute).
15
+ #
16
+ # `dy` is not an attribute: the :metanorma profile rejects it on a
17
+ # tspan. A run starting a new line sets `line_shift` instead, and the
18
+ # parent Text turns it into an absolute `y` (see Text#place_lines).
19
+ # Everything else (font family/size, fill, text-anchor) is inherited
20
+ # from the parent <text> element and never repeated here.
21
+ class Tspan < Element
22
+ attribute :x, :float
23
+ attribute :y, :float
24
+ # Lines below the previous placed run; never written to the SVG.
25
+ attribute :line_shift, :integer
26
+ attribute :font_weight, :string
27
+ attribute :font_style, :string
28
+ attribute :font_family, :string
29
+ attribute :font_size, :string
30
+ attribute :text_decoration, :string
31
+ attribute :content, :string, collection: true
32
+
33
+ writes_attributes :x, :y, :font_weight, :font_style, :font_family,
34
+ :font_size, :text_decoration
35
+
36
+ protected
37
+
38
+ # `content` is declared `collection: true`, so join rather than
39
+ # interpolate.
40
+ #
41
+ # @return [String] XML string
42
+ def element_markup
43
+ escaped_content = Escaping.escape_text(Array(content).join)
44
+ "<tspan#{build_attributes}>#{escaped_content}</tspan>"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "svg/escaping"
4
+ require_relative "svg/numbers"
5
+ require_relative "svg/path_geometry"
6
+ require_relative "svg/style"
7
+ require_relative "svg/element"
8
+ require_relative "svg/document"
9
+ require_relative "svg/group"
10
+ require_relative "svg/rect"
11
+ require_relative "svg/circle"
12
+ require_relative "svg/line"
13
+ require_relative "svg/polygon"
14
+ require_relative "svg/arrowhead"
15
+ require_relative "svg/path"
16
+ require_relative "svg/polyline"
17
+ require_relative "svg/tspan"
18
+ require_relative "svg/text"
19
+ require_relative "svg/ellipse"
20
+
21
+ module Etassia
22
+ # The SVG document model. Everything Etassia writes into an SVG goes
23
+ # through these classes.
24
+ module Svg
25
+ # The svg_conform profile Etassia's output is built to satisfy.
26
+ #
27
+ # Requires a viewBox, rejects @import/<link>/external images, and
28
+ # enforces the SVG Tiny 1.2 element/attribute table -- but does not
29
+ # by itself guarantee self-containment: an external
30
+ # <?xml-stylesheet?> PI still validates clean under it. Nothing
31
+ # Etassia emits produces one; spec/etassia/svg_conformance_spec.rb holds
32
+ # that line -- don't drop it assuming the profile alone covers it.
33
+ #
34
+ # :svg_1_2_rfc restricts colour/fonts and would erase themes -- not
35
+ # a drop-in equivalent.
36
+ CONFORMANCE_PROFILE = :metanorma
37
+ end
38
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED by scripts/generate_text_advances.rb; do not edit by hand.
4
+ #
5
+ # Horizontal advance widths in per-mille em, read from the hmtx table of
6
+ # Liberation Sans Regular (SIL OFL 1.1), which is metric-compatible with
7
+ # Arial and Helvetica. Cross-checked against Arial where it has the glyph:
8
+ # a codepoint where the two differ by more than 1/1000 em is
9
+ # absent here, not guessed.
10
+ # Advances are numeric facts about a glyph, not a copy of any font.
11
+ module Etassia
12
+ class TextMeasurement
13
+ module ArialAdvances
14
+ # A line "U+XXXX: a b c" starts a run at that codepoint; every number
15
+ # is the advance of the next consecutive codepoint, and a line without
16
+ # a marker continues the previous run.
17
+ DATA = <<~RUNS
18
+ U+0020: 278 278 355 556 556 889 667 191 333 333 389 584 278 333 278 278
19
+ 556 556 556 556 556 556 556 556 556 556 278 278 584 584 584 556
20
+ 1015 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778
21
+ 667 778 722 667 611 722 667 944 667 667 611 278 278 278 469 556
22
+ 333 556 556 500 556 556 278 556 556 222 222 500 222 833 556 556
23
+ 556 556 333 500 278 556 500 722 500 500 500 334 260 334 584
24
+ U+00A0: 278 333 556 556 556 556 260 556 333 737 370 556 584 333 737 552
25
+ 400 549 333 333 333 576 537 333 333 333 365 556 834 834 834 611
26
+ 667 667 667 667 667 667 1000 722 667 667 667 667 278 278 278 278
27
+ 722 722 778 778 778 778 778 584 778 722 722 722 722 667 667 611
28
+ 556 556 556 556 556 556 889 500 556 556 556 556 278 278 278 278
29
+ 556 556 556 556 556 556 556 549 611 556 556 556 556 500 556 500
30
+ 667 556 667 556 667 556 722 500 722 500 722 500 722 500 722 615
31
+ 722 556 667 556 667 556 667 556 667 556 667 556 778 556 778 556
32
+ 778 556 778 556 722 556 722 556 278 278 278 278 278 278 278 222
33
+ 278 278 735 444 500 222 667 500 500 556 222 556 222 556 292 556
34
+ 334 556 222 722 556 722 556 722 556 604 723 556 778 556 778 556
35
+ 778 556 1000 944 722 333 722 333 722 333 667 500 667 500 667 500
36
+ 667 500 611 278 611 375 611 278 722 556 722 556 722 556 722 556
37
+ 722 556 722 556 944 722 667 500 667 611 500 611 500 611 500 222
38
+ 556 758 656 556 656 556 722 722 500 722 810 656 556 557 667 752
39
+ 604 611 556 778 624 881 222 278 667 500 222 500 891 722 556 778
40
+ 857 656 868 667 754 556 667 667 500 618 380 278 611 278 611 854
41
+ 669 748 722 772 500 611 500 611 611 545 545 556 556 458 487 556
42
+ 260 413 584 278 1333 1222 1049 1062 833 451 1222 944 771 667 556 278
43
+ 222 778 556 722 556 722 556 722 556 722 556 722 556 556 667 556
44
+ 667 556 1000 889 778 556 778 556 667 500 778 556 778 556 611 545
45
+ 222 1333 1222 1049 778 556 1034 618 722 556 667 556 1000 889 778 611
46
+ 667 556 667 556 667 556 667 556 278 278 278 278 778 556 778 556
47
+ 722 333 722 333 722 556 722 556 667 500 611 278 545 437 722 556
48
+ 706 682 604 565 611 500 667 556 667 556 778 556 778 556 778 556
49
+ 778 556 667 500 349 685 367 222 887 887 667 722 500 556 611 500
50
+ 500 581 453 667 722 668 667 556 500 222 737 556 722 333 667 500
51
+ U+0374: 333 333
52
+ U+037A: 333 500 500 500 278
53
+ U+0384: 333 333 667 278 784 838 384
54
+ U+038C: 774
55
+ U+038E: 855 752 222 667 667 551 668 667 611 722 778 278 667 668 833 722
56
+ 650 778 722 667
57
+ U+03A3: 618 611 667 798 667 835 748 278 667 578 446 556 222 547 578 575
58
+ 500 557 446 441 556 556 222 500 500 576 500 448 556 690 569 482
59
+ 617 395 547 648 525 713 781 222 547 556 547 781
60
+ U+03D0: 575 547 772 958 772 560 781 601 778 556 722 500 611 404 625 529
61
+ 756 577 891 833 674 556 674 500 667 667 609 596 737 554 464 410
62
+ 601 573 500 222 778 442 442 667 556 722 833 688 569 722 722 722
63
+ 667 667 865 542 719 667 278 278 500 1057 1010 854 583 719 635 719
64
+ 667 656 667 542 677 667 923 604 719 719 583 656 833 722 778 719
65
+ 667 722 611 635 760 667 740 667 917 938 792 885 656 719 1010 722
66
+ 556 573 531 365 583 556 669 458 559 559 438 583 688 552 556 542
67
+ 556 500 458 500 823 500 573 521 802 823 625 719 521 510 750 542
68
+ 556 556 556 365 510 500 222 278 222 906 813 556 438 559 500 552
69
+ 1338 624 778 613 950 713 668 500 897 695 829 685 1053 867 604 458
70
+ 796 688 778 556 803 631 803 631
71
+ U+047A: 833 612 1191 852 1338 624 722 500 503 0 0 0 0 0 0 0
72
+ 719 559 656 521 667 556 489 411 542 365 670 549 923 669 604 458
73
+ 583 438 583 438 583 438 742 536 722 552 879 648 1137 870 753 521
74
+ 722 500 611 458 556 500 556 500 667 500 925 691 667 521 667 521
75
+ 667 556 861 666 861 666 278 923 669 667 551 656 583 722 552 722
76
+ 552 667 521 833 688 222 667 556 667 556 1000 889 667 556 752 556
77
+ 752 556 923 669 604 458 604 545 719 559 719 559 778 556 778 556
78
+ 778 556 719 510 635 500 635 500 635 500 667 521 542 365 885 719
79
+ 542 365 667 500 667 500
80
+ U+2000: 500 1000 500 1000 333 250 167 556 278 200 83
81
+ U+2010: 333
82
+ U+2012: 556 556 1000 1000 413 552 222 222 222 222 333 333 333 333 556 556
83
+ 350
84
+ U+2026: 1000
85
+ U+202F: 200 1000
86
+ U+2032: 188 354 354
87
+ U+2039: 333 333
88
+ U+203C: 500
89
+ U+203E: 333
90
+ U+2044: 167
91
+ U+205E: 278
92
+ U+20A0: 556 722 722 556 556 833 722 1094 1164 944
93
+ U+20AB: 513 556 667 611 1000 521 667 778 667 556 722
94
+ U+20BF: 740
95
+ U+2105: 885
96
+ U+2113: 323
97
+ U+2116: 1073 737
98
+ U+2122: 1000
99
+ U+2126: 768
100
+ U+212E: 600
101
+ U+214D: 943 490
102
+ U+2190: 1000 500 1000 500 1000 500
103
+ U+21A8: 500
104
+ U+21D4: 1000
105
+ RUNS
106
+
107
+ # codepoint => advance in per-mille em
108
+ TABLE = begin
109
+ codepoint = 0
110
+ DATA.each_line.with_object({}) do |line, table|
111
+ start, advances =
112
+ line.include?(":") ? line.split(":", 2) : [nil, line]
113
+ codepoint = start.delete_prefix("U+").to_i(16) if start
114
+ advances.split.each do |advance|
115
+ table[codepoint] = advance.to_i
116
+ codepoint += 1
117
+ end
118
+ end.freeze
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED by scripts/generate_dejavu_advances.rb; do not edit by hand.
4
+ #
5
+ # Horizontal advance widths of DejaVu Sans Regular and Bold, in design
6
+ # units of a 2048-unit em, for Basic Latin and Latin-1 through Latin
7
+ # Extended-B. Advances are numeric facts about a glyph, not a copy of any
8
+ # font. Same layout as ArialAdvances::DATA; REGULAR and BOLD hold them
9
+ # in per-mille em.
10
+ module Etassia
11
+ class TextMeasurement
12
+ module DejaVuAdvances
13
+ REGULAR_DATA = <<~RUNS
14
+ U+0020: 651 821 942 1716 1303 1946 1597 563 799 799 1024 1716 651 739 651 690
15
+ 1303 1303 1303 1303 1303 1303 1303 1303 1303 1303 690 690 1716 1716 1716 1087
16
+ 2048 1401 1405 1430 1577 1294 1178 1587 1540 604 604 1343 1141 1767 1532 1612
17
+ 1235 1612 1423 1300 1251 1499 1401 2025 1403 1251 1403 799 690 799 1716 1024
18
+ 1024 1255 1300 1126 1300 1260 721 1300 1298 569 569 1186 569 1995 1298 1253
19
+ 1300 1300 842 1067 803 1298 1212 1675 1212 1212 1075 1303 690 1303 1716
20
+ U+00A0: 651 821 1303 1303 1303 1303 690 1024 1024 2048 965 1253 1716 739 2048 1024
21
+ 1024 1716 821 821 1024 1303 1303 651 1024 821 965 1253 1985 1985 1985 1087
22
+ 1401 1401 1401 1401 1401 1401 1995 1430 1294 1294 1294 1294 604 604 604 604
23
+ 1587 1532 1612 1612 1612 1612 1612 1716 1612 1499 1499 1499 1499 1251 1239 1290
24
+ 1255 1255 1255 1255 1255 1255 2011 1126 1260 1260 1260 1260 569 569 569 569
25
+ 1253 1298 1253 1253 1253 1253 1253 1716 1253 1298 1298 1298 1298 1212 1300 1212
26
+ 1401 1255 1401 1255 1401 1255 1430 1126 1430 1126 1430 1126 1430 1126 1577 1300
27
+ 1587 1300 1294 1260 1294 1260 1294 1260 1294 1260 1294 1260 1587 1300 1587 1300
28
+ 1587 1300 1587 1300 1540 1298 1876 1423 604 569 604 569 604 569 604 569
29
+ 604 569 1208 1138 604 569 1343 1186 1186 1141 569 1141 569 1141 768 1141
30
+ 700 1151 582 1532 1298 1532 1298 1532 1298 1666 1532 1298 1612 1253 1612 1253
31
+ 1612 1253 2191 2095 1423 842 1423 842 1423 842 1300 1067 1300 1067 1300 1067
32
+ 1300 1067 1251 803 1251 803 1251 803 1499 1298 1499 1298 1499 1298 1499 1298
33
+ 1499 1298 1499 1298 2025 1675 1251 1212 1251 1403 1075 1403 1075 1403 1075 721
34
+ 1300 1505 1405 1300 1405 1300 1440 1430 1126 1587 1677 1405 1300 1253 1294 1612
35
+ 1258 1178 721 1587 1406 2015 724 604 1527 1186 569 1212 1995 1532 1298 1612
36
+ 1870 1253 1943 1555 1335 1300 1423 1300 1067 1294 688 803 1251 803 1251 1757
37
+ 1298 1565 1476 1523 1496 1403 1075 1364 1364 1183 1075 1303 1364 1183 1045 1300
38
+ 604 1008 940 605 2912 2660 2364 1711 1611 935 1907 1892 1633 1401 1255 604
39
+ 569 1612 1253 1499 1298 1499 1298 1499 1298 1499 1298 1499 1298 1260 1401 1255
40
+ 1401 1255 1995 2011 1587 1300 1587 1300 1343 1186 1612 1253 1612 1253 1364 1183
41
+ 569 2912 2660 2364 1587 1300 2279 1397 1532 1298 1401 1255 1995 2011 1612 1253
42
+ 1401 1255 1401 1255 1294 1260 1294 1260 604 569 604 569 1612 1253 1612 1253
43
+ 1423 842 1423 842 1499 1298 1499 1298 1300 1067 1251 803 1284 1068 1540 1298
44
+ 1506 1716 1430 1250 1403 1075 1401 1255 1294 1260 1612 1253 1612 1253 1612 1253
45
+ 1612 1253 1251 1212 972 1726 977 569 2044 2044 1401 1430 1126 1141 1251 1067
46
+ 1075 1235 981 1405 1499 1401 1294 1260 604 569 1600 1300 1423 842 1251 1212
47
+ RUNS
48
+
49
+ BOLD_DATA = <<~RUNS
50
+ U+0020: 713 934 1067 1716 1425 2052 1786 627 936 936 1071 1716 778 850 778 748
51
+ 1425 1425 1425 1425 1425 1425 1425 1425 1425 1425 819 819 1716 1716 1716 1188
52
+ 2048 1585 1561 1503 1700 1399 1399 1681 1714 762 762 1587 1305 2038 1714 1741
53
+ 1501 1741 1577 1475 1397 1663 1585 2259 1579 1483 1485 936 748 936 1716 1024
54
+ 1024 1382 1466 1214 1466 1389 891 1466 1458 702 702 1362 702 2134 1458 1407
55
+ 1466 1466 1010 1219 979 1458 1335 1892 1321 1335 1192 1458 748 1458 1716
56
+ U+00A0: 713 934 1425 1425 1303 1425 748 1024 1024 2048 1155 1323 1716 850 2048 1024
57
+ 1024 1716 897 897 1024 1507 1303 778 1024 897 1155 1323 2120 2120 2120 1188
58
+ 1585 1585 1585 1585 1585 1585 2222 1503 1399 1399 1399 1399 762 762 762 762
59
+ 1716 1714 1741 1741 1741 1741 1741 1716 1741 1663 1663 1663 1663 1483 1511 1473
60
+ 1382 1382 1382 1382 1382 1382 2146 1214 1389 1389 1389 1389 702 702 702 702
61
+ 1407 1458 1407 1407 1407 1407 1407 1716 1407 1458 1458 1458 1458 1335 1466 1335
62
+ 1585 1382 1585 1382 1585 1382 1503 1214 1503 1214 1503 1214 1503 1214 1700 1466
63
+ 1716 1466 1399 1389 1399 1389 1399 1389 1399 1389 1399 1389 1681 1466 1681 1466
64
+ 1681 1466 1681 1466 1714 1458 1994 1618 762 702 762 702 762 702 762 702
65
+ 762 702 1524 1404 762 702 1587 1362 1362 1305 702 1305 702 1305 982 1305
66
+ 1140 1315 760 1714 1458 1714 1458 1714 1458 2013 1714 1458 1741 1407 1741 1407
67
+ 1741 1407 2390 2241 1577 1010 1577 1010 1577 1010 1475 1219 1475 1219 1475 1219
68
+ 1475 1219 1397 979 1397 979 1397 979 1663 1458 1663 1458 1663 1458 1663 1458
69
+ 1663 1458 1663 1458 2259 1892 1483 1335 1483 1485 1192 1485 1192 1485 1192 891
70
+ 1466 1661 1561 1466 1561 1466 1503 1503 1214 1716 1800 1550 1466 1408 1399 1739
71
+ 1425 1399 891 1681 1624 2140 892 797 1587 1362 738 1212 2134 1714 1458 1741
72
+ 1789 1407 2217 1868 1601 1466 1577 1475 1219 1399 1130 979 1447 979 1397 1711
73
+ 1458 1741 1666 1633 1594 1485 1192 1582 1582 1312 1192 1425 1582 1312 1173 1466
74
+ 762 1349 1114 762 3185 2892 2658 2067 2007 1404 2476 2416 2160 1585 1382 762
75
+ 702 1741 1407 1663 1458 1663 1458 1663 1458 1663 1458 1663 1458 1389 1585 1382
76
+ 1585 1382 2222 2146 1681 1466 1681 1466 1587 1362 1741 1407 1741 1407 1582 1192
77
+ 702 3185 2892 2658 1681 1466 2639 1612 1714 1458 1585 1382 2222 2146 1741 1407
78
+ 1585 1382 1585 1382 1399 1389 1399 1389 762 702 762 702 1741 1407 1741 1407
79
+ 1577 1010 1577 1010 1663 1458 1663 1458 1475 1219 1397 979 1414 1244 1714 1458
80
+ 1714 1771 1657 1349 1485 1192 1585 1382 1399 1389 1741 1407 1741 1407 1741 1407
81
+ 1741 1407 1483 1335 1007 1775 1048 702 2228 2228 1585 1503 1214 1305 1397 1219
82
+ 1192 1601 1258 1561 1663 1585 1399 1389 762 702 1762 1620 1577 1010 1483 1335
83
+ RUNS
84
+
85
+ UNITS_PER_EM = 2048.0
86
+
87
+ # codepoint => advance in per-mille em
88
+ def self.parse(data)
89
+ codepoint = 0
90
+ data.each_line.with_object({}) do |line, table|
91
+ start, values = split(line)
92
+ codepoint = start.delete_prefix("U+").to_i(16) if start
93
+ values.each do |value|
94
+ table[codepoint] = value.to_i * 1000 / UNITS_PER_EM
95
+ codepoint += 1
96
+ end
97
+ end.freeze
98
+ end
99
+
100
+ # A run's marker, if the line starts one, and its advances.
101
+ def self.split(line)
102
+ start, values = line.include?(":") ? line.split(":", 2) : [nil, line]
103
+ [start, values.split]
104
+ end
105
+
106
+ REGULAR = parse(REGULAR_DATA)
107
+ BOLD = parse(BOLD_DATA)
108
+ private_class_method :parse, :split
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED by scripts/generate_times_advances.rb; do not edit by hand.
4
+ #
5
+ # Horizontal advance widths in per-mille em of Times New Roman Regular,
6
+ # for Basic Latin, Latin-1 through Latin Extended-B and U+FB02. Advances
7
+ # are numeric facts about a glyph, not a copy of any font.
8
+ module Etassia
9
+ class TextMeasurement
10
+ module TimesAdvances
11
+ # Same layout as ArialAdvances::DATA.
12
+ DATA = <<~RUNS
13
+ U+0020: 250 333 408 500 500 833 778 180 333 333 500 564 250 333 250 278
14
+ 500 500 500 500 500 500 500 500 500 500 278 278 564 564 564 444
15
+ 921 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722
16
+ 556 722 667 556 611 722 722 944 722 722 611 333 278 333 469 500
17
+ 333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500
18
+ 500 500 333 389 278 500 500 722 500 500 444 480 200 480 541
19
+ U+00A0: 250 333 500 500 500 500 200 500 333 760 276 500 564 333 760 500
20
+ 400 549 300 300 333 576 453 333 333 300 310 500 750 750 750 444
21
+ 722 722 722 722 722 722 889 667 611 611 611 611 333 333 333 333
22
+ 722 722 722 722 722 722 722 564 722 722 722 722 722 722 556 500
23
+ 444 444 444 444 444 444 667 444 444 444 444 444 278 278 278 278
24
+ 500 500 500 500 500 500 500 549 500 500 500 500 500 500 500 500
25
+ 722 444 722 444 722 444 667 444 667 444 667 444 667 444 722 646
26
+ 722 500 611 444 611 444 611 444 611 444 611 444 722 500 722 500
27
+ 722 500 722 500 722 500 722 500 333 278 333 278 333 278 333 278
28
+ 333 278 708 552 389 278 722 500 500 611 278 611 278 611 406 611
29
+ 344 611 278 722 500 722 500 722 500 604 702 495 722 500 722 500
30
+ 722 500 889 722 667 333 667 333 667 333 556 389 556 389 556 389
31
+ 556 389 611 278 611 427 611 278 722 500 722 500 722 500 722 500
32
+ 722 500 722 500 944 722 722 500 722 611 444 611 444 611 444 278
33
+ 500 760 574 500 574 500 667 667 444 722 815 574 500 471 611 722
34
+ 501 556 500 722 722 770 253 333 722 500 278 485 816 722 500 722
35
+ 722 529 925 691 650 500 556 556 389 582 344 278 611 278 611 776
36
+ 542 743 722 781 500 611 444 539 539 444 444 500 500 443 422 500
37
+ 200 281 249 333 1333 1166 944 1000 889 556 1111 1000 778 722 444 333
38
+ 278 722 500 722 500 722 500 722 500 722 500 722 500 444 722 444
39
+ 722 444 889 667 722 500 722 500 722 500 722 500 722 500 539 444
40
+ 278 1333 1166 944 722 500 950 560 722 500 722 444 889 667 722 500
41
+ 722 444 722 444 611 444 611 444 333 278 333 278 722 500 722 500
42
+ 667 333 667 333 722 500 722 500 556 389 611 278 563 395 722 500
43
+ 650 500 604 500 611 444 722 444 611 444 722 500 722 500 722 500
44
+ 722 500 722 500 278 500 317 278 774 772 722 667 500 611 611 389
45
+ 444 534 397 667 722 725 611 444 389 278 702 500 667 333 722 500
46
+ U+FB02: 556
47
+ RUNS
48
+
49
+ # codepoint => advance in per-mille em
50
+ TABLE = begin
51
+ codepoint = 0
52
+ DATA.each_line.with_object({}) do |line, table|
53
+ start, values =
54
+ line.include?(":") ? line.split(":", 2) : [nil, line]
55
+ codepoint = start.delete_prefix("U+").to_i(16) if start
56
+ values.split.each do |value|
57
+ table[codepoint] = value.to_i
58
+ codepoint += 1
59
+ end
60
+ end.freeze
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # GENERATED by scripts/generate_trebuchet_advances.rb; do not edit by hand.
4
+ #
5
+ # Horizontal advance widths in per-mille em of Trebuchet MS Regular,
6
+ # for Basic Latin and Latin-1 through Latin Extended-B. Advances are
7
+ # numeric facts about a glyph, not a copy of any font.
8
+ module Etassia
9
+ class TextMeasurement
10
+ module TrebuchetAdvances
11
+ # Same layout as ArialAdvances::DATA.
12
+ DATA = <<~RUNS
13
+ U+0020: 301 367 325 524 524 600 706 160 367 367 367 524 367 367 367 524
14
+ 524 524 524 524 524 524 524 524 524 524 367 367 524 524 524 367
15
+ 771 590 566 598 613 536 525 676 654 278 477 576 506 709 638 674
16
+ 558 676 582 481 581 648 587 852 557 570 550 367 355 367 524 524
17
+ 524 525 557 495 557 545 370 502 546 285 367 504 295 830 546 537
18
+ 557 557 389 405 396 546 490 744 501 493 475 367 524 367 524
19
+ U+00A0: 301 367 524 524 524 570 524 454 524 713 367 524 524 367 713 524
20
+ 524 524 451 454 524 546 524 367 524 451 367 524 814 814 814 367
21
+ 590 590 590 590 590 590 867 598 536 536 536 536 278 278 278 278
22
+ 613 638 674 674 674 674 674 524 657 648 648 648 648 570 556 546
23
+ 525 525 525 525 525 525 873 495 545 545 545 545 285 285 285 285
24
+ 549 546 537 537 537 537 537 524 545 546 546 546 546 493 553 493
25
+ 590 525 590 525 590 525 598 495 598 495 598 495 598 495 613 691
26
+ 613 557 536 545 536 545 536 545 536 545 536 545 676 502 676 502
27
+ 676 502 676 502 654 546 681 548 278 285 278 285 278 285 278 285
28
+ 278 285 727 602 477 367 576 504 545 506 295 506 295 506 295 506
29
+ 330 506 298 638 546 638 546 638 546 635 653 546 674 537 674 537
30
+ 674 537 993 924 582 389 582 389 582 389 481 405 481 405 481 405
31
+ 481 405 581 396 581 496 581 396 648 546 648 546 648 546 648 546
32
+ 648 546 648 546 852 744 570 493 570 550 475 550 475 550 475 331
33
+ U+0192: 388
34
+ U+01FA: 590 525 867 873 657 545
35
+ U+0218: 481 405 581 396
36
+ RUNS
37
+
38
+ # codepoint => advance in per-mille em
39
+ TABLE = begin
40
+ codepoint = 0
41
+ DATA.each_line.with_object({}) do |line, table|
42
+ start, values =
43
+ line.include?(":") ? line.split(":", 2) : [nil, line]
44
+ codepoint = start.delete_prefix("U+").to_i(16) if start
45
+ values.split.each do |value|
46
+ table[codepoint] = value.to_i
47
+ codepoint += 1
48
+ end
49
+ end.freeze
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Etassia
4
+ class TextMeasurement
5
+ # Trebuchet MS kern adjustments used by the remaining Mindmap corpus.
6
+ # Values are design units from the regular face's kern table.
7
+ module TrebuchetKerning
8
+ UNITS_PER_EM = 2048.0
9
+ PAIRS = {
10
+ " A" => -113,
11
+ " T" => -37,
12
+ "Pe" => -96,
13
+ "Po" => -96,
14
+ "Re" => -83,
15
+ "Ro" => -83,
16
+ "To" => -255,
17
+ }.freeze
18
+
19
+ module_function
20
+
21
+ def adjustment(text, font_size:)
22
+ units = text.each_char.each_cons(2).sum do |pair|
23
+ PAIRS.fetch(pair.join, 0)
24
+ end
25
+ units * font_size / UNITS_PER_EM
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "text_measurement/arial_advances"
4
+ require_relative "text_measurement/dejavu_advances"
5
+ require_relative "text_measurement/trebuchet_advances"
6
+
7
+ module Etassia
8
+ # Estimates text dimensions for layout, in pure Ruby: no font file is read
9
+ # at runtime. Width is the sum of per-glyph advances of the default theme's
10
+ # stack ("Arial, Helvetica, sans-serif"), from the generated ArialAdvances.
11
+ #
12
+ # BOUNDS: every codepoint in ArialAdvances (exact in Liberation Sans, and in
13
+ # Arial wherever Arial has the glyph; macOS Arial lacks U+0487, U+2010,
14
+ # U+202F, U+20BF and U+21D4); CJK and fullwidth at 1.0 em, the four Arabic
15
+ # ligatures in OUTLIERS, and zero-width marks (all measured in Chrome).
16
+ # ESTIMATES: emoji, and any pictographic character followed by U+FE0F, at
17
+ # 1.5 em; everything else at 1.0 em. A ZWJ sequence counts each emoji.
18
+ # DOES NOT BOUND: a font the viewer substitutes for a glyph Arial lacks,
19
+ # other stacks (DejaVu, Verdana run up to 1.19 times wider), bold, italic,
20
+ # kerning (it can widen a pair as well as narrow it), shaping beyond
21
+ # OUTLIERS. Callers that need room use Renderer::Base#reserved_text_width.
22
+ #
23
+ # @example Basic usage
24
+ # TextMeasurement.measure("Hello", font_size: 14)
25
+ # # => { width: 31.892, height: 14.0 }
26
+ #
27
+ # @example With dimension overrides
28
+ # TextMeasurement.measure("Text", font_size: 12, width: 100, height: 20)
29
+ # # => { width: 100, height: 20 }
30
+ class TextMeasurement
31
+ # Text height as ratio of font size
32
+ HEIGHT_RATIO = 1.0
33
+
34
+ # Per-mille em for a codepoint no rule below knows.
35
+ DEFAULT_ADVANCE = 1000
36
+ EMOJI_ADVANCE = 1500
37
+ MONOSPACE_ADVANCE = 600
38
+ # DejaVu Sans Mono: 1233 units of 2048 per glyph.
39
+ DEJAVU_MONO_ADVANCE = 1233 * 1000.0 / 2048
40
+ SPACE_ADVANCE = ArialAdvances::TABLE.fetch(0x20)
41
+
42
+ # SVG draws one <text> as ONE line: a tab, newline or carriage return is
43
+ # collapsed to a space. A CRLF is counted twice (an over-estimate).
44
+ SVG_WHITESPACE = /[\t\n\r]/
45
+ ASCII_WHITESPACE = [9, 10, 13].freeze
46
+
47
+ # Codepoints whose width comes from ligature substitution, so no
48
+ # per-character rule describes them. Chrome measured 1.234, 1.025, 1.221
49
+ # and 6.489 em; these round up.
50
+ OUTLIERS = {
51
+ 0xFDFA => 1250, 0xFDFB => 1050, 0xFDFC => 1250, 0xFDFD => 6500
52
+ }.freeze
53
+
54
+ # The faces a caller can ask for. A codepoint a face lacks falls back to
55
+ # the default one.
56
+ FACE_TABLES = {
57
+ arial: ArialAdvances::TABLE,
58
+ trebuchet: TrebuchetAdvances::TABLE,
59
+ dejavu: DejaVuAdvances::REGULAR,
60
+ dejavu_bold: DejaVuAdvances::BOLD,
61
+ }.freeze
62
+
63
+ ZERO_WIDTH = /[\p{Mn}\p{Me}\p{Cf}\p{Cc}]/
64
+ EMOJI = /\p{Extended_Pictographic}/
65
+ # Ruby 4 moved to Unicode 17, where U+266D no longer matches
66
+ # Extended_Pictographic. Keep the measured width independent of the
67
+ # Unicode tables bundled with the running Ruby.
68
+ PINNED_PICTOGRAPHS = [0x266D].freeze
69
+
70
+ # A pictographic character plus U+FE0F asks for the emoji glyph, even for
71
+ # one the table has as text (U+00A9 is 0.737 em as text, 1.0 em as emoji
72
+ # in Chrome). Any other character is a cluster of its own.
73
+ CLUSTER = /#{EMOJI}\uFE0F|./m
74
+
75
+ # Measures the approximate dimensions of text.
76
+ #
77
+ # @param text [String] the text to measure, as one line: a caller that
78
+ # draws several lines measures each line on its own
79
+ # @param font_size [Numeric] the font size in points
80
+ # @param width [Numeric, nil] optional width override
81
+ # @param height [Numeric, nil] optional height override
82
+ # @param monospace [Boolean] measure for a monospace font-family
83
+ # @return [Hash] hash with :width and :height keys
84
+ def self.measure(text, font_size:, width: nil, height: nil,
85
+ monospace: false)
86
+ {
87
+ width: width || calculate_width(text, font_size, monospace, :arial),
88
+ height: height || calculate_height(font_size),
89
+ }
90
+ end
91
+
92
+ # Measures text in a face other than the default, with the default
93
+ # standing in for a codepoint the face lacks.
94
+ #
95
+ # @param text [String] the text to measure, as one line
96
+ # @param font_size [Numeric] the font size in points
97
+ # @param face [Symbol] :arial, :trebuchet, :dejavu or :dejavu_bold
98
+ # @return [Hash] hash with :width and :height keys
99
+ def self.measure_in(face, text, font_size:)
100
+ {
101
+ width: calculate_width(text, font_size, false, face),
102
+ height: calculate_height(font_size),
103
+ }
104
+ end
105
+
106
+ # Measures text in the `monospace` family PlantUML's JAR resolves to,
107
+ # DejaVu Sans Mono: every glyph advances 1233/2048 em (a combining mark
108
+ # or control character advances nothing).
109
+ #
110
+ # @param text [String] the text to measure, as one line
111
+ # @param font_size [Numeric] the font size in points
112
+ # @return [Hash] hash with :width and :height keys
113
+ def self.measure_mono(text, font_size:)
114
+ cells = normalize(text).scan(CLUSTER).count do |cluster|
115
+ !cluster.match?(ZERO_WIDTH)
116
+ end
117
+ { width: cells * DEJAVU_MONO_ADVANCE * font_size / 1000.0,
118
+ height: calculate_height(font_size) }
119
+ end
120
+
121
+ # @return [Float] the width of the text drawn as one line
122
+ def self.calculate_width(text, font_size, monospace, face)
123
+ normalized = normalize(text)
124
+ if normalized.ascii_only?
125
+ return ascii_width(normalized, monospace, face) * font_size / 1000.0
126
+ end
127
+
128
+ total = normalized.scan(CLUSTER).sum do |cluster|
129
+ cluster.length == 2 ? EMOJI_ADVANCE : advance(cluster, monospace, face)
130
+ end
131
+ total * font_size / 1000.0
132
+ end
133
+
134
+ def self.ascii_width(text, monospace, face)
135
+ text.each_byte.sum { |code| ascii_advance(code, monospace, face) }
136
+ end
137
+
138
+ def self.ascii_advance(code, monospace, face)
139
+ return whitespace_advance(monospace) if ASCII_WHITESPACE.include?(code)
140
+ return 0 if code < 32 || code == 127
141
+
142
+ table = FACE_TABLES.fetch(face)[code] || ArialAdvances::TABLE[code]
143
+ table_advance(table, monospace)
144
+ end
145
+
146
+ # @return [Integer] the advance of one character in per-mille em
147
+ def self.advance(char, monospace, face)
148
+ return whitespace_advance(monospace) if char.match?(SVG_WHITESPACE)
149
+ return 0 if char.match?(ZERO_WIDTH)
150
+
151
+ code = char.ord
152
+ table = FACE_TABLES.fetch(face)[code] || ArialAdvances::TABLE[code]
153
+ return table_advance(table, monospace) if table
154
+
155
+ OUTLIERS.fetch(code) { fallback_advance(char, monospace) }
156
+ end
157
+
158
+ # Monospace keeps a zero advance (combining marks) at zero.
159
+ def self.table_advance(table, monospace)
160
+ monospace && table.positive? ? MONOSPACE_ADVANCE : table
161
+ end
162
+
163
+ def self.whitespace_advance(monospace)
164
+ monospace ? MONOSPACE_ADVANCE : SPACE_ADVANCE
165
+ end
166
+
167
+ def self.fallback_advance(char, monospace)
168
+ return EMOJI_ADVANCE if PINNED_PICTOGRAPHS.include?(char.ord) ||
169
+ char.match?(EMOJI)
170
+
171
+ monospace ? MONOSPACE_ADVANCE : DEFAULT_ADVANCE
172
+ end
173
+
174
+ # Never raises on an undecodable string: a layout must not fail on bytes.
175
+ # The final re-tag is needed for UTF-8 too: encode from CESU-8 and the
176
+ # UTF8-DoCoMo/KDDI/SoftBank family can leave a stray continuation byte
177
+ # that still reports valid, and only a re-scan of the bytes sees it.
178
+ def self.normalize(text)
179
+ string = text.to_s
180
+ unless string.encoding == Encoding::UTF_8
181
+ string = string.encode(Encoding::UTF_8, invalid: :replace,
182
+ undef: :replace)
183
+ end
184
+ string.b.force_encoding(Encoding::UTF_8).scrub
185
+ rescue EncodingError
186
+ string.b.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
187
+ end
188
+
189
+ # @return [Float] the calculated height
190
+ def self.calculate_height(font_size)
191
+ font_size * HEIGHT_RATIO
192
+ end
193
+
194
+ private_class_method :calculate_width, :calculate_height, :advance,
195
+ :fallback_advance, :table_advance, :whitespace_advance,
196
+ :normalize, :ascii_width, :ascii_advance
197
+ end
198
+ end