diagrammatron 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f620125fb02691c986e3f340cc3248fbab02ecc99cd075ed9b0a9dfd2159a541
4
- data.tar.gz: b384432f4b082379eedce471810cd8ad011bc1e016dc5410c00b99e3b1187b70
3
+ metadata.gz: 393c2881f870f2371e5af2e9a33fcfac3f82d9c3da69f7f377d87606b7230557
4
+ data.tar.gz: '019f726f35066af4fc209d61a2adbf36de1c6393d0089924912ca6c0e73baef0'
5
5
  SHA512:
6
- metadata.gz: edd885e247f16df32a67c6524cbfabfddaf9c6901fce6104c373fb6c7bd107c734fb275be133c09f06f128bade0bd34e9c626f87e14e097b580817a970277020
7
- data.tar.gz: 3b7febb11202fc30fd0ba522d276e6f41ab4c25d72b2bf468c11ce8bd4b7f3c27001e7520e3e68705518e4b5646bb6708152ab766059cbd6b646f10b703e272c
6
+ metadata.gz: 737105dcbe2c8dc6d636833079d2313be3b5f2c66d86d252127664948365b92f976622b65019e9b5ddd1f7b760f35a15fef9e30fdd749fae99441a31fb03bb8e
7
+ data.tar.gz: c091a6a5f862353afb8f730dbf8b35cf226c5627e6d352f1ad8366ca6d03cb338e61264c22876948806afdc0965f1df0ee81223f07750f61c73a8cd171ab0538
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 Ismo Kärkkäinen
1
+ Copyright (c) 2021-2023 Ismo Kärkkäinen
2
2
 
3
3
  The Universal Permissive License (UPL), Version 1.0
4
4
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Copyright © 2021, 2022 Ismo Kärkkäinen
4
+ # Copyright © 2021-2023 Ismo Kärkkäinen
5
5
  # Licensed under Universal Permissive License. See LICENSE.txt.
6
6
 
7
7
  require_relative '../lib/common'
@@ -443,97 +443,11 @@ def segment_order(a, b)
443
443
  a[0].edge_index <=> b[0].edge_index
444
444
  end
445
445
 
446
- GapState = Struct.new(:order, :cross_count, :lut) do
447
- def fitness(segments, k)
448
- table = lut[k]
449
- crossings = 0
450
- order.each do |n|
451
- crossings += table[n]
452
- end
453
- cross_count + crossings
454
- end
455
- end
456
-
457
- def candidate_compare(a, b)
458
- d = a[1] <=> b[1]
459
- return d unless d == 0
460
- a[0] <=> b[0]
461
- end
462
-
463
- def candidate_order(lut, used)
464
- # Compute crossing sums for all remaining segments among themselves.
465
- cands = []
466
- lut.keys.each do |k|
467
- next if used.include? k
468
- total = 0
469
- lut.each_pair do |idx, v|
470
- total += v[k] unless used.include? idx
471
- end
472
- cands.push([k, total])
473
- end
474
- cands.sort! { |a, b| candidate_compare(a, b) }
475
- cands.map { |a| a[0] }
476
- end
477
-
478
- def depth_first_search(segments, state, best)
479
- if state.order.size == segments.size
480
- $stderr.puts state.order.join(', '), state.cross_count
481
- return GapState.new(state.order.clone, state.cross_count, state.lut)
482
- end
483
- cands = candidate_order(state.lut, state.order)
484
- cands.each do |k|
485
- c = state.fitness(segments, k)
486
- next if (best.nil? ? c + 1 : best.cross_count) <= c
487
- state.order.push(k)
488
- best = depth_first_search(segments, GapState.new(state.order, c, state.lut), best)
489
- state.order.pop
490
- end
491
- best
492
- end
493
-
494
446
  def zigzag_order(from_right_up_to_left, from_left_up_to_right)
495
- # Interleave the two sets.
447
+ # Eventually interleave the two sets, if it makes sense.
496
448
  out = []
497
449
  from_right_up_to_left.each { |x| out.push x }
498
450
  from_left_up_to_right.each { |x| out.push x }
