rsyntaxtree 1.7.0 → 1.8.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/workflows/test.yml +35 -0
- data/CHANGELOG.md +49 -0
- data/CITATION.cff +2 -2
- data/Dockerfile +3 -4
- data/README.md +14 -2
- data/bin/rsyntaxtree +29 -20
- data/lib/rsyntaxtree/base_graph.rb +381 -2
- data/lib/rsyntaxtree/element.rb +14 -0
- data/lib/rsyntaxtree/lsif_graph.rb +12 -2
- data/lib/rsyntaxtree/string_parser.rb +1 -4
- data/lib/rsyntaxtree/svg_graph.rb +12 -9
- data/lib/rsyntaxtree/utils.rb +7 -4
- data/lib/rsyntaxtree/version.rb +1 -1
- data/lib/rsyntaxtree.rb +53 -50
- data/rsyntaxtree.gemspec +6 -2
- metadata +3 -266
- data/dev/generate_examples.rb +0 -96
- data/dev/region_shade_proposal.md +0 -66
- data/docs/.gitignore +0 -5
- data/docs/404.html +0 -25
- data/docs/Gemfile +0 -33
- data/docs/_config.yml +0 -77
- data/docs/_examples/000.md +0 -28
- data/docs/_examples/001.md +0 -26
- data/docs/_examples/002.md +0 -35
- data/docs/_examples/003.md +0 -29
- data/docs/_examples/004.md +0 -29
- data/docs/_examples/005.md +0 -26
- data/docs/_examples/006.md +0 -29
- data/docs/_examples/007.md +0 -30
- data/docs/_examples/008.md +0 -32
- data/docs/_examples/009.md +0 -28
- data/docs/_examples/010.md +0 -52
- data/docs/_examples/011.md +0 -41
- data/docs/_examples/012.md +0 -44
- data/docs/_examples/013.md +0 -66
- data/docs/_examples/014.md +0 -51
- data/docs/_examples/015.md +0 -34
- data/docs/_examples/016.md +0 -86
- data/docs/_examples/017.md +0 -26
- data/docs/_examples/018.md +0 -32
- data/docs/_examples/019.md +0 -63
- data/docs/_examples/020.md +0 -43
- data/docs/_examples/021.md +0 -46
- data/docs/_examples/022.md +0 -61
- data/docs/_examples/023.md +0 -26
- data/docs/_examples/024.md +0 -26
- data/docs/_examples/025.md +0 -90
- data/docs/_examples/026.md +0 -30
- data/docs/_examples/027.md +0 -57
- data/docs/_examples/028.md +0 -23
- data/docs/_examples/029.md +0 -59
- data/docs/_examples/030.md +0 -36
- data/docs/_examples/031.md +0 -23
- data/docs/_examples/032.md +0 -30
- data/docs/_examples/033.md +0 -27
- data/docs/_examples/034.md +0 -29
- data/docs/_examples/035.md +0 -37
- data/docs/_examples/036.md +0 -20
- data/docs/_examples/037.md +0 -21
- data/docs/_examples/038.md +0 -33
- data/docs/_examples/039.md +0 -17
- data/docs/_examples/040.md +0 -63
- data/docs/_examples/041.md +0 -35
- data/docs/_examples/042.md +0 -22
- data/docs/_examples/043.md +0 -40
- data/docs/_examples/044.md +0 -16
- data/docs/_examples/045.md +0 -48
- data/docs/_examples/046.md +0 -440
- data/docs/_examples/047.md +0 -21
- data/docs/_examples/048.md +0 -71
- data/docs/_examples/049.md +0 -49
- data/docs/_examples/050.md +0 -96
- data/docs/_examples/051.md +0 -95
- data/docs/_examples/052.md +0 -58
- data/docs/_examples/053.md +0 -34
- data/docs/_examples/054.md +0 -22
- data/docs/_examples/055.md +0 -24
- data/docs/_examples/056.md +0 -25
- data/docs/_examples/057.md +0 -34
- data/docs/_examples/058.md +0 -47
- data/docs/_examples/059.md +0 -54
- data/docs/_examples/060.md +0 -72
- data/docs/_examples/061.md +0 -97
- data/docs/_examples/062.md +0 -96
- data/docs/_examples/063.md +0 -53
- data/docs/_examples/064.md +0 -25
- data/docs/_examples/065.md +0 -22
- data/docs/_includes/box_and_circle_table.html +0 -78
- data/docs/_includes/escape_char_table.html +0 -29
- data/docs/_includes/social_media_links.html +0 -13
- data/docs/_layouts/default.html +0 -43
- data/docs/assets/css/style.scss +0 -31
- data/docs/assets/img/000.png +0 -0
- data/docs/assets/img/001.png +0 -0
- data/docs/assets/img/002.png +0 -0
- data/docs/assets/img/003.png +0 -0
- data/docs/assets/img/004.png +0 -0
- data/docs/assets/img/005.png +0 -0
- data/docs/assets/img/006.png +0 -0
- data/docs/assets/img/007.png +0 -0
- data/docs/assets/img/008.png +0 -0
- data/docs/assets/img/009.png +0 -0
- data/docs/assets/img/010.png +0 -0
- data/docs/assets/img/011.png +0 -0
- data/docs/assets/img/012.png +0 -0
- data/docs/assets/img/013.png +0 -0
- data/docs/assets/img/014.png +0 -0
- data/docs/assets/img/015.png +0 -0
- data/docs/assets/img/016.png +0 -0
- data/docs/assets/img/017.png +0 -0
- data/docs/assets/img/018.png +0 -0
- data/docs/assets/img/019.png +0 -0
- data/docs/assets/img/020.png +0 -0
- data/docs/assets/img/021.png +0 -0
- data/docs/assets/img/022.png +0 -0
- data/docs/assets/img/023.png +0 -0
- data/docs/assets/img/024.png +0 -0
- data/docs/assets/img/025.png +0 -0
- data/docs/assets/img/026.png +0 -0
- data/docs/assets/img/027.png +0 -0
- data/docs/assets/img/028.png +0 -0
- data/docs/assets/img/029.png +0 -0
- data/docs/assets/img/030.png +0 -0
- data/docs/assets/img/031.png +0 -0
- data/docs/assets/img/032.png +0 -0
- data/docs/assets/img/033.png +0 -0
- data/docs/assets/img/034.png +0 -0
- data/docs/assets/img/035.png +0 -0
- data/docs/assets/img/036.png +0 -0
- data/docs/assets/img/037.png +0 -0
- data/docs/assets/img/038.png +0 -0
- data/docs/assets/img/039.png +0 -0
- data/docs/assets/img/040.png +0 -0
- data/docs/assets/img/041.png +0 -0
- data/docs/assets/img/042.png +0 -0
- data/docs/assets/img/043.png +0 -0
- data/docs/assets/img/044.png +0 -0
- data/docs/assets/img/045.png +0 -0
- data/docs/assets/img/046.png +0 -0
- data/docs/assets/img/047.png +0 -0
- data/docs/assets/img/048.png +0 -0
- data/docs/assets/img/049.png +0 -0
- data/docs/assets/img/050.png +0 -0
- data/docs/assets/img/051.png +0 -0
- data/docs/assets/img/052.png +0 -0
- data/docs/assets/img/053.png +0 -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/img/057.png +0 -0
- data/docs/assets/img/058.png +0 -0
- data/docs/assets/img/059.png +0 -0
- data/docs/assets/img/060.png +0 -0
- data/docs/assets/img/061.png +0 -0
- data/docs/assets/img/062.png +0 -0
- data/docs/assets/img/063.png +0 -0
- data/docs/assets/img/064.png +0 -0
- data/docs/assets/img/065.png +0 -0
- data/docs/assets/img/elements/arrow_both.png +0 -0
- data/docs/assets/img/elements/arrow_both_bold.png +0 -0
- data/docs/assets/img/elements/arrow_left.png +0 -0
- data/docs/assets/img/elements/arrow_left_bold.png +0 -0
- data/docs/assets/img/elements/arrow_right.png +0 -0
- data/docs/assets/img/elements/arrow_right_bold.png +0 -0
- data/docs/assets/img/elements/circle.png +0 -0
- data/docs/assets/img/elements/circle_abc.png +0 -0
- data/docs/assets/img/elements/circle_bold.png +0 -0
- data/docs/assets/img/elements/circle_hatched.png +0 -0
- data/docs/assets/img/elements/circle_one.png +0 -0
- data/docs/assets/img/elements/connector.png +0 -0
- data/docs/assets/img/elements/connector_bold.png +0 -0
- data/docs/assets/img/elements/square.png +0 -0
- data/docs/assets/img/elements/square_abc.png +0 -0
- data/docs/assets/img/elements/square_bold.png +0 -0
- data/docs/assets/img/elements/square_hatched.png +0 -0
- data/docs/assets/img/elements/square_one.png +0 -0
- data/docs/assets/img/favicon/apple-touch-icon.png +0 -0
- data/docs/assets/img/favicon/favicon-16x16.png +0 -0
- data/docs/assets/img/favicon/favicon-32x32.png +0 -0
- data/docs/assets/img/favicon/favicon.ico +0 -0
- data/docs/assets/svg/000.svg +0 -74
- data/docs/assets/svg/001.svg +0 -48
- data/docs/assets/svg/002.svg +0 -74
- data/docs/assets/svg/003.svg +0 -63
- data/docs/assets/svg/004.svg +0 -77
- data/docs/assets/svg/005.svg +0 -50
- data/docs/assets/svg/006.svg +0 -56
- data/docs/assets/svg/007.svg +0 -64
- data/docs/assets/svg/008.svg +0 -72
- data/docs/assets/svg/009.svg +0 -70
- data/docs/assets/svg/010.svg +0 -94
- data/docs/assets/svg/011.svg +0 -58
- data/docs/assets/svg/012.svg +0 -64
- data/docs/assets/svg/013.svg +0 -212
- data/docs/assets/svg/014.svg +0 -190
- data/docs/assets/svg/015.svg +0 -69
- data/docs/assets/svg/016.svg +0 -810
- data/docs/assets/svg/017.svg +0 -86
- data/docs/assets/svg/018.svg +0 -75
- data/docs/assets/svg/019.svg +0 -235
- data/docs/assets/svg/020.svg +0 -110
- data/docs/assets/svg/021.svg +0 -95
- data/docs/assets/svg/022.svg +0 -172
- data/docs/assets/svg/023.svg +0 -125
- data/docs/assets/svg/024.svg +0 -56
- data/docs/assets/svg/025.svg +0 -179
- data/docs/assets/svg/026.svg +0 -50
- data/docs/assets/svg/027.svg +0 -101
- data/docs/assets/svg/028.svg +0 -51
- data/docs/assets/svg/029.svg +0 -122
- data/docs/assets/svg/030.svg +0 -76
- data/docs/assets/svg/031.svg +0 -42
- data/docs/assets/svg/032.svg +0 -85
- data/docs/assets/svg/033.svg +0 -81
- data/docs/assets/svg/034.svg +0 -88
- data/docs/assets/svg/035.svg +0 -77
- data/docs/assets/svg/036.svg +0 -47
- data/docs/assets/svg/037.svg +0 -68
- data/docs/assets/svg/038.svg +0 -82
- data/docs/assets/svg/039.svg +0 -30
- data/docs/assets/svg/040.svg +0 -120
- data/docs/assets/svg/041.svg +0 -93
- data/docs/assets/svg/042.svg +0 -42
- data/docs/assets/svg/043.svg +0 -304
- data/docs/assets/svg/044.svg +0 -32
- data/docs/assets/svg/045.svg +0 -107
- data/docs/assets/svg/046.svg +0 -990
- data/docs/assets/svg/047.svg +0 -62
- data/docs/assets/svg/048.svg +0 -134
- data/docs/assets/svg/049.svg +0 -97
- data/docs/assets/svg/050.svg +0 -193
- data/docs/assets/svg/051.svg +0 -179
- data/docs/assets/svg/052.svg +0 -96
- data/docs/assets/svg/053.svg +0 -81
- data/docs/assets/svg/054.svg +0 -51
- data/docs/assets/svg/055.svg +0 -54
- data/docs/assets/svg/056.svg +0 -71
- data/docs/assets/svg/057.svg +0 -91
- data/docs/assets/svg/058.svg +0 -95
- data/docs/assets/svg/059.svg +0 -111
- data/docs/assets/svg/060.svg +0 -134
- data/docs/assets/svg/061.svg +0 -193
- data/docs/assets/svg/062.svg +0 -179
- data/docs/assets/svg/063.svg +0 -94
- data/docs/assets/svg/064.svg +0 -63
- data/docs/assets/svg/065.svg +0 -54
- data/docs/documentation.md +0 -303
- data/docs/documentation_ja.md +0 -313
- data/docs/examples.html +0 -76
- data/docs/index.html +0 -2
- data/fonts/NotoSans-Bold.ttf +0 -0
- data/fonts/NotoSans-BoldItalic.ttf +0 -0
- data/fonts/NotoSans-Italic.ttf +0 -0
- data/fonts/NotoSans-Regular.ttf +0 -0
- data/fonts/NotoSansJP-Bold.otf +0 -0
- data/fonts/NotoSansJP-Regular.otf +0 -0
- data/fonts/NotoSansMath-Regular.ttf +0 -0
- data/fonts/NotoSansMono_SemiCondensed-Bold.ttf +0 -0
- data/fonts/NotoSansMono_SemiCondensed-Regular.ttf +0 -0
- data/fonts/NotoSerif-Bold.ttf +0 -0
- data/fonts/NotoSerif-BoldItalic.ttf +0 -0
- data/fonts/NotoSerif-Italic.ttf +0 -0
- data/fonts/NotoSerif-Regular.ttf +0 -0
- data/fonts/NotoSerifJP-Bold.otf +0 -0
- data/fonts/NotoSerifJP-Regular.otf +0 -0
- data/fonts/OpenMoji-black-glyf.ttf +0 -0
- data/fonts/wqy-zenhei.ttf +0 -0
- data/img/rsyntaxtree-web-screenshot.png +0 -0
- data/img/rsyntaxtree.png +0 -0
- data/img/sample.png +0 -0
- data/img/sample.svg +0 -38
- data/test/cli_test.rb +0 -262
- data/test/example_verify_test.rb +0 -79
- data/test/format_converter_test.rb +0 -129
- data/test/lsif_test.rb +0 -304
- data/test/markup_parser_test.rb +0 -260
- data/test/node_styling_test.rb +0 -377
- data/test/overlap_test.rb +0 -122
- data/test/tikz_test.rb +0 -147
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 27e1c2eb4e8e276a63ab92e99b32bd3ef607451df95088f379ff093f6a206001
|
|
4
|
+
data.tar.gz: 5147922ca1269a629761d7b93f364f9ae9d22fc41d63ce28fdd4c75223cccc52
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36edfb6922b94b9e8c0821e72f9154b58ad58fc43bd7f55ae913807534f39acd9dbe8becd00e9f14c30c999bb90cc15b6d7ba9cf38e75a6e1feaeca9c090edb9
|
|
7
|
+
data.tar.gz: 58f60c25f6c8ab2566ff1755c74c353769ea80a970e020f3e2c656bb2b6ee7d8e75fe82831b5d10c3788f8539d601a6817a257c5f57006d492ca11526c30e77b
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
ruby-version: ["3.2", "3.4"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install system dependencies
|
|
20
|
+
run: |
|
|
21
|
+
sudo apt-get update
|
|
22
|
+
sudo apt-get install -y \
|
|
23
|
+
libpango1.0-dev librsvg2-dev libmagickwand-dev \
|
|
24
|
+
libgirepository1.0-dev gobject-introspection \
|
|
25
|
+
fonts-noto-core fonts-noto-cjk
|
|
26
|
+
sudo fc-cache -f
|
|
27
|
+
|
|
28
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
29
|
+
uses: ruby/setup-ruby@v1
|
|
30
|
+
with:
|
|
31
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
32
|
+
bundler-cache: true
|
|
33
|
+
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: bundle exec rake test
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.0] - 2026-08
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `tidy` layout scale, one option covering every layout mode from the most
|
|
7
|
+
spacious to the most dense: `symmetric` (radical symmetrization) | `off` |
|
|
8
|
+
`low` (contour packing, strict leaf positions) | `medium` (packing with
|
|
9
|
+
cross-row tucking that never lets two leaves swap their left-right order) |
|
|
10
|
+
`high` (free tucking; leaf order kept per row only). Connector heights
|
|
11
|
+
adjust automatically: a small height budget (5% of the tree's height) is
|
|
12
|
+
spent on the levels whose branches spread widest, evening out branch
|
|
13
|
+
angles. Tidy never produces overlapping labels (collisions roll back).
|
|
14
|
+
- `mirror` option: flips the finished layout horizontally for the
|
|
15
|
+
right-to-left tree convention of Arabic/Hebrew syntax (composes with
|
|
16
|
+
`direction`).
|
|
17
|
+
- `hspacing` option: scales every horizontal gap in every layout mode — the
|
|
18
|
+
horizontal counterpart of `vheight`/connector height.
|
|
19
|
+
- Pass-through empty nodes: a node labeled only `<>` renders as an invisible
|
|
20
|
+
joint with the connector running continuously through it, so a `<>` chain
|
|
21
|
+
aligns a shallow leaf with deeper leaves without a broken line.
|
|
22
|
+
- Full CJK coverage in every font style: the family chains fall back to
|
|
23
|
+
Noto Sans/Serif/Mono CJK, so Hangul and simplified/traditional Han render
|
|
24
|
+
in all styles (the standalone Noto JP faces carry no Hangul).
|
|
25
|
+
- Example gallery: Multilingual category (the same UD-PUD sentence in nine
|
|
26
|
+
languages, constituency derived mechanically from the dependency
|
|
27
|
+
annotation; the Arabic example demonstrates `mirror`), a Morphology
|
|
28
|
+
category, and per-figure tidy settings across the whole gallery.
|
|
29
|
+
- CI on GitHub Actions (Ruby 3.2/3.4).
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
- LSIF output records the layout settings a reader cannot recover from the
|
|
33
|
+
coordinates: `geometry.mirror`, and `tidy`, `mirror`, `direction` and
|
|
34
|
+
`horizontal_spacing` under `meta.source.params`.
|
|
35
|
+
- The standalone `symmetrize` option and `-y` flag are deprecated aliases of
|
|
36
|
+
`tidy: symmetric`; `tidy_spacing` is a deprecated alias of `hspacing`.
|
|
37
|
+
- `--direction` now owns the `-d` short flag (it had been auto-assigned to
|
|
38
|
+
`--hide-default-connectors`, so the documented `-d ltr` silently did
|
|
39
|
+
nothing). Every published short flag is now declared explicitly rather
|
|
40
|
+
than derived from the option set. One undocumented auto-assignment moved
|
|
41
|
+
as a result: `-e` was `--direction` in 1.7.0 and is `--version` here.
|
|
42
|
+
- The gem no longer bundles font files (38MB that were never opened at
|
|
43
|
+
runtime since the Pango migration): fonts resolve by family name through
|
|
44
|
+
fontconfig. See README for the system font packages. The dead `--font`
|
|
45
|
+
CLI option (its value was never read) is gone.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- Boolean options left at their defaults are no longer misread as enabled
|
|
49
|
+
when the caller passes only a partial parameter set (e.g. `tidy: off`
|
|
50
|
+
rendered as `symmetric` in the web UI).
|
|
51
|
+
|
|
3
52
|
## [1.7.0] - 2026-08
|
|
4
53
|
|
|
5
54
|
### Changed
|
data/CITATION.cff
CHANGED
|
@@ -11,8 +11,8 @@ repository-code: "https://github.com/yohasebe/rsyntaxtree"
|
|
|
11
11
|
# Concept DOI: always resolves to the latest archived version on Zenodo
|
|
12
12
|
doi: "10.5281/zenodo.21916150"
|
|
13
13
|
license: MIT
|
|
14
|
-
version: 1.
|
|
15
|
-
date-released:
|
|
14
|
+
version: 1.8.0
|
|
15
|
+
date-released: 2026-08-15
|
|
16
16
|
keywords:
|
|
17
17
|
- linguistics
|
|
18
18
|
- syntax tree
|
data/Dockerfile
CHANGED
|
@@ -7,16 +7,15 @@ RUN apk update && \
|
|
|
7
7
|
apk add --no-cache linux-headers libxml2-dev make gcc libc-dev bash && \
|
|
8
8
|
apk add --no-cache librsvg librsvg-dev pango-dev imagemagick imagemagick-dev xz-dev libbz2 && \
|
|
9
9
|
apk add --no-cache gobject-introspection gobject-introspection-dev && \
|
|
10
|
-
apk add --no-cache -t .build-packages --no-cache build-base curl-dev wget gcompat
|
|
10
|
+
apk add --no-cache -t .build-packages --no-cache build-base curl-dev wget gcompat && \
|
|
11
|
+
apk add --no-cache font-noto font-noto-cjk font-noto-cjk-extra font-noto-emoji \
|
|
12
|
+
font-noto-arabic font-noto-devanagari font-noto-thai
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
ADD Gemfile $WORKSPACE
|
|
14
16
|
ADD rsyntaxtree.gemspec $WORKSPACE
|
|
15
17
|
RUN bundle install -j4
|
|
16
18
|
|
|
17
|
-
ADD fonts $WORKSPACE
|
|
18
|
-
RUN mkdir -p /usr/share/fonts/yh
|
|
19
|
-
COPY ./fonts/* /usr/share/fonts/yh/
|
|
20
19
|
RUN fc-cache -fv
|
|
21
20
|
|
|
22
21
|
ADD . $WORKSPACE
|
data/README.md
CHANGED
|
@@ -110,6 +110,16 @@ See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/example
|
|
|
110
110
|
|
|
111
111
|
<img src='https://github.com/yohasebe/rsyntaxtree/blob/master/img/sample.png?raw=true' width='600' />
|
|
112
112
|
|
|
113
|
+
## System Fonts
|
|
114
|
+
|
|
115
|
+
RSyntaxTree resolves fonts by family name through fontconfig (measurement via Pango, rendering via librsvg), so the fonts must be installed on the system that generates the images. Recommended:
|
|
116
|
+
|
|
117
|
+
- Debian/Ubuntu: `apt install fonts-noto-core fonts-noto-cjk fonts-noto-color-emoji`
|
|
118
|
+
- Alpine: `apk add font-noto font-noto-cjk font-noto-cjk-extra font-noto-emoji` (the `-extra` package carries Noto Serif CJK)
|
|
119
|
+
- macOS: install [Noto Sans/Serif](https://fonts.google.com/noto) (and Noto Sans/Serif JP for CJK); otherwise the system falls back to available fonts
|
|
120
|
+
|
|
121
|
+
Any script supported by an installed font renders correctly — the family chains fall back from Noto Sans/Serif to the JP and CJK variants, so Japanese, Chinese (simplified and traditional) and Korean are covered by the Noto CJK package. As of v1.8.0 the gem no longer bundles font files (they were not used at runtime).
|
|
122
|
+
|
|
113
123
|
## Installation
|
|
114
124
|
|
|
115
125
|
```bash
|
|
@@ -156,9 +166,11 @@ Usage:
|
|
|
156
166
|
| `-n, --fontstyle` | Font style: sans, serif, cjk, mono | `sans` |
|
|
157
167
|
| `-s, --fontsize` | Font size: 8-26 | `16` |
|
|
158
168
|
| `-c, --color` | Color mode: modern, traditional, off | `modern` |
|
|
159
|
-
| `-y, --symmetrize` | Symmetrical tree: on, off | `off` |
|
|
160
169
|
| `-p, --polyline` | Polyline connectors: on, off | `off` |
|
|
161
170
|
| `-d, --direction` | Tree layout direction: ttb, ltr | `ttb` |
|
|
171
|
+
| `--tidy` | Layout scale: off, symmetric, low, medium, high | `off` |
|
|
172
|
+
| `--hspacing` | Horizontal spacing factor, all layout modes (0.5-3.0) | `1.0` |
|
|
173
|
+
| `-m, --mirror` | Flip the tree horizontally (RTL convention): on, off | `off` |
|
|
162
174
|
|
|
163
175
|
Run `rsyntaxtree -h` for the full list of options.
|
|
164
176
|
|
|
@@ -201,7 +213,7 @@ If you use RSyntaxTree in your research, please cite it. You can use the "Cite t
|
|
|
201
213
|
title = {RSyntaxTree: A graphical syntax tree image generator},
|
|
202
214
|
url = {https://yohasebe.com/rsyntaxtree},
|
|
203
215
|
doi = {10.5281/zenodo.21916150},
|
|
204
|
-
version = {1.
|
|
216
|
+
version = {1.8.0},
|
|
205
217
|
year = {2026}
|
|
206
218
|
}
|
|
207
219
|
```
|
data/bin/rsyntaxtree
CHANGED
|
@@ -15,7 +15,6 @@ CONFIG_VALIDATORS = {
|
|
|
15
15
|
format: ->(v) { /\A(png|jpg|gif|pdf|svg|lsif)\z/ =~ v.to_s ? nil : "must be png, jpg, gif, pdf, svg, or lsif" },
|
|
16
16
|
leafstyle: ->(v) { /\A(auto|triangle|bar|nothing)\z/ =~ v.to_s ? nil : "must be auto, triangle, bar, or nothing" },
|
|
17
17
|
fontstyle: ->(v) { /\A(sans|serif|cjk|mono)\z/ =~ v.to_s ? nil : "must be sans, serif, cjk, or mono" },
|
|
18
|
-
font: ->(v) { v.nil? || File.exist?(v) ? nil : "must be path to an existing ttf font" },
|
|
19
18
|
fontsize: ->(v) { v.is_a?(Integer) && v >= 8 && v <= 26 ? nil : "must be in the range of 8-26" },
|
|
20
19
|
linewidth: ->(v) { v.is_a?(Integer) && v >= 1 && v <= 5 ? nil : "must be in the range of 1-5" },
|
|
21
20
|
vheight: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 5.0 ? nil : "must be in the range of 0.5-5.0" },
|
|
@@ -24,6 +23,10 @@ CONFIG_VALIDATORS = {
|
|
|
24
23
|
transparent: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
25
24
|
polyline: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
26
25
|
hide_default_connectors: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
26
|
+
mirror: ->(v) { /\A(on|off|true|false)\z/ =~ v.to_s ? nil : "must be on or off" },
|
|
27
|
+
tidy: ->(v) { /\A(off|symmetric|low|medium|high|on|compact|true|false)\z/ =~ v.to_s ? nil : "must be off, symmetric, low, medium, or high" },
|
|
28
|
+
hspacing: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 3.0 ? nil : "must be in the range of 0.5-3.0" },
|
|
29
|
+
tidy_spacing: ->(v) { v.is_a?(Numeric) && v >= 0.5 && v <= 3.0 ? nil : "must be in the range of 0.5-3.0" },
|
|
27
30
|
direction: ->(v) { /\A(ttb|ltr)\z/ =~ v.to_s ? nil : "must be ttb or ltr" }
|
|
28
31
|
}.freeze
|
|
29
32
|
|
|
@@ -84,7 +87,7 @@ unless loaded[:errors].empty?
|
|
|
84
87
|
end
|
|
85
88
|
|
|
86
89
|
opts = Optimist.options do
|
|
87
|
-
version "RSyntaxTree #{RSyntaxTree::VERSION} (c)
|
|
90
|
+
version "RSyntaxTree #{RSyntaxTree::VERSION} (c) 2026 Yoichiro Hasebe"
|
|
88
91
|
banner <<~BANNER
|
|
89
92
|
RSyntaxTree, (linguistic) syntax tree generator written in Ruby.
|
|
90
93
|
|
|
@@ -96,21 +99,24 @@ opts = Optimist.options do
|
|
|
96
99
|
where [options] are:
|
|
97
100
|
BANNER
|
|
98
101
|
|
|
99
|
-
opt :outdir, "Output directory", default: "./"
|
|
100
|
-
opt :outfilename, "Output file base name", default: "syntree"
|
|
101
|
-
opt :format, "Output format: png, jpg, gif, pdf, svg, or lsif", default: "png"
|
|
102
|
-
opt :leafstyle, "visual style of tree leaves: auto, triangle, bar, or nothing", default: "auto"
|
|
103
|
-
opt :fontstyle, "Font style
|
|
104
|
-
opt :
|
|
105
|
-
opt :
|
|
106
|
-
opt :
|
|
107
|
-
opt :
|
|
108
|
-
opt :
|
|
109
|
-
opt :
|
|
110
|
-
opt :
|
|
111
|
-
opt :
|
|
112
|
-
opt :
|
|
113
|
-
opt :
|
|
102
|
+
opt :outdir, "Output directory", default: "./", short: :o
|
|
103
|
+
opt :outfilename, "Output file base name", default: "syntree", short: :u
|
|
104
|
+
opt :format, "Output format: png, jpg, gif, pdf, svg, or lsif", default: "png", short: :f
|
|
105
|
+
opt :leafstyle, "visual style of tree leaves: auto, triangle, bar, or nothing", default: "auto", short: :l
|
|
106
|
+
opt :fontstyle, "Font style: sans, serif, cjk, mono", default: "sans", short: :n
|
|
107
|
+
opt :fontsize, "Size: 8-26", default: 16, short: :s
|
|
108
|
+
opt :linewidth, "Size: 1-5", default: 1, short: :i
|
|
109
|
+
opt :vheight, "Connector Height: 0.5-5.0", default: 2.0, short: :v
|
|
110
|
+
opt :color, "Color text and bars: modern, traditional, or off", default: "modern", short: :c
|
|
111
|
+
opt :symmetrize, "DEPRECATED alias of --tidy symmetric: on or off", default: "off", short: :y
|
|
112
|
+
opt :transparent, "Make background transparent: on or off", default: "off", short: :r
|
|
113
|
+
opt :polyline, "draw polyline connectors: on or off", default: "off", short: :p
|
|
114
|
+
opt :hide_default_connectors, "make default connectors transparent: on or off", default: "off", short: :none
|
|
115
|
+
opt :mirror, "flip the tree horizontally (RTL linguistics convention: first word at the right edge): on or off", default: "off"
|
|
116
|
+
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
|
|
117
|
+
opt :hspacing, "Horizontal spacing factor (counterpart of vheight): 0.5-3.0", default: 1.0, short: :none
|
|
118
|
+
opt :tidy_spacing, "DEPRECATED alias of --hspacing: 0.5-3.0", default: 1.0, short: :none
|
|
119
|
+
opt :direction, "Tree layout direction: ttb (top-to-bottom) or ltr (left-to-right)", default: "ttb", short: :d
|
|
114
120
|
opt :help, "This is a custom help message", short: :h
|
|
115
121
|
end
|
|
116
122
|
|
|
@@ -119,7 +125,6 @@ Optimist.die :direction, "must be ttb or ltr" unless /\A(ttb|ltr)\z/ =~ opts[:di
|
|
|
119
125
|
Optimist.die :format, "must be png, pdf, svg, or lsif" unless /\A(png|jpg|gif|pdf|svg|lsif)\z/ =~ opts[:format]
|
|
120
126
|
Optimist.die :leafstyle, "must be auto, triangle, bar, or nothing" unless /\A(auto|triangle|bar|nothing)\z/ =~ opts[:leafstyle]
|
|
121
127
|
Optimist.die :fontstyle, "must be sans, serif, cjk, or mono" unless /\A(sans|serif|cjk|mono)\z/ =~ opts[:fontstyle]
|
|
122
|
-
Optimist.die :font, "must be path to an existing ttf font" if opts[:font] && !File.exist?(opts[:font])
|
|
123
128
|
Optimist.die :fontsize, "must be in the range of 8-26" unless opts[:fontsize] >= 8 && opts[:fontsize] <= 26
|
|
124
129
|
Optimist.die :linewidth, "must be in the range of 1-5" unless opts[:linewidth] >= 1 && opts[:linewidth] <= 5
|
|
125
130
|
Optimist.die :color, "must be either modern, traditional, or off" unless /\A(modern|traditional|on|off|true|false)\z/ =~ opts[:color]
|
|
@@ -128,6 +133,10 @@ Optimist.die :vheight, "must be in the range of 0.5-5.0" if opts[:vheight] < 0.5
|
|
|
128
133
|
Optimist.die :transparent, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:transparent]
|
|
129
134
|
Optimist.die :polyline, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:polyline]
|
|
130
135
|
Optimist.die :hide_default_connectors, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:hide_default_connectors]
|
|
136
|
+
Optimist.die :mirror, "must be either on or off" unless /\A(on|off|true|false)\z/ =~ opts[:mirror]
|
|
137
|
+
Optimist.die :tidy, "must be off, symmetric, low, medium, or high" unless /\A(off|symmetric|low|medium|high|on|compact|true|false)\z/ =~ opts[:tidy]
|
|
138
|
+
Optimist.die :hspacing, "must be in the range of 0.5-3.0" if opts[:hspacing] < 0.5 || opts[:hspacing] > 3.0
|
|
139
|
+
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
|
|
131
140
|
|
|
132
141
|
# Merge config file options with CLI options (CLI takes precedence)
|
|
133
142
|
string_opts = {}
|
|
@@ -140,8 +149,8 @@ end
|
|
|
140
149
|
# Then, apply CLI options (overrides config file)
|
|
141
150
|
opts.each do |key, value|
|
|
142
151
|
key_sym = key.to_sym
|
|
143
|
-
# Skip internal optimist keys
|
|
144
|
-
next if key.to_s.start_with?('_')
|
|
152
|
+
# Skip internal optimist keys
|
|
153
|
+
next if key.to_s.start_with?('_')
|
|
145
154
|
# Only override if explicitly given on CLI or not in config
|
|
146
155
|
if opts[:"#{key}_given"] || !file_config.key?(key_sym)
|
|
147
156
|
string_opts[key_sym] = value
|