drawio_dsl 0.3.0 → 0.4.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/.templates/command.rb +8 -0
  3. data/.builders/.templates/schema_shape.rb +9 -0
  4. data/.builders/blueprint/shapes.rb +19 -0
  5. data/.builders/boot.rb +1 -0
  6. data/.builders/generators/25-themes.rb +3 -0
  7. data/CHANGELOG.md +7 -0
  8. data/lib/drawio_dsl/configuration.rb +36 -27
  9. data/lib/drawio_dsl/dom_builder.rb +15 -0
  10. data/lib/drawio_dsl/drawio.rb +19 -1
  11. data/lib/drawio_dsl/layout_engine.rb +1 -1
  12. data/lib/drawio_dsl/schema/_.rb +23 -0
  13. data/lib/drawio_dsl/schema/common_style.rb +42 -0
  14. data/lib/drawio_dsl/schema/default_palette.rb +31 -0
  15. data/lib/drawio_dsl/schema/diagram.rb +57 -0
  16. data/lib/drawio_dsl/schema/layouts/flex_layout.rb +87 -0
  17. data/lib/drawio_dsl/schema/layouts/grid_layout.rb +102 -0
  18. data/lib/drawio_dsl/schema/layouts/layout.rb +41 -0
  19. data/lib/drawio_dsl/schema/node.rb +53 -0
  20. data/lib/drawio_dsl/schema/page.rb +135 -0
  21. data/lib/drawio_dsl/schema/shapes/callout.rb +9 -0
  22. data/lib/drawio_dsl/schema/shapes/circle.rb +9 -0
  23. data/lib/drawio_dsl/schema/shapes/cloud.rb +9 -0
  24. data/lib/drawio_dsl/schema/shapes/diamond.rb +9 -0
  25. data/lib/drawio_dsl/schema/shapes/ellipse.rb +9 -0
  26. data/lib/drawio_dsl/schema/shapes/hexagon.rb +9 -0
  27. data/lib/drawio_dsl/schema/shapes/note.rb +9 -0
  28. data/lib/drawio_dsl/schema/shapes/process.rb +9 -0
  29. data/lib/drawio_dsl/schema/shapes/rectangle.rb +9 -0
  30. data/lib/drawio_dsl/schema/shapes/shape.rb +125 -0
  31. data/lib/drawio_dsl/schema/shapes/square.rb +9 -0
  32. data/lib/drawio_dsl/version.rb +1 -1
  33. data/lib/drawio_dsl.rb +1 -1
  34. data/package-lock.json +2 -2
  35. data/package.json +1 -1
  36. metadata +25 -3
  37. data/lib/drawio_dsl/schema.rb +0 -617