499
- return out
500
- return segments if segments.size < 2
501
- # DFS. Fitness is how many end segments cross the placed segments.
502
- # Sort so that those that cross least when at start are first and vice versa.
503
- lut = {}
504
- segments.each_index do |k|
505
- crossings = Hash.new(0)
506
- lut[k] = crossings
507
- s = segments[k]
508
- prev = (s[1] == 1) ? s[2].range.max : s[2].range.min
509
- segments.each_index do |n|
510
- next if k == n
511
- other = segments[n]
512
- if other[2].range.min <= prev && prev <= other[2].range.max
513
- crossings[n] = crossings[n] + 1
514
- end
515
- v = (other[1] == 1) ? other[2].range.min : other[2].range.max
516
- if s[2].range.min <= v && v <= s[2].range.max
517
- crossings[n] = crossings[n] + 1
518
- end
519
- end
520
- end
521
- $stderr.puts segments.size, lut
522
- # Could take all crossings for k, sort, sum up to get minimum fitness for
523
- # used set size N ignoring what set has. Since real fitness can not be
524
- # lower, once minimal sum + cross_count exceeds best, we can not use that
525
- # segment in any later position and can cut off search.
526
- # Add to GapState after lut.
527
- # Also, coult set time budget for single search and terminate search.
528
- best = nil
529
- cands = candidate_order(lut, [])
530
- cands.each do |k|
531
- best = depth_first_search(segments, GapState.new([ k ], 0, lut), best)
532
- end
533
- out = []
534
- best.order.each do |k|
535
- out.push segments[k]
536
- end
537
451
  out
538
452
  end
539
453
 
@@ -717,10 +631,17 @@ def place_edges(work)
717
631
  end
718
632
  gaps.each_value do |direction|
719
633
  direction.each_value do |gap|
720
- gap.sort! { |a, b| segment_order(a, b) }
634
+ #gap.sort! { |a, b| segment_order(a, b) }
721
635
  gleft = gap.select { |a| a[1].zero? }
636
+ gleft.sort! { |a, b| segment_order(a, b) }
722
637
  gright = gap.select { |a| a[1] == 3 }
723
- gmiddle = zigzag_order(gap.select() { |a| a[1] == 1 }, gap.select() { |a| a[1] == 2 })
638
+ gright.sort! { |a, b| segment_order(a, b) }
639
+ gright.reverse!
640
+ grul = gap.select() { |a| a[1] == 1 }
641
+ grul.sort! { |a, b| segment_order(a, b) }
642
+ glur = gap.select() { |a| a[1] == 2 }
643
+ glur.sort! { |a, b| segment_order(a, b) }
644
+ gmiddle = zigzag_order(grul, glur)
724
645
  gmiddle.each do |s|
725
646
  s[1] = 1
726
647
  end
@@ -735,7 +656,7 @@ def place_edges(work)
735
656
  denominator = 1 + c[0]
736
657
  (1...c.size).each do |k|
737
658
  denominator += c[k]
738
- before[k] = c[k - 1] + before[k - 1]
659
+ before.push(c[k - 1] + before.last)
739
660
  end
740
661
  gap.each do |sg|
741
662
  sg[0].offset = c[sg[1]] + 1 - sg[0].offset if sg[1] > 1
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Copyright © 2021, 2022 Ismo Kärkkäinen
4
+ # Copyright © 2021-2023 Ismo Kärkkäinen
5
5
  # Licensed under Universal Permissive License. See LICENSE.txt.
6
6
 
7
7
  require_relative '../lib/common'
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Copyright © 2021, 2022 Ismo Kärkkäinen
4
+ # Copyright © 2021-2023 Ismo Kärkkäinen
5
5
  # Licensed under Universal Permissive License. See LICENSE.txt.
6
6
 
7
7
  require_relative '../lib/common'
@@ -78,8 +78,12 @@ end
78
78
 
79
79
  class Styles
80
80
  def base_styles(m, styles, group)
81
- d = styles.dig(group, 'default') || {}
82
- m['default'] = m.fetch('default', {}).merge(d)
81
+ d = styles.dig(group, 'default')
82
+ if d.nil?
83
+ d = m.fetch('default', {}) if d.nil?
84
+ else
85
+ m['default'] = m.fetch('default', {}).merge(d)
86
+ end
83
87
  styles.fetch(group, {}).each_pair do |name, values|
84
88
  s = d.clone
85
89
  s.merge!(values) unless name == 'default'
