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,81 @@
1
+ = User Journey Examples
2
+
3
+ == Purpose
4
+
5
+ User journey diagrams map user experiences and interactions with a system, showing tasks, satisfaction levels, and different actors involved in each step.
6
+
7
+ == When to Use
8
+
9
+ * User experience (UX) design
10
+ * Customer journey mapping
11
+ * Service design documentation
12
+ * Stakeholder engagement visualization
13
+ * Process improvement analysis
14
+
15
+ == Syntax Overview
16
+
17
+ [source,mermaid]
18
+ ----
19
+ journey
20
+ title My Journey
21
+ section Section 1
22
+ Task 1: 5: Actor 1
23
+ Task 2: 3: Actor 1, Actor 2
24
+ ----
25
+
26
+ **Satisfaction Levels**: 1 (low) to 5 (high)
27
+
28
+ == Examples
29
+
30
+ === 01: Simple Journey
31
+
32
+ Demonstrates basic user journey with single actor and satisfaction scoring.
33
+
34
+ **File**: link:01-simple-journey.mmd[01-simple-journey.mmd]
35
+
36
+ [source,mermaid]
37
+ ----
38
+ include::01-simple-journey.mmd[]
39
+ ----
40
+
41
+ image::01-simple-journey.svg[]
42
+
43
+ === 02: Multi-Actor
44
+
45
+ Showcases complex journey with multiple actors and sections.
46
+
47
+ **File**: link:02-multi-actor.mmd[02-multi-actor.mmd]
48
+
49
+ [source,mermaid]
50
+ ----
51
+ include::02-multi-actor.mmd[]
52
+ ----
53
+
54
+ image::02-multi-actor.svg[]
55
+
56
+ == Features Demonstrated
57
+
58
+ [%header,cols="1,1"]
59
+ |===
60
+ | Feature | Example
61
+
62
+ | Basic journey mapping
63
+ | 01, 02
64
+
65
+ | Satisfaction scoring
66
+ | 01, 02
67
+
68
+ | Multiple actors
69
+ | 02
70
+
71
+ | Section grouping
72
+ | 01, 02
73
+
74
+ | Task visualization
75
+ | 01, 02
76
+ |===
77
+
78
+ == Additional Resources
79
+
80
+ * link:../../README.adoc[Main Documentation]
81
+ * https://mermaid.js.org/syntax/userJourney.html[Mermaid User Journey Documentation]
@@ -0,0 +1,5 @@
1
+ xychart-beta
2
+ title "Monthly Sales Performance"
3
+ x-axis [Jan, Feb, Mar, Apr, May, Jun]
4
+ y-axis "Sales ($1000)" 0 --> 100
5
+ line [45, 52, 68, 75, 82, 90]
@@ -0,0 +1,43 @@
1
+ <svg
2
+ width="800.0"
3
+ height="500.0"
4
+ viewBox="0 0 800.0 500.0"
5
+ version="1.2"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ >
8
+ <text fill="#000000" x="400.0" y="30.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="16.0" font-weight="bold">Monthly Sales Performance</text>
9
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="80.0" x2="740.0" y2="80.0" stroke-dasharray="3,3"/>
10
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="148.0" x2="740.0" y2="148.0" stroke-dasharray="3,3"/>
11
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="216.0" x2="740.0" y2="216.0" stroke-dasharray="3,3"/>
12
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="284.0" x2="740.0" y2="284.0" stroke-dasharray="3,3"/>
13
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="352.0" x2="740.0" y2="352.0" stroke-dasharray="3,3"/>
14
+ <line stroke="#e5e7eb" stroke-width="1" x1="153.0" y1="80.0" x2="153.0" y2="420.0" stroke-dasharray="3,3"/>
15
+ <line stroke="#e5e7eb" stroke-width="1" x1="259.0" y1="80.0" x2="259.0" y2="420.0" stroke-dasharray="3,3"/>
16
+ <line stroke="#e5e7eb" stroke-width="1" x1="365.0" y1="80.0" x2="365.0" y2="420.0" stroke-dasharray="3,3"/>
17
+ <line stroke="#e5e7eb" stroke-width="1" x1="471.0" y1="80.0" x2="471.0" y2="420.0" stroke-dasharray="3,3"/>
18
+ <line stroke="#e5e7eb" stroke-width="1" x1="577.0" y1="80.0" x2="577.0" y2="420.0" stroke-dasharray="3,3"/>
19
+ <line stroke="#e5e7eb" stroke-width="1" x1="683.0" y1="80.0" x2="683.0" y2="420.0" stroke-dasharray="3,3"/>
20
+ <line stroke="#000000" stroke-width="2" x1="100.0" y1="420.0" x2="740.0" y2="420.0"/>
21
+ <line stroke="#000000" stroke-width="2" x1="100.0" y1="80.0" x2="100.0" y2="420.0"/>
22
+ <polyline fill="none" stroke="#2563eb" stroke-width="2"/>
23
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="153.0" cy="267.0" r="4.0"/>
24
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="259.0" cy="243.2" r="4.0"/>
25
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="365.0" cy="188.79999999999998" r="4.0"/>
26
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="471.0" cy="165.0" r="4.0"/>
27
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="577.0" cy="141.2" r="4.0"/>
28
+ <circle fill="#2563eb" stroke="#ffffff" stroke-width="2" cx="683.0" cy="114.0" r="4.0"/>
29
+ <text fill="#000000" x="153.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Jan</text>
30
+ <text fill="#000000" x="259.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Feb</text>
31
+ <text fill="#000000" x="365.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Mar</text>
32
+ <text fill="#000000" x="471.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Apr</text>
33
+ <text fill="#000000" x="577.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">May</text>
34
+ <text fill="#000000" x="683.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Jun</text>
35
+ <text transform="rotate(-90, 20, 250)" fill="#000000" x="20.0" y="250.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="14.0" font-weight="bold">Sales ($1000)</text>
36
+ <text fill="#000000" x="90.0" y="84.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">100.0</text>
37
+ <text fill="#000000" x="90.0" y="152.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">80.0</text>
38
+ <text fill="#000000" x="90.0" y="220.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">60.0</text>
39
+ <text fill="#000000" x="90.0" y="288.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">40.0</text>
40
+ <text fill="#000000" x="90.0" y="356.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">20.0</text>
41
+ <rect fill="#2563eb" stroke="none" x="650.0" y="52.0" width="15.0" height="15.0"/>
42
+ <text fill="#000000" x="670.0" y="64.0" text-anchor="start" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Line</text>
43
+ </svg>
@@ -0,0 +1,7 @@
1
+ xychart-beta
2
+ title "Quarterly Revenue Comparison"
3
+ x-axis [Q1, Q2, Q3, Q4]
4
+ y-axis "Revenue (Million USD)" 0 --> 100
5
+ bar [65, 75, 85, 95]
6
+ bar [55, 70, 80, 90]
7
+ bar [45, 60, 75, 85]
@@ -0,0 +1,48 @@
1
+ <svg
2
+ width="800.0"
3
+ height="500.0"
4
+ viewBox="0 0 800.0 500.0"
5
+ version="1.2"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ >
8
+ <text fill="#000000" x="400.0" y="30.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="16.0" font-weight="bold">Quarterly Revenue Comparison</text>
9
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="80.0" x2="740.0" y2="80.0" stroke-dasharray="3,3"/>
10
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="148.0" x2="740.0" y2="148.0" stroke-dasharray="3,3"/>
11
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="216.0" x2="740.0" y2="216.0" stroke-dasharray="3,3"/>
12
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="284.0" x2="740.0" y2="284.0" stroke-dasharray="3,3"/>
13
+ <line stroke="#e5e7eb" stroke-width="1" x1="100.0" y1="352.0" x2="740.0" y2="352.0" stroke-dasharray="3,3"/>
14
+ <line stroke="#e5e7eb" stroke-width="1" x1="180.0" y1="80.0" x2="180.0" y2="420.0" stroke-dasharray="3,3"/>
15
+ <line stroke="#e5e7eb" stroke-width="1" x1="340.0" y1="80.0" x2="340.0" y2="420.0" stroke-dasharray="3,3"/>
16
+ <line stroke="#e5e7eb" stroke-width="1" x1="500.0" y1="80.0" x2="500.0" y2="420.0" stroke-dasharray="3,3"/>
17
+ <line stroke="#e5e7eb" stroke-width="1" x1="660.0" y1="80.0" x2="660.0" y2="420.0" stroke-dasharray="3,3"/>
18
+ <line stroke="#000000" stroke-width="2" x1="100.0" y1="420.0" x2="740.0" y2="420.0"/>
19
+ <line stroke="#000000" stroke-width="2" x1="100.0" y1="80.0" x2="100.0" y2="420.0"/>
20
+ <rect fill="#2563eb" fill-opacity="0.8" stroke="#2563eb" stroke-width="1" x="132.0" y="199.0" width="96.0" height="221.0" fill-opacity="0.8"/>
21
+ <rect fill="#2563eb" fill-opacity="0.8" stroke="#2563eb" stroke-width="1" x="292.0" y="165.0" width="96.0" height="255.0" fill-opacity="0.8"/>
22
+ <rect fill="#2563eb" fill-opacity="0.8" stroke="#2563eb" stroke-width="1" x="452.0" y="131.0" width="96.0" height="289.0" fill-opacity="0.8"/>
23
+ <rect fill="#2563eb" fill-opacity="0.8" stroke="#2563eb" stroke-width="1" x="612.0" y="97.0" width="96.0" height="323.0" fill-opacity="0.8"/>
24
+ <rect fill="#7c3aed" fill-opacity="0.8" stroke="#7c3aed" stroke-width="1" x="132.0" y="232.99999999999997" width="96.0" height="187.00000000000003" fill-opacity="0.8"/>
25
+ <rect fill="#7c3aed" fill-opacity="0.8" stroke="#7c3aed" stroke-width="1" x="292.0" y="182.00000000000003" width="96.0" height="237.99999999999997" fill-opacity="0.8"/>
26
+ <rect fill="#7c3aed" fill-opacity="0.8" stroke="#7c3aed" stroke-width="1" x="452.0" y="148.0" width="96.0" height="272.0" fill-opacity="0.8"/>
27
+ <rect fill="#7c3aed" fill-opacity="0.8" stroke="#7c3aed" stroke-width="1" x="612.0" y="114.0" width="96.0" height="306.0" fill-opacity="0.8"/>
28
+ <rect fill="#db2777" fill-opacity="0.8" stroke="#db2777" stroke-width="1" x="132.0" y="267.0" width="96.0" height="153.0" fill-opacity="0.8"/>
29
+ <rect fill="#db2777" fill-opacity="0.8" stroke="#db2777" stroke-width="1" x="292.0" y="216.0" width="96.0" height="204.0" fill-opacity="0.8"/>
30
+ <rect fill="#db2777" fill-opacity="0.8" stroke="#db2777" stroke-width="1" x="452.0" y="165.0" width="96.0" height="255.0" fill-opacity="0.8"/>
31
+ <rect fill="#db2777" fill-opacity="0.8" stroke="#db2777" stroke-width="1" x="612.0" y="131.0" width="96.0" height="289.0" fill-opacity="0.8"/>
32
+ <text fill="#000000" x="180.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Q1</text>
33
+ <text fill="#000000" x="340.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Q2</text>
34
+ <text fill="#000000" x="500.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Q3</text>
35
+ <text fill="#000000" x="660.0" y="440.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Q4</text>
36
+ <text transform="rotate(-90, 20, 250)" fill="#000000" x="20.0" y="250.0" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="14.0" font-weight="bold">Revenue (Million USD)</text>
37
+ <text fill="#000000" x="90.0" y="84.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">100.0</text>
38
+ <text fill="#000000" x="90.0" y="152.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">80.0</text>
39
+ <text fill="#000000" x="90.0" y="220.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">60.0</text>
40
+ <text fill="#000000" x="90.0" y="288.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">40.0</text>
41
+ <text fill="#000000" x="90.0" y="356.0" text-anchor="end" font-family="Arial, Helvetica, sans-serif" font-size="12.0">20.0</text>
42
+ <rect fill="#2563eb" stroke="none" x="650.0" y="52.0" width="15.0" height="15.0"/>
43
+ <text fill="#000000" x="670.0" y="64.0" text-anchor="start" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Bar</text>
44
+ <rect fill="#7c3aed" stroke="none" x="650.0" y="77.0" width="15.0" height="15.0"/>
45
+ <text fill="#000000" x="670.0" y="89.0" text-anchor="start" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Bar</text>
46
+ <rect fill="#db2777" stroke="none" x="650.0" y="102.0" width="15.0" height="15.0"/>
47
+ <text fill="#000000" x="670.0" y="114.0" text-anchor="start" font-family="Arial, Helvetica, sans-serif" font-size="12.0">Bar</text>
48
+ </svg>
@@ -0,0 +1,80 @@
1
+ = XY Chart Examples
2
+
3
+ == Purpose
4
+
5
+ XY charts display data using x and y coordinates, supporting line and bar chart variations for trend visualization.
6
+
7
+ == When to Use
8
+
9
+ * Time series data visualization
10
+ * Statistical trend analysis
11
+ * Performance metrics over time
12
+ * Comparative data analysis
13
+ * Revenue/sales tracking
14
+
15
+ == Syntax Overview
16
+
17
+ [source,mermaid]
18
+ ----
19
+ xychart-beta
20
+ title "Chart Title"
21
+ x-axis [Q1, Q2, Q3, Q4]
22
+ y-axis "Revenue" 0 --> 100
23
+ line [20, 40, 60, 80]
24
+ bar [15, 35, 55, 75]
25
+ ----
26
+
27
+ == Examples
28
+
29
+ === 01: Line Chart
30
+
31
+ Demonstrates basic XY line chart with labeled axes.
32
+
33
+ **File**: link:01-line-chart.mmd[01-line-chart.mmd]
34
+
35
+ [source,mermaid]
36
+ ----
37
+ include::01-line-chart.mmd[]
38
+ ----
39
+
40
+ image::01-line-chart.svg[]
41
+
42
+ === 02: Bar Chart
43
+
44
+ Showcases bar chart variation with multiple series.
45
+
46
+ **File**: link:02-bar-chart.mmd[02-bar-chart.mmd]
47
+
48
+ [source,mermaid]
49
+ ----
50
+ include::02-bar-chart.mmd[]
51
+ ----
52
+
53
+ image::02-bar-chart.svg[]
54
+
55
+ == Features Demonstrated
56
+
57
+ [%header,cols="1,1"]
58
+ |===
59
+ | Feature | Example
60
+
61
+ | Line charts
62
+ | 01
63
+
64
+ | Bar charts
65
+ | 02
66
+
67
+ | Axis labeling
68
+ | 01, 02
69
+
70
+ | Multiple data series
71
+ | 02
72
+
73
+ | Value ranges
74
+ | 01, 02
75
+ |===
76
+
77
+ == Additional Resources
78
+
79
+ * link:../../README.adoc[Main Documentation]
80
+ * https://mermaid.js.org/syntax/xychart.html[Mermaid XY Chart Documentation]
data/exe/sirena ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/sirena'
5
+ require_relative '../lib/sirena/cli'
6
+
7
+ Sirena::Cli.start(ARGV)
data/lib/sirena/cli.rb ADDED
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ module Sirena
6
+ # Command-line interface for sirena.
7
+ #
8
+ # Provides commands for rendering Mermaid diagrams to SVG and
9
+ # managing diagram types.
10
+ class Cli < Thor
11
+ def self.exit_on_failure?
12
+ true
13
+ end
14
+
15
+ desc 'render [FILE]', 'Render a Mermaid diagram to SVG'
16
+ long_desc <<~DESC
17
+ Renders a Mermaid diagram from FILE or stdin to SVG format.
18
+
19
+ If FILE is not provided or is "-", reads from stdin.
20
+ Output is written to stdout by default, or to the file specified
21
+ with --output.
22
+
23
+ Examples:
24
+ sirena render diagram.mmd
25
+ sirena render diagram.mmd --output diagram.svg
26
+ sirena render diagram.mmd --theme dark
27
+ sirena render diagram.mmd --theme /path/to/custom-theme.yml
28
+ cat diagram.mmd | sirena render
29
+ sirena render --verbose diagram.mmd
30
+ DESC
31
+ method_option :output,
32
+ aliases: '-o',
33
+ type: :string,
34
+ desc: 'Output file path (default: stdout)'
35
+ method_option :format,
36
+ aliases: '-f',
37
+ type: :string,
38
+ default: 'svg',
39
+ desc: 'Output format (only svg supported)'
40
+ method_option :theme,
41
+ aliases: '-t',
42
+ type: :string,
43
+ desc: 'Theme name or path to theme file ' \
44
+ '(default, dark, light, high_contrast)'
45
+ method_option :verbose,
46
+ aliases: '-v',
47
+ type: :boolean,
48
+ default: false,
49
+ desc: 'Enable verbose output'
50
+ def render(file = '-')
51
+ require_relative 'commands/render'
52
+ Commands::RenderCommand.new(file, options).run
53
+ rescue StandardError => e
54
+ handle_error(e)
55
+ end
56
+
57
+ desc 'types', 'List supported diagram types'
58
+ long_desc <<~DESC
59
+ Lists all diagram types currently supported by sirena.
60
+
61
+ Examples:
62
+ sirena types
63
+ DESC
64
+ def types
65
+ require_relative 'commands/types'
66
+ Commands::TypesCommand.new(options).run
67
+ rescue StandardError => e
68
+ handle_error(e)
69
+ end
70
+
71
+ desc 'batch', 'Batch render multiple Mermaid diagrams'
72
+ long_desc <<~DESC
73
+ Renders all Mermaid diagrams in a directory to SVG format.
74
+
75
+ Recursively finds all .mmd files in the input directory and
76
+ generates corresponding SVG files in the output directory.
77
+
78
+ Examples:
79
+ sirena batch --input docs/diagrams --output docs/images
80
+ sirena batch -i diagrams -o output --theme dark
81
+ sirena batch -i docs -o output -v
82
+ DESC
83
+ method_option :input,
84
+ aliases: '-i',
85
+ type: :string,
86
+ default: '.',
87
+ desc: 'Input directory or file'
88
+ method_option :output,
89
+ aliases: '-o',
90
+ type: :string,
91
+ default: 'output',
92
+ desc: 'Output directory'
93
+ method_option :theme,
94
+ aliases: '-t',
95
+ type: :string,
96
+ desc: 'Theme name or path to theme file'
97
+ method_option :verbose,
98
+ aliases: '-v',
99
+ type: :boolean,
100
+ default: false,
101
+ desc: 'Enable verbose output'
102
+ def batch
103
+ require_relative 'commands/batch'
104
+ Commands::BatchCommand.new(options).run
105
+ rescue StandardError => e
106
+ handle_error(e)
107
+ end
108
+
109
+ desc 'version', 'Show sirena version'
110
+ long_desc <<~DESC
111
+ Displays the current version of sirena.
112
+
113
+ Examples:
114
+ sirena version
115
+ DESC
116
+ def version
117
+ require_relative 'commands/version'
118
+ Commands::VersionCommand.new(options).run
119
+ rescue StandardError => e
120
+ handle_error(e)
121
+ end
122
+
123
+ # Make version available as --version flag
124
+ map %w[--version -V] => :version
125
+
126
+ private
127
+
128
+ # Handles errors and exits with appropriate code.
129
+ #
130
+ # @param error [StandardError] the error to handle
131
+ # @return [void]
132
+ def handle_error(error)
133
+ warn "Error: #{error.message}"
134
+ warn error.backtrace.join("\n") if options[:verbose]
135
+ exit 1
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module Sirena
6
+ module Commands
7
+ # Batch command for rendering multiple Mermaid diagrams.
8
+ #
9
+ # Processes entire directories of .mmd files and generates
10
+ # corresponding SVG output files.
11
+ class BatchCommand
12
+ attr_reader :options
13
+
14
+ def initialize(options = {})
15
+ @options = options
16
+ @stats = { success: 0, failed: 0, errors: [] }
17
+ end
18
+
19
+ # Execute the batch rendering command.
20
+ #
21
+ # @return [void]
22
+ def run
23
+ input_path = options[:input] || '.'
24
+ output_path = options[:output] || 'output'
25
+
26
+ puts "Sirena Batch Renderer"
27
+ puts "=" * 60
28
+ puts "Input: #{input_path}"
29
+ puts "Output: #{output_path}"
30
+ puts "Theme: #{options[:theme] || 'default'}"
31
+ puts
32
+
33
+ files = find_mermaid_files(input_path)
34
+
35
+ if files.empty?
36
+ puts "No .mmd files found in: #{input_path}"
37
+ return
38
+ end
39
+
40
+ puts "Found #{files.length} diagram files"
41
+ puts
42
+
43
+ FileUtils.mkdir_p(output_path)
44
+
45
+ files.each_with_index do |file, idx|
46
+ process_file(file, input_path, output_path, idx + 1, files.length)
47
+ end
48
+
49
+ print_summary
50
+ end
51
+
52
+ private
53
+
54
+ def find_mermaid_files(path)
55
+ if File.directory?(path)
56
+ Dir.glob(File.join(path, '**', '*.mmd'))
57
+ elsif File.file?(path)
58
+ [path]
59
+ else
60
+ []
61
+ end
62
+ end
63
+
64
+ def process_file(file, input_base, output_base, current, total)
65
+ # Calculate relative path
66
+ relative = file.sub(/^#{Regexp.escape(input_base)}\/?/, '')
67
+ output_file = File.join(output_base, relative.sub(/\.mmd$/, '.svg'))
68
+
69
+ print "[#{current}/#{total}] #{relative}... "
70
+
71
+ begin
72
+ source = File.read(file)
73
+ svg = Sirena.render(source,
74
+ theme: options[:theme],
75
+ verbose: options[:verbose])
76
+
77
+ FileUtils.mkdir_p(File.dirname(output_file))
78
+ File.write(output_file, svg)
79
+
80
+ @stats[:success] += 1
81
+ puts "✅"
82
+ rescue => e
83
+ @stats[:failed] += 1
84
+ @stats[:errors] << { file: relative, error: e.message }
85
+ puts "❌ #{e.class.name}"
86
+ puts " #{e.message}" if options[:verbose]
87
+ end
88
+ end
89
+
90
+ def print_summary
91
+ puts "\n" + "=" * 60
92
+ puts "BATCH RENDERING SUMMARY"
93
+ puts "=" * 60
94
+ puts "✅ Success: #{@stats[:success]}"
95
+ puts "❌ Failed: #{@stats[:failed]}"
96
+ puts " Total: #{@stats[:success] + @stats[:failed]}"
97
+
98
+ if @stats[:failed] > 0
99
+ puts "\nErrors:"
100
+ @stats[:errors].first(5).each do |err|
101
+ puts " #{err[:file]}: #{err[:error].lines.first.strip}"
102
+ end
103
+ if @stats[:errors].length > 5
104
+ puts " ... and #{@stats[:errors].length - 5} more errors"
105
+ end
106
+ puts "\nUse --verbose to see full error details"
107
+ end
108
+
109
+ if @stats[:success] + @stats[:failed] > 0
110
+ success_rate = (@stats[:success].to_f /
111
+ (@stats[:success] + @stats[:failed]) * 100).round(1)
112
+ puts "\nSuccess rate: #{success_rate}%"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sirena
4
+ module Commands
5
+ # Command to render Mermaid diagrams to SVG.
6
+ class RenderCommand
7
+ attr_reader :file, :options
8
+
9
+ # Creates a new render command.
10
+ #
11
+ # @param file [String] input file path or '-' for stdin
12
+ # @param options [Hash] command options
13
+ def initialize(file, options = {})
14
+ @file = file
15
+ @options = options
16
+ end
17
+
18
+ # Executes the render command.
19
+ #
20
+ # @return [void]
21
+ def run
22
+ validate_format!
23
+
24
+ source = read_input
25
+ engine = Engine.new(
26
+ verbose: options[:verbose],
27
+ theme: options[:theme]
28
+ )
29
+ svg = engine.render(source)
30
+
31
+ write_output(svg)
32
+ end
33
+
34
+ private
35
+
36
+ # Validates the output format option.
37
+ #
38
+ # @return [void]
39
+ # @raise [ArgumentError] if format is not supported
40
+ def validate_format!
41
+ return if options[:format] == 'svg'
42
+
43
+ raise ArgumentError,
44
+ "Unsupported format: #{options[:format]}. " \
45
+ 'Only SVG format is currently supported.'
46
+ end
47
+
48
+ # Reads input from file or stdin.
49
+ #
50
+ # @return [String] Mermaid source code
51
+ def read_input
52
+ if file == '-' || file.nil?
53
+ $stdin.read
54
+ else
55
+ File.read(file)
56
+ end
57
+ rescue Errno::ENOENT
58
+ raise ArgumentError, "File not found: #{file}"
59
+ rescue Errno::EACCES
60
+ raise ArgumentError, "Permission denied: #{file}"
61
+ end
62
+
63
+ # Writes output to file or stdout.
64
+ #
65
+ # @param svg [String] SVG content
66
+ # @return [void]
67
+ def write_output(svg)
68
+ if options[:output]
69
+ File.write(options[:output], svg)
70
+ puts "SVG written to #{options[:output]}" if options[:verbose]
71
+ else
72
+ puts svg
73
+ end
74
+ rescue Errno::EACCES
75
+ raise ArgumentError,
76
+ "Permission denied writing to: #{options[:output]}"
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sirena
4
+ module Commands
5
+ # Command to list supported diagram types.
6
+ class TypesCommand
7
+ attr_reader :options
8
+
9
+ # Creates a new types command.
10
+ #
11
+ # @param options [Hash] command options
12
+ def initialize(options = {})
13
+ @options = options
14
+ end
15
+
16
+ # Executes the types command.
17
+ #
18
+ # @return [void]
19
+ def run
20
+ puts 'Supported diagram types:'
21
+ puts
22
+
23
+ DiagramRegistry.types.each do |type|
24
+ puts " #{type}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sirena
4
+ module Commands
5
+ # Command to display the gem version.
6
+ class VersionCommand
7
+ attr_reader :options
8
+
9
+ # Creates a new version command.
10
+ #
11
+ # @param options [Hash] command options
12
+ def initialize(options = {})
13
+ @options = options
14
+ end
15
+
16
+ # Executes the version command.
17
+ #
18
+ # @return [void]
19
+ def run
20
+ puts "sirena version #{Sirena::VERSION}"
21
+ end
22
+ end
23
+ end
24
+ end