rsyntaxtree 1.1.3 → 1.2.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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.tags +581 -102
  4. data/docs/_examples/000.md +25 -0
  5. data/docs/_examples/010.md +0 -1
  6. data/docs/_examples/029.md +56 -0
  7. data/docs/_examples/030.md +33 -0
  8. data/docs/_examples/031.md +20 -0
  9. data/docs/_examples/032.md +26 -0
  10. data/docs/_examples/033.md +26 -0
  11. data/docs/_examples/034.md +26 -0
  12. data/docs/assets/img/000.png +0 -0
  13. data/docs/assets/img/001.png +0 -0
  14. data/docs/assets/img/002.png +0 -0
  15. data/docs/assets/img/003.png +0 -0
  16. data/docs/assets/img/004.png +0 -0
  17. data/docs/assets/img/005.png +0 -0
  18. data/docs/assets/img/006.png +0 -0
  19. data/docs/assets/img/007.png +0 -0
  20. data/docs/assets/img/008.png +0 -0
  21. data/docs/assets/img/009.png +0 -0
  22. data/docs/assets/img/010.png +0 -0
  23. data/docs/assets/img/011.png +0 -0
  24. data/docs/assets/img/012.png +0 -0
  25. data/docs/assets/img/013.png +0 -0
  26. data/docs/assets/img/014.png +0 -0
  27. data/docs/assets/img/015.png +0 -0
  28. data/docs/assets/img/017.png +0 -0
  29. data/docs/assets/img/018.png +0 -0
  30. data/docs/assets/img/019.png +0 -0
  31. data/docs/assets/img/020.png +0 -0
  32. data/docs/assets/img/021.png +0 -0
  33. data/docs/assets/img/022.png +0 -0
  34. data/docs/assets/img/023.png +0 -0
  35. data/docs/assets/img/024.png +0 -0
  36. data/docs/assets/img/025.png +0 -0
  37. data/docs/assets/img/026.png +0 -0
  38. data/docs/assets/img/027.png +0 -0
  39. data/docs/assets/img/028.png +0 -0
  40. data/docs/assets/img/029.png +0 -0
  41. data/docs/assets/img/030.png +0 -0
  42. data/docs/assets/img/031.png +0 -0
  43. data/docs/assets/img/032.png +0 -0
  44. data/docs/assets/img/033.png +0 -0
  45. data/docs/assets/img/034.png +0 -0
  46. data/docs/assets/svg/000.svg +68 -0
  47. data/docs/assets/svg/001.svg +3 -0
  48. data/docs/assets/svg/002.svg +3 -0
  49. data/docs/assets/svg/003.svg +3 -0
  50. data/docs/assets/svg/004.svg +3 -0
  51. data/docs/assets/svg/005.svg +3 -0
  52. data/docs/assets/svg/006.svg +3 -0
  53. data/docs/assets/svg/007.svg +3 -0
  54. data/docs/assets/svg/008.svg +3 -0
  55. data/docs/assets/svg/009.svg +3 -0
  56. data/docs/assets/svg/010.svg +13 -8
  57. data/docs/assets/svg/011.svg +3 -0
  58. data/docs/assets/svg/012.svg +3 -0
  59. data/docs/assets/svg/013.svg +3 -0
  60. data/docs/assets/svg/014.svg +3 -0
  61. data/docs/assets/svg/015.svg +3 -0
  62. data/docs/assets/svg/016.svg +3 -0
  63. data/docs/assets/svg/017.svg +3 -0
  64. data/docs/assets/svg/018.svg +3 -0
  65. data/docs/assets/svg/019.svg +186 -183
  66. data/docs/assets/svg/020.svg +3 -0
  67. data/docs/assets/svg/021.svg +3 -0
  68. data/docs/assets/svg/022.svg +69 -66
  69. data/docs/assets/svg/023.svg +18 -15
  70. data/docs/assets/svg/024.svg +3 -0
  71. data/docs/assets/svg/025.svg +3 -0
  72. data/docs/assets/svg/026.svg +3 -0
  73. data/docs/assets/svg/027.svg +3 -0
  74. data/docs/assets/svg/028.svg +3 -0
  75. data/docs/assets/svg/029.svg +126 -0
  76. data/docs/assets/svg/030.svg +76 -0
  77. data/docs/assets/svg/031.svg +36 -0
  78. data/docs/assets/svg/032.svg +73 -0
  79. data/docs/assets/svg/033.svg +74 -0
  80. data/docs/assets/svg/034.svg +91 -0
  81. data/docs/documentation.md +18 -5
  82. data/docs/documentation_ja.md +11 -3
  83. data/docs/examples.html +44 -41
  84. data/lib/rsyntaxtree/element.rb +1 -2
  85. data/lib/rsyntaxtree/markup_parser.rb +1 -1
  86. data/lib/rsyntaxtree/svg_graph.rb +90 -18
  87. data/lib/rsyntaxtree/version.rb +1 -1
  88. data/test/markup_parser_test.rb +2 -0
  89. metadata +24 -3
