rsyntaxtree 1.3.2 → 1.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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +6 -0
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +115 -52
- data/bin/rsyntaxtree +107 -19
- data/docs/_examples/054.md +22 -0
- data/docs/_examples/055.md +24 -0
- data/docs/_examples/056.md +27 -0
- data/docs/assets/img/054.png +0 -0
- data/docs/assets/img/055.png +0 -0
- data/docs/assets/img/056.png +0 -0
- data/docs/assets/svg/054.svg +50 -0
- data/docs/assets/svg/055.svg +53 -0
- data/docs/assets/svg/056.svg +73 -0
- data/docs/documentation.md +89 -0
- data/docs/documentation_ja.md +90 -1
- data/lib/rsyntaxtree/base_graph.rb +5 -5
- data/lib/rsyntaxtree/element.rb +3 -2
- data/lib/rsyntaxtree/elementlist.rb +3 -5
- data/lib/rsyntaxtree/format_converter.rb +65 -0
- data/lib/rsyntaxtree/markup_parser.rb +13 -2
- data/lib/rsyntaxtree/string_parser.rb +1 -1
- data/lib/rsyntaxtree/svg_graph.rb +9 -2
- data/lib/rsyntaxtree/tikz_generator.rb +131 -0
- data/lib/rsyntaxtree/utils.rb +1 -1
- data/lib/rsyntaxtree/version.rb +1 -1
- data/lib/rsyntaxtree.rb +42 -24
- data/rsyntaxtree.gemspec +2 -0
- data/syntree.svg +41 -0
- data/test/cli_test.rb +262 -0
- data/test/format_converter_test.rb +129 -0
- data/test/node_styling_test.rb +239 -0
- data/test/tikz_test.rb +89 -0
- metadata +51 -6
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require "minitest/pride"
|
|
5
|
+
require_relative "../lib/rsyntaxtree/format_converter"
|
|
6
|
+
|
|
7
|
+
class FormatConverterTest < Minitest::Test
|
|
8
|
+
# ===================
|
|
9
|
+
# Penn TreeBank format conversion
|
|
10
|
+
# ===================
|
|
11
|
+
|
|
12
|
+
def test_simple_penn_to_bracket
|
|
13
|
+
penn = "(S (NP hello) (VP world))"
|
|
14
|
+
expected = "[S [NP hello] [VP world]]"
|
|
15
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_nested_penn_to_bracket
|
|
19
|
+
penn = "(S (NP (Det the) (N dog)) (VP (V runs)))"
|
|
20
|
+
expected = "[S [NP [Det the] [N dog]] [VP [V runs]]]"
|
|
21
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_penn_with_spaces
|
|
25
|
+
penn = "( S ( NP hello ) ( VP world ) )"
|
|
26
|
+
expected = "[S [NP hello] [VP world]]"
|
|
27
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_penn_multiline
|
|
31
|
+
penn = <<~PENN
|
|
32
|
+
(S
|
|
33
|
+
(NP (Det the) (N cat))
|
|
34
|
+
(VP (V sat)))
|
|
35
|
+
PENN
|
|
36
|
+
expected = "[S [NP [Det the] [N cat]] [VP [V sat]]]"
|
|
37
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_penn_with_complex_labels
|
|
41
|
+
penn = "(S (NP-SBJ hello) (VP world))"
|
|
42
|
+
expected = "[S [NP-SBJ hello] [VP world]]"
|
|
43
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_empty_node
|
|
47
|
+
penn = "(S (NP) (VP test))"
|
|
48
|
+
expected = "[S [NP] [VP test]]"
|
|
49
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# ===================
|
|
53
|
+
# Format detection
|
|
54
|
+
# ===================
|
|
55
|
+
|
|
56
|
+
def test_detect_penn_format
|
|
57
|
+
penn = "(S (NP hello) (VP world))"
|
|
58
|
+
assert_equal :penn, RSyntaxTree::FormatConverter.detect_format(penn)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_detect_bracket_format
|
|
62
|
+
bracket = "[S [NP hello] [VP world]]"
|
|
63
|
+
assert_equal :bracket, RSyntaxTree::FormatConverter.detect_format(bracket)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_detect_bracket_with_markup
|
|
67
|
+
bracket = "[S [NP **hello**] [VP world]]"
|
|
68
|
+
assert_equal :bracket, RSyntaxTree::FormatConverter.detect_format(bracket)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# ===================
|
|
72
|
+
# Auto-conversion
|
|
73
|
+
# ===================
|
|
74
|
+
|
|
75
|
+
def test_auto_convert_penn
|
|
76
|
+
penn = "(S (NP hello) (VP world))"
|
|
77
|
+
expected = "[S [NP hello] [VP world]]"
|
|
78
|
+
assert_equal expected, RSyntaxTree::FormatConverter.to_bracket(penn)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_auto_convert_bracket_unchanged
|
|
82
|
+
bracket = "[S [NP hello] [VP world]]"
|
|
83
|
+
assert_equal bracket, RSyntaxTree::FormatConverter.to_bracket(bracket)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# ===================
|
|
87
|
+
# Edge cases
|
|
88
|
+
# ===================
|
|
89
|
+
|
|
90
|
+
def test_penn_single_node
|
|
91
|
+
penn = "(NP hello)"
|
|
92
|
+
expected = "[NP hello]"
|
|
93
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_penn_leaf_only
|
|
97
|
+
penn = "(N dog)"
|
|
98
|
+
expected = "[N dog]"
|
|
99
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_penn_with_numbers
|
|
103
|
+
penn = "(NP (CD 123) (NN items))"
|
|
104
|
+
expected = "[NP [CD 123] [NN items]]"
|
|
105
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ===================
|
|
109
|
+
# Escaped characters
|
|
110
|
+
# ===================
|
|
111
|
+
|
|
112
|
+
def test_penn_with_escaped_parentheses
|
|
113
|
+
penn = '(S (NP hello\(world\)) (VP test))'
|
|
114
|
+
expected = "[S [NP hello(world)] [VP test]]"
|
|
115
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_penn_with_escaped_brackets
|
|
119
|
+
penn = '(S (NP \[hello\]) (VP test))'
|
|
120
|
+
expected = '[S [NP \[hello\]] [VP test]]'
|
|
121
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_penn_with_mixed_escaped_chars
|
|
125
|
+
penn = '(S (NP \(a\) and \[b\]) (VP test))'
|
|
126
|
+
expected = '[S [NP (a) and \[b\]] [VP test]]'
|
|
127
|
+
assert_equal expected, RSyntaxTree::FormatConverter.penn_to_bracket(penn)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require "minitest/pride"
|
|
5
|
+
require_relative "../lib/rsyntaxtree"
|
|
6
|
+
|
|
7
|
+
class NodeStylingTest < Minitest::Test
|
|
8
|
+
def setup
|
|
9
|
+
@base_opts = { fontstyle: "sans" }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# ===================
|
|
13
|
+
# Named color tests
|
|
14
|
+
# ===================
|
|
15
|
+
|
|
16
|
+
def test_named_color_red
|
|
17
|
+
opts = @base_opts.merge(data: "[S [@red:NP hello] [VP world]]")
|
|
18
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
19
|
+
svg = rsg.draw_svg
|
|
20
|
+
|
|
21
|
+
assert_kind_of String, svg
|
|
22
|
+
assert svg.include?("red"), "Should contain red color styling"
|
|
23
|
+
assert svg.include?("hello"), "Should contain the text"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_named_color_blue
|
|
27
|
+
opts = @base_opts.merge(data: "[S [NP hello] [@blue:VP world]]")
|
|
28
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
29
|
+
svg = rsg.draw_svg
|
|
30
|
+
|
|
31
|
+
assert_kind_of String, svg
|
|
32
|
+
assert svg.include?("blue"), "Should contain blue color styling"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_named_color_green
|
|
36
|
+
opts = @base_opts.merge(data: "[S [@green:NP hello] [VP world]]")
|
|
37
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
38
|
+
svg = rsg.draw_svg
|
|
39
|
+
|
|
40
|
+
assert_kind_of String, svg
|
|
41
|
+
assert svg.include?("green"), "Should contain green color"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# ===================
|
|
45
|
+
# Hex color tests
|
|
46
|
+
# ===================
|
|
47
|
+
|
|
48
|
+
def test_hex_color_full
|
|
49
|
+
opts = @base_opts.merge(data: "[S [@#FF0000:NP hello] [VP world]]")
|
|
50
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
51
|
+
svg = rsg.draw_svg
|
|
52
|
+
|
|
53
|
+
assert_kind_of String, svg
|
|
54
|
+
# Hex color should be preserved in output
|
|
55
|
+
assert svg.include?("#FF0000") || svg.include?("#ff0000"), "Should contain hex color"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_hex_color_short
|
|
59
|
+
opts = @base_opts.merge(data: "[S [@#F00:NP hello] [VP world]]")
|
|
60
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
61
|
+
svg = rsg.draw_svg
|
|
62
|
+
|
|
63
|
+
assert_kind_of String, svg
|
|
64
|
+
# Short hex should be converted or preserved
|
|
65
|
+
assert svg.include?("#F00") || svg.include?("#f00") || svg.include?("#FF0000"), "Should contain hex color"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# ===================
|
|
69
|
+
# Multiple colors in tree
|
|
70
|
+
# ===================
|
|
71
|
+
|
|
72
|
+
def test_multiple_colors
|
|
73
|
+
opts = @base_opts.merge(data: "[S [@red:NP hello] [@blue:VP world]]")
|
|
74
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
75
|
+
svg = rsg.draw_svg
|
|
76
|
+
|
|
77
|
+
assert_kind_of String, svg
|
|
78
|
+
assert svg.include?("red"), "Should contain red"
|
|
79
|
+
assert svg.include?("blue"), "Should contain blue"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_nested_colored_nodes
|
|
83
|
+
opts = @base_opts.merge(data: "[S [@red:NP [@green:Det the] [N dog]] [VP runs]]")
|
|
84
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
85
|
+
svg = rsg.draw_svg
|
|
86
|
+
|
|
87
|
+
assert_kind_of String, svg
|
|
88
|
+
assert svg.include?("red"), "Should contain red for NP"
|
|
89
|
+
assert svg.include?("green"), "Should contain green for Det"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# ===================
|
|
93
|
+
# Color with other decorations
|
|
94
|
+
# ===================
|
|
95
|
+
|
|
96
|
+
def test_color_with_bold
|
|
97
|
+
opts = @base_opts.merge(data: "[S [@red:**NP** hello] [VP world]]")
|
|
98
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
99
|
+
svg = rsg.draw_svg
|
|
100
|
+
|
|
101
|
+
assert_kind_of String, svg
|
|
102
|
+
assert svg.include?("red"), "Should contain red color"
|
|
103
|
+
assert svg.include?("bold"), "Should contain bold styling"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_color_with_italic
|
|
107
|
+
opts = @base_opts.merge(data: "[S [@blue:*NP* hello] [VP world]]")
|
|
108
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
109
|
+
svg = rsg.draw_svg
|
|
110
|
+
|
|
111
|
+
assert_kind_of String, svg
|
|
112
|
+
assert svg.include?("blue"), "Should contain blue color"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# ===================
|
|
116
|
+
# Edge cases
|
|
117
|
+
# ===================
|
|
118
|
+
|
|
119
|
+
def test_color_on_terminal
|
|
120
|
+
opts = @base_opts.merge(data: "[S [NP @red:hello] [VP world]]")
|
|
121
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
122
|
+
svg = rsg.draw_svg
|
|
123
|
+
|
|
124
|
+
assert_kind_of String, svg
|
|
125
|
+
assert svg.include?("red"), "Should color terminal node"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_mixed_colored_and_uncolored
|
|
129
|
+
opts = @base_opts.merge(data: "[S [NP hello] [@orange:VP world] [PP there]]")
|
|
130
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
131
|
+
svg = rsg.draw_svg
|
|
132
|
+
|
|
133
|
+
assert_kind_of String, svg
|
|
134
|
+
assert svg.include?("orange"), "Should contain orange color"
|
|
135
|
+
# Other nodes should use default colors
|
|
136
|
+
assert svg.include?("hello"), "Should contain uncolored text"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_color_without_interference
|
|
140
|
+
# Ensure @ in other contexts doesn't break parsing
|
|
141
|
+
opts = @base_opts.merge(data: "[S [NP hello] [VP world]]")
|
|
142
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
143
|
+
svg = rsg.draw_svg
|
|
144
|
+
|
|
145
|
+
assert_kind_of String, svg
|
|
146
|
+
refute_empty svg
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# ===================
|
|
150
|
+
# Color with enclosure (#)
|
|
151
|
+
# ===================
|
|
152
|
+
|
|
153
|
+
def test_color_with_brackets_enclosure
|
|
154
|
+
# Order: # (enclosure) then @color:
|
|
155
|
+
opts = @base_opts.merge(data: '[S [#@red:NP hello] [VP world]]')
|
|
156
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
157
|
+
svg = rsg.draw_svg
|
|
158
|
+
|
|
159
|
+
assert_kind_of String, svg
|
|
160
|
+
assert svg.include?("red"), "Should contain red color"
|
|
161
|
+
# Check for bracket polyline (enclosure)
|
|
162
|
+
assert svg.include?("polyline"), "Should contain bracket enclosure"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_color_with_rectangle_enclosure
|
|
166
|
+
opts = @base_opts.merge(data: '[S [##@blue:NP hello] [VP world]]')
|
|
167
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
168
|
+
svg = rsg.draw_svg
|
|
169
|
+
|
|
170
|
+
assert_kind_of String, svg
|
|
171
|
+
assert svg.include?("blue"), "Should contain blue color"
|
|
172
|
+
assert svg.include?("polygon"), "Should contain rectangle enclosure"
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def test_hex_color_with_enclosure
|
|
176
|
+
opts = @base_opts.merge(data: '[S [#@#FF5733:NP hello] [VP world]]')
|
|
177
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
178
|
+
svg = rsg.draw_svg
|
|
179
|
+
|
|
180
|
+
assert_kind_of String, svg
|
|
181
|
+
assert svg.include?("#FF5733") || svg.include?("#ff5733"), "Should contain hex color"
|
|
182
|
+
assert svg.include?("polyline"), "Should contain bracket enclosure"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# ===================
|
|
186
|
+
# Color with triangle (^)
|
|
187
|
+
# ===================
|
|
188
|
+
|
|
189
|
+
def test_color_with_triangle
|
|
190
|
+
opts = @base_opts.merge(data: "[S [^@red:NP the quick fox] [VP runs]]")
|
|
191
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
192
|
+
svg = rsg.draw_svg
|
|
193
|
+
|
|
194
|
+
assert_kind_of String, svg
|
|
195
|
+
assert svg.include?("red"), "Should contain red color"
|
|
196
|
+
assert svg.include?("polygon"), "Should contain triangle"
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def test_hex_color_with_triangle
|
|
200
|
+
opts = @base_opts.merge(data: "[S [^@#00FF00:NP the lazy dog] [VP sleeps]]")
|
|
201
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
202
|
+
svg = rsg.draw_svg
|
|
203
|
+
|
|
204
|
+
assert_kind_of String, svg
|
|
205
|
+
assert svg.include?("#00FF00") || svg.include?("#00ff00"), "Should contain hex color"
|
|
206
|
+
assert svg.include?("polygon"), "Should contain triangle"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# ===================
|
|
210
|
+
# Color with both enclosure and triangle
|
|
211
|
+
# ===================
|
|
212
|
+
|
|
213
|
+
def test_color_with_triangle_and_enclosure
|
|
214
|
+
# Order: ^ (triangle) then # (enclosure) then @color:
|
|
215
|
+
opts = @base_opts.merge(data: '[S [^#@purple:NP the quick fox] [VP runs]]')
|
|
216
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
217
|
+
svg = rsg.draw_svg
|
|
218
|
+
|
|
219
|
+
assert_kind_of String, svg
|
|
220
|
+
assert svg.include?("purple"), "Should contain purple color"
|
|
221
|
+
# Should have both triangle and bracket
|
|
222
|
+
assert svg.count("polygon") >= 1, "Should contain polygon (triangle)"
|
|
223
|
+
assert svg.include?("polyline"), "Should contain bracket enclosure"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def test_complex_tree_with_mixed_styling
|
|
227
|
+
# Complex example like 056.md
|
|
228
|
+
data = '[S [#@red:NP [^@blue:N the quick brown fox]] [#@green:VP [V jumps] [PP [P over] [^@purple:NP the lazy dog]]]]'
|
|
229
|
+
opts = @base_opts.merge(data: data)
|
|
230
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
231
|
+
svg = rsg.draw_svg
|
|
232
|
+
|
|
233
|
+
assert_kind_of String, svg
|
|
234
|
+
assert svg.include?("red"), "Should contain red for NP"
|
|
235
|
+
assert svg.include?("blue"), "Should contain blue for N"
|
|
236
|
+
assert svg.include?("green"), "Should contain green for VP"
|
|
237
|
+
assert svg.include?("purple"), "Should contain purple for NP"
|
|
238
|
+
end
|
|
239
|
+
end
|
data/test/tikz_test.rb
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require "minitest/pride"
|
|
5
|
+
require_relative "../lib/rsyntaxtree"
|
|
6
|
+
|
|
7
|
+
class TikZTest < Minitest::Test
|
|
8
|
+
def setup
|
|
9
|
+
@simple_opts = {
|
|
10
|
+
data: "[S [NP hello] [VP world]]",
|
|
11
|
+
fontstyle: "sans"
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_draw_tikz_returns_string
|
|
16
|
+
rsg = RSyntaxTree::RSGenerator.new(@simple_opts)
|
|
17
|
+
tikz = rsg.draw_tikz
|
|
18
|
+
|
|
19
|
+
assert_kind_of String, tikz
|
|
20
|
+
refute_empty tikz
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_tikz_contains_forest_environment
|
|
24
|
+
rsg = RSyntaxTree::RSGenerator.new(@simple_opts)
|
|
25
|
+
tikz = rsg.draw_tikz
|
|
26
|
+
|
|
27
|
+
assert tikz.include?("\\begin{forest}"), "Should contain forest begin"
|
|
28
|
+
assert tikz.include?("\\end{forest}"), "Should contain forest end"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_tikz_contains_tree_structure
|
|
32
|
+
rsg = RSyntaxTree::RSGenerator.new(@simple_opts)
|
|
33
|
+
tikz = rsg.draw_tikz
|
|
34
|
+
|
|
35
|
+
assert tikz.include?("[S"), "Should contain root node S"
|
|
36
|
+
assert tikz.include?("[NP"), "Should contain NP node"
|
|
37
|
+
assert tikz.include?("[VP"), "Should contain VP node"
|
|
38
|
+
assert tikz.include?("hello"), "Should contain terminal hello"
|
|
39
|
+
assert tikz.include?("world"), "Should contain terminal world"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_tikz_with_nested_tree
|
|
43
|
+
opts = {
|
|
44
|
+
data: "[S [NP [Det the] [N dog]] [VP [V runs]]]",
|
|
45
|
+
fontstyle: "sans"
|
|
46
|
+
}
|
|
47
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
48
|
+
tikz = rsg.draw_tikz
|
|
49
|
+
|
|
50
|
+
assert tikz.include?("[Det"), "Should contain Det node"
|
|
51
|
+
assert tikz.include?("[N"), "Should contain N node"
|
|
52
|
+
assert tikz.include?("[V"), "Should contain V node"
|
|
53
|
+
assert tikz.include?("the"), "Should contain terminal 'the'"
|
|
54
|
+
assert tikz.include?("dog"), "Should contain terminal 'dog'"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_tikz_escapes_special_chars
|
|
58
|
+
# Use % and $ which are LaTeX special but not RSyntaxTree special
|
|
59
|
+
# (underscore _ is RSyntaxTree subscript markup, so we avoid it)
|
|
60
|
+
opts = {
|
|
61
|
+
data: "[S [NP 50%] [VP $100]]",
|
|
62
|
+
fontstyle: "sans"
|
|
63
|
+
}
|
|
64
|
+
rsg = RSyntaxTree::RSGenerator.new(opts)
|
|
65
|
+
tikz = rsg.draw_tikz
|
|
66
|
+
|
|
67
|
+
# LaTeX special chars should be escaped
|
|
68
|
+
assert tikz.include?("\\%"), "Should escape percent sign"
|
|
69
|
+
assert tikz.include?("\\$"), "Should escape dollar sign"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_tikz_generates_standalone_option
|
|
73
|
+
rsg = RSyntaxTree::RSGenerator.new(@simple_opts)
|
|
74
|
+
tikz = rsg.draw_tikz(standalone: true)
|
|
75
|
+
|
|
76
|
+
assert tikz.include?("\\documentclass"), "Standalone should have documentclass"
|
|
77
|
+
assert tikz.include?("\\usepackage{forest}"), "Should include forest package"
|
|
78
|
+
assert tikz.include?("\\begin{document}"), "Should have document begin"
|
|
79
|
+
assert tikz.include?("\\end{document}"), "Should have document end"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_tikz_non_standalone_no_preamble
|
|
83
|
+
rsg = RSyntaxTree::RSGenerator.new(@simple_opts)
|
|
84
|
+
tikz = rsg.draw_tikz(standalone: false)
|
|
85
|
+
|
|
86
|
+
refute tikz.include?("\\documentclass"), "Non-standalone should not have documentclass"
|
|
87
|
+
refute tikz.include?("\\begin{document}"), "Non-standalone should not have document"
|
|
88
|
+
end
|
|
89
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rsyntaxtree
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yoichiro Hasebe
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: optimist
|
|
@@ -66,6 +65,20 @@ dependencies:
|
|
|
66
65
|
- - ">="
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
67
|
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: minitest
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
69
82
|
- !ruby/object:Gem::Dependency
|
|
70
83
|
name: nokogiri
|
|
71
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,6 +93,20 @@ dependencies:
|
|
|
80
93
|
- - ">="
|
|
81
94
|
- !ruby/object:Gem::Version
|
|
82
95
|
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: rake
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
83
110
|
- !ruby/object:Gem::Dependency
|
|
84
111
|
name: yaml
|
|
85
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -102,9 +129,13 @@ executables:
|
|
|
102
129
|
extensions: []
|
|
103
130
|
extra_rdoc_files: []
|
|
104
131
|
files:
|
|
132
|
+
- ".github/FUNDING.yml"
|
|
105
133
|
- ".gitignore"
|
|
134
|
+
- ".ruby-version"
|
|
135
|
+
- CHANGELOG.md
|
|
106
136
|
- Dockerfile
|
|
107
137
|
- Gemfile
|
|
138
|
+
- LICENSE
|
|
108
139
|
- README.md
|
|
109
140
|
- Rakefile
|
|
110
141
|
- bin/rsyntaxtree
|
|
@@ -167,6 +198,9 @@ files:
|
|
|
167
198
|
- docs/_examples/051.md
|
|
168
199
|
- docs/_examples/052.md
|
|
169
200
|
- docs/_examples/053.md
|
|
201
|
+
- docs/_examples/054.md
|
|
202
|
+
- docs/_examples/055.md
|
|
203
|
+
- docs/_examples/056.md
|
|
170
204
|
- docs/_includes/box_and_circle_table.html
|
|
171
205
|
- docs/_includes/escape_char_table.html
|
|
172
206
|
- docs/_includes/social_media_links.html
|
|
@@ -226,6 +260,9 @@ files:
|
|
|
226
260
|
- docs/assets/img/051.png
|
|
227
261
|
- docs/assets/img/052.png
|
|
228
262
|
- docs/assets/img/053.png
|
|
263
|
+
- docs/assets/img/054.png
|
|
264
|
+
- docs/assets/img/055.png
|
|
265
|
+
- docs/assets/img/056.png
|
|
229
266
|
- docs/assets/img/elements/arrow_both.png
|
|
230
267
|
- docs/assets/img/elements/arrow_both_bold.png
|
|
231
268
|
- docs/assets/img/elements/arrow_left.png
|
|
@@ -302,6 +339,9 @@ files:
|
|
|
302
339
|
- docs/assets/svg/051.svg
|
|
303
340
|
- docs/assets/svg/052.svg
|
|
304
341
|
- docs/assets/svg/053.svg
|
|
342
|
+
- docs/assets/svg/054.svg
|
|
343
|
+
- docs/assets/svg/055.svg
|
|
344
|
+
- docs/assets/svg/056.svg
|
|
305
345
|
- docs/documentation.md
|
|
306
346
|
- docs/documentation_ja.md
|
|
307
347
|
- docs/examples.html
|
|
@@ -331,19 +371,25 @@ files:
|
|
|
331
371
|
- lib/rsyntaxtree/base_graph.rb
|
|
332
372
|
- lib/rsyntaxtree/element.rb
|
|
333
373
|
- lib/rsyntaxtree/elementlist.rb
|
|
374
|
+
- lib/rsyntaxtree/format_converter.rb
|
|
334
375
|
- lib/rsyntaxtree/markup_parser.rb
|
|
335
376
|
- lib/rsyntaxtree/string_parser.rb
|
|
336
377
|
- lib/rsyntaxtree/svg_graph.rb
|
|
378
|
+
- lib/rsyntaxtree/tikz_generator.rb
|
|
337
379
|
- lib/rsyntaxtree/utils.rb
|
|
338
380
|
- lib/rsyntaxtree/version.rb
|
|
339
381
|
- rsyntaxtree.gemspec
|
|
382
|
+
- syntree.svg
|
|
383
|
+
- test/cli_test.rb
|
|
340
384
|
- test/example_verify_test.rb
|
|
385
|
+
- test/format_converter_test.rb
|
|
341
386
|
- test/markup_parser_test.rb
|
|
387
|
+
- test/node_styling_test.rb
|
|
388
|
+
- test/tikz_test.rb
|
|
342
389
|
homepage: http://github.com/yohasebe/rsyntaxtree
|
|
343
390
|
licenses:
|
|
344
391
|
- MIT
|
|
345
392
|
metadata: {}
|
|
346
|
-
post_install_message:
|
|
347
393
|
rdoc_options: []
|
|
348
394
|
require_paths:
|
|
349
395
|
- lib
|
|
@@ -358,8 +404,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
358
404
|
- !ruby/object:Gem::Version
|
|
359
405
|
version: '0'
|
|
360
406
|
requirements: []
|
|
361
|
-
rubygems_version:
|
|
362
|
-
signing_key:
|
|
407
|
+
rubygems_version: 4.0.3
|
|
363
408
|
specification_version: 4
|
|
364
409
|
summary: RSyntaxTree is a graphical syntax tree generator written in Ruby
|
|
365
410
|
test_files: []
|