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,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Group element <g>
9
+ #
10
+ # Groups multiple SVG elements together for collective transformation
11
+ # and styling. Implements the Composite pattern for hierarchical
12
+ # SVG structure.
13
+ class Group < Element
14
+ attribute :children, Element, collection: true
15
+
16
+ xml do
17
+ root 'g'
18
+ map_attribute 'id', to: :id
19
+ map_attribute 'class', to: :class_name
20
+ map_attribute 'transform', to: :transform
21
+ map_attribute 'fill', to: :fill
22
+ map_attribute 'stroke', to: :stroke
23
+ map_attribute 'stroke-width', to: :stroke_width
24
+ map_attribute 'opacity', to: :opacity
25
+
26
+ map_element 'g', to: :children
27
+ map_element 'rect', to: :children
28
+ map_element 'circle', to: :children
29
+ map_element 'ellipse', to: :children
30
+ map_element 'line', to: :children
31
+ map_element 'path', to: :children
32
+ map_element 'polygon', to: :children
33
+ map_element 'polyline', to: :children
34
+ map_element 'text', to: :children
35
+ end
36
+
37
+ def initialize(**args)
38
+ super(**args)
39
+ self.children ||= []
40
+ end
41
+
42
+ # Add a child element to this group
43
+ #
44
+ # @param element [Element] SVG element to add
45
+ # @return [void]
46
+ def add_child(element)
47
+ children << element
48
+ end
49
+
50
+ alias << add_child
51
+
52
+ # Generate XML with children
53
+ #
54
+ # @return [String] XML string
55
+ def to_xml
56
+ attrs = build_attributes
57
+
58
+ if children.empty?
59
+ "<g#{attrs}/>"
60
+ else
61
+ parts = ["<g#{attrs}>"]
62
+ children.each do |child|
63
+ parts << " #{child.to_xml}" if child.respond_to?(:to_xml)
64
+ end
65
+ parts << "</g>"
66
+ parts.join("\n")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Line element <line>
9
+ #
10
+ # Represents a straight line between two points.
11
+ class Line < Element
12
+ attribute :x1, :float
13
+ attribute :y1, :float
14
+ attribute :x2, :float
15
+ attribute :y2, :float
16
+ attribute :stroke_dasharray, :string
17
+
18
+ xml do
19
+ root 'line'
20
+ map_attribute 'id', to: :id
21
+ map_attribute 'class', to: :class_name
22
+ map_attribute 'x1', to: :x1
23
+ map_attribute 'y1', to: :y1
24
+ map_attribute 'x2', to: :x2
25
+ map_attribute 'y2', to: :y2
26
+ map_attribute 'stroke', to: :stroke
27
+ map_attribute 'stroke-width', to: :stroke_width
28
+ map_attribute 'stroke-dasharray', to: :stroke_dasharray
29
+ map_attribute 'transform', to: :transform
30
+ map_attribute 'opacity', to: :opacity
31
+ end
32
+
33
+ protected
34
+
35
+ # Hook for element-specific attributes
36
+ #
37
+ # @return [Array<String>] array of attribute strings
38
+ def element_attributes
39
+ attrs = []
40
+ attrs << %( x1="#{x1}") if x1
41
+ attrs << %( y1="#{y1}") if y1
42
+ attrs << %( x2="#{x2}") if x2
43
+ attrs << %( y2="#{y2}") if y2
44
+ attrs << %( stroke-dasharray="#{stroke_dasharray}") if stroke_dasharray
45
+ attrs
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Path element <path>
9
+ #
10
+ # Represents complex shapes and lines using SVG path data syntax.
11
+ # Commonly used for drawing edges in diagrams with curves and bend points.
12
+ class Path < Element
13
+ attribute :d, :string
14
+ attribute :stroke_dasharray, :string
15
+ attribute :stroke_linecap, :string
16
+ attribute :stroke_linejoin, :string
17
+ attribute :marker_end, :string
18
+ attribute :marker_start, :string
19
+
20
+ xml do
21
+ root 'path'
22
+ map_attribute 'id', to: :id
23
+ map_attribute 'class', to: :class_name
24
+ map_attribute 'd', to: :d
25
+ map_attribute 'fill', to: :fill
26
+ map_attribute 'stroke', to: :stroke
27
+ map_attribute 'stroke-width', to: :stroke_width
28
+ map_attribute 'stroke-dasharray', to: :stroke_dasharray
29
+ map_attribute 'stroke-linecap', to: :stroke_linecap
30
+ map_attribute 'stroke-linejoin', to: :stroke_linejoin
31
+ map_attribute 'marker-end', to: :marker_end
32
+ map_attribute 'marker-start', to: :marker_start
33
+ map_attribute 'transform', to: :transform
34
+ map_attribute 'opacity', to: :opacity
35
+ end
36
+
37
+ # Helper to build path data from move and line commands
38
+ #
39
+ # @param commands [Array<Hash>] Path commands
40
+ # @return [String] Path data string
41
+ def self.build_path_data(commands)
42
+ commands.map do |cmd|
43
+ case cmd[:type]
44
+ when :move
45
+ "M #{cmd[:x]} #{cmd[:y]}"
46
+ when :line
47
+ "L #{cmd[:x]} #{cmd[:y]}"
48
+ when :curve
49
+ "Q #{cmd[:cx]} #{cmd[:cy]} #{cmd[:x]} #{cmd[:y]}"
50
+ when :bezier
51
+ c1x = cmd[:c1x]
52
+ c1y = cmd[:c1y]
53
+ c2x = cmd[:c2x]
54
+ c2y = cmd[:c2y]
55
+ "C #{c1x} #{c1y} #{c2x} #{c2y} #{cmd[:x]} #{cmd[:y]}"
56
+ when :close
57
+ 'Z'
58
+ end
59
+ end.join(' ')
60
+ end
61
+
62
+ protected
63
+
64
+ def element_attributes
65
+ attrs = []
66
+ attrs << %( d="#{d}") if d
67
+ attrs << %( stroke-dasharray="#{stroke_dasharray}") if stroke_dasharray
68
+ attrs << %( stroke-linecap="#{stroke_linecap}") if stroke_linecap
69
+ attrs << %( stroke-linejoin="#{stroke_linejoin}") if stroke_linejoin
70
+ attrs << %( marker-end="#{marker_end}") if marker_end
71
+ attrs << %( marker-start="#{marker_start}") if marker_start
72
+ attrs
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Polygon element <polygon>
9
+ #
10
+ # Represents a closed shape defined by a series of points.
11
+ class Polygon < Element
12
+ attribute :points, :string
13
+
14
+ xml do
15
+ root 'polygon'
16
+ map_attribute 'id', to: :id
17
+ map_attribute 'class', to: :class_name
18
+ map_attribute 'points', to: :points
19
+ map_attribute 'fill', to: :fill
20
+ map_attribute 'stroke', to: :stroke
21
+ map_attribute 'stroke-width', to: :stroke_width
22
+ map_attribute 'transform', to: :transform
23
+ map_attribute 'opacity', to: :opacity
24
+ end
25
+
26
+ # Helper to build points string from coordinates array
27
+ #
28
+ # @param coords [Array<Array>] Array of [x, y] coordinates
29
+ # @return [String] Points string for polygon
30
+ def self.build_points(coords)
31
+ coords.map { |x, y| "#{x},#{y}" }.join(' ')
32
+ end
33
+
34
+ protected
35
+
36
+ def element_attributes
37
+ attrs = []
38
+ attrs << %( points="#{points}") if points
39
+ attrs
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Polyline element <polyline>
9
+ #
10
+ # Represents an open shape defined by a series of connected points.
11
+ class Polyline < Element
12
+ attribute :points, :string
13
+
14
+ xml do
15
+ root 'polyline'
16
+ map_attribute 'id', to: :id
17
+ map_attribute 'class', to: :class_name
18
+ map_attribute 'points', to: :points
19
+ map_attribute 'fill', to: :fill
20
+ map_attribute 'stroke', to: :stroke
21
+ map_attribute 'stroke-width', to: :stroke_width
22
+ map_attribute 'transform', to: :transform
23
+ map_attribute 'opacity', to: :opacity
24
+ end
25
+
26
+ # Helper to build points string from coordinates array
27
+ #
28
+ # @param coords [Array<Array>] Array of [x, y] coordinates
29
+ # @return [String] Points string for polyline
30
+ def self.build_points(coords)
31
+ coords.map { |x, y| "#{x},#{y}" }.join(' ')
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Rectangle element <rect>
9
+ #
10
+ # Represents a rectangle shape with position, dimensions, and optional
11
+ # rounded corners.
12
+ class Rect < Element
13
+ attribute :x, :float
14
+ attribute :y, :float
15
+ attribute :width, :float
16
+ attribute :height, :float
17
+ attribute :rx, :float
18
+ attribute :ry, :float
19
+ attribute :stroke_dasharray, :string
20
+ attribute :fill_opacity, :string
21
+
22
+ xml do
23
+ root 'rect'
24
+ map_attribute 'id', to: :id
25
+ map_attribute 'class', to: :class_name
26
+ map_attribute 'x', to: :x
27
+ map_attribute 'y', to: :y
28
+ map_attribute 'width', to: :width
29
+ map_attribute 'height', to: :height
30
+ map_attribute 'rx', to: :rx
31
+ map_attribute 'ry', to: :ry
32
+ map_attribute 'fill', to: :fill
33
+ map_attribute 'fill-opacity', to: :fill_opacity
34
+ map_attribute 'stroke', to: :stroke
35
+ map_attribute 'stroke-width', to: :stroke_width
36
+ map_attribute 'stroke-dasharray', to: :stroke_dasharray
37
+ map_attribute 'transform', to: :transform
38
+ map_attribute 'opacity', to: :opacity
39
+ end
40
+
41
+ protected
42
+
43
+ def element_attributes
44
+ attrs = []
45
+ attrs << %( x="#{x}") if x
46
+ attrs << %( y="#{y}") if y
47
+ attrs << %( width="#{width}") if width
48
+ attrs << %( height="#{height}") if height
49
+ attrs << %( rx="#{rx}") if rx
50
+ attrs << %( ry="#{ry}") if ry
51
+ attrs << %( stroke-dasharray="#{stroke_dasharray}") if stroke_dasharray
52
+ attrs << %( fill-opacity="#{fill_opacity}") if fill_opacity
53
+ attrs
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+
5
+ module Sirena
6
+ module Svg
7
+ # Represents CSS styling for SVG elements
8
+ #
9
+ # Encapsulates style properties that can be applied to SVG elements
10
+ # as inline styles or style attributes.
11
+ class Style < Lutaml::Model::Serializable
12
+ attribute :fill, :string
13
+ attribute :stroke, :string
14
+ attribute :stroke_width, :float
15
+ attribute :stroke_dasharray, :string
16
+ attribute :opacity, :float
17
+ attribute :fill_opacity, :float
18
+ attribute :stroke_opacity, :float
19
+ attribute :font_family, :string
20
+ attribute :font_size, :float
21
+ attribute :font_weight, :string
22
+ attribute :text_anchor, :string
23
+
24
+ # Convert style to CSS string for inline style attribute
25
+ #
26
+ # @return [String] CSS style string
27
+ def to_css
28
+ properties = []
29
+ properties << "fill:#{fill}" if fill
30
+ properties << "stroke:#{stroke}" if stroke
31
+ properties << "stroke-width:#{stroke_width}" if stroke_width
32
+ properties << "stroke-dasharray:#{stroke_dasharray}" if stroke_dasharray
33
+ properties << "opacity:#{opacity}" if opacity
34
+ properties << "fill-opacity:#{fill_opacity}" if fill_opacity
35
+ properties << "stroke-opacity:#{stroke_opacity}" if stroke_opacity
36
+ properties << "font-family:#{font_family}" if font_family
37
+ properties << "font-size:#{font_size}" if font_size
38
+ properties << "font-weight:#{font_weight}" if font_weight
39
+ properties << "text-anchor:#{text_anchor}" if text_anchor
40
+ properties.join(';')
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lutaml/model'
4
+ require_relative 'element'
5
+
6
+ module Sirena
7
+ module Svg
8
+ # SVG Text element <text>
9
+ #
10
+ # Displays text content at specified coordinates with optional styling
11
+ # and anchoring. Used for labels, annotations, and textual content.
12
+ class Text < Element
13
+ attribute :x, :float
14
+ attribute :y, :float
15
+ attribute :dx, :float
16
+ attribute :dy, :float
17
+ attribute :text_anchor, :string
18
+ attribute :font_family, :string
19
+ attribute :font_size, :string
20
+ attribute :font_weight, :string
21
+ attribute :font_style, :string
22
+ attribute :dominant_baseline, :string
23
+ attribute :content, :string
24
+
25
+ xml do
26
+ root 'text', mixed: true
27
+ map_attribute 'id', to: :id
28
+ map_attribute 'class', to: :class_name
29
+ map_attribute 'x', to: :x
30
+ map_attribute 'y', to: :y
31
+ map_attribute 'dx', to: :dx
32
+ map_attribute 'dy', to: :dy
33
+ map_attribute 'text-anchor', to: :text_anchor
34
+ map_attribute 'font-family', to: :font_family
35
+ map_attribute 'font-size', to: :font_size
36
+ map_attribute 'font-weight', to: :font_weight
37
+ map_attribute 'font-style', to: :font_style
38
+ map_attribute 'fill', to: :fill
39
+ map_attribute 'stroke', to: :stroke
40
+ map_attribute 'stroke-width', to: :stroke_width
41
+ map_attribute 'transform', to: :transform
42
+ map_attribute 'opacity', to: :opacity
43
+ map_attribute 'dominant-baseline', to: :dominant_baseline
44
+
45
+ map_content to: :content
46
+ end
47
+
48
+ # Override to_xml to include text content
49
+ def to_xml
50
+ attrs = build_attributes
51
+ "<text#{attrs}>#{content}</text>"
52
+ end
53
+
54
+ protected
55
+
56
+ def element_attributes
57
+ attrs = []
58
+ attrs << %( x="#{x}") if x
59
+ attrs << %( y="#{y}") if y
60
+ attrs << %( dx="#{dx}") if dx
61
+ attrs << %( dy="#{dy}") if dy
62
+ attrs << %( text-anchor="#{text_anchor}") if text_anchor
63
+ attrs << %( font-family="#{font_family}") if font_family
64
+ attrs << %( font-size="#{font_size}") if font_size
65
+ attrs << %( font-weight="#{font_weight}") if font_weight
66
+ attrs << %( font-style="#{font_style}") if font_style
67
+ attrs << %( dominant-baseline="#{dominant_baseline}") if dominant_baseline
68
+ attrs
69
+ end
70
+ end
71
+ end
72
+ end
data/lib/sirena/svg.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'svg/style'
4
+ require_relative 'svg/element'
5
+ require_relative 'svg/document'
6
+ require_relative 'svg/group'
7
+ require_relative 'svg/rect'
8
+ require_relative 'svg/circle'
9
+ require_relative 'svg/path'
10
+ require_relative 'svg/line'
11
+ require_relative 'svg/polygon'
12
+ require_relative 'svg/polyline'
13
+ require_relative 'svg/text'
14
+ require_relative 'svg/ellipse'
15
+
16
+ module Sirena
17
+ module Svg
18
+ end
19
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sirena
4
+ # Provides text dimension calculation for layout purposes.
5
+ #
6
+ # This utility calculates approximate text dimensions using character-based
7
+ # estimates, avoiding the need for font metrics libraries. The dimensions
8
+ # are used by the layout engine to size diagram nodes appropriately.
9
+ #
10
+ # @example Basic usage
11
+ # dims = TextMeasurement.measure("Hello World", font_size: 14)
12
+ # # => { width: 77.0, height: 14.0 }
13
+ #
14
+ # @example With dimension overrides
15
+ # dims = TextMeasurement.measure("Text", font_size: 12,
16
+ # width: 100, height: 20)
17
+ # # => { width: 100, height: 20 }
18
+ class TextMeasurement
19
+ # Average character width as ratio of font size
20
+ AVERAGE_CHAR_WIDTH_RATIO = 0.5
21
+
22
+ # Text height as ratio of font size
23
+ HEIGHT_RATIO = 1.0
24
+
25
+ # Measures the approximate dimensions of text.
26
+ #
27
+ # @param text [String] the text to measure
28
+ # @param font_size [Numeric] the font size in points
29
+ # @param width [Numeric, nil] optional width override
30
+ # @param height [Numeric, nil] optional height override
31
+ # @return [Hash] hash with :width and :height keys
32
+ #
33
+ # @example Basic measurement
34
+ # TextMeasurement.measure("Hello", font_size: 14)
35
+ # # => { width: 35.0, height: 14.0 }
36
+ #
37
+ # @example With overrides
38
+ # TextMeasurement.measure("Hi", font_size: 14, width: 50)
39
+ # # => { width: 50, height: 14.0 }
40
+ def self.measure(text, font_size:, width: nil, height: nil)
41
+ calculated_width = calculate_width(text, font_size)
42
+ calculated_height = calculate_height(font_size)
43
+
44
+ {
45
+ width: width || calculated_width,
46
+ height: height || calculated_height
47
+ }
48
+ end
49
+
50
+ # Calculates the width of text.
51
+ #
52
+ # @param text [String] the text to measure
53
+ # @param font_size [Numeric] the font size in points
54
+ # @return [Float] the calculated width
55
+ def self.calculate_width(text, font_size)
56
+ char_count = text.to_s.length
57
+ avg_char_width = font_size * AVERAGE_CHAR_WIDTH_RATIO
58
+ char_count * avg_char_width
59
+ end
60
+
61
+ # Calculates the height of text.
62
+ #
63
+ # @param font_size [Numeric] the font size in points
64
+ # @return [Float] the calculated height
65
+ def self.calculate_height(font_size)
66
+ font_size * HEIGHT_RATIO
67
+ end
68
+
69
+ private_class_method :calculate_width, :calculate_height
70
+ end
71
+ end
@@ -0,0 +1,70 @@
1
+ name: dark
2
+ description: "Dark theme optimized for low-light environments"
3
+
4
+ colors:
5
+ background: "#1e1e1e"
6
+ surface: "#2d2d30"
7
+ surface_variant: "#3e3e42"
8
+
9
+ foreground: "#d4d4d4"
10
+ foreground_secondary: "#969696"
11
+
12
+ primary: "#3794ff"
13
+ secondary: "#858585"
14
+ accent: "#4ec9b0"
15
+ error: "#f48771"
16
+ warning: "#dcdcaa"
17
+ success: "#89d185"
18
+ info: "#9cdcfe"
19
+
20
+ node_fill: "#2d2d30"
21
+ node_stroke: "#858585"
22
+ edge_stroke: "#858585"
23
+ label_text: "#d4d4d4"
24
+
25
+ hover_fill: "#3e3e42"
26
+ active_fill: "#505050"
27
+ disabled_fill: "#404040"
28
+
29
+ typography:
30
+ font_family: "Arial, Helvetica, sans-serif"
31
+ font_family_monospace: "Courier New, monospace"
32
+ font_size_small: 12.0
33
+ font_size_normal: 14.0
34
+ font_size_large: 16.0
35
+ font_size_title: 20.0
36
+ font_weight_normal: "normal"
37
+ font_weight_bold: "bold"
38
+ line_height: 1.5
39
+ text_transform: "none"
40
+
41
+ shapes:
42
+ stroke_width: 2.0
43
+ stroke_width_thick: 3.0
44
+ stroke_width_thin: 1.0
45
+ fill_opacity: 1.0
46
+ stroke_opacity: 1.0
47
+ corner_radius: 5.0
48
+ corner_radius_large: 10.0
49
+ dash_pattern_dotted: "2,2"
50
+ dash_pattern_dashed: "5,5"
51
+
52
+ spacing:
53
+ node_padding_x: 10.0
54
+ node_padding_y: 5.0
55
+ node_margin: 20.0
56
+ edge_spacing: 10.0
57
+ edge_label_offset: 5.0
58
+ rank_spacing: 100.0
59
+ node_spacing: 50.0
60
+
61
+ effects:
62
+ shadow_enabled: true
63
+ shadow_color: "#00000066"
64
+ shadow_blur: 8.0
65
+ shadow_offset_x: 3.0
66
+ shadow_offset_y: 3.0
67
+ gradient_enabled: false
68
+ gradient_type: "linear"
69
+ arrow_size: 10.0
70
+ arrow_style: "filled"
@@ -0,0 +1,80 @@
1
+ name: default
2
+ description: "Sirena default theme with clean, professional styling"
3
+
4
+ colors:
5
+ background: "#ffffff"
6
+ surface: "#f5f5f5"
7
+ surface_variant: "#e0e0e0"
8
+
9
+ foreground: "#000000"
10
+ foreground_secondary: "#666666"
11
+
12
+ primary: "#007bff"
13
+ secondary: "#6c757d"
14
+ accent: "#28a745"
15
+ error: "#dc3545"
16
+ warning: "#ffc107"
17
+ success: "#28a745"
18
+ info: "#17a2b8"
19
+
20
+ node_fill: "#ffffff"
21
+ node_stroke: "#000000"
22
+ edge_stroke: "#000000"
23
+ label_text: "#000000"
24
+
25
+ hover_fill: "#f0f0f0"
26
+ active_fill: "#e0e0e0"
27
+ disabled_fill: "#cccccc"
28
+
29
+ typography:
30
+ font_family: "Arial, Helvetica, sans-serif"
31
+ font_family_monospace: "Courier New, monospace"
32
+
33
+ font_size_small: 12.0
34
+ font_size_normal: 14.0
35
+ font_size_large: 16.0
36
+ font_size_title: 20.0
37
+
38
+ font_weight_normal: "normal"
39
+ font_weight_bold: "bold"
40
+
41
+ line_height: 1.5
42
+ text_transform: "none"
43
+
44
+ shapes:
45
+ stroke_width: 2.0
46
+ stroke_width_thick: 3.0
47
+ stroke_width_thin: 1.0
48
+
49
+ fill_opacity: 1.0
50
+ stroke_opacity: 1.0
51
+
52
+ corner_radius: 5.0
53
+ corner_radius_large: 10.0
54
+
55
+ dash_pattern_dotted: "2,2"
56
+ dash_pattern_dashed: "5,5"
57
+
58
+ spacing:
59
+ node_padding_x: 10.0
60
+ node_padding_y: 5.0
61
+ node_margin: 20.0
62
+
63
+ edge_spacing: 10.0
64
+ edge_label_offset: 5.0
65
+
66
+ rank_spacing: 100.0
67
+ node_spacing: 50.0
68
+
69
+ effects:
70
+ shadow_enabled: false
71
+ shadow_color: "#00000033"
72
+ shadow_blur: 5.0
73
+ shadow_offset_x: 2.0
74
+ shadow_offset_y: 2.0
75
+
76
+ gradient_enabled: false
77
+ gradient_type: "linear"
78
+
79
+ arrow_size: 10.0
80
+ arrow_style: "filled"