@@ -129,12 +129,25 @@ The backslash character `\` must be used to print certain characters used in the
129
129
 
130
130
  You can draw any number of paths of three different types:
131
131
 
132
- - Non-directional (rendered `- - -`)
133
- - Directional (rendered `----->`)
134
- - Bidirectional (rendered `<----->`)
132
+ - Non-directional (rendered as dashed line `- - -`)
133
+ - Directional (rendered as solid line `----->`)
134
+ - Bidirectional (rendered as solid line `<----->`)
135
135
 
136
- Each path is distinguished by a path ID number. The path ID is specified by putting a plus sign and a number (e.g. `+7`) at the end of the node text. If a greater-than sign is placed between the plus sign and the number (e.g. `+>7`), an arrowhead will appear at the end of the path.
137
- A node can have any number of path IDs. The same path ID must appear in the text of the *two* nodes between which the path is rendered. The same ID number cannot appear in more than two places.
136
+ Each path is distinguished by a unique ID number. The ID is specified by putting a plus sign and a number (e.g. `+7`) at the end of the node text. If a greater-than sign is placed between the plus sign and the number (e.g. `+>7`), an arrowhead will appear at the end of the path.
137
+
138
+ A node can have any number of IDs. The same ID must appear in the text of the *two* nodes between which the path is rendered. The same ID number cannot appear in more than two places.
139
+
140
+ ### Draw Extra Connectors between Nodes (experimental)
141
+
142
+ You can also add extra connector between nodes in the same fasion as you draw paths between nodes. Extra connectors are drawn as straigt lines (not as `polyline`s).
143
+
144
+ - Non-directional (rendered as solid line `-----`)
145
+ - Directional (rendered as solid line `----->`)
146
+ - Bidirectional (rendered as solid line `<----->`)
147
+
148
+ Each additional connectors is distinguished by an ID number. The ID is specified by putting a a number after a sequence of a plus and a minus symbols (e.g. `+-8`) at the end of the node text. If a greater-than sign is placed between the minus sign and the number (e.g. `+->8`), an arrowhead will appear at the end of the connector.
149
+
150
+ A node can have any number of IDs. The same ID must appear in the text of the *two* nodes between which the additional connector is rendered. The same ID number cannot appear in more than two places.
138
151
 
139
152
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
140
153
  <script src="https://cdn.jsdelivr.net/npm/lightbox2@2.11.3/src/js/lightbox.js"></script>
@@ -143,10 +143,18 @@ SVG形式を用いる場合,期待通りの表示を得るためには,ご
143
143
  - 方向(矢印)のあるパス(`----->`)
144
144
  - 両方向の矢印のあるパス(`<----->`)
145
145
 
146
- 樹形図の中でパスを表示したいとき,パスの両端をIDで指定します.パスIDをプラス(`+`)記号と共にノードのテキストの最後で指定してください(例:`+7`).
147
- プラス記号とパスIDの間に `>` 記号を入れると(例:`+>7`),パスの終端に矢印が付きます.
146
+ 樹形図の中でパスを表示したいとき,パスの両端を数字のIDで指定します。数字をプラス(`+`)記号と共にノードのテキストの最後で指定してください(例:`+7`).
147
+ プラス記号とID番号の間に `>` 記号を入れると(例:`+>7`),パスの終端に矢印が付きます.
148
148
 
149
- パスIDにはどのような数字を用いても構いませんが,必ず **2箇所** で同じIDを指定することが必要です.同じIDを2箇所以上で指定することはできません.
149
+ IDにはどのような数字を用いても構いませんが,必ず **2箇所** で同じIDを指定することが必要です.同じIDを3箇所以上で指定することはできません.
150
+
151
+ ### ノードからノードへの追加的なコネクターの描画(試験的機能)
152
+
153
+ パスの指定と類似した方式でノードからノードへのコネクターを追加することができます。追加的なコネクターは直線で描画されます(`polyline`にはなりません)。
154
+
155
+ 追加のコネクターは数字のIDで指定します,プラスとマイナスを連続させた(`+-`)後にIDを指定してください(例:`+-8`).マイナス記号とID番号の間に `>` 記号を入れると(例:`+->8`),コネクターの終端に矢印が付きます.
156
+
157
+ IDにはどのような数字を用いても構いませんが,必ず **2箇所** で同じIDを指定することが必要です.同じIDを3箇所以上で指定することはできません.
150
158
 
151
159
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
152
160
  <script src="https://cdn.jsdelivr.net/npm/lightbox2@2.11.3/src/js/lightbox.js"></script>
data/docs/examples.html CHANGED
@@ -8,55 +8,58 @@ layout: default
8
8
  {% assign categories = all_examples | map: 'category' | join: ',' | split: ',' | group_by: category %}
9
9
  <ul>
10
10
  {%- for category in categories -%}
11
- <li><a href="#category-{{ category.name | slugify }}">{{ category.name }}</a> [{{category.size}}]</li>
11
+ {%- if category.name != "Test" -%}
12
+ <li><a href="#category-{{ category.name | slugify }}">{{ category.name }}</a> [{{category.size}}]</li>
13
+ {%- endif -%}
12
14
  {%- endfor -%}
13
15
  </ul>
14
16
 
15
17
  {%- for category in categories -%}
16
- <hr />
17
- <h2 id="category-{{category.name | slugify }}"><b>{{ category.name }}</b></h2>
18
- {%- for example in all_examples -%}
19
- {% if example.category contains category.name %}
20
- <h3>{{ example.caption }}</h3>
21
- <div style='text-align:left;'>
22
- <button onclick="copyToClipBoard('text-{{ example.name }}')" style='margin: 20px 0; font-size: 0.85em;'>
23
- Copy to Clipboard
24
- </button>
25
- </div>
26
- <div class='grid'>
27
- <div style='margin-top: 0; margin-bottom: auto;'>
28
- <div id="text-{{example.name}}" style='max-height: 600px; overflow-y: auto; margin-bottom: 20px;'>
29
- {{ example.content | markdownify }}
30
- </div>
31
- <table style='line-height: 110%; font-size: 0.85em; margin-bottom: 20px;'>
32
- <thead></thead>
33
- <tbody>
34
- <tr><td>Category</td><td>{{ example.category}}</td></tr>
35
- <tr><td>Connector</td><td>{{ example.connector }}</td></tr>
36
- <tr><td>Polyline</td><td>{{ example.polyline }}</td></tr>
37
- <tr><td>Colorization</td><td>{{ example.colorization }}</td></tr>
38
- <tr><td>Radical Symmetirization</td><td>{{ example.symmetrization }}</td></tr>
39
- <tr><td>Font</td><td>{{ example.font }}</td></tr>
40
- {% if example.reference %}
41
- <tr><td>Reference</td><td>{{ example.reference }}</td></tr>
42
- {% endif %}
43
- </tbody>
44
- </table>
45
- </div>
46
- <div style='margin-top: 0; margin-bottom: auto;'>
47
- <a href='assets/img/{{ example.name }}.png' data-lightbox='{{ example.name }}'>
48
- <img src='assets/img/{{ example.name}}.png'/>
49
- </a>
50
- </div>
51
- </div>
52
- <div><a href="#examples">🔝</a></div>
53
- {% endif %}
54
- {%- endfor -%}
18
+ {%- if category.name != "Test" -%}
19
+ <hr />
20
+ <h2 id="category-{{category.name | slugify }}"><b>{{ category.name }}</b></h2>
21
+ {%- for example in all_examples -%}
22
+ {%- if example.category contains category.name -%}
23
+ <h3>{{ example.caption }}</h3>
24
+ <div style='text-align:left;'>
25
+ <button onclick="copyToClipBoard('text-{{ example.name }}')" style='margin: 20px 0; font-size: 0.85em;'>
26
+ Copy to Clipboard
27
+ </button>
28
+ </div>
29
+ <div class='grid'>
30
+ <div style='margin-top: 0; margin-bottom: auto;'>
31
+ <div id="text-{{example.name}}" style='max-height: 600px; overflow-y: auto; margin-bottom: 20px;'>
32
+ {{ example.content | markdownify }}
33
+ </div>
34
+ <table style='line-height: 110%; font-size: 0.85em; margin-bottom: 20px;'>
35
+ <thead></thead>
36
+ <tbody>
37
+ <tr><td>Category</td><td>{{ example.category}}</td></tr>
38
+ <tr><td>Connector</td><td>{{ example.connector }}</td></tr>
39
+ <tr><td>Polyline</td><td>{{ example.polyline }}</td></tr>
40
+ <tr><td>Colorization</td><td>{{ example.colorization }}</td></tr>
41
+ <tr><td>Radical Symmetirization</td><td>{{ example.symmetrization }}</td></tr>
42
+ <tr><td>Font</td><td>{{ example.font }}</td></tr>
43
+ {% if example.reference %}
44
+ <tr><td>Reference</td><td>{{ example.reference }}</td></tr>
45
+ {% endif %}
46
+ </tbody>
47
+ </table>
48
+ </div>
49
+ <div style='margin-top: 0; margin-bottom: auto;'>
50
+ <a href='assets/img/{{ example.name }}.png' data-lightbox='{{ example.name }}'>
51
+ <img src='assets/img/{{ example.name}}.png'/>
52
+ </a>
53
+ </div>
54
+ </div>
55
+ <div><a href="#examples">🔝</a></div>
56
+ {%- endif -%}
57
+ {%- endfor -%}
58
+ {%- endif -%}
55
59
  {%- endfor -%}
56
60
 
57
61
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
58
62
  <script src="https://cdn.jsdelivr.net/npm/lightbox2@2.11.3/src/js/lightbox.js"></script>
59
-
60
63
  <script>
61
64
  function copyToClipBoard(id){
62
65
  var copyText = document.getElementById(id).innerText;
@@ -20,7 +20,6 @@ module RSyntaxTree
20
20
  @id = id # Unique element id
21
21
  @parent = parent # Parent element id
22
22
  @children = [] # Child element ids
23
- @type = type # Element type
24
23
  @level = level # Element level in the tree (0=top etc...)
25
24
  @width = 0 # Width of the part of the tree including itself and it governs
26
25
  @content_width = 0 # Width of the content
@@ -28,7 +27,7 @@ module RSyntaxTree
28
27
  @vertical_indent = 0 # Drawing offset
29
28
  content = content.strip
30
29
 
31
- @path = if /.+?\^?((?:\+>?\d+)+)\^?\z/m =~ content
30
+ @path = if /.+?\^?((?:\+-?>?\d+)+)\^?\z/m =~ content
32
31
  $1.sub(/\A\+/, "").split("+")
33
32
  else
34
33
  []
@@ -13,7 +13,7 @@ class MarkupParser < Parslet::Parser
13
13
  rule(:brackets) { str('#') }
14
14
  rule(:triangle) { str('^') }
15
15
 
16
- rule(:path) { (str('+') >> str('>').maybe >> match('\d').repeat(1)).as(:path) }
16
+ rule(:path) { (str('+') >> str('-').maybe >> str('>').maybe >> match('\d').repeat(1)).as(:path) }
17
17
  rule(:escaped) { str('\\') >> match('[#<>{}\\^+*_=~\|\n\-]').as(:chr) }
18
18
  rule(:non_escaped) { ((match('[#<>{}\\^+*_=~\|\-]') | str('\\n')).absent? >> any).as(:chr) }
19
19
  rule(:text) { (escaped | non_escaped).repeat(1).as(:text) }
@@ -49,8 +49,9 @@ module RSyntaxTree
49
49
  y2 = @height + @margin
50
50
  extra_lines = @extra_lines.join("\n")
51
51
 
52
+ as = @global[:h_gap_between_nodes] / 4 * 0.8
52
53
  as2 = @global[:h_gap_between_nodes] / 2 * 0.8
53
- as = as2 / 2
54
+ as3 = @global[:h_gap_between_nodes] / 2 * 0.5
54
55
 
55
56
  header = <<~HDR
56
57
  <?xml version="1.0" standalone="no"?>
@@ -60,6 +61,9 @@ module RSyntaxTree
60
61
  <marker id="arrow" markerUnits="strokeWidth" markerWidth="#{as2}" markerHeight="#{as2}" viewBox="0 0 #{as2} #{as2}" refX="#{as}" refY="0">
61
62
  <polyline fill="none" stroke="#{@col_path}" stroke-width="1" points="0,#{as2},#{as},0,#{as2},#{as2}" />
62
63
  </marker>
64
+ <marker id="arrowSolid" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="#{as3}" markerHeight="#{as3}" orient="auto-start-reverse">
65
+ <path d="M 0 0 L 10 5 L 0 10 z" stroke="#{@col_line}"/>
66
+ </marker>
63
67
  <pattern id="hatchBlack" x="10" y="10" width="10" height="10" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
64
68
  <line x1="0" y="0" x2="0" y2="10" stroke="black" stroke-width="4"></line>
65
69
  </pattern>
@@ -85,9 +89,13 @@ module RSyntaxTree
85
89
  end
86
90
  end
87
91
 
92
+ def draw_direct_line(s_x, s_y, t_x, t_y, s_arrow = false, t_arrow = false)
93
+ @extra_lines << generate_connector(s_x, s_y, t_x, t_y, @col_line, false, s_arrow, t_arrow)
94
+ end
95
+
88
96
  def draw_a_path(s_x, s_y, t_x, t_y, target_arrow = :none)
89
97
  x_spacing = @global[:h_gap_between_nodes] * 1.25
90
- y_spacing = @global[:height_connector] * 0.65
98
+ y_spacing = @global[:height_connector] * 0.75
91
99
 
92
100
  ymax = [s_y, t_y].max
93
101
  new_y = if ymax < @height
@@ -112,14 +120,15 @@ module RSyntaxTree
112
120
  @visited_x[t_x] = 1
113
121
  end
114
122
 
115
- s_y += @global[:h_gap_between_nodes] / 2
116
- t_y += @global[:h_gap_between_nodes] / 2
117
- new_y += @global[:h_gap_between_nodes] / 2
123
+ # s_y += @global[:h_gap_between_nodes] / 2
124
+ # t_y += @global[:h_gap_between_nodes] / 2
125
+ # new_y += @global[:h_gap_between_nodes] / 2
118
126
 
119
127
  dashed = true if target_arrow == :none
120
128
 
121
129
  case target_arrow
122
130
  when :single
131
+ @extra_lines << generate_line(new_s_x, s_y, new_s_x, new_y, @col_path, dashed)
123
132
  @extra_lines << generate_line(new_s_x, s_y, new_s_x, new_y, @col_path, dashed)
124
133
  @extra_lines << generate_line(new_s_x, new_y, new_t_x, new_y, @col_path, dashed)
125
134
  @extra_lines << generate_line(new_t_x, new_y, new_t_x, t_y, @col_path, dashed, true)
@@ -218,11 +227,17 @@ module RSyntaxTree
218
227
  case @fontstyle
219
228
  when /(?:cjk)/
220
229
  fontstyle = "'WenQuanYi Zen Hei', 'Noto Sans', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
221
- when /(?:sans|mono)/
230
+ when /(?:mono)/
222
231
  fontstyle = if e[:cjk]
223
- "'Noto Sans JP', 'Noto Sans Mono SemiConcensed', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
232
+ "'Noto Sans JP', 'Noto Sans Mono SemiCondensed', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
224
233
  else
225
- "'Noto Sans Mono SemiConcensed', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
234
+ "'Noto Sans Mono SemiCondensed', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
235
+ end
236
+ when /(?:sans)/
237
+ fontstyle = if e[:cjk]
238
+ "'Noto Sans JP', 'Noto Sans', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
239
+ else
240
+ "'Noto Sans', 'Noto Sans JP', OpenMoji, 'OpenMoji Color', 'OpenMoji Black', sans-serif"
226
241
  end
227
242
  when /(?:serif)/
228
243
  fontstyle = if e[:cjk]
@@ -356,37 +371,64 @@ module RSyntaxTree
356
371
  end
357
372
 
358
373
  def draw_paths
374
+ paths = []
359
375
  path_pool_target = {}
360
376
  path_pool_other = {}
361
377
  path_pool_source = {}
362
378
  path_flags = []
379
+
380
+ line_pool = {}
381
+ line_flags = []
382
+
363
383
  # elist = @element_list.get_elements.reverse
364
384
  elist = @element_list.get_elements
365
385
 
366
- elist.each do |element|
386
+ elist.each_with_index do |element, i|
387
+ x0 = element.horizontal_indent - @global[:h_gap_between_nodes]
367
388
  x1 = element.horizontal_indent + element.content_width / 2
389
+ x2 = element.horizontal_indent + element.content_width + @global[:h_gap_between_nodes]
390
+ y0 = if /nothing|none/ =~ @leafstyle && element.type == ETYPE_LEAF && element.enclosure != :none
391
+ element.vertical_indent - @global[:height_connector_to_text]
392
+ else
393
+ element.vertical_indent + @global[:height_connector_to_text] / 2
394
+ end
368
395
  y1 = element.vertical_indent + element.content_height
369
- y1 += @global[:height_connector_to_text] if element.enclosure != :none
396
+ if i == elist.size - 1 && /nothing|none/ =~ @leafstyle
397
+ y1 -= @global[:height_connector_to_text] / 2
398
+ else
399
+ y1 += @global[:height_connector_to_text]
400
+ end
370
401
  et = element.path
371
402
  et.each do |tr|
372
- if /\A>(\d+)\z/ =~ tr
403
+ if /\A-(>)?(\d+)\z/ =~ tr
404
+ arrow = $1
405
+ tr = $2
406
+ if line_pool[tr]
407
+ line_pool[tr] << { x: { left: x0, center: x1, right: x2 }, y: { top: y0, center: y0 + (y1 - y0) / 2, bottom: y1 }, arrow: arrow }
408
+ else
409
+ line_pool[tr] = [{ x: { left: x0, center: x1, right: x2 }, y: { top: y0, center: y0 + (y1 - y0) / 2, bottom: y1 }, arrow: arrow }]
410
+ end
411
+ line_flags << tr
412
+ elsif /\A>(\d+)\z/ =~ tr
373
413
  tr = $1
374
414
  if path_pool_target[tr]
375
415
  path_pool_target[tr] << [x1, y1]
376
416
  else
377
417
  path_pool_target[tr] = [[x1, y1]]
378
418
  end
419
+ path_flags << tr
379
420
  elsif path_pool_source[tr]
380
421
  if path_pool_other[tr]
381
422
  path_pool_other[tr] << [x1, y1]
382
423
  else
383
424
  path_pool_other[tr] = [[x1, y1]]
384
425
  end
426
+ path_flags << tr
385
427
  else
386
428
  path_pool_source[tr] = [x1, y1]
429
+ path_flags << tr
387
430
  end
388
- path_flags << tr
389
- raise RSTError, "Error: input text contains a path having more than two ends:\n > #{tr}" if path_flags.tally.any? { |_k, v| v > 2 }
431
+ raise RSTError, "Error: input text contains a path having more than two ends:\n > #{tr}" if path_flags.tally.any? { |_k, v| v > 2 } || line_flags.tally.any? { |_k, v| v > 2 }
390
432
  end
391
433
  end
392
434
 
@@ -394,7 +436,6 @@ module RSyntaxTree
394
436
  raise RSTError, "Error: input text contains a path having only one end:\n > #{k}" if v == 1
395
437
  end
396
438
 
397
- paths = []
398
439
  path_pool_source.each do |k, v|
399
440
  path_flags.delete(k)
400
441
  if (targets = path_pool_target[k])
@@ -417,12 +458,43 @@ module RSyntaxTree
417
458
  end
418
459
 
419
460
  paths.each do |t|
420
- draw_a_path(t[:x1], t[:y1] + @global[:height_connector_to_text] / 2,
421
- t[:x2], t[:y2] + @global[:height_connector_to_text] / 2,
422
- t[:arrow])
461
+ # draw_a_path(t[:x1], t[:y1] - @global[:height_connector_to_text], t[:x2], t[:y2] - @global[:height_connector_to_text], t[:arrow])
462
+ draw_a_path(t[:x1], t[:y1], t[:x2], t[:y2], t[:arrow])
423
463
  end
424
464
 
425
- paths.size
465
+ line_pool.each do |_k, v|
466
+ a = v[0]
467
+ b = v[1]
468
+
469
+ if (a[:y][:bottom] > b[:y][:top] && a[:y][:top] < b[:y][:bottom]) || (b[:y][:bottom] > a[:y][:top] && b[:y][:top] < a[:y][:bottom])
470
+ y_top = [a[:y][:top], b[:y][:top]].max
471
+ y_bottom = [a[:y][:bottom], b[:y][:bottom]].min
472
+ y_center = y_top + (y_top - y_bottom).abs / 2
473
+ if a[:x][:center] < b[:x][:center]
474
+ draw_direct_line(a[:x][:right], y_center, b[:x][:left], y_center, a[:arrow], b[:arrow])
475
+ else
476
+ draw_direct_line(b[:x][:right], y_center, a[:x][:left], y_center, b[:arrow], a[:arrow])
477
+ end
478
+ next
479
+ end
480
+
481
+ if a[:y][:bottom] < b[:y][:bottom]
482
+ draw_direct_line(a[:x][:center], a[:y][:bottom], b[:x][:center], b[:y][:top], a[:arrow], b[:arrow])
483
+ else
484
+ draw_direct_line(a[:x][:center], a[:y][:top], b[:x][:center], b[:y][:bottom], a[:arrow], b[:arrow])
485
+ end
486
+ end
487
+ paths.size + line_pool.keys.size
488
+ end
489
+
490
+ def generate_connector(x1, y1, x2, y2, col, dashed = false, s_arrow = false, t_arrow = false, stroke_width = 1)
491
+ string = +""
492
+ string << "marker-start='url(#arrowSolid)' " if s_arrow
493
+ string << "marker-end='url(#arrowSolid)' " if t_arrow
494
+ dasharray = dashed ? "stroke-dasharray='8 8'" : ""
495
+ swidth = FONT_SCALING * stroke_width
496
+
497
+ "<line x1='#{x1}' y1='#{y1}' x2='#{x2}' y2='#{y2}' style='fill: none; stroke: #{col}; stroke-width:#{swidth}' #{dasharray} #{string}/>"
426
498
  end
427
499
 
428
500
  def generate_line(x1, y1, x2, y2, col, dashed = false, arrow = false, stroke_width = 1)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RSyntaxTree
4
- VERSION = "1.1.3"
4
+ VERSION = "1.2.0"
5
5
  end
@@ -29,6 +29,8 @@ class MarkupParserTest < Minitest::Test
29
29
  # {:path=>"+12"@0}
30
30
  @parser.path.parse('+>34')
31
31
  # {:path=>"+>34"@0}d
32
+ @parser.path.parse('+-87')
33
+ # {:path=>"+-87"@0}d
32
34
  end
33
35
 
34
36
  def test_rule_escaped
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsyntaxtree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoichiro Hasebe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: optimist
@@ -112,6 +112,7 @@ files:
112
112
  - docs/404.html
113
113
  - docs/Gemfile
114
114
  - docs/_config.yml
115
+ - docs/_examples/000.md
115
116
  - docs/_examples/001.md
116
117
  - docs/_examples/002.md
117
118
  - docs/_examples/003.md
@@ -140,11 +141,18 @@ files:
140
141
  - docs/_examples/026.md
141
142
  - docs/_examples/027.md
142
143
  - docs/_examples/028.md
144
+ - docs/_examples/029.md
145
+ - docs/_examples/030.md
146
+ - docs/_examples/031.md
147
+ - docs/_examples/032.md
148
+ - docs/_examples/033.md
149
+ - docs/_examples/034.md
143
150
  - docs/_includes/box_and_circle_table.html
144
151
  - docs/_includes/escape_char_table.html
145
152
  - docs/_includes/social_media_links.html
146
153
  - docs/_layouts/default.html
147
154
  - docs/assets/css/style.scss
155
+ - docs/assets/img/000.png
148
156
  - docs/assets/img/001.png
149
157
  - docs/assets/img/002.png
150
158
  - docs/assets/img/003.png
@@ -173,6 +181,12 @@ files:
173
181
  - docs/assets/img/026.png
174
182
  - docs/assets/img/027.png
175
183
  - docs/assets/img/028.png
184
+ - docs/assets/img/029.png
185
+ - docs/assets/img/030.png
186
+ - docs/assets/img/031.png
187
+ - docs/assets/img/032.png
188
+ - docs/assets/img/033.png
189
+ - docs/assets/img/034.png
176
190
  - docs/assets/img/elements/circle.png
177
191
  - docs/assets/img/elements/circle_abc.png
178
192
  - docs/assets/img/elements/circle_bold.png
@@ -189,6 +203,7 @@ files:
189
203
  - docs/assets/img/favicon/favicon-16x16.png
190
204
  - docs/assets/img/favicon/favicon-32x32.png
191
205
  - docs/assets/img/favicon/favicon.ico
206
+ - docs/assets/svg/000.svg
192
207
  - docs/assets/svg/001.svg
193
208
  - docs/assets/svg/002.svg
194
209
  - docs/assets/svg/003.svg
@@ -217,6 +232,12 @@ files:
217
232
  - docs/assets/svg/026.svg
218
233
  - docs/assets/svg/027.svg
219
234
  - docs/assets/svg/028.svg
235
+ - docs/assets/svg/029.svg
236
+ - docs/assets/svg/030.svg
237
+ - docs/assets/svg/031.svg
238
+ - docs/assets/svg/032.svg
239
+ - docs/assets/svg/033.svg
240
+ - docs/assets/svg/034.svg
220
241
  - docs/documentation.md
221
242
  - docs/documentation_ja.md
222
243
  - docs/examples.html
@@ -274,7 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
274
295
  - !ruby/object:Gem::Version
275
296
  version: '0'
276
297
  requirements: []
277
- rubygems_version: 3.4.2
298
+ rubygems_version: 3.3.3
278
299
  signing_key:
279
300
  specification_version: 4
280
301
  summary: RSyntaxTree is a graphical syntax tree generator written in Ruby