@@ -107,7 +111,7 @@ class Styles
107
111
  end
108
112
  s.merge!(mapping['default']) unless found # Merge default at least.
109
113
  # Keep values specified explicitly.
110
- item.merge!(s) {|key, existing, from_template| existing }
114
+ item.merge!(s) { |key, existing, from_template| existing || from_template }
111
115
  end
112
116
 
113
117
  def apply_node_styles(node)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Copyright © 2021, 2022 Ismo Kärkkäinen
4
+ # Copyright © 2021-2023 Ismo Kärkkäinen
5
5
  # Licensed under Universal Permissive License. See LICENSE.txt.
6
6
 
7
7
  require_relative '../lib/common'
@@ -21,11 +21,15 @@ def add_field(doc, field_name, content)
21
21
  end
22
22
 
23
23
  def missing(doc)
24
- %w[template].each do |key|
24
+ %w[template styles].each do |key|
25
25
  next if doc.key? key
26
26
  next if doc.key? "base64#{key}"
27
27
  return aargh("#{key} is missing", 4)
28
28
  end
29
+ %w[node edge diagram].each do |key|
30
+ v = doc.dig('styles', key, 'default')
31
+ return aargh("styles #{key} default is missing", 4) if v.nil?
32
+ end
29
33
  nil
30
34
  end
31
35
 
@@ -50,15 +54,24 @@ def main
50
54
  Pairs all parameter field-names with content-files contents, starting with
51
55
  either given root YAML file or with an empty root.
52
56
 
53
- Any field name either in root document or in parameters is trusted to be
54
- base-64 encoded without further checking.
55
-
56
57
  Outputs a YAML-file that case be used with diagrammatron-render as a template.
57
58
  All fields are base64-encoded for safety. diagrammatron-render will decode
58
59
  them and rename the fields by removing the base64 prefix.
59
60
 
60
- Presence of "defaults", "sizes", and "template" fields is checked for.
61
+ Root document is expected to have at least the following:
62
+ styles:
63
+ node:
64
+ defaults: {}
65
+ edge:
66
+ defaults: {}
67
+ diagram:
68
+ defaults: {}
69
+
70
+ Presence of "template" field is checked for.
61
71
  Extra fields are not restricted in any manner.
72
+
73
+ Any field name in parameters starting with "base64" is trusted to be base-64
74
+ encoded without further checking.
62
75
  )
63
76
  exit 0
64
77
  end
@@ -29,4 +29,4 @@ styles:
29
29
  default:
30
30
  stroke_width: 2
31
31
  stroke: "#000000"
