sirena 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 (382) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/build_deploy.yml +59 -0
  3. data/.github/workflows/links.yml +85 -0
  4. data/.github/workflows/rake.yml +15 -0
  5. data/.github/workflows/release.yml +27 -0
  6. data/.gitignore +68 -0
  7. data/.rspec +3 -0
  8. data/.rubocop.yml +14 -0
  9. data/.rubocop_todo.yml +70 -0
  10. data/ARCHITECTURE.md +744 -0
  11. data/Gemfile +12 -0
  12. data/LICENSE +25 -0
  13. data/README.adoc +357 -0
  14. data/Rakefile +11 -0
  15. data/docs/.gitignore +1 -0
  16. data/docs/Gemfile +13 -0
  17. data/docs/_config.yml +182 -0
  18. data/docs/_diagram_types/architecture-diagram.adoc +314 -0
  19. data/docs/_diagram_types/block-diagram.adoc +345 -0
  20. data/docs/_diagram_types/c4-diagram.adoc +559 -0
  21. data/docs/_diagram_types/class-diagram.adoc +816 -0
  22. data/docs/_diagram_types/er-diagram.adoc +719 -0
  23. data/docs/_diagram_types/error-diagram.adoc +114 -0
  24. data/docs/_diagram_types/examples/flowchart-examples.adoc +29 -0
  25. data/docs/_diagram_types/flowchart.adoc +488 -0
  26. data/docs/_diagram_types/gantt-chart.adoc +502 -0
  27. data/docs/_diagram_types/git-graph.adoc +600 -0
  28. data/docs/_diagram_types/index.adoc +192 -0
  29. data/docs/_diagram_types/info-diagram.adoc +103 -0
  30. data/docs/_diagram_types/kanban-diagram.adoc +262 -0
  31. data/docs/_diagram_types/mindmap.adoc +603 -0
  32. data/docs/_diagram_types/packet-diagram.adoc +378 -0
  33. data/docs/_diagram_types/pie-chart.adoc +335 -0
  34. data/docs/_diagram_types/quadrant-chart.adoc +406 -0
  35. data/docs/_diagram_types/radar-chart.adoc +528 -0
  36. data/docs/_diagram_types/requirement-diagram.adoc +416 -0
  37. data/docs/_diagram_types/sankey-diagram.adoc +357 -0
  38. data/docs/_diagram_types/sequence-diagram.adoc +664 -0
  39. data/docs/_diagram_types/state-diagram.adoc +658 -0
  40. data/docs/_diagram_types/timeline.adoc +352 -0
  41. data/docs/_diagram_types/treemap-diagram.adoc +462 -0
  42. data/docs/_diagram_types/user-journey.adoc +602 -0
  43. data/docs/_features/index.adoc +129 -0
  44. data/docs/_guides/cli-reference.adoc +203 -0
  45. data/docs/_guides/index.adoc +56 -0
  46. data/docs/_guides/installation.adoc +100 -0
  47. data/docs/_guides/quick-start.adoc +132 -0
  48. data/docs/_pages/comparison.adoc +441 -0
  49. data/docs/_pages/compatibility.adoc +300 -0
  50. data/docs/_pages/index.adoc +39 -0
  51. data/docs/_references/index.adoc +103 -0
  52. data/docs/_tutorials/index.adoc +57 -0
  53. data/docs/index.adoc +166 -0
  54. data/docs/lychee.toml +54 -0
  55. data/examples/.gitignore +10 -0
  56. data/examples/README.adoc +196 -0
  57. data/examples/README.md +64 -0
  58. data/examples/architecture/01-basic-services.mmd +9 -0
  59. data/examples/architecture/01-basic-services.svg +37 -0
  60. data/examples/architecture/02-service-groups.mmd +16 -0
  61. data/examples/architecture/02-service-groups.svg +55 -0
  62. data/examples/architecture/README.adoc +79 -0
  63. data/examples/block/01-basic-blocks.mmd +13 -0
  64. data/examples/block/01-basic-blocks.svg +44 -0
  65. data/examples/block/02-block-shapes.mmd +13 -0
  66. data/examples/block/02-block-shapes.svg +47 -0
  67. data/examples/block/README.adoc +85 -0
  68. data/examples/c4/01-context-diagram.mmd +10 -0
  69. data/examples/c4/01-context-diagram.svg +45 -0
  70. data/examples/c4/02-container-diagram.mmd +24 -0
  71. data/examples/c4/02-container-diagram.svg +105 -0
  72. data/examples/c4/README.adoc +92 -0
  73. data/examples/class_diagram/01-basic-classes.mmd +61 -0
  74. data/examples/class_diagram/01-basic-classes.svg +117 -0
  75. data/examples/class_diagram/02-relationships.mmd +61 -0
  76. data/examples/class_diagram/02-relationships.svg +129 -0
  77. data/examples/class_diagram/README.adoc +93 -0
  78. data/examples/er_diagram/01-basic-entities.mmd +64 -0
  79. data/examples/er_diagram/01-basic-entities.svg +5 -0
  80. data/examples/er_diagram/02-cardinality.mmd +57 -0
  81. data/examples/er_diagram/02-cardinality.svg +125 -0
  82. data/examples/er_diagram/README.adoc +88 -0
  83. data/examples/error/01-basic-error.mmd +1 -0
  84. data/examples/error/01-basic-error.svg +13 -0
  85. data/examples/error/02-error-display.mmd +1 -0
  86. data/examples/error/02-error-display.svg +13 -0
  87. data/examples/error/README.adoc +71 -0
  88. data/examples/error_message_example.svg +13 -0
  89. data/examples/flowchart/00-original.mmd +13 -0
  90. data/examples/flowchart/00-original.svg +5 -0
  91. data/examples/flowchart/01-basic-flow.mmd +7 -0
  92. data/examples/flowchart/01-basic-flow.svg +52 -0
  93. data/examples/flowchart/01-basic-flow.yml +13 -0
  94. data/examples/flowchart/02*.svg +87 -0
  95. data/examples/flowchart/02-node-shapes.mmd +9 -0
  96. data/examples/flowchart/02-node-shapes.svg +33 -0
  97. data/examples/flowchart/03-edge-types.mmd +7 -0
  98. data/examples/flowchart/03-edge-types.svg +53 -0
  99. data/examples/flowchart/04-subgraphs.mmd +9 -0
  100. data/examples/flowchart/04-subgraphs.svg +33 -0
  101. data/examples/flowchart/05-styling.mmd +9 -0
  102. data/examples/flowchart/05-styling.svg +33 -0
  103. data/examples/flowchart/06-complex-flow.mmd +8 -0
  104. data/examples/flowchart/06-complex-flow.svg +59 -0
  105. data/examples/flowchart/README.adoc +167 -0
  106. data/examples/gantt/01-simple-timeline.* +14 -0
  107. data/examples/gantt/01-simple-timeline.mmd +6 -0
  108. data/examples/gantt/01-simple-timeline.svg +26 -0
  109. data/examples/gantt/02-task-dependencies.mmd +6 -0
  110. data/examples/gantt/02-task-dependencies.svg +26 -0
  111. data/examples/gantt/README.adoc +86 -0
  112. data/examples/git_graph/01-linear-history.mmd +12 -0
  113. data/examples/git_graph/01-linear-history.svg +26 -0
  114. data/examples/git_graph/02-branching.mmd +12 -0
  115. data/examples/git_graph/02-branching.svg +26 -0
  116. data/examples/git_graph/README.adoc +73 -0
  117. data/examples/info/02-showinfo.mmd +1 -0
  118. data/examples/info/02-showinfo.svg +10 -0
  119. data/examples/info/README.adoc +58 -0
  120. data/examples/info_showinfo_example.svg +10 -0
  121. data/examples/kanban/01-simple-board.mmd +8 -0
  122. data/examples/kanban/01-simple-board.svg +43 -0
  123. data/examples/kanban/02-workflow.mmd +8 -0
  124. data/examples/kanban/02-workflow.svg +43 -0
  125. data/examples/kanban/README.adoc +79 -0
  126. data/examples/mindmap/01-simple-tree.mmd +19 -0
  127. data/examples/mindmap/01-simple-tree.svg +61 -0
  128. data/examples/mindmap/02-knowledge-map.mmd +19 -0
  129. data/examples/mindmap/02-knowledge-map.svg +61 -0
  130. data/examples/mindmap/README.adoc +77 -0
  131. data/examples/packet/01-basic-packet.* +17 -0
  132. data/examples/packet/01-basic-packet.mmd +4 -0
  133. data/examples/packet/01-basic-packet.svg +82 -0
  134. data/examples/packet/README.adoc +58 -0
  135. data/examples/pie/01-simple-chart.mmd +5 -0
  136. data/examples/pie/01-simple-chart.svg +17 -0
  137. data/examples/pie/02-labeled-slices.mmd +6 -0
  138. data/examples/pie/02-labeled-slices.svg +19 -0
  139. data/examples/pie/README.adoc +75 -0
  140. data/examples/quadrant/01-basic-quadrant.mmd +13 -0
  141. data/examples/quadrant/01-basic-quadrant.svg +33 -0
  142. data/examples/quadrant/02-positioned-items.mmd +14 -0
  143. data/examples/quadrant/02-positioned-items.svg +35 -0
  144. data/examples/quadrant/README.adoc +84 -0
  145. data/examples/radar/01-simple-radar.* +5 -0
  146. data/examples/radar/01-simple-radar.mmd +3 -0
  147. data/examples/radar/01-simple-radar.svg +25 -0
  148. data/examples/radar/02-multiple-curves.mmd +4 -0
  149. data/examples/radar/02-multiple-curves.svg +43 -0
  150. data/examples/radar/README.adoc +75 -0
  151. data/examples/requirement/01-basic-requirements.mmd +23 -0
  152. data/examples/requirement/01-basic-requirements.svg +49 -0
  153. data/examples/requirement/02-risk-levels.mmd +23 -0
  154. data/examples/requirement/02-risk-levels.svg +49 -0
  155. data/examples/requirement/README.adoc +85 -0
  156. data/examples/sankey/01-simple-flow.mmd +7 -0
  157. data/examples/sankey/01-simple-flow.svg +34 -0
  158. data/examples/sankey/02-multi-stage.mmd +11 -0
  159. data/examples/sankey/02-multi-stage.svg +44 -0
  160. data/examples/sankey/README.adoc +74 -0
  161. data/examples/sequence/01-basic-sequence.mmd +27 -0
  162. data/examples/sequence/01-basic-sequence.svg +5 -0
  163. data/examples/sequence/02-activations.mmd +17 -0
  164. data/examples/sequence/02-activations.svg +78 -0
  165. data/examples/sequence/README.adoc +86 -0
  166. data/examples/state_diagram/01-simple-states.mmd +29 -0
  167. data/examples/state_diagram/01-simple-states.svg +5 -0
  168. data/examples/state_diagram/02-composite.mmd +19 -0
  169. data/examples/state_diagram/02-composite.svg +81 -0
  170. data/examples/state_diagram/README.adoc +90 -0
  171. data/examples/timeline/01-simple-timeline.mmd +11 -0
  172. data/examples/timeline/01-simple-timeline.svg +36 -0
  173. data/examples/timeline/02-periods.mmd +15 -0
  174. data/examples/timeline/02-periods.svg +47 -0
  175. data/examples/timeline/README.adoc +78 -0
  176. data/examples/treemap/01-basic-treemap.mmd +12 -0
  177. data/examples/treemap/01-basic-treemap.svg +59 -0
  178. data/examples/treemap/README.adoc +59 -0
  179. data/examples/user_journey/01-simple-journey.mmd +23 -0
  180. data/examples/user_journey/01-simple-journey.svg +5 -0
  181. data/examples/user_journey/02-multi-actor.mmd +18 -0
  182. data/examples/user_journey/02-multi-actor.svg +129 -0
  183. data/examples/user_journey/README.adoc +81 -0
  184. data/examples/xychart/01-line-chart.mmd +5 -0
  185. data/examples/xychart/01-line-chart.svg +43 -0
  186. data/examples/xychart/02-bar-chart.mmd +7 -0
  187. data/examples/xychart/02-bar-chart.svg +48 -0
  188. data/examples/xychart/README.adoc +80 -0
  189. data/exe/sirena +7 -0
  190. data/lib/sirena/cli.rb +138 -0
  191. data/lib/sirena/commands/batch.rb +117 -0
  192. data/lib/sirena/commands/render.rb +80 -0
  193. data/lib/sirena/commands/types.rb +29 -0
  194. data/lib/sirena/commands/version.rb +24 -0
  195. data/lib/sirena/diagram/architecture.rb +46 -0
  196. data/lib/sirena/diagram/base.rb +61 -0
  197. data/lib/sirena/diagram/block.rb +81 -0
  198. data/lib/sirena/diagram/c4.rb +328 -0
  199. data/lib/sirena/diagram/class_diagram.rb +385 -0
  200. data/lib/sirena/diagram/er_diagram.rb +238 -0
  201. data/lib/sirena/diagram/error.rb +38 -0
  202. data/lib/sirena/diagram/flowchart.rb +160 -0
  203. data/lib/sirena/diagram/gantt.rb +71 -0
  204. data/lib/sirena/diagram/git_graph.rb +36 -0
  205. data/lib/sirena/diagram/info.rb +38 -0
  206. data/lib/sirena/diagram/kanban.rb +178 -0
  207. data/lib/sirena/diagram/mindmap.rb +54 -0
  208. data/lib/sirena/diagram/packet.rb +79 -0
  209. data/lib/sirena/diagram/pie.rb +115 -0
  210. data/lib/sirena/diagram/quadrant.rb +138 -0
  211. data/lib/sirena/diagram/radar.rb +52 -0
  212. data/lib/sirena/diagram/requirement.rb +133 -0
  213. data/lib/sirena/diagram/sankey.rb +217 -0
  214. data/lib/sirena/diagram/sequence.rb +242 -0
  215. data/lib/sirena/diagram/state_diagram.rb +237 -0
  216. data/lib/sirena/diagram/timeline.rb +171 -0
  217. data/lib/sirena/diagram/treemap.rb +84 -0
  218. data/lib/sirena/diagram/user_journey.rb +149 -0
  219. data/lib/sirena/diagram/xy_chart.rb +76 -0
  220. data/lib/sirena/diagram.rb +8 -0
  221. data/lib/sirena/diagram_registry.rb +101 -0
  222. data/lib/sirena/engine.rb +292 -0
  223. data/lib/sirena/parser/architecture.rb +41 -0
  224. data/lib/sirena/parser/base.rb +41 -0
  225. data/lib/sirena/parser/block.rb +72 -0
  226. data/lib/sirena/parser/c4.rb +53 -0
  227. data/lib/sirena/parser/class_diagram.rb +63 -0
  228. data/lib/sirena/parser/er_diagram.rb +40 -0
  229. data/lib/sirena/parser/error.rb +49 -0
  230. data/lib/sirena/parser/flowchart.rb +71 -0
  231. data/lib/sirena/parser/gantt.rb +60 -0
  232. data/lib/sirena/parser/git_graph.rb +95 -0
  233. data/lib/sirena/parser/grammars/architecture.rb +145 -0
  234. data/lib/sirena/parser/grammars/block.rb +190 -0
  235. data/lib/sirena/parser/grammars/c4.rb +226 -0
  236. data/lib/sirena/parser/grammars/class_diagram.rb +284 -0
  237. data/lib/sirena/parser/grammars/common.rb +84 -0
  238. data/lib/sirena/parser/grammars/er_diagram.rb +114 -0
  239. data/lib/sirena/parser/grammars/error.rb +40 -0
  240. data/lib/sirena/parser/grammars/flowchart.rb +298 -0
  241. data/lib/sirena/parser/grammars/gantt.rb +252 -0
  242. data/lib/sirena/parser/grammars/git_graph.rb +167 -0
  243. data/lib/sirena/parser/grammars/info.rb +58 -0
  244. data/lib/sirena/parser/grammars/kanban.rb +83 -0
  245. data/lib/sirena/parser/grammars/mindmap.rb +115 -0
  246. data/lib/sirena/parser/grammars/packet.rb +73 -0
  247. data/lib/sirena/parser/grammars/pie.rb +128 -0
  248. data/lib/sirena/parser/grammars/quadrant.rb +199 -0
  249. data/lib/sirena/parser/grammars/radar.rb +150 -0
  250. data/lib/sirena/parser/grammars/requirement.rb +188 -0
  251. data/lib/sirena/parser/grammars/sankey.rb +104 -0
  252. data/lib/sirena/parser/grammars/sequence.rb +247 -0
  253. data/lib/sirena/parser/grammars/state_diagram.rb +172 -0
  254. data/lib/sirena/parser/grammars/timeline.rb +142 -0
  255. data/lib/sirena/parser/grammars/treemap.rb +120 -0
  256. data/lib/sirena/parser/grammars/xy_chart.rb +120 -0
  257. data/lib/sirena/parser/info.rb +49 -0
  258. data/lib/sirena/parser/kanban.rb +97 -0
  259. data/lib/sirena/parser/mindmap.rb +106 -0
  260. data/lib/sirena/parser/packet.rb +76 -0
  261. data/lib/sirena/parser/pie.rb +49 -0
  262. data/lib/sirena/parser/quadrant.rb +57 -0
  263. data/lib/sirena/parser/radar.rb +104 -0
  264. data/lib/sirena/parser/requirement.rb +70 -0
  265. data/lib/sirena/parser/sankey.rb +64 -0
  266. data/lib/sirena/parser/sequence.rb +51 -0
  267. data/lib/sirena/parser/state_diagram.rb +69 -0
  268. data/lib/sirena/parser/timeline.rb +57 -0
  269. data/lib/sirena/parser/transforms/architecture.rb +97 -0
  270. data/lib/sirena/parser/transforms/block.rb +254 -0
  271. data/lib/sirena/parser/transforms/c4.rb +347 -0
  272. data/lib/sirena/parser/transforms/class_diagram.rb +352 -0
  273. data/lib/sirena/parser/transforms/er_diagram.rb +169 -0
  274. data/lib/sirena/parser/transforms/error.rb +58 -0
  275. data/lib/sirena/parser/transforms/flowchart.rb +293 -0
  276. data/lib/sirena/parser/transforms/gantt.rb +215 -0
  277. data/lib/sirena/parser/transforms/git_graph.rb +160 -0
  278. data/lib/sirena/parser/transforms/info.rb +58 -0
  279. data/lib/sirena/parser/transforms/kanban.rb +176 -0
  280. data/lib/sirena/parser/transforms/mindmap.rb +227 -0
  281. data/lib/sirena/parser/transforms/packet.rb +63 -0
  282. data/lib/sirena/parser/transforms/pie.rb +143 -0
  283. data/lib/sirena/parser/transforms/quadrant.rb +177 -0
  284. data/lib/sirena/parser/transforms/radar.rb +126 -0
  285. data/lib/sirena/parser/transforms/requirement.rb +272 -0
  286. data/lib/sirena/parser/transforms/sankey.rb +122 -0
  287. data/lib/sirena/parser/transforms/sequence.rb +342 -0
  288. data/lib/sirena/parser/transforms/state_diagram.rb +292 -0
  289. data/lib/sirena/parser/transforms/timeline.rb +177 -0
  290. data/lib/sirena/parser/transforms/treemap.rb +81 -0
  291. data/lib/sirena/parser/transforms/xy_chart.rb +132 -0
  292. data/lib/sirena/parser/treemap.rb +98 -0
  293. data/lib/sirena/parser/user_journey.rb +120 -0
  294. data/lib/sirena/parser/xy_chart.rb +114 -0
  295. data/lib/sirena/parser.rb +8 -0
  296. data/lib/sirena/renderer/architecture.rb +251 -0
  297. data/lib/sirena/renderer/base.rb +251 -0
  298. data/lib/sirena/renderer/block.rb +286 -0
  299. data/lib/sirena/renderer/c4.rb +490 -0
  300. data/lib/sirena/renderer/class_diagram.rb +499 -0
  301. data/lib/sirena/renderer/er_diagram.rb +417 -0
  302. data/lib/sirena/renderer/error.rb +131 -0
  303. data/lib/sirena/renderer/flowchart.rb +301 -0
  304. data/lib/sirena/renderer/gantt.rb +331 -0
  305. data/lib/sirena/renderer/git_graph.rb +368 -0
  306. data/lib/sirena/renderer/info.rb +93 -0
  307. data/lib/sirena/renderer/kanban.rb +295 -0
  308. data/lib/sirena/renderer/mindmap.rb +396 -0
  309. data/lib/sirena/renderer/packet.rb +239 -0
  310. data/lib/sirena/renderer/pie.rb +235 -0
  311. data/lib/sirena/renderer/quadrant.rb +292 -0
  312. data/lib/sirena/renderer/radar.rb +323 -0
  313. data/lib/sirena/renderer/requirement.rb +371 -0
  314. data/lib/sirena/renderer/sankey.rb +255 -0
  315. data/lib/sirena/renderer/sequence.rb +424 -0
  316. data/lib/sirena/renderer/state_diagram.rb +328 -0
  317. data/lib/sirena/renderer/timeline.rb +304 -0
  318. data/lib/sirena/renderer/treemap.rb +152 -0
  319. data/lib/sirena/renderer/user_journey.rb +331 -0
  320. data/lib/sirena/renderer/xy_chart.rb +452 -0
  321. data/lib/sirena/renderer.rb +8 -0
  322. data/lib/sirena/svg/circle.rb +41 -0
  323. data/lib/sirena/svg/document.rb +103 -0
  324. data/lib/sirena/svg/element.rb +65 -0
  325. data/lib/sirena/svg/ellipse.rb +33 -0
  326. data/lib/sirena/svg/group.rb +71 -0
  327. data/lib/sirena/svg/line.rb +49 -0
  328. data/lib/sirena/svg/path.rb +76 -0
  329. data/lib/sirena/svg/polygon.rb +43 -0
  330. data/lib/sirena/svg/polyline.rb +35 -0
  331. data/lib/sirena/svg/rect.rb +57 -0
  332. data/lib/sirena/svg/style.rb +44 -0
  333. data/lib/sirena/svg/text.rb +72 -0
  334. data/lib/sirena/svg.rb +19 -0
  335. data/lib/sirena/text_measurement.rb +71 -0
  336. data/lib/sirena/theme/builtin/dark.yml +70 -0
  337. data/lib/sirena/theme/builtin/default.yml +80 -0
  338. data/lib/sirena/theme/builtin/high_contrast.yml +70 -0
  339. data/lib/sirena/theme/builtin/light.yml +70 -0
  340. data/lib/sirena/theme/color_palette.rb +48 -0
  341. data/lib/sirena/theme/effect_styles.rb +28 -0
  342. data/lib/sirena/theme/registry.rb +41 -0
  343. data/lib/sirena/theme/shape_styles.rb +28 -0
  344. data/lib/sirena/theme/spacing_config.rb +24 -0
  345. data/lib/sirena/theme/typography.rb +30 -0
  346. data/lib/sirena/theme.rb +69 -0
  347. data/lib/sirena/transform/architecture.rb +273 -0
  348. data/lib/sirena/transform/base.rb +199 -0
  349. data/lib/sirena/transform/block.rb +215 -0
  350. data/lib/sirena/transform/c4.rb +288 -0
  351. data/lib/sirena/transform/class_diagram.rb +296 -0
  352. data/lib/sirena/transform/er_diagram.rb +204 -0
  353. data/lib/sirena/transform/error.rb +39 -0
  354. data/lib/sirena/transform/flowchart.rb +161 -0
  355. data/lib/sirena/transform/gantt.rb +253 -0
  356. data/lib/sirena/transform/git_graph.rb +283 -0
  357. data/lib/sirena/transform/info.rb +39 -0
  358. data/lib/sirena/transform/kanban.rb +180 -0
  359. data/lib/sirena/transform/mindmap.rb +251 -0
  360. data/lib/sirena/transform/packet.rb +185 -0
  361. data/lib/sirena/transform/pie.rb +62 -0
  362. data/lib/sirena/transform/quadrant.rb +167 -0
  363. data/lib/sirena/transform/radar.rb +227 -0
  364. data/lib/sirena/transform/requirement.rb +233 -0
  365. data/lib/sirena/transform/sankey.rb +212 -0
  366. data/lib/sirena/transform/sequence.rb +143 -0
  367. data/lib/sirena/transform/state_diagram.rb +228 -0
  368. data/lib/sirena/transform/timeline.rb +139 -0
  369. data/lib/sirena/transform/treemap.rb +120 -0
  370. data/lib/sirena/transform/user_journey.rb +207 -0
  371. data/lib/sirena/transform/xy_chart.rb +273 -0
  372. data/lib/sirena/transform.rb +8 -0
  373. data/lib/sirena/version.rb +5 -0
  374. data/lib/sirena.rb +328 -0
  375. data/lib/tasks/benchmark.rake +532 -0
  376. data/lib/tasks/examples.rake +468 -0
  377. data/lib/tasks/generate_mermaid_fixtures.rake +363 -0
  378. data/lib/tasks/mermaid_fixtures.rake +46 -0
  379. data/scripts/extract_mermaid_tests.rb +493 -0
  380. data/scripts/rename_to_sirena.rb +73 -0
  381. data/sirena.gemspec +47 -0
  382. metadata +529 -0
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "common"
4
+
5
+ module Sirena
6
+ module Parser
7
+ module Grammars
8
+ # Parslet grammar for architecture diagrams
9
+ class Architecture < Common
10
+ root(:diagram)
11
+
12
+ # Main diagram structure
13
+ rule(:diagram) do
14
+ ws? >>
15
+ header >>
16
+ ws? >>
17
+ statements.maybe >>
18
+ ws?
19
+ end
20
+
21
+ rule(:header) do
22
+ str("architecture-beta").as(:header)
23
+ end
24
+
25
+ rule(:statements) do
26
+ (statement >> ws?).repeat(1)
27
+ end
28
+
29
+ rule(:statement) do
30
+ title_statement |
31
+ acc_title_statement |
32
+ acc_descr_statement |
33
+ group_def |
34
+ service_def |
35
+ edge_def
36
+ end
37
+
38
+ # Title statement
39
+ rule(:title_statement) do
40
+ str("title") >> space.repeat(1) >>
41
+ (line_end.absent? >> any).repeat(1).as(:title) >>
42
+ line_end
43
+ end
44
+
45
+ # Accessibility title
46
+ rule(:acc_title_statement) do
47
+ str("accTitle:") >> space.repeat(1) >>
48
+ (line_end.absent? >> any).repeat(1).as(:acc_title) >>
49
+ line_end
50
+ end
51
+
52
+ # Accessibility description
53
+ rule(:acc_descr_statement) do
54
+ str("accDescr:") >> space.repeat(1) >>
55
+ (line_end.absent? >> any).repeat(1).as(:acc_descr) >>
56
+ line_end
57
+ end
58
+
59
+ # Group definition
60
+ rule(:group_def) do
61
+ str("group").as(:stmt_type) >> space.repeat(1) >>
62
+ arch_identifier.as(:id) >>
63
+ icon_spec.maybe >>
64
+ label_spec.maybe >>
65
+ in_clause.maybe.as(:parent) >>
66
+ line_end
67
+ end
68
+
69
+ # Service definition
70
+ rule(:service_def) do
71
+ str("service").as(:stmt_type) >> space.repeat(1) >>
72
+ arch_identifier.as(:id) >>
73
+ icon_spec >>
74
+ label_spec >>
75
+ in_clause.maybe.as(:group) >>
76
+ line_end
77
+ end
78
+
79
+ # Edge definition - handles various formats
80
+ # Format: from:fromPos --> toPos:to or from --> to
81
+ rule(:edge_def) do
82
+ arch_identifier.as(:from) >>
83
+ position_spec.maybe.as(:from_pos) >>
84
+ space? >>
85
+ arrow.as(:arrow) >>
86
+ space? >>
87
+ (reverse_position_spec.as(:to_pos) >> colon).maybe >>
88
+ arch_identifier.as(:to) >>
89
+ (space? >> colon >> space? >> edge_label.as(:label)).maybe >>
90
+ line_end
91
+ end
92
+
93
+ # Reverse position spec: L: instead of :L (for target position)
94
+ rule(:reverse_position_spec) do
95
+ match("[LRTB]").repeat(1)
96
+ end
97
+
98
+ # Icon specification
99
+ rule(:icon_spec) do
100
+ lparen >> icon_content.as(:icon) >> rparen
101
+ end
102
+
103
+ rule(:icon_content) do
104
+ (rparen.absent? >> any).repeat(1)
105
+ end
106
+
107
+ # Label specification
108
+ rule(:label_spec) do
109
+ lbracket >> label_content.as(:label) >> rbracket
110
+ end
111
+
112
+ rule(:label_content) do
113
+ (rbracket.absent? >> any).repeat(1)
114
+ end
115
+
116
+ # In clause for group membership
117
+ rule(:in_clause) do
118
+ space.repeat(1) >> str("in") >> space.repeat(1) >> arch_identifier.as(:group_id)
119
+ end
120
+
121
+ # Position specification (e.g., :L, :R, :T, :B)
122
+ rule(:position_spec) do
123
+ colon >> match("[LRTB]").repeat(1).as(:pos_value)
124
+ end
125
+
126
+ # Arrow patterns - order matters, check longer first
127
+ rule(:arrow) do
128
+ str("L--R") | str("R--L") |
129
+ str("T--B") | str("B--T") |
130
+ str("-->") | str("--")
131
+ end
132
+
133
+ # Edge label
134
+ rule(:edge_label) do
135
+ (line_end.absent? >> any).repeat(1)
136
+ end
137
+
138
+ # Architecture-specific identifier (allows hyphens and numbers)
139
+ rule(:arch_identifier) do
140
+ match("[a-zA-Z0-9_-]").repeat(1)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module Sirena
6
+ module Parser
7
+ module Grammars
8
+ # Parslet grammar for Block diagrams.
9
+ #
10
+ # Handles block diagram syntax including column layout, blocks with
11
+ # various shapes, compound blocks, connections, and styling.
12
+ class Block < Common
13
+ root(:diagram)
14
+
15
+ # Main diagram structure
16
+ rule(:diagram) do
17
+ ws? >>
18
+ header >>
19
+ ws? >>
20
+ statements.maybe >>
21
+ ws?
22
+ end
23
+
24
+ rule(:header) do
25
+ str('block-beta').as(:header) >> ws?
26
+ end
27
+
28
+ rule(:statements) do
29
+ (statement >> ws?).repeat(1)
30
+ end
31
+
32
+ rule(:statement) do
33
+ columns_statement |
34
+ style_statement |
35
+ connection_statement |
36
+ compound_block_statement |
37
+ block_statement
38
+ end
39
+
40
+ # Columns: columns N
41
+ rule(:columns_statement) do
42
+ str('columns').as(:columns_keyword) >> space >>
43
+ integer.as(:columns_value) >>
44
+ line_end
45
+ end
46
+
47
+ # Compound block: block:ID ... end or block ... end
48
+ rule(:compound_block_statement) do
49
+ str('block').as(:compound_keyword) >>
50
+ (colon >> block_id.as(:compound_id)).maybe >>
51
+ space? >>
52
+ line_end >>
53
+ ws? >>
54
+ compound_statements.maybe.as(:compound_statements) >>
55
+ ws? >>
56
+ str('end').as(:compound_end) >>
57
+ line_end
58
+ end
59
+
60
+ rule(:compound_statements) do
61
+ (compound_statement >> ws?).repeat(1)
62
+ end
63
+
64
+ rule(:compound_statement) do
65
+ compound_block_statement |
66
+ block_statement
67
+ end
68
+
69
+ # Style: style blockId fill:#f9f,stroke:#333
70
+ rule(:style_statement) do
71
+ str('style').as(:style_keyword) >> space >>
72
+ block_id.as(:style_target) >>
73
+ space >>
74
+ style_properties.as(:style_props) >>
75
+ line_end
76
+ end
77
+
78
+ rule(:style_properties) do
79
+ style_property >> (comma >> style_property).repeat
80
+ end
81
+
82
+ rule(:style_property) do
83
+ (line_end.absent? >> comma.absent? >> any).repeat(1)
84
+ end
85
+
86
+ # Connection: A --> B or A --- B
87
+ rule(:connection_statement) do
88
+ block_id.as(:from) >>
89
+ space? >>
90
+ arrow.as(:arrow) >>
91
+ space? >>
92
+ block_id.as(:to) >>
93
+ line_end
94
+ end
95
+
96
+ rule(:arrow) do
97
+ str('-->').as(:arrow_type) |
98
+ str('---').as(:line_type)
99
+ end
100
+
101
+ # Block statement: can be space, simple block, or block with shape/width
102
+ rule(:block_statement) do
103
+ space_block |
104
+ arrow_block |
105
+ block_with_shape
106
+ end
107
+
108
+ # Space placeholder
109
+ rule(:space_block) do
110
+ str('space').as(:space_keyword) >> line_end
111
+ end
112
+
113
+ # Arrow block: blockArrowId<["&nbsp;"]>(down)
114
+ rule(:arrow_block) do
115
+ block_id.as(:arrow_id) >>
116
+ str('<').as(:arrow_open) >>
117
+ lbracket >>
118
+ (rbracket.absent? >> any).repeat.as(:arrow_label) >>
119
+ rbracket >>
120
+ str('>').as(:arrow_close) >>
121
+ lparen >>
122
+ arrow_direction.as(:arrow_direction) >>
123
+ rparen >>
124
+ line_end
125
+ end
126
+
127
+ rule(:arrow_direction) do
128
+ (str('up') | str('down') | str('left') | str('right')).as(:direction)
129
+ end
130
+
131
+ # Block with optional shape and width
132
+ rule(:block_with_shape) do
133
+ block_id.as(:block_id) >>
134
+ (space? >> block_shape.as(:block_shape)).maybe >>
135
+ (block_width.as(:block_width)).maybe >>
136
+ line_end
137
+ end
138
+
139
+ # Block width: :N
140
+ rule(:block_width) do
141
+ colon >> integer
142
+ end
143
+
144
+ # Block shapes
145
+ rule(:block_shape) do
146
+ shape_double_circle |
147
+ shape_rectangle
148
+ end
149
+
150
+ # Rectangle shape: ["label"]
151
+ rule(:shape_rectangle) do
152
+ lbracket.as(:open) >>
153
+ (rbracket.absent? >> any).repeat.as(:label) >>
154
+ rbracket.as(:close)
155
+ end
156
+
157
+ # Circle shape: (("label"))
158
+ rule(:shape_double_circle) do
159
+ str('((').as(:open) >>
160
+ (str('))').absent? >> any).repeat.as(:label) >>
161
+ str('))').as(:close)
162
+ end
163
+
164
+ # Block identifier - can be quoted string or identifier
165
+ # but not reserved keywords when standalone
166
+ rule(:block_id) do
167
+ quoted_string |
168
+ (reserved_keyword.absent? >> identifier)
169
+ end
170
+
171
+ # Reserved keywords that can't be used as standalone block IDs
172
+ # Only keywords that would be ambiguous in block_statement context
173
+ rule(:reserved_keyword) do
174
+ (str('block') | str('end') | str('space')) >>
175
+ (identifier_char.absent?)
176
+ end
177
+
178
+ # Identifier character (for lookahead)
179
+ rule(:identifier_char) do
180
+ match['a-zA-Z0-9_']
181
+ end
182
+
183
+ # Line terminator
184
+ rule(:line_end) do
185
+ semicolon.maybe >> space? >> (comment.maybe >> newline | eof)
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'common'
4
+
5
+ module Sirena
6
+ module Parser
7
+ module Grammars
8
+ # Parslet grammar for C4 diagrams.
9
+ #
10
+ # Handles C4 diagram syntax including Context, Container, Component,
11
+ # Dynamic, and Deployment diagrams with elements, relationships, and
12
+ # boundaries.
13
+ class C4 < Common
14
+ root(:diagram)
15
+
16
+ # Main diagram structure
17
+ rule(:diagram) do
18
+ ws? >>
19
+ header >>
20
+ ws? >>
21
+ statements.maybe >>
22
+ ws?
23
+ end
24
+
25
+ # C4 level headers
26
+ rule(:header) do
27
+ (
28
+ str('C4Context') |
29
+ str('C4Container') |
30
+ str('C4Component') |
31
+ str('C4Dynamic') |
32
+ str('C4Deployment') |
33
+ str('C4 diagram')
34
+ ).as(:header) >>
35
+ # Allow optional ${whitespace} or ${variable} or semicolon after header
36
+ (
37
+ (dollar >> lbrace >> identifier >> rbrace) |
38
+ str(';')
39
+ ).maybe >>
40
+ ws?
41
+ end
42
+
43
+ rule(:statements) do
44
+ (statement >> ws?).repeat(1)
45
+ end
46
+
47
+ rule(:statement) do
48
+ title_statement |
49
+ update_layout_config |
50
+ boundary |
51
+ relationship |
52
+ element
53
+ end
54
+
55
+ # Title statement
56
+ rule(:title_statement) do
57
+ str('title') >> space.repeat(1) >>
58
+ (line_end.absent? >> dollar.absent? >> any).repeat(1).as(:title) >>
59
+ # Allow optional ${whitespace} or ${variable} at end
60
+ (dollar >> lbrace >> identifier >> rbrace).maybe >>
61
+ line_end
62
+ end
63
+
64
+ # UpdateLayoutConfig
65
+ rule(:update_layout_config) do
66
+ str('UpdateLayoutConfig') >> space? >> lparen >> space? >>
67
+ config_params.as(:config_params) >>
68
+ space? >> rparen >> line_end
69
+ end
70
+
71
+ rule(:config_params) do
72
+ config_param >>
73
+ (space? >> comma >> space? >> config_param).repeat
74
+ end
75
+
76
+ rule(:config_param) do
77
+ (dollar >> identifier).as(:key) >> space? >> equals >> space? >>
78
+ (quoted_string | number).as(:value)
79
+ end
80
+
81
+ # Boundaries (can contain elements and nested boundaries)
82
+ rule(:boundary) do
83
+ boundary_type.as(:boundary_type) >> space? >> lparen >> space? >>
84
+ boundary_params >>
85
+ space? >> rparen >> space? >> lbrace >>
86
+ ws? >>
87
+ boundary_body.maybe.as(:body) >>
88
+ ws? >>
89
+ rbrace >> line_end
90
+ end
91
+
92
+ rule(:boundary_type) do
93
+ str('Enterprise_Boundary') |
94
+ str('System_Boundary') |
95
+ str('Boundary') |
96
+ # Handle variable boundary types like ${macroName}
97
+ (dollar >> lbrace >> identifier.as(:var) >> rbrace).as(:variable)
98
+ end
99
+
100
+ rule(:boundary_params) do
101
+ (variable_or_identifier).as(:id) >>
102
+ (space? >> comma >> space? >>
103
+ param_value.as(:label)).maybe >>
104
+ (space? >> comma >> space? >>
105
+ param_value.as(:type)).maybe >>
106
+ boundary_attributes.maybe
107
+ end
108
+
109
+ rule(:boundary_body) do
110
+ (boundary | element).as(:item) >>
111
+ (ws? >> (boundary | element).as(:item)).repeat
112
+ end
113
+
114
+ rule(:boundary_attributes) do
115
+ (space? >> comma >> space? >> boundary_attribute).repeat(1)
116
+ end
117
+
118
+ rule(:boundary_attribute) do
119
+ (dollar >> str('link') >> equals >> quoted_string).as(:link) |
120
+ (dollar >> str('tags') >> equals >> quoted_string).as(:tags)
121
+ end
122
+
123
+ # Elements (Person, System, Container, Component, etc.)
124
+ rule(:element) do
125
+ element_type.as(:element_type) >> space? >> lparen >> space? >>
126
+ element_params >>
127
+ space? >> rparen >>
128
+ # Allow optional ${whitespace} or ${variable} at end
129
+ (dollar >> lbrace >> identifier >> rbrace).maybe >>
130
+ line_end
131
+ end
132
+
133
+ rule(:element_type) do
134
+ # Order matters: check longer patterns first
135
+ str('Enterprise_Boundary') | str('System_Boundary') |
136
+ str('Person_Ext') | str('Person') |
137
+ str('SystemDb_Ext') | str('SystemDb') |
138
+ str('SystemQueue_Ext') | str('SystemQueue') |
139
+ str('System_Ext') | str('System') |
140
+ str('ContainerDb') | str('ContainerQueue') | str('Container') |
141
+ str('Component') |
142
+ # Handle variable element types
143
+ (dollar >> lbrace >> identifier.as(:var) >> rbrace).as(:variable)
144
+ end
145
+
146
+ rule(:element_params) do
147
+ (variable_or_identifier).as(:id) >>
148
+ (space? >> comma >> space? >>
149
+ param_value.as(:label)).maybe >>
150
+ (space? >> comma >> space? >>
151
+ param_value.as(:description)).maybe >>
152
+ (space? >> comma >> space? >>
153
+ param_value.as(:technology)).maybe >>
154
+ element_attributes.maybe
155
+ end
156
+
157
+ rule(:element_attributes) do
158
+ (space? >> comma >> space? >> element_attribute).repeat(1)
159
+ end
160
+
161
+ rule(:element_attribute) do
162
+ (dollar >> str('sprite') >> equals >> quoted_string).as(:sprite) |
163
+ (dollar >> str('link') >> equals >> quoted_string).as(:link) |
164
+ (dollar >> str('tags') >> equals >> quoted_string).as(:tags)
165
+ end
166
+
167
+ # Relationships
168
+ rule(:relationship) do
169
+ relationship_type.as(:rel_type) >> space? >> lparen >> space? >>
170
+ relationship_params >>
171
+ space? >> rparen >>
172
+ # Allow optional ${whitespace} or ${variable} at end
173
+ (dollar >> lbrace >> identifier >> rbrace).maybe >>
174
+ line_end
175
+ end
176
+
177
+ rule(:relationship_type) do
178
+ str('BiRel') | str('Rel')
179
+ end
180
+
181
+ rule(:relationship_params) do
182
+ (variable_or_identifier).as(:from) >>
183
+ space? >> comma >> space? >>
184
+ (variable_or_identifier).as(:to) >>
185
+ (space? >> comma >> space? >>
186
+ param_value.as(:label)).maybe >>
187
+ (space? >> comma >> space? >>
188
+ param_value.as(:technology)).maybe
189
+ end
190
+
191
+ # Parameter value (can be quoted string, unquoted text, or variable)
192
+ # But should not match attributes (things starting with $name=)
193
+ rule(:param_value) do
194
+ quoted_string |
195
+ variable_or_identifier |
196
+ unquoted_param
197
+ end
198
+
199
+ rule(:unquoted_param) do
200
+ # Don't match if it starts with $identifier=
201
+ (dollar >> match['a-zA-Z_']).absent? >>
202
+ (comma.absent? >> rparen.absent? >> line_end.absent? >>
203
+ any).repeat(1)
204
+ end
205
+
206
+ # Variable or identifier
207
+ rule(:variable_or_identifier) do
208
+ variable | identifier
209
+ end
210
+
211
+ rule(:variable) do
212
+ dollar >> lbrace >> identifier.as(:var) >> rbrace
213
+ end
214
+
215
+ rule(:dollar) { str('$') }
216
+
217
+ # Override string to capture content
218
+ rule(:quoted_string) do
219
+ str('"') >> (
220
+ str('\\') >> any | str('"').absent? >> any
221
+ ).repeat.as(:string) >> str('"')
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end