rsyntaxtree 1.13.2 → 2.0.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/CHANGELOG.md +211 -23
- data/README.md +57 -4
- data/bin/rsyntaxtree +10 -11
- data/lib/rsyntaxtree/base_graph.rb +17 -8
- data/lib/rsyntaxtree/element.rb +35 -3
- data/lib/rsyntaxtree/lsif_graph.rb +9 -3
- data/lib/rsyntaxtree/markup_parser.rb +16 -4
- data/lib/rsyntaxtree/notation_core.md +108 -42
- data/lib/rsyntaxtree/notation_examples.md +97 -5
- data/lib/rsyntaxtree/string_parser.rb +50 -1
- data/lib/rsyntaxtree/svg_graph.rb +271 -15
- data/lib/rsyntaxtree/tikz_generator.rb +9 -0
- data/lib/rsyntaxtree/version.rb +1 -1
- data/lib/rsyntaxtree.rb +93 -68
- data/rsyntaxtree.gemspec +4 -3
- metadata +1 -29
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ccd433053f296c9189c9eceb87f61c91ed815ff6b1be77f1cd2115a73eaf1cd
|
|
4
|
+
data.tar.gz: f769d68efb73c1aafc9dc9af9f0e4e7cbd7a0c741caf253905ebe11dc3c454be
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0e6218bc0ddf1f4c49e8fac2c8972cbd3e0eb251fe7087150ea73f63b054fe546483588e582a0f01e52ab26c20fd883ab2c67da07adf1f3120755447a7956945
|
|
7
|
+
data.tar.gz: b0810c0df9ede2cd1c36100ae9a3c055ece2d59261f8278ef8de8b79e07921702c7b8db83fa43f81810184c363b860bae3d9a9c1f45b4a02307f5f8220354fa8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,166 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [2.0.0] - 2026-08-28
|
|
4
|
+
|
|
5
|
+
The removals announced in 1.10.0 and 1.12.0, and the fixes that came out of
|
|
6
|
+
looking at what was left. Every figure in the gallery draws exactly as it did.
|
|
7
|
+
|
|
8
|
+
### Removed
|
|
9
|
+
- JPG and GIF output. JPEG blurs line art and GIF has nothing to offer that
|
|
10
|
+
PNG does not do better, and they were the only reason for the RMagick
|
|
11
|
+
dependency. `-f jpg` and `-f gif` are now refused the way any unknown
|
|
12
|
+
format is. Use `-f png`.
|
|
13
|
+
- The RMagick dependency, and with it ImageMagick. A machine that installs
|
|
14
|
+
this gem no longer needs ImageMagick's headers to build one, and the gem
|
|
15
|
+
now asks for four libraries instead of five.
|
|
16
|
+
- The deprecated aliases, which a major release is the moment to drop:
|
|
17
|
+
`symmetrize` and its `-y` flag (say `tidy: symmetric`), `tidy_spacing`
|
|
18
|
+
(say `hspacing`), the undocumented `tidy_nest`, and `nothing`'s
|
|
19
|
+
undocumented spelling `none` in `leafstyle`. Each is refused by name and
|
|
20
|
+
told what replaced it. An unknown option is passed over in silence, since
|
|
21
|
+
a caller may hand its own parameters through, and a removed one read that
|
|
22
|
+
way would have handed back a different figure without a word.
|
|
23
|
+
- `symmetrize` from the LSIF `meta.source.params` block. The layout scale it
|
|
24
|
+
duplicated, `tidy`, is written there already.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- A triangle drawn bottom to top pointed the wrong way. The shape spans the
|
|
28
|
+
child's text and points at the parent, and which way that is depends on
|
|
29
|
+
which of the two sits higher — the question the connectors ask and the
|
|
30
|
+
triangle did not. Bottom to top the figure folded through itself: the base
|
|
31
|
+
struck through the leaf and the apex through the node. No gallery figure
|
|
32
|
+
carries one, because every bottom-to-top example is a derivation, which
|
|
33
|
+
draws rules instead of connectors.
|
|
34
|
+
- Every label now keeps the same air above it as below it. The connector
|
|
35
|
+
endpoints were measured from the layout box, whose edges sit unevenly
|
|
36
|
+
around the ink, so every figure carried a little more space under each
|
|
37
|
+
label than over it — visibly once a figure was tilted. The enclosures
|
|
38
|
+
were built with symmetric clearances all along; the plain labels now get
|
|
39
|
+
what the boxes always had. Nearly every gallery figure changes by a few
|
|
40
|
+
pixels of line length; no label, no position and no size moves.
|
|
41
|
+
- A movement rail could reach past the right edge of a left-to-right
|
|
42
|
+
canvas and be cut off at it: the rail grows the canvas as it routes, and
|
|
43
|
+
the width it grew — unlike the height — was then recomputed from the
|
|
44
|
+
elements alone. Four pixels at the default spacing, twenty-four at
|
|
45
|
+
hspacing 0.5.
|
|
46
|
+
- A rule written `---` (or `===` for a double rule) was refused inside a
|
|
47
|
+
`#( … #)` matrix, though it was drawn in every other kind of label. Two
|
|
48
|
+
hyphens and four were accepted there and three were not — a distinction
|
|
49
|
+
nothing could explain. The matrix grammar had no rule for it and the
|
|
50
|
+
matrix renderer dropped every row that was not text.
|
|
51
|
+
- The bracket of a matrix that followed something in the same cell was drawn
|
|
52
|
+
on top of it: `AGR |1| [ … ]`, which is how a shared value is written, put
|
|
53
|
+
the right edge of the tag and the left edge of the bracket on the same
|
|
54
|
+
coordinate exactly. A block now keeps as much room in front of it as the
|
|
55
|
+
bracket keeps inside it.
|
|
56
|
+
- In a left-to-right tree, `hspacing` and `vheight` both moved the width and
|
|
57
|
+
nothing moved the height. The layout replaces the gap that separates
|
|
58
|
+
sisters with one of its own and was not scaling it by `hspacing`, so a
|
|
59
|
+
left-to-right figure could be made wider but never shorter.
|
|
60
|
+
- `storoke-width` in the style of every text element of every SVG. Renderers
|
|
61
|
+
ignored the misspelling, so nothing ever looked wrong.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
- `shear`: the drawn figure tilts by the given angle (degrees, positive
|
|
65
|
+
leaning the top to the right) and lies on a plane drawn behind it, so the
|
|
66
|
+
lean reads as a surface seen at an angle rather than as a mistake. The
|
|
67
|
+
whole picture shears as one affine piece — layout untouched, region
|
|
68
|
+
shades coming out parallelograms on their own, and nothing able to newly
|
|
69
|
+
touch or cross. The plane is fill without an edge — a region shade is
|
|
70
|
+
bounded because it marks one part of a figure off from the rest, and a
|
|
71
|
+
line round the whole drawing would read as a frame. `shear_plane` turns
|
|
72
|
+
it off or gives it a colour, and a transparent background takes it away
|
|
73
|
+
for you: a clear background is asked for in order to lay the figure over
|
|
74
|
+
something else, and a sheet under it is what would defeat that.
|
|
75
|
+
TikZ refuses a sheared figure the way it refuses a derivation.
|
|
76
|
+
- `vmargin`: the clearance between a label and its connectors, the same
|
|
77
|
+
above and below, measured from the ink its row actually contains — a row
|
|
78
|
+
of capitals pays nothing for descenders nobody wrote, and the ends of a
|
|
79
|
+
row's connectors stay level. From 0.1 to 1.0; at nothing at all a node's
|
|
80
|
+
box stops holding a label that draws its own shape.
|
|
81
|
+
- Three gallery examples, in two new categories: the Indo-European family
|
|
82
|
+
tree (Historical Linguistics), where the region shade groups branches
|
|
83
|
+
rather than marking a c-command domain; type-driven semantic composition
|
|
84
|
+
(Formal Semantics); and a tree of typed feature structures with structure
|
|
85
|
+
sharing (Formal Grammar), which is the figure the matrix rule was missing.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
- The documents name every option. Four were missing from the one-page
|
|
89
|
+
reference and one from the README, because the test that reads the
|
|
90
|
+
documents built its roll-call from the tables of listed and numeric
|
|
91
|
+
values — and so never asked after the options that take on or off. It
|
|
92
|
+
reads the roll-call from the defaults now, and the README is one of the
|
|
93
|
+
documents it reads.
|
|
94
|
+
- Three tests were added for the shapes of defect this release fixed: one
|
|
95
|
+
asks every feature in the index to read the same in a label, in a matrix
|
|
96
|
+
and in a matrix inside a matrix; one reads the drawn shapes back out of
|
|
97
|
+
the SVG and asks whether any two of them touch; and one asks a
|
|
98
|
+
left-to-right tree to answer to `hspacing` in its height.
|
|
99
|
+
- The sweep draws two more figures — one with a triangle, one with a
|
|
100
|
+
movement rail — and moves the direction, `vmargin` and `shear` among its
|
|
101
|
+
settings, and asks of every triangle that it have an area. Each of the two
|
|
102
|
+
defects above lived in a figure the sweep did not draw, at a direction it
|
|
103
|
+
did not set: the settings alone could not have found either, and a
|
|
104
|
+
triangle folded flat passes every other check there is.
|
|
105
|
+
- The manuals say what TikZ output does with what it cannot draw: it drops
|
|
106
|
+
it rather than refusing, so a label that is a matrix arrives with its
|
|
107
|
+
cells run together on one line.
|
|
108
|
+
|
|
109
|
+
### Migration
|
|
110
|
+
- `format: "jpg"` / `"gif"` → `"png"`.
|
|
111
|
+
- `symmetrize: "on"` → `tidy: "symmetric"`; `tidy_spacing: n` → `hspacing: n`;
|
|
112
|
+
`leafstyle: "none"` → `"nothing"`. Each has been the documented spelling
|
|
113
|
+
since 1.12.0.
|
|
114
|
+
- Everything else — every other option, and every piece of notation — is
|
|
115
|
+
unchanged.
|
|
116
|
+
|
|
117
|
+
## [1.14.0] - 2026-08-27
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
- The notation has a map. The reference the gem ships (`--notation`) is one
|
|
121
|
+
page: the characters that already mean something, then every feature at a
|
|
122
|
+
line each with the notation beside it, then the options. Both manuals open
|
|
123
|
+
with the same list, each row pointing at the section that explains it. A test
|
|
124
|
+
reads the feature set out of the grammar itself and draws every sample, so a
|
|
125
|
+
feature the grammar gains with no row in the documents fails the build, and a
|
|
126
|
+
sample that stops meaning what it says fails with it.
|
|
127
|
+
- The changelog is on the documentation site, at /changelog, built from
|
|
128
|
+
CHANGELOG.md and linked from the manuals and the README.
|
|
129
|
+
|
|
130
|
+
### Changed
|
|
131
|
+
- Every release in the changelog is dated to the day, from the git tags. Two of
|
|
132
|
+
the old month-only dates were wrong.
|
|
133
|
+
- What the trap section warns about is now, by definition, what the tool
|
|
134
|
+
accepts and draws as something other than what was meant. A mistake the tool
|
|
135
|
+
refuses is the error message's job, and its card has come down; the warning
|
|
136
|
+
about parentheses, which the Penn Treebank conversion had made false, tells
|
|
137
|
+
the truth again.
|
|
138
|
+
- The arrow markers' dimensions are rounded; the defs of every SVG carried
|
|
139
|
+
float dust in an attribute.
|
|
140
|
+
|
|
141
|
+
### Fixed
|
|
142
|
+
- Turning `derivation` on no longer deletes a column from a node that has no
|
|
143
|
+
daughters. A rule name is written after a column break and names the step
|
|
144
|
+
that produced a node from its daughters, so a node with none names no rule —
|
|
145
|
+
but the label is read before the tree is built, and the name was taken out
|
|
146
|
+
anyway and then had no rule to be drawn beside. `[A\tfoo]` drew "A foo" with
|
|
147
|
+
the option off and "A" with it on. The label is put back once the tree is
|
|
148
|
+
known.
|
|
149
|
+
- A mistake inside a node's label keeps the name of what is wrong with it. The
|
|
150
|
+
first raw space splits a token into a label and its children, and when the
|
|
151
|
+
label would not parse, every cause but one was relabelled "a raw space split
|
|
152
|
+
this" — so the message named an unknown colour while the code and the hint
|
|
153
|
+
talked about spaces, and a caller acting on the code was sent to fix what was
|
|
154
|
+
not wrong. Which story is right is now asked of the parser rather than
|
|
155
|
+
guessed: the token is put back together with its spaces written as the
|
|
156
|
+
notation writes them, and if it reads, the space was the cause.
|
|
157
|
+
- A hex colour is three digits or six, which is what every message about colour
|
|
158
|
+
here already said. The grammar asked for three to six, so four and five
|
|
159
|
+
parsed, passed the validator — which does not look at a value beginning with
|
|
160
|
+
`#` — and reached librsvg, which cannot read them and draws the label black
|
|
161
|
+
without reporting it.
|
|
162
|
+
|
|
163
|
+
## [1.13.2] - 2026-08-27
|
|
4
164
|
|
|
5
165
|
### Fixed
|
|
6
166
|
- A movement path is drawn as one stroke with its corners eased, in place of
|
|
@@ -25,7 +185,7 @@
|
|
|
25
185
|
the gallery is unchanged to the pixel — every raster figure is byte-identical
|
|
26
186
|
and the SVGs differ only in the family list they carry.
|
|
27
187
|
|
|
28
|
-
## [1.13.1] - 2026-08
|
|
188
|
+
## [1.13.1] - 2026-08-27
|
|
29
189
|
|
|
30
190
|
### Fixed
|
|
31
191
|
- `^` at the head of a leaf draws the triangle it asks for. The mark may be
|
|
@@ -44,7 +204,7 @@
|
|
|
44
204
|
every input, because the form still read a `format` select the page no longer
|
|
45
205
|
had. A value that is actually wrong is still rejected.
|
|
46
206
|
|
|
47
|
-
## [1.13.0] - 2026-08
|
|
207
|
+
## [1.13.0] - 2026-08-24
|
|
48
208
|
|
|
49
209
|
### Added
|
|
50
210
|
- Derivations. A derivation puts the words first and the result last, and
|
|
@@ -63,7 +223,7 @@
|
|
|
63
223
|
have when the root is at the top, so every line ran from above the daughter,
|
|
64
224
|
through its label and the mother's, to below the mother.
|
|
65
225
|
|
|
66
|
-
## [1.12.0] - 2026-08
|
|
226
|
+
## [1.12.0] - 2026-08-22
|
|
67
227
|
|
|
68
228
|
Everything needed to write this notation is now available as text, built from
|
|
69
229
|
the files the tool itself reads, and a refusal says where that text is.
|
|
@@ -93,7 +253,7 @@ the files the tool itself reads, and a refusal says where that text is.
|
|
|
93
253
|
meant waiting on a pipe that never closes when stdin is not a terminal,
|
|
94
254
|
which is how a script reaches them.
|
|
95
255
|
|
|
96
|
-
## [1.11.0] - 2026-08
|
|
256
|
+
## [1.11.0] - 2026-08-21
|
|
97
257
|
|
|
98
258
|
Every input the tool accepts now draws, and every input it refuses says why.
|
|
99
259
|
Line thickness follows the type size, so figures drawn at any font size keep
|
|
@@ -152,7 +312,7 @@ fifth lighter than before.
|
|
|
152
312
|
read as a path to the current directory.
|
|
153
313
|
- Overline was documented as missing from PNG output. It has been there.
|
|
154
314
|
|
|
155
|
-
## [1.10.0] - 2026-08
|
|
315
|
+
## [1.10.0] - 2026-08-19
|
|
156
316
|
|
|
157
317
|
A transitional release ahead of 2.0, which drops JPG/GIF output and the
|
|
158
318
|
RMagick dependency.
|
|
@@ -175,7 +335,7 @@ RMagick dependency.
|
|
|
175
335
|
file here carries `frozen_string_literal`, which made the working form the
|
|
176
336
|
unobvious one.
|
|
177
337
|
|
|
178
|
-
## [1.9.0] - 2026-08
|
|
338
|
+
## [1.9.0] - 2026-08-19
|
|
179
339
|
|
|
180
340
|
### Added
|
|
181
341
|
- `hyphen: literal`, which trades the two readings of a hyphen: a bare one is
|
|
@@ -243,7 +403,7 @@ RMagick dependency.
|
|
|
243
403
|
the arrow was drawn small to fit; now the pair is spread and the arrow keeps
|
|
244
404
|
its size. Only pairs that carry a link move, and only when they need to.
|
|
245
405
|
|
|
246
|
-
## [1.8.2] - 2026-08
|
|
406
|
+
## [1.8.2] - 2026-08-17
|
|
247
407
|
|
|
248
408
|
### Changed
|
|
249
409
|
- `tidy: high` now compresses as far as its name promises. The level-balance
|
|
@@ -271,7 +431,7 @@ RMagick dependency.
|
|
|
271
431
|
resolved nowhere on macOS, Debian/Ubuntu or Alpine; the chain fell through
|
|
272
432
|
to `Noto Sans Mono`, which it now names directly.
|
|
273
433
|
|
|
274
|
-
## [1.8.1] - 2026-08
|
|
434
|
+
## [1.8.1] - 2026-08-15
|
|
275
435
|
|
|
276
436
|
### Fixed
|
|
277
437
|
- Arabic rendered as isolated, unjoined letterforms in some environments.
|
|
@@ -300,7 +460,7 @@ RMagick dependency.
|
|
|
300
460
|
- Documentation records how to override any of the named families with a
|
|
301
461
|
fontconfig alias, for users who prefer their own script fonts.
|
|
302
462
|
|
|
303
|
-
## [1.8.0] - 2026-08
|
|
463
|
+
## [1.8.0] - 2026-08-15
|
|
304
464
|
|
|
305
465
|
### Added
|
|
306
466
|
- `tidy` layout scale, one option covering every layout mode from the most
|
|
@@ -349,7 +509,7 @@ RMagick dependency.
|
|
|
349
509
|
when the caller passes only a partial parameter set (e.g. `tidy: off`
|
|
350
510
|
rendered as `symmetric` in the web UI).
|
|
351
511
|
|
|
352
|
-
## [1.7.0] - 2026-08
|
|
512
|
+
## [1.7.0] - 2026-08-13
|
|
353
513
|
|
|
354
514
|
### Changed
|
|
355
515
|
- Text measurement now uses Pango, the same engine (and the same fontconfig
|
|
@@ -369,7 +529,7 @@ RMagick dependency.
|
|
|
369
529
|
- Runtime dependency on the `pango` gem (ruby-gnome). No new system
|
|
370
530
|
requirements: librsvg already depends on Pango.
|
|
371
531
|
|
|
372
|
-
## [1.6.3] - 2026-07
|
|
532
|
+
## [1.6.3] - 2026-07-19
|
|
373
533
|
|
|
374
534
|
### Fixed
|
|
375
535
|
- Packaged files no longer carry owner-only permissions. `gem build` preserves
|
|
@@ -381,14 +541,14 @@ RMagick dependency.
|
|
|
381
541
|
tree had picked up on data files (images, fonts, Markdown, CSS, library
|
|
382
542
|
sources).
|
|
383
543
|
|
|
384
|
-
## [1.6.2] - 2026-06
|
|
544
|
+
## [1.6.2] - 2026-06-26
|
|
385
545
|
|
|
386
546
|
### Fixed
|
|
387
547
|
- Region shade no longer touches the image edge when its padded bounds reach
|
|
388
548
|
past the tree's natural extent (e.g. a deep enclosed/multi-line node): the
|
|
389
549
|
canvas now grows with a margin around the shaded plane.
|
|
390
550
|
|
|
391
|
-
## [1.6.1] - 2026-06
|
|
551
|
+
## [1.6.1] - 2026-06-26
|
|
392
552
|
|
|
393
553
|
### Improved
|
|
394
554
|
- Region shade rendering wraps the subtree more cleanly: wider, balanced
|
|
@@ -402,7 +562,7 @@ RMagick dependency.
|
|
|
402
562
|
- Example 065: nested (overlapping) region shades, shown as progressively
|
|
403
563
|
darker gray.
|
|
404
564
|
|
|
405
|
-
## [1.6.0] - 2026-06
|
|
565
|
+
## [1.6.0] - 2026-06-25
|
|
406
566
|
|
|
407
567
|
### Added
|
|
408
568
|
- Region shade (`%` prefix): paints a semi-transparent plane behind the whole
|
|
@@ -430,7 +590,7 @@ RMagick dependency.
|
|
|
430
590
|
- Region shade on the root/topmost node no longer clipped by the canvas: the
|
|
431
591
|
SVG viewBox now grows to include region planes that extend past the tree.
|
|
432
592
|
|
|
433
|
-
## [1.5.0] - 2026-04
|
|
593
|
+
## [1.5.0] - 2026-04-06
|
|
434
594
|
|
|
435
595
|
### Added
|
|
436
596
|
- Left-to-right tree layout (`-d ltr` / `--direction ltr`)
|
|
@@ -445,7 +605,7 @@ RMagick dependency.
|
|
|
445
605
|
### Improved
|
|
446
606
|
- TTB path bulge proportional to endpoint distance (reduced excess)
|
|
447
607
|
|
|
448
|
-
## [1.4.0] - 2026-01
|
|
608
|
+
## [1.4.0] - 2026-01-06
|
|
449
609
|
|
|
450
610
|
### Added
|
|
451
611
|
- LSIF (Linguistic Structure Interchange Format) JSON output (`-f lsif`)
|
|
@@ -461,18 +621,46 @@ RMagick dependency.
|
|
|
461
621
|
- Added examples for per-node coloring (054, 055, 056)
|
|
462
622
|
- Added example 057: Subscript and superscript demo
|
|
463
623
|
|
|
464
|
-
## [1.3.2] -
|
|
624
|
+
## [1.3.2] - 2025-03-03
|
|
465
625
|
|
|
466
626
|
- Garbage collection friendly implementation
|
|
467
627
|
|
|
468
|
-
## [1.3.1] - 2024
|
|
628
|
+
## [1.3.1] - 2024-10-24
|
|
469
629
|
|
|
630
|
+
- Square brackets can be escaped with `\[` and `\]`
|
|
470
631
|
- Bug fixes and improvements
|
|
471
632
|
|
|
472
|
-
## [1.3.0] - 2024
|
|
633
|
+
## [1.3.0] - 2024-08-27
|
|
473
634
|
|
|
474
635
|
- TikZ/forest LaTeX output support
|
|
475
636
|
|
|
476
|
-
##
|
|
477
|
-
|
|
478
|
-
|
|
637
|
+
## Earlier releases (2018–2023)
|
|
638
|
+
|
|
639
|
+
Before this file was kept, the web interface carried the release notes. Moved
|
|
640
|
+
here so the history has one home.
|
|
641
|
+
|
|
642
|
+
- 2023-09 — Cross-hatch rendering issue fixed
|
|
643
|
+
- 2023-02 — PDF download; improved line edges; `Line width` option;
|
|
644
|
+
`Traditional` colour option; `Hide connectors` option; extra connectors
|
|
645
|
+
between nodes
|
|
646
|
+
- 2023-01 — `Noto Sans Mono` font option
|
|
647
|
+
- 2022-11 — `¥` accepted in place of the backslash for escapes; documentation
|
|
648
|
+
in Japanese
|
|
649
|
+
- 2022-06 — RSyntaxTree on the Web: the UI as a source package, runnable
|
|
650
|
+
locally with Docker
|
|
651
|
+
- 2022-02 — `Polyline connector` option
|
|
652
|
+
- 2022-01 — comprehensive rewrite; path drawing (non-directional, directional,
|
|
653
|
+
bidirectional); more flexible text markup; new markup patterns (newlines,
|
|
654
|
+
brackets, horizontal lines, boxed text); triangles in every connector mode;
|
|
655
|
+
improved error display and image zoom in the UI
|
|
656
|
+
- 2021-12 — subscript `_text_` and superscript `__text__`; `\n` inside
|
|
657
|
+
terminal nodes
|
|
658
|
+
- 2021-11 — label-less terminal nodes (`[A [B] [C]]`); auto bracket close;
|
|
659
|
+
math symbol rendering; better image quality; some decoration symbols altered
|
|
660
|
+
- 2019-11 — SVG download error fixed
|
|
661
|
+
- 2019-04 — SVG colour on/off fixed
|
|
662
|
+
- 2018-06 — whitespace in labels with `<>` (`Modal<>AUX`)
|
|
663
|
+
- 2018-03 — `V spacing` option (then called Connector height); syntax
|
|
664
|
+
highlighting of the input; text styles (italic, bold) and decoration
|
|
665
|
+
(underline, overline, line-through); refined site design
|
|
666
|
+
- 2018-02 — margins around the image; better editor (Ace)
|
data/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Connect nodes with lines or arrows:
|
|
|
69
69
|
|
|
70
70
|
### Multiple Output Formats
|
|
71
71
|
|
|
72
|
-
Generate trees in PNG, SVG, PDF, or LSIF (JSON) format.
|
|
72
|
+
Generate trees in PNG, SVG, PDF, TikZ, or LSIF (JSON) format.
|
|
73
73
|
|
|
74
74
|
## Web Interface
|
|
75
75
|
|
|
@@ -170,18 +170,25 @@ Usage:
|
|
|
170
170
|
| Option | Description | Default |
|
|
171
171
|
|--------|-------------|---------|
|
|
172
172
|
| `-o, --outdir` | Output directory | `./` |
|
|
173
|
-
| `-f, --format` | Output format: png, svg, pdf, lsif, tikz
|
|
173
|
+
| `-f, --format` | Output format: png, svg, pdf, lsif, tikz | `png` |
|
|
174
174
|
| `-l, --leafstyle` | Leaf style: auto, triangle, bar, nothing | `auto` |
|
|
175
175
|
| `-n, --fontstyle` | Font style: sans, serif, cjk, mono | `sans` |
|
|
176
176
|
| `-s, --fontsize` | Font size: 6-26 | `16` |
|
|
177
177
|
| `-i, --linewidth` | Line width relative to the font size: 0.5-3.0 (`1` = 5% of the font size) | `1.0` |
|
|
178
178
|
| `-c, --color` | Color mode: modern, traditional, gray (black text, grey lines), off | `modern` |
|
|
179
179
|
| `-p, --polyline` | Polyline connectors: on, off | `off` |
|
|
180
|
-
|
|
|
180
|
+
| `--hide-default-connectors` | Draw no parent-to-child lines, leaving only the ones written with `+-n`: on, off | `off` |
|
|
181
|
+
| `-d, --direction` | Tree layout direction: ttb, ltr, btt | `ttb` |
|
|
181
182
|
| `--tidy` | Layout scale: off, symmetric, low, medium, high | `off` |
|
|
182
|
-
| `--hspacing` |
|
|
183
|
+
| `--hspacing` | How far apart sisters sit, all layout modes (0.5-3.0) | `1.0` |
|
|
184
|
+
| `-v, --vheight` | How far apart levels sit (0.5-5.0) | `2.0` |
|
|
185
|
+
| `--derivation` | Join each node to its daughters with one rule drawn across them: on, off | `off` |
|
|
183
186
|
| `--hyphen` | How a hyphen reads: markup (`-underline-`) or literal | `markup` |
|
|
184
187
|
| `-m, --mirror` | Flip the tree horizontally (RTL convention): on, off | `off` |
|
|
188
|
+
| `--shear` | Tilt the drawn figure, in degrees (-45 to 45, positive leans the top right) | `0` |
|
|
189
|
+
| `--shear-plane` | The plane behind a sheared figure: on, off, or a colour | `on` |
|
|
190
|
+
| `--vmargin` | Clearance between a label and its connectors (0.1-1.0, same above and below) | `0.4` |
|
|
191
|
+
| `-r, --transparent` | Leave the background clear instead of painting it white: on, off | `off` |
|
|
185
192
|
| `--validate` | Check the input without drawing: a JSON diagnosis on stdout, the verdict in the exit code | |
|
|
186
193
|
| `--notation` | Print a short reference for the notation | |
|
|
187
194
|
|
|
@@ -206,6 +213,51 @@ fontsize: 18
|
|
|
206
213
|
|
|
207
214
|
CLI options override config file settings.
|
|
208
215
|
|
|
216
|
+
## Using RSyntaxTree with an AI Model
|
|
217
|
+
|
|
218
|
+
The notation is small, but several characters in it already mean something, so
|
|
219
|
+
a model writing it does better with the reference in front of it than without.
|
|
220
|
+
|
|
221
|
+
**If the model only writes the notation** and you draw it yourself — in the
|
|
222
|
+
[web interface](https://yohasebe.com/rsyntaxtree) or on your own machine —
|
|
223
|
+
nothing needs installing. Give the model one of these to read:
|
|
224
|
+
|
|
225
|
+
- [The reference, on one page](https://yohasebe.github.io/rsyntaxtree/notation.txt):
|
|
226
|
+
the characters that already mean something, then every feature at a line
|
|
227
|
+
each, then the options. About 6 KB.
|
|
228
|
+
- [Everything in one file](https://yohasebe.github.io/rsyntaxtree/llms-full.txt):
|
|
229
|
+
the reference, the manual and all the gallery examples, about 85 KB.
|
|
230
|
+
|
|
231
|
+
**If the model can run a shell**, it can draw and then look at what it drew,
|
|
232
|
+
which is the part that lets it correct itself:
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
docker run --rm -v "$PWD:/work" -w /work ghcr.io/yohasebe/rsyntaxtree \
|
|
236
|
+
rsyntaxtree --notation # the reference, on stdout
|
|
237
|
+
docker run --rm -v "$PWD:/work" -w /work ghcr.io/yohasebe/rsyntaxtree \
|
|
238
|
+
rsyntaxtree -f png -o . "[S [NP a tree] [VP appears]]"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Then read `syntree.png` back. `--examples` prints every gallery example with
|
|
242
|
+
the settings it was drawn at, and `--validate` reports what is wrong with an
|
|
243
|
+
input as JSON — including whether rewriting it is worth trying — without
|
|
244
|
+
drawing anything:
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{ "schema": "rsyntaxtree.error/1", "ok": false,
|
|
248
|
+
"errors": [ { "code": "unbalanced_brackets",
|
|
249
|
+
"message": "Error: open and close brackets do not match",
|
|
250
|
+
"hint": "Count the brackets: every '[' needs one ']'.",
|
|
251
|
+
"retryable": true } ],
|
|
252
|
+
"reference": "rsyntaxtree --notation, or https://yohasebe.github.io/rsyntaxtree/llms-full.txt" }
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The exit code carries the verdict too, so a script can branch on it without
|
|
256
|
+
reading the JSON. The Docker image is used above because this tool draws
|
|
257
|
+
through Pango and librsvg, and a figure depends on which versions of those —
|
|
258
|
+
and which fonts — are installed; the image fixes all of them. Installed as a
|
|
259
|
+
gem it works the same, once those libraries are on the machine.
|
|
260
|
+
|
|
209
261
|
## Documentation
|
|
210
262
|
|
|
211
263
|
For detailed documentation on syntax and markup:
|
|
@@ -213,6 +265,7 @@ For detailed documentation on syntax and markup:
|
|
|
213
265
|
- [Documentation in English](https://yohasebe.github.io/rsyntaxtree/documentation)
|
|
214
266
|
- [日本語ドキュメント](https://yohasebe.github.io/rsyntaxtree/documentation_ja)
|
|
215
267
|
- [Example Gallery](https://yohasebe.github.io/rsyntaxtree/examples)
|
|
268
|
+
- [Changelog](https://yohasebe.github.io/rsyntaxtree/changelog)
|
|
216
269
|
|
|
217
270
|
## How to Cite
|
|
218
271
|
|
data/bin/rsyntaxtree
CHANGED
|
@@ -9,7 +9,7 @@ require_relative '../lib/rsyntaxtree'
|
|
|
9
9
|
require_relative '../lib/rsyntaxtree/utils'
|
|
10
10
|
require_relative '../lib/rsyntaxtree/format_converter'
|
|
11
11
|
|
|
12
|
-
# "png,
|
|
12
|
+
# "png, pdf, svg, lsif, or tikz" — built once from the library's
|
|
13
13
|
# own list so the three places that name the formats cannot drift apart.
|
|
14
14
|
FORMAT_LIST_MESSAGE = FORMATS.join(", ").sub(/, ([^,]+)\z/, ', or \1')
|
|
15
15
|
|
|
@@ -24,14 +24,15 @@ CONFIG_VALIDATORS = {
|
|
|
24
24
|
linewidth: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 3.0 ? nil : "must be in the range of 0.5-3.0" },
|
|
25
25
|
vheight: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 5.0 ? nil : "must be in the range of 0.5-5.0" },
|
|
26
26
|
color: ->(v) { OPTION_VALUES[:color].include?(v.to_s) ? nil : "must be modern, traditional, gray, or off" },
|
|
27
|
-
symmetrize: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
28
27
|
transparent: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
29
28
|
polyline: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
30
29
|
hide_default_connectors: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
31
30
|
mirror: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
31
|
+
shear: ->(v) { v.is_a?(Numeric) && v >= -45 && v <= 45 ? nil : "must be in the range of -45-45" },
|
|
32
|
+
vmargin: ->(v) { v.is_a?(Numeric) && v >= 0.1 && v <= 1.0 ? nil : "must be in the range of 0.1-1.0" },
|
|
33
|
+
shear_plane: ->(v) { v.to_s =~ /\A(on|off)\z/ || RSyntaxTree::COLOR_NAMES.include?(v.to_s.downcase) || v.to_s =~ /\A#(\h{3}|\h{6})\z/ ? nil : "must be on, off, or a colour" },
|
|
32
34
|
tidy: ->(v) { OPTION_VALUES[:tidy].include?(v.to_s) ? nil : "must be off, symmetric, low, medium, or high" },
|
|
33
35
|
hspacing: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 3.0 ? nil : "must be in the range of 0.5-3.0" },
|
|
34
|
-
tidy_spacing: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 3.0 ? nil : "must be in the range of 0.5-3.0" },
|
|
35
36
|
direction: ->(v) { OPTION_VALUES[:direction].include?(v.to_s) ? nil : "must be one of: #{OPTION_VALUES[:direction].join(', ')}" },
|
|
36
37
|
hyphen: ->(v) { OPTION_VALUES[:hyphen].include?(v.to_s) ? nil : "must be markup or literal" }
|
|
37
38
|
}.freeze
|
|
@@ -114,14 +115,15 @@ opts = Optimist.options do
|
|
|
114
115
|
opt :linewidth, "Size: 0.5-3.0", default: 1.0, short: :i
|
|
115
116
|
opt :vheight, "Connector Height: 0.5-5.0", default: 2.0, short: :v
|
|
116
117
|
opt :color, "Color text and bars: modern, traditional, gray, or off", default: "modern", short: :c
|
|
117
|
-
opt :symmetrize, "DEPRECATED alias of --tidy symmetric: on or off", default: "off", short: :y
|
|
118
118
|
opt :transparent, "Make background transparent: on or off", default: "off", short: :r
|
|
119
119
|
opt :polyline, "draw polyline connectors: on or off", default: "off", short: :p
|
|
120
120
|
opt :hide_default_connectors, "make default connectors transparent: on or off", default: "off", short: :none
|
|
121
121
|
opt :mirror, "flip the tree horizontally (RTL linguistics convention: first word at the right edge): on or off", default: "off"
|
|
122
|
+
opt :shear, "Tilt the drawn figure, in degrees: -45 to 45, positive leaning the top to the right", default: 0.0, short: :none
|
|
123
|
+
opt :shear_plane, "The plane behind a sheared figure: on, off, a colour name, or a hex colour", default: "on", short: :none
|
|
124
|
+
opt :vmargin, "Clearance between a label and its connectors, 0.1-1.0", default: 0.4, short: :none
|
|
122
125
|
opt :tidy, "tidy tree layout: off, symmetric (radical symmetrization), low (packed, strict leaf positions), medium (packed; leaves may overlap but never swap order), or high (packed; leaf order kept per row only)", default: "off", short: :none
|
|
123
126
|
opt :hspacing, "Horizontal spacing factor (counterpart of vheight): 0.5-3.0", default: 1.0, short: :none
|
|
124
|
-
opt :tidy_spacing, "DEPRECATED alias of --hspacing: 0.5-3.0", default: 1.0, short: :none
|
|
125
127
|
opt :direction, "Tree layout direction: ttb (top-to-bottom), ltr (left-to-right) or btt (bottom-to-top, the root last)", default: "ttb", short: :d
|
|
126
128
|
opt :derivation, "Join each node to its daughters with one rule drawn across them, as a derivation is written, rather than with a line to each: on, off", default: "off", short: :none
|
|
127
129
|
opt :hyphen, "How a hyphen in a label reads: markup (-underline-) or literal (a hyphen; \-underline\- then underlines)", default: "markup", short: :none
|
|
@@ -140,8 +142,10 @@ Optimist.die :leafstyle, "must be auto, triangle, bar, or nothing" unless OPTION
|
|
|
140
142
|
Optimist.die :fontstyle, "must be sans, serif, cjk, or mono" unless OPTION_VALUES[:fontstyle].include?(opts[:fontstyle])
|
|
141
143
|
Optimist.die :fontsize, "must be in the range of 6-26" unless opts[:fontsize] >= 6 && opts[:fontsize] <= 26
|
|
142
144
|
Optimist.die :linewidth, "must be in the range of 0.5-3.0" unless opts[:linewidth] >= 0.5 && opts[:linewidth] <= 3.0
|
|
145
|
+
Optimist.die :shear, "must be in the range of -45-45" unless opts[:shear] >= -45 && opts[:shear] <= 45
|
|
146
|
+
Optimist.die :vmargin, "must be in the range of 0.1-1.0" unless opts[:vmargin] >= 0.1 && opts[:vmargin] <= 1.0
|
|
147
|
+
Optimist.die :shear_plane, "must be on, off, or a colour" unless /\A(on|off)\z/ =~ opts[:shear_plane] || RSyntaxTree::COLOR_NAMES.include?(opts[:shear_plane].downcase) || /\A#(\h{3}|\h{6})\z/ =~ opts[:shear_plane]
|
|
143
148
|
Optimist.die :color, "must be either modern, traditional, gray, or off" unless OPTION_VALUES[:color].include?(opts[:color])
|
|
144
|
-
Optimist.die :symmetrize, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:symmetrize]
|
|
145
149
|
Optimist.die :vheight, "must be in the range of 0.5-5.0" if opts[:vheight] < 0.5 || opts[:vheight] > 5.0
|
|
146
150
|
Optimist.die :transparent, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:transparent]
|
|
147
151
|
Optimist.die :polyline, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:polyline]
|
|
@@ -149,7 +153,6 @@ Optimist.die :hide_default_connectors, "must be either on or off" unless /\A(on|
|
|
|
149
153
|
Optimist.die :mirror, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:mirror]
|
|
150
154
|
Optimist.die :tidy, "must be off, symmetric, low, medium, or high" unless OPTION_VALUES[:tidy].include?(opts[:tidy])
|
|
151
155
|
Optimist.die :hspacing, "must be in the range of 0.5-3.0" if opts[:hspacing] < 0.5 || opts[:hspacing] > 3.0
|
|
152
|
-
Optimist.die :tidy_spacing, "must be in the range of 0.5-3.0" if opts[:tidy_spacing] < 0.5 || opts[:tidy_spacing] > 3.0
|
|
153
156
|
|
|
154
157
|
# Merge config file options with CLI options (CLI takes precedence)
|
|
155
158
|
string_opts = {}
|
|
@@ -170,10 +173,6 @@ opts.each do |key, value|
|
|
|
170
173
|
end
|
|
171
174
|
end
|
|
172
175
|
|
|
173
|
-
if %w[jpg gif].include?(string_opts[:format])
|
|
174
|
-
warn "Warning: #{string_opts[:format].upcase} output is deprecated and will be removed in RSyntaxTree 2.0. Use PNG instead."
|
|
175
|
-
end
|
|
176
|
-
|
|
177
176
|
# These print and exit, so they answer before the input is read. Reading
|
|
178
177
|
# first meant waiting on a pipe that never closes when stdin is not a
|
|
179
178
|
# terminal, which is how they are reached from a script.
|
|
@@ -14,7 +14,6 @@ module RSyntaxTree
|
|
|
14
14
|
def initialize(element_list, params, global)
|
|
15
15
|
@global = global
|
|
16
16
|
@element_list = element_list
|
|
17
|
-
@symmetrize = params[:symmetrize] == true
|
|
18
17
|
@direction = params[:direction] || "ttb"
|
|
19
18
|
|
|
20
19
|
case params[:color]
|
|
@@ -72,13 +71,10 @@ module RSyntaxTree
|
|
|
72
71
|
# "off" | "low" (packing, strict leaf positions) | "medium" (packing
|
|
73
72
|
# with cross-row tucking as long as no two leaves swap left-right
|
|
74
73
|
# order) | "high" (free tucking; leaf order kept per row only).
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
# meaningless, so packing wins over a legacy symmetrize flag.
|
|
74
|
+
# One scale, and nothing beside it: the standalone symmetrize and
|
|
75
|
+
# tidy_nest flags that used to lift a mode into another were removed
|
|
76
|
+
# in 2.0, so what is asked for is what is drawn.
|
|
79
77
|
tidy_mode = params[:tidy].to_s
|
|
80
|
-
tidy_mode = "high" if tidy_mode == "low" && params[:tidy_nest] == true
|
|
81
|
-
tidy_mode = "symmetric" if tidy_mode == "off" && @symmetrize
|
|
82
78
|
@tidy = %w[low medium high].include?(tidy_mode)
|
|
83
79
|
# :none — leaf spans may not overlap at all (strict positions)
|
|
84
80
|
# :ordered — spans may overlap, but leaf centers keep their order
|
|
@@ -966,7 +962,13 @@ module RSyntaxTree
|
|
|
966
962
|
# is disproportionately large relative to the swapped content dimensions.
|
|
967
963
|
# Use height_connector_to_text / 2 (= font_height / 4) for tight
|
|
968
964
|
# vertical packing proportional to the font size.
|
|
969
|
-
|
|
965
|
+
#
|
|
966
|
+
# Scaled by hspacing, like the gap it replaces. Without it the two
|
|
967
|
+
# spacing options both pushed the width in this direction — hspacing
|
|
968
|
+
# only through the margins it is left in — and nothing at all decided
|
|
969
|
+
# how far apart siblings sat, so a left-to-right tree could be made
|
|
970
|
+
# wider but never shorter.
|
|
971
|
+
@global[:h_gap_between_nodes] = @global[:height_connector_to_text] / 2 * @global[:hspacing]
|
|
970
972
|
|
|
971
973
|
# In LTR, height_connector becomes horizontal depth between levels.
|
|
972
974
|
# After content swap, content_height = original content_width (small),
|
|
@@ -1090,7 +1092,14 @@ module RSyntaxTree
|
|
|
1090
1092
|
max_x = @rule_name_edge if @rule_name_edge.to_f > max_x
|
|
1091
1093
|
width = max_x + @global[:h_gap_between_nodes]
|
|
1092
1094
|
height = max_y
|
|
1095
|
+
# A movement path routes outside the tree — below it top-to-bottom,
|
|
1096
|
+
# beyond it to the right left-to-right — and grows @height or @width as
|
|
1097
|
+
# it goes. The height has always been read back here; the width was
|
|
1098
|
+
# computed from the elements alone and then overwrote what the path had
|
|
1099
|
+
# grown, so a left-to-right path could reach past the canvas and be cut
|
|
1100
|
+
# off at its edge.
|
|
1093
1101
|
height = @height if @height > height
|
|
1102
|
+
width = @width if @width > width
|
|
1094
1103
|
{ height: height, width: width }
|
|
1095
1104
|
end
|
|
1096
1105
|
end
|