32
- base64template: PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwlPQp3LCBoaCA9ICRyZW5kZXIuZGltZW5zaW9ucwpoaCArPSAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnaGVpZ2h0X21hcmdpbicpCgpvdXQgPSBbCiAgJSg8c3ZnIHdpZHRoPSIje3cgKyAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnd2lkdGhfbWFyZ2luJyl9IiBoZWlnaHQ9IiN7aGh9IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiPikKXQokcmVuZGVyLmRvYy5mZXRjaCgnbm9kZXMnLCBbXSkuZWFjaCBkbyB8bm9kZXwKICB3ID0gbm9kZVsndyddLnRvX2kKICBoID0gbm9kZVsnaCddLnRvX2kKICB4ID0gbm9kZVsneG8nXS50b19pCiAgeSA9IGhoIC0gbm9kZVsneW8nXS50b19pIC0gaAogIG5vZGVzdHlsZSA9ICUoZmlsbD0iI3tub2RlWydmaWxsJ119IiBzdHJva2U9IiN7bm9kZVsnc3Ryb2tlJ119IiBzdHJva2Utd2lkdGg9IiN7bm9kZVsnc3Ryb2tlX3dpZHRoJ119IikKICBvdXQucHVzaCglKDxyZWN0ICN7bm9kZXN0eWxlfSBoZWlnaHQ9IiN7aH0iIHdpZHRoPSIje3d9IiB4PSIje3h9IiB5PSIje3l9Ii8+KSkKICB4ICs9IG5vZGVbJ3dpZHRoX21hcmdpbiddCiAgZnMgPSBub2RlWydmb250X3NpemUnXQogIGxoID0gZnMgKiAoMSArIG5vZGVbJ2ZvbnRfbGluZV9zcGFjaW5nJ10pCiAgeSArPSBub2RlWydoZWlnaHRfbWFyZ2luJ10gKyBmcyAqIG5vZGVbJ2ZvbnRfYXNjZW5kJ10gIyBCYXNlbGluZSBmb3IgZmlyc3QgbGluZS4KICB1cmwgPSBub2RlLmZldGNoKCd1cmwnLCBuaWwpCiAgdXJsLmVuY29kZSEoOnhtbCA9PiA6YXR0cikgdW5sZXNzIHVybC5uaWw/CiAgeTAgPSB5CiAgdGV4dHN0eWxlID0gJShmaWxsPSIje25vZGVbJ2ZvbnRfZmlsbCddfSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IiN7ZnN9IiBzdHJva2U9IiN7bm9kZVsnZm9udF9maWxsJ119IiBzdHJva2Utd2lkdGg9IjAiIHhtbDpzcGFjZT0icHJlc2VydmUiKQogIGxpbmtzdHlsZSA9ICUoZmlsbD0iI3tub2RlWyd1cmxfZmlsbCddfSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IiN7ZnN9IiBzdHJva2U9IiN7bm9kZVsndXJsX2ZpbGwnXX0iIHN0cm9rZS13aWR0aD0iMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIpCiAgbm9kZVsndGV4dCddLmVhY2ggZG8gfGxpbmV8CiAgICBsaW5lLmVuY29kZSEoOnhtbCA9PiA6dGV4dCkKICAgIGlmIHVybC5uaWw/CiAgICAgIG91dC5wdXNoKCUoPHRleHQgI3t0ZXh0c3R5bGV9IHg9IiN7eH0iIHk9IiN7eTB9Ij4je2xpbmV9PC90ZXh0PikpCiAgICBlbHNlCiAgICAgIG91dC5wdXNoKCUoPGEgeGxpbms6aHJlZj0je3VybH0gdGFyZ2V0PSJfcGFyZW50Ij48dGV4dCAje2xpbmtzdHlsZX0geD0iI3t4fSIgeT0iI3t5MH0iPiN7bGluZX08L3RleHQ+PC9hPikpCiAgICBlbmQKICAgIHkwICs9IGxoICMgU2hpZnQgYmFzZWxpbmUgYnkgZnVsbCBsaW5lICsgc3BhY2luZyBoZWlnaHQuCiAgZW5kCmVuZAokcmVuZGVyLmRvYy5mZXRjaCgnZWRnZXMnLCBbXSkuZWFjaCBkbyB8ZWRnZXwKICBsaW5lc3R5bGUgPSAlKGZpbGw9Im5vbmUiIHN0cm9rZT0iI3tlZGdlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tlZGdlWydzdHJva2Vfd2lkdGgnXX0iKQogIHBhdGggPSBlZGdlLmZldGNoKCdwYXRoJywgbmlsKQogIG5leHQgaWYgcGF0aC5uaWw/CiAgcGF0aC5lYWNoIGRvIHxwfAogICAgcFsneG8nXSA9IHBbJ3hvJ10udG9faS50b19zCiAgICBwWyd5byddID0gKGhoIC0gcFsneW8nXSkudG9faS50b19zCiAgZW5kCiAgaWYgcGF0aC5zaXplID09IDIKICAgIG91dC5wdXNoKCUoPGxpbmUgI3tsaW5lc3R5bGV9IHgxPSIje3BhdGhbMF1bJ3hvJ119IiB4Mj0iI3twYXRoWzFdWyd4byddfSIgeTE9IiN7cGF0aFswXVsneW8nXX0iIHkyPSIje3BhdGhbMV1bJ3lvJ119Ii8+KSkKICBlbHNlCiAgICBwdHMgPSBwYXRoLm1hcCB7IHxwfCAiI3twWyd4byddfSwje3BbJ3lvJ119IiB9CiAgICBvdXQucHVzaCglKDxwb2x5bGluZSAje2xpbmVzdHlsZX0gcG9pbnRzPSIje3B0cy5qb2luKCcgJyl9Ii8+KSkKICBlbmQKZW5kCm91dC5qb2luKCJcbiIpCiU+Cjwvc3ZnPgo=
32
+ base64template: PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwlPQp3LCBoaCA9ICRyZW5kZXIuZGltZW5zaW9ucwpoaCArPSAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnaGVpZ2h0X21hcmdpbicpCgpvdXQgPSBbCiAgJSg8c3ZnIHdpZHRoPSIje3cgKyAkcmVuZGVyLmRvYy5kaWcoJ2RpYWdyYW0nLCAnd2lkdGhfbWFyZ2luJyl9IiBoZWlnaHQ9IiN7aGh9IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiPikKXQokcmVuZGVyLmRvYy5mZXRjaCgnZWRnZXMnLCBbXSkuZWFjaCBkbyB8ZWRnZXwKICBsaW5lc3R5bGUgPSAlKGZpbGw9Im5vbmUiIHN0cm9rZT0iI3tlZGdlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tlZGdlWydzdHJva2Vfd2lkdGgnXX0iKQogIHBhdGggPSBlZGdlLmZldGNoKCdwYXRoJywgbmlsKQogIG5leHQgaWYgcGF0aC5uaWw/CiAgcGF0aC5lYWNoIGRvIHxwfAogICAgcFsneG8nXSA9IHBbJ3hvJ10udG9faS50b19zCiAgICBwWyd5byddID0gKGhoIC0gcFsneW8nXSkudG9faS50b19zCiAgZW5kCiAgaWYgcGF0aC5zaXplID09IDIKICAgIG91dC5wdXNoKCUoPGxpbmUgI3tsaW5lc3R5bGV9IHgxPSIje3BhdGhbMF1bJ3hvJ119IiB4Mj0iI3twYXRoWzFdWyd4byddfSIgeTE9IiN7cGF0aFswXVsneW8nXX0iIHkyPSIje3BhdGhbMV1bJ3lvJ119Ii8+KSkKICBlbHNlCiAgICBwdHMgPSBwYXRoLm1hcCB7IHxwfCAiI3twWyd4byddfSwje3BbJ3lvJ119IiB9CiAgICBvdXQucHVzaCglKDxwb2x5bGluZSAje2xpbmVzdHlsZX0gcG9pbnRzPSIje3B0cy5qb2luKCcgJyl9Ii8+KSkKICBlbmQKZW5kCiRyZW5kZXIuZG9jLmZldGNoKCdub2RlcycsIFtdKS5lYWNoIGRvIHxub2RlfAogIHcgPSBub2RlWyd3J10udG9faQogIGggPSBub2RlWydoJ10udG9faQogIHggPSBub2RlWyd4byddLnRvX2kKICB5ID0gaGggLSBub2RlWyd5byddLnRvX2kgLSBoCiAgbm9kZXN0eWxlID0gJShmaWxsPSIje25vZGVbJ2ZpbGwnXX0iIHN0cm9rZT0iI3tub2RlWydzdHJva2UnXX0iIHN0cm9rZS13aWR0aD0iI3tub2RlWydzdHJva2Vfd2lkdGgnXX0iKQogIG91dC5wdXNoKCUoPHJlY3QgI3tub2Rlc3R5bGV9IGhlaWdodD0iI3tofSIgd2lkdGg9IiN7d30iIHg9IiN7eH0iIHk9IiN7eX0iLz4pKQogIHggKz0gbm9kZVsnd2lkdGhfbWFyZ2luJ10KICBmcyA9IG5vZGVbJ2ZvbnRfc2l6ZSddCiAgbGggPSBmcyAqICgxICsgbm9kZVsnZm9udF9saW5lX3NwYWNpbmcnXSkKICB5ICs9IG5vZGVbJ2hlaWdodF9tYXJnaW4nXSArIGZzICogbm9kZVsnZm9udF9hc2NlbmQnXSAjIEJhc2VsaW5lIGZvciBmaXJzdCBsaW5lLgogIHVybCA9IG5vZGUuZmV0Y2goJ3VybCcsIG5pbCkKICB1cmwuZW5jb2RlISg6eG1sID0+IDphdHRyKSB1bmxlc3MgdXJsLm5pbD8KICB5MCA9IHkKICB0ZXh0c3R5bGUgPSAlKGZpbGw9IiN7bm9kZVsnZm9udF9maWxsJ119IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iI3tmc30iIHN0cm9rZT0iI3tub2RlWydmb250X2ZpbGwnXX0iIHN0cm9rZS13aWR0aD0iMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIpCiAgbGlua3N0eWxlID0gJShmaWxsPSIje25vZGVbJ3VybF9maWxsJ119IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iI3tmc30iIHN0cm9rZT0iI3tub2RlWyd1cmxfZmlsbCddfSIgc3Ryb2tlLXdpZHRoPSIwIiB4bWw6c3BhY2U9InByZXNlcnZlIikKICBub2RlWyd0ZXh0J10uZWFjaCBkbyB8bGluZXwKICAgIGxpbmUuZW5jb2RlISg6eG1sID0+IDp0ZXh0KQogICAgaWYgdXJsLm5pbD8KICAgICAgb3V0LnB1c2goJSg8dGV4dCAje3RleHRzdHlsZX0geD0iI3t4fSIgeT0iI3t5MH0iPiN7bGluZX08L3RleHQ+KSkKICAgIGVsc2UKICAgICAgb3V0LnB1c2goJSg8YSB4bGluazpocmVmPSN7dXJsfSB0YXJnZXQ9Il9wYXJlbnQiPjx0ZXh0ICN7bGlua3N0eWxlfSB4PSIje3h9IiB5PSIje3kwfSI+I3tsaW5lfTwvdGV4dD48L2E+KSkKICAgIGVuZAogICAgeTAgKz0gbGggIyBTaGlmdCBiYXNlbGluZSBieSBmdWxsIGxpbmUgKyBzcGFjaW5nIGhlaWdodC4KICBlbmQKZW5kCm91dC5qb2luKCJcbiIpCiU+Cjwvc3ZnPgo=
data/template/svg_1.1.erb CHANGED
@@ -6,6 +6,21 @@ hh += $render.doc.dig('diagram', 'height_margin')
6
6
  out = [
7
7
  %(<svg width="#{w + $render.doc.dig('diagram', 'width_margin')}" height="#{hh}" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">)
8
8
  ]
9
+ $render.doc.fetch('edges', []).each do |edge|
10
+ linestyle = %(fill="none" stroke="#{edge['stroke']}" stroke-width="#{edge['stroke_width']}")
11
+ path = edge.fetch('path', nil)
12
+ next if path.nil?
13
+ path.each do |p|
14
+ p['xo'] = p['xo'].to_i.to_s
15
+ p['yo'] = (hh - p['yo']).to_i.to_s
16
+ end
17
+ if path.size == 2
18
+ out.push(%(<line #{linestyle} x1="#{path[0]['xo']}" x2="#{path[1]['xo']}" y1="#{path[0]['yo']}" y2="#{path[1]['yo']}"/>))
19
+ else
20
+ pts = path.map { |p| "#{p['xo']},#{p['yo']}" }
21
+ out.push(%(<polyline #{linestyle} points="#{pts.join(' ')}"/>))
22
+ end
23
+ end
9
24
  $render.doc.fetch('nodes', []).each do |node|
10
25
  w = node['w'].to_i
11
26
  h = node['h'].to_i
@@ -32,21 +47,6 @@ $render.doc.fetch('nodes', []).each do |node|
32
47
  y0 += lh # Shift baseline by full line + spacing height.
33
48
  end
34
49
  end
35
- $render.doc.fetch('edges', []).each do |edge|
36
- linestyle = %(fill="none" stroke="#{edge['stroke']}" stroke-width="#{edge['stroke_width']}")
37
- path = edge.fetch('path', nil)
38
- next if path.nil?
39
- path.each do |p|
40
- p['xo'] = p['xo'].to_i.to_s
41
- p['yo'] = (hh - p['yo']).to_i.to_s
42
- end
43
- if path.size == 2
44
- out.push(%(<line #{linestyle} x1="#{path[0]['xo']}" x2="#{path[1]['xo']}" y1="#{path[0]['yo']}" y2="#{path[1]['yo']}"/>))
45
- else
46
- pts = path.map { |p| "#{p['xo']},#{p['yo']}" }
47
- out.push(%(<polyline #{linestyle} points="#{pts.join(' ')}"/>))
48
- end
49
- end
50
50
  out.join("\n")
51
51
  %>
52
52
  </svg>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diagrammatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismo Kärkkäinen