drawio_dsl 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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"