@@ -1,617 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DrawioDsl
4
- module Schema
5
- # Common Style is the reused on Diagram, Page and Shape
6
- #
7
- # When styles are not provided at each level, then they will inherit from
8
- # the parent common style.
9
- #
10
- # Shapes will use the common style of their page
11
- class CommonStyle
12
- attr_accessor :theme
13
- attr_accessor :white_space
14
- attr_accessor :html
15
- attr_accessor :rounded
16
- attr_accessor :shadow
17
- attr_accessor :glass
18
- attr_accessor :sketch
19
-
20
- def initialize(**args, &block)
21
- @white_space = args[:white_space]
22
- @html = args[:html]
23
- @rounded = args[:rounded]
24
- @shadow = args[:shadow]
25
- @sketch = args[:sketch]
26
- @glass = args[:glass]
27
-
28
- instance_eval(&block) if block_given?
29
- end
30
-
31
- def to_h
32
- {
33
- white_space: white_space,
34
- html: html,
35
- rounded: rounded,
36
- shadow: shadow,
37
- sketch: sketch,
38
- glass: glass
39
- }
40
- end
41
- end
42
-
43
- # Default Palette contains palette information that can be inherited at each level
44
- class DefaultPalette
45
- attr_accessor :fill_color
46
- attr_accessor :stroke_color
47
- attr_accessor :font_color
48
- attr_accessor :gradient
49
-
50
- def initialize(owner, **args, &block)
51
- @fill_color = args[:fill_color]
52
- @stroke_color = args[:stroke_color]
53
- @font_color = args[:font_color]
54
- @gradient = args[:gradient]
55
-
56
- instance_exec(owner, &block) if block_given?
57
- end
58
-
59
- def to_h
60
- {
61
- fill_color: fill_color,
62
- stroke_color: stroke_color,
63
- font_color: font_color,
64
- gradient: gradient
65
- }
66
- end
67
- end
68
-
69
- # Diagram is the root of the schema, it contains pages
70
- class Diagram
71
- attr_accessor :host
72
- attr_accessor :theme
73
- attr_accessor :style
74
- attr_accessor :palette
75
- attr_accessor :pages
76
-
77
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
78
- def initialize(**args)
79
- @host = args[:host] || SecureRandom.alphanumeric(3)
80
-
81
- # Apply a random theme to the diagram if none is specified.
82
- @theme = args[:theme] || KConfig.configuration.drawio.random_theme
83
-
84
- @style = DrawioDsl::Schema::CommonStyle.new(**args) do
85
- default_style = KConfig.configuration.drawio.base_style
86
-
87
- # Inherit from configured style when specific style not specified.
88
- @white_space ||= default_style.white_space
89
- @html ||= default_style.html
90
- @rounded ||= default_style.rounded
91
- @shadow ||= default_style.shadow
92
- @sketch ||= default_style.sketch
93
- @glass ||= default_style.glass
94
- end
95
-
96
- @palette = DrawioDsl::Schema::DefaultPalette.new(self, **args) do |diagram|
97
- theme_palette = KConfig.configuration.drawio.palette(diagram.theme)
98
-
99
- # Inherit from theme when specific palette options are not specified.
100
- @fill_color ||= theme_palette.fill_color
101
- @stroke_color ||= theme_palette.stroke_color
102
- @font_color ||= theme_palette.font_color
103
- @gradient ||= theme_palette.gradient
104
- end
105
-
106
- @pages = args[:pages] || []
107
- end
108
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
109
-
110
- def to_h
111
- {
112
- host: host,
113
- theme: theme,
114
- palette: palette.to_h,
115
- style: style.to_h,
116
- pages: pages.map(&:to_h)
117
- }
118
- end
119
- end
120
-
121
- # Page is a container for nodes
122
- class Page
123
- attr_accessor :diagram
124
-
125
- # These transient attributes hold the current x, y location for the last element added to the page
126
- attr_accessor :position_x
127
- attr_accessor :position_y
128
-
129
- attr_accessor :id
130
- attr_accessor :name
131
- attr_accessor :theme
132
- attr_accessor :style
133
- attr_accessor :palette
134
- attr_accessor :margin_left
135
- attr_accessor :margin_top
136
- attr_accessor :nodes
137
-
138
- # attr_accessor :dx # dx = "2636"
139
- # attr_accessor :dy # dy = "2332"
140
- attr_accessor :grid # grid = "0"
141
- attr_accessor :grid_size # gridSize = "10"
142
- attr_accessor :guides # guides = "1"
143
- attr_accessor :tooltips # tooltips = "1"
144
- attr_accessor :connect # connect = "1"
145
- attr_accessor :arrows # arrows = "1"
146
- attr_accessor :fold # fold = "1"
147
- attr_accessor :page_no # page = "1"
148
- attr_accessor :page_scale # pageScale = "1"
149
- attr_accessor :page_width # pageWidth = "583"
150
- attr_accessor :page_height # pageHeight = "827"
151
- attr_accessor :background # background = "#FFFACD"
152
- attr_accessor :page_shadow # shadow = "0"
153
- attr_accessor :math # math = "0"
154
-
155
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
156
- def initialize(diagram, **args)
157
- @diagram = diagram
158
-
159
- @position_x = 0
160
- @position_y = 0
161
-
162
- @id = args[:id]
163
- @name = args[:name]
164
- @theme = args[:theme] || diagram.theme
165
- @margin_left = args[:margin_left] || 50
166
- @margin_top = args[:margin_top] || 50
167
-
168
- @grid = args[:grid] || 0
169
- @grid_size = args[:grid_size] || 10
170
- @guides = args[:guides] || 1
171
- @tooltips = args[:tooltips] || 1
172
- @connect = args[:connect] || 1
173
- @arrows = args[:arrows] || 1
174
- @fold = args[:fold] || 1
175
- @page_no = args[:page_no] || 1
176
- @page_scale = args[:page_scale] || 1
177
- @page_width = args[:page_width] || 1169 # A4
178
- @page_height = args[:page_height] || 827 # A4
179
- @background = args[:background] || '#FFFACD'
180
- @page_shadow = args[:page_shadow] || 0
181
- @math = args[:math] || 0
182
-
183
- @style = DrawioDsl::Schema::CommonStyle.new(**args) do
184
- # Inherit from the diagram style when specific style not specified.
185
- @white_space ||= diagram.style.white_space
186
- @html ||= diagram.style.html
187
- @rounded ||= diagram.style.rounded
188
- @shadow ||= diagram.style.shadow
189
- @sketch ||= diagram.style.sketch
190
- @glass ||= diagram.style.glass
191
- end
192
-
193
- @palette = DrawioDsl::Schema::DefaultPalette.new(self, **args) do |page|
194
- theme_palette = KConfig.configuration.drawio.palette(page.theme)
195
-
196
- # Inherit from theme when specific palette options are not specified.
197
- @fill_color ||= theme_palette.fill_color
198
- @stroke_color ||= theme_palette.stroke_color
199
- @font_color ||= theme_palette.font_color
200
- @gradient ||= theme_palette.gradient
201
- end
202
-
203
- @nodes = args[:nodes] || []
204
- end
205
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
206
-
207
- def to_h
208
- {
209
- id: id,
210
- name: name,
211
- theme: theme,
212
- palette: palette.to_h,
213
- style: style.to_h,
214
- margin_left: margin_left,
215
- margin_top: margin_top,
216
- position_x: position_x,
217
- position_y: position_y,
218
- nodes: nodes.map(&:to_h)
219
- }
220
- end
221
- end
222
-
223
- # Node is a base for shapes, connections, positioners and layout rules
224
- class Node
225
- attr_accessor :id
226
- attr_accessor :page
227
- attr_accessor :classification
228
-
229
- def initialize(page, **args)
230
- @page = page
231
- @id = args[:id]
232
- @classification = args[:classification] || :unknown
233
- end
234
-
235
- def to_h
236
- {
237
- id: id,
238
- classification: classification
239
- }
240
- end
241
-
242
- def debug(format: :detail)
243
- if format == :detail
244
- debug_detail(to_h)
245
- else
246
- debug_row(classification, id)
247
- end
248
- end
249
-
250
- def debug_detail(**key_values)
251
- key_values.each do |key, value|
252
- puts "#{key.to_s.ljust(15)}: #{value}"
253
- end
254
- end
255
-
256
- # rubocop:disable Metrics/AbcSize, Metrics/ParameterLists
257
- def debug_row(classification, id, type = nil, x = nil, y = nil, width = nil, height = nil)
258
- row = []
259
- row << classification.to_s.ljust(11)
260
- row << id.to_s.ljust(6)
261
- row << (type.nil? ? '' : type).to_s.ljust(15)
262
- row << (x.nil? ? '' : x).to_s.rjust(5)
263
- row << (y.nil? ? '' : y).to_s.rjust(5)
264
- row << (width.nil? ? '' : width).to_s.rjust(5)
265
- row << (height.nil? ? '' : height).to_s.rjust(5)
266
- puts row.join(' | ')
267
- end
268
- # rubocop:enable Metrics/AbcSize, Metrics/ParameterLists
269
- end
270
-
271
- # Provides base configuration for automatic layouts
272
- class LayoutRule < Node
273
- attr_accessor :type
274
-
275
- # represents the x coordinate of the top left corner layout area
276
- # this coordinate is based on the current location of the page
277
- attr_accessor :anchor_x
278
- attr_accessor :anchor_y
279
-
280
- def initialize(page, **args)
281
- @after_init_fired = false
282
-
283
- super(page, **args.merge(classification: :layout_rule))
284
- end
285
-
286
- def fire_after_init
287
- return if @after_init_fired
288
-
289
- @after_init_fired = true
290
- after_init
291
- end
292
-
293
- def after_init
294
- @anchor_x ||= page.position_x
295
- @anchor_y ||= page.position_y
296
- end
297
-
298
- def to_h
299
- super.merge(
300
- type: type,
301
- anchor_x: anchor_x,
302
- anchor_y: anchor_y
303
- )
304
- end
305
- end
306
-
307
- # Provides grid style layouts
308
- class GridLayout < LayoutRule
309
- attr_accessor :direction
310
- attr_accessor :wrap_at
311
- attr_accessor :grid_size
312
- attr_accessor :cell_no
313
- attr_accessor :h_align
314
- attr_accessor :v_align
315
-
316
- def initialize(page, **args)
317
- @type = :grid_layout
318
- @direction = args[:direction] || :horizontal
319
- @wrap_at = args[:wrap_at] || 5
320
- @grid_size = args[:grid_size] || 220
321
- @h_align = args[:h_align] || :center
322
- @v_align = args[:v_align] || :center
323
- @cell_no = 1
324
-
325
- super(page, **args)
326
- end
327
-
328
- def position_shape(shape)
329
- fire_after_init
330
-
331
- shape.x = horizontal_shape_alignment(shape)
332
- shape.y = vertical_shape_alignment(shape)
333
-
334
- # puts '------------------'
335
- # puts "cell: #{cell_no}"
336
- # puts "wrap_at: #{wrap_at}"
337
- # puts "shape-x: #{shape.x}"
338
- # puts "shape-y: #{shape.y}"
339
- # puts "page-x: #{page.position_x}"
340
- # puts "page-y: #{page.position_y}"
341
- # puts "anchor-x: #{anchor_x}"
342
- # puts "anchor-y: #{anchor_y}"
343
-
344
- move_cell_horizontally if direction == :horizontal
345
- move_cell_vertically if direction == :vertical
346
- end
347
-
348
- def to_h
349
- super.merge(
350
- direction: direction,
351
- wrap_at: wrap_at,
352
- grid_size: grid_size,
353
- cell_no: cell_no
354
- )
355
- end
356
-
357
- private
358
-
359
- # rubocop:disable Metrics/AbcSize
360
- def horizontal_shape_alignment(shape)
361
- return page.position_x + ((grid_size - shape.w) / 2) if h_align == :center
362
- return page.position_x + (grid_size - shape.w) if h_align == :right
363
-
364
- page.position_x
365
- end
366
- # rubocop:enable Metrics/AbcSize
367
-
368
- # rubocop:disable Metrics/AbcSize
369
- def vertical_shape_alignment(shape)
370
- return page.position_y + ((grid_size - shape.h) / 2) if v_align == :center || v_align == :middle
371
- return page.position_y + (grid_size - shape.h) if v_align == :bottom
372
-
373
- page.position_y
374
- end
375
- # rubocop:enable Metrics/AbcSize
376
-
377
- def move_cell_horizontally
378
- if cell_no < wrap_at
379
- page.position_x += grid_size
380
- @cell_no += 1
381
- return
382
- end
383
-
384
- # Flow down to the next row
385
- page.position_x = anchor_x
386
- page.position_y += grid_size
387
- @cell_no = 1
388
- end
389
-
390
- def move_cell_vertically
391
- if cell_no < wrap_at
392
- page.position_y += grid_size
393
- @cell_no += 1
394
- return
395
- end
396
-
397
- # Flow right to the next column
398
- page.position_y = anchor_y
399
- page.position_x += grid_size
400
- @cell_no = 1
401
- end
402
- end
403
-
404
- # Provides flex style layouts
405
- class FlexLayout < LayoutRule
406
- attr_accessor :direction
407
- attr_accessor :wrap_at
408
-
409
- def initialize(page, **args)
410
- @type = :flex_layout
411
- @direction = args[:direction] || :horizontal
412
- @wrap_at = args[:wrap_at] || (direction == :horizontal ? 1000 : 800)
413
-
414
- super(page, **args)
415
- end
416
-
417
- # rubocop:disable Metrics/AbcSize, Style/GuardClause
418
- def position_shape(shape)
419
- fire_after_init
420
-
421
- shape.x = page.position_x
422
- shape.y = page.position_y
423
-
424
- # Flow down to the next row
425
- if direction == :horizontal
426
- if page.position_x + shape.w > boundary
427
- page.position_x = anchor_x
428
- page.position_y += grid_size
429
- @cell_no = 0
430
- else
431
- page.position_x += grid_size
432
- end
433
- end
434
-
435
- # Flow right to the next column
436
- if direction == :vertical
437
- if page.position_y + shape.h > boundary
438
- page.position_y = anchor_y
439
- page.position_x += grid_size
440
- @cell_no = 0
441
- else
442
- page.position_y += grid_size
443
- end
444
- end
445
- end
446
- # rubocop:enable Metrics/AbcSize, Style/GuardClause
447
-
448
- private
449
-
450
- def boundary
451
- return @boundary if defined? @boundary
452
-
453
- bounds = grid_size * wrap_at
454
- @boundary = bounds + (direction == :horizontal ? anchor_x : anchor_y)
455
- end
456
-
457
- def to_h
458
- super.merge(direction: direction, wrap_at: wrap_at)
459
- end
460
- end
461
-
462
- # Shape is a graphical element, it can be a shape, a text, or a group (todo)
463
- class Shape < Node
464
- attr_accessor :theme
465
- attr_accessor :title
466
-
467
- # The style of the element, these will derive from the page style if not provided
468
- attr_accessor :white_space
469
- attr_accessor :html
470
- attr_accessor :rounded
471
- attr_accessor :shadow
472
- attr_accessor :glass
473
- attr_accessor :sketch
474
-
475
- attr_accessor :fill_color
476
- attr_accessor :stroke_color
477
- attr_accessor :font_color
478
- attr_accessor :gradient
479
-
480
- attr_accessor :type
481
- attr_accessor :x
482
- attr_accessor :y
483
- attr_accessor :w
484
- attr_accessor :h
485
- attr_accessor :style_modifiers
486
-
487
- def initialize(page, **args)
488
- args[:classification] = :shape
489
- super(page, **args)
490
-
491
- apply_defaults(args, KConfig.configuration.drawio.shape)
492
- end
493
-
494
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
495
- def apply_defaults(args, shape_defaults)
496
- @theme = args[:theme] || page.theme # KConfig.configuration.drawio.themes.sample
497
- theme_palette = KConfig.configuration.drawio.palette(theme)
498
- @title = args[:title] || ''
499
-
500
- @white_space = args[:white_space] || page.style.white_space # wrap or nil
501
- @html = args[:html] || page.style.html
502
- @rounded = args[:rounded] || page.style.rounded
503
- @shadow = args[:shadow] || page.style.shadow
504
- @sketch = args[:sketch] || page.style.sketch
505
- @glass = args[:glass] || page.style.glass
506
-
507
- @type = args[:type] || shape_defaults.type
508
- @x = args[:x] || shape_defaults.x
509
- @y = args[:y] || shape_defaults.y
510
- @w = args[:w] || shape_defaults.w
511
- @h = args[:h] || shape_defaults.h
512
- @style_modifiers = args[:style_modifiers] || shape_defaults.style_modifiers
513
-
514
- @fill_color = args[:fill_color] || theme_palette.fill_color
515
- @stroke_color = args[:stroke_color] || theme_palette.stroke_color
516
- @font_color = args[:font_color] || theme_palette.font_color
517
- @gradient = args[:gradient] || theme_palette.gradient
518
- end
519
-
520
- def style
521
- key_values = []
522
- key_values << style_modifiers unless style_modifiers.empty?
523
- key_values << "whiteSpace=#{white_space}" if white_space
524
- key_values << "html=#{html}" if html
525
- key_values << "rounded=#{rounded}" if rounded
526
- key_values << "shadow=#{shadow}" if shadow
527
- key_values << "sketch=#{sketch}" if sketch
528
- key_values << "glass=#{glass}" if glass
529
- key_values << "fillColor=#{fill_color}" if fill_color
530
- key_values << "strokeColor=#{stroke_color}" if stroke_color
531
- key_values << "fontColor=#{font_color}" if font_color
532
- key_values << "gradient=#{gradient}" if gradient
533
-
534
- key_values.join(';')
535
- end
536
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
537
-
538
- def to_h
539
- {
540
- id: id,
541
- classification: classification,
542
- type: type,
543
- x: x,
544
- y: y,
545
- w: w,
546
- h: h,
547
- style: style
548
- }
549
- end
550
-
551
- def debug(format: :detail)
552
- if format == :detail
553
- debug_detail({ id: id, classification: classification, type: type })
554
- else
555
- debug_row(classification, id, type, x, y, w, h)
556
- end
557
- end
558
- end
559
-
560
- class Square < Shape
561
- def initialize(page, **args)
562
- super(page, **args)
563
-
564
- apply_defaults(args, KConfig.configuration.drawio.square)
565
- end
566
- end
567
-
568
- class Rectangle < Shape
569
- def initialize(page, **args)
570
- super(page, **args)
571
-
572
- apply_defaults(args, KConfig.configuration.drawio.rectangle)
573
- end
574
- end
575
-
576
- class Circle < Shape
577
- def initialize(page, **args)
578
- super(page, **args)
579
-
580
- apply_defaults(args, KConfig.configuration.drawio.circle)
581
- end
582
- end
583
-
584
- class Process < Shape
585
- def initialize(page, **args)
586
- super(page, **args)
587
-
588
- apply_defaults(args, KConfig.configuration.drawio.process)
589
- end
590
- end
591
-
592
- class Ellipse < Shape
593
- def initialize(page, **args)
594
- super(page, **args)
595
-
596
- apply_defaults(args, KConfig.configuration.drawio.ellipse)
597
- end
598
- end
599
-
600
- class Diamond < Shape
601
- def initialize(page, **args)
602
- super(page, **args)
603
-
604
- apply_defaults(args, KConfig.configuration.drawio.diamond)
605
- end
606
- end
607
-
608
- class Hexagon < Shape
609
- def initialize(page, **args)
610
- super(page, **args)
611
-
612
- apply_defaults(args, KConfig.configuration.drawio.hexagon)
613
- end
614
- end
615
- end
616
- end
617
- # dx="800" dy="583" background="#FFFACD" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0"