rsyntaxtree 1.8.1 → 1.8.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b9513e8d667af90de0a12e427eae11d0089f6a969ed1a47714ca30401001821
4
- data.tar.gz: '0458b65b7f9ad1f495d344963b41b801b7c26562b0256abe48885756a1481bef'
3
+ metadata.gz: 232efc991d608eb2af9ff19d6816d9f22f9bc4a1006506276507c1b8705f34ec
4
+ data.tar.gz: da8e1ab08b470d76d47809b89ae4fd5b7bf0ef7519847ef3bc7e2955814f5521
5
5
  SHA512:
6
- metadata.gz: d1738b00df2a2dbe5cafba5d52b19c44149472912c2859c8183384582770be0b54c0c4e96688fe4c0a808969c96096504956b7ce7dffc76bd3c682ee28124cf6
7
- data.tar.gz: a8363b3b3e6b11f345603f020e36766275f740ab0f80af4ecb4be3f9160dd7860d4a26c4cdd2788a8b02e27d4c99d1147bd9843200cdd41cf48f87b6ce373e34
6
+ metadata.gz: 5af80d2af48070f3733c21f19cb543da6a2f443b4e4e2fb4fa2f5a0760584cedcfac5e3b86067623f5f24ba63cfe3267e69692f5ddbc44b3c9fdf35f1de34ace
7
+ data.tar.gz: 3d391279ae3b669f87f6c62cfa6b2f44cb607a6f5c9d0adbfd37e147cd9a9d2a8c4f998a3e508c423886a4adfe56610e5041c838ffcd40d47f958e96b45d9d49
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.2] - 2026-08
4
+
5
+ ### Changed
6
+ - `tidy: high` now compresses as far as its name promises. The level-balance
7
+ floor added in 1.8.0, which keeps a pair of siblings from being tucked
8
+ narrower than the level below it, applied to `medium` and `high` alike and
9
+ bound first in nearly every tree: across the 75 gallery examples the two
10
+ modes produced identical figures 70 times. The floor now applies to `medium`
11
+ only, leaving `high` free to trade even branch angles for width — 29 of the
12
+ 75 examples now differ, by up to 19%. `off`, `low` and `medium` are
13
+ unchanged; `high`, like `symmetric` at the other end of the scale, is for
14
+ figures that ask for it.
15
+ - Mathematical alphanumerics (U+1D400–, such as the little *v* of *v*P) are
16
+ named in the family chains. Neither Noto Sans nor Noto Serif covers the
17
+ block, so the glyphs came from whatever the machine offered: Noto Sans Math
18
+ on Alpine, DejaVu Serif on Debian/Ubuntu, STIX Two Math on macOS. The serif
19
+ style now asks for a serif source first, so a serif tree no longer shows a
20
+ sans *v*. The Docker images install `font-dejavu` for it.
21
+
22
+ ### Fixed
23
+ - The CLI printed parse errors to stdout and exited 0, so a script generating
24
+ figures in bulk could not tell a rejected input from a drawn one. Errors go
25
+ to stderr and the exit status is 1.
26
+ - Dropped `Noto Sans Mono SemiCondensed` from the mono chain. It is a width
27
+ style of the variable Noto Sans Mono rather than a family of its own, and
28
+ resolved nowhere on macOS, Debian/Ubuntu or Alpine; the chain fell through
29
+ to `Noto Sans Mono`, which it now names directly.
30
+
3
31
  ## [1.8.1] - 2026-08
4
32
 
5
33
  ### Fixed
@@ -7,11 +35,13 @@
7
35
  Scripts outside Latin and CJK were left to the system's generic font
8
36
  fallback, which is not the same font on every machine: on Alpine the Arabic
9
37
  block was claimed by Noto Sans Math, which has the glyphs but no joining
10
- rules, while on Debian the same text fell to DejaVu Sans. The family chains
11
- now name the scripts the gallery covers — Arabic (`Noto Sans Arabic`, with
12
- `Noto Naskh Arabic` for the serif style), Hebrew, Devanagari, Thai and
13
- Khmer — so the same input renders the same way everywhere. Gallery example
14
- 067 (Arabic) was affected and has been regenerated.
38
+ rules, while on Debian/Ubuntu the same text fell to DejaVu Sans. The family
39
+ chains now name the scripts the gallery covers — Arabic (`Noto Sans Arabic`,
40
+ with `Noto Naskh Arabic` for the serif style), Hebrew, Devanagari, Thai and
41
+ Khmer — so machines that have those fonts installed produce the same shapes.
42
+ Mathematical alphanumerics (U+1D400–) are not named yet and still vary by
43
+ environment. Gallery example 067 (Arabic) was affected and has been
44
+ regenerated.
15
45
  - Emoji were measured with one font and drawn with another where a colour
16
46
  emoji font was installed: Pango selects `Noto Color Emoji`, but the
17
47
  librsvg/Cairo pipeline does not rasterise its bitmap glyphs, so the drawing
data/CITATION.cff CHANGED
@@ -11,7 +11,7 @@ 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.8.1
14
+ version: 1.8.2
15
15
  date-released: 2026-08-15
16
16
  keywords:
17
17
  - linguistics
data/Dockerfile CHANGED
@@ -10,7 +10,8 @@ RUN apk update && \
10
10
  apk add --no-cache -t .build-packages --no-cache build-base curl-dev wget gcompat && \
11
11
  apk add --no-cache font-noto font-noto-cjk font-noto-cjk-extra \
12
12
  font-noto-arabic font-noto-naskh-arabic font-noto-hebrew \
13
- font-noto-devanagari font-noto-thai font-noto-khmer
13
+ font-noto-devanagari font-noto-thai font-noto-khmer \
14
+ font-dejavu
14
15
 
15
16
  # Noto Sans Math (pulled in by font-noto) claims the Arabic block but carries no
16
17
  # joining rules, and fontconfig ranks it above Noto Sans Arabic — Arabic then
data/README.md CHANGED
@@ -112,20 +112,19 @@ See [RSyntaxTree Example Gallery](https://yohasebe.github.io/rsyntaxtree/example
112
112
 
113
113
  ## System Fonts
114
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:
115
+ RSyntaxTree resolves fonts by family name through fontconfig (measurement via Pango, rendering via librsvg), so the fonts must be installed on the machine that generates the images. As of v1.8.0 the gem no longer bundles font files; they were not used at runtime.
116
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
117
+ - Debian/Ubuntu: `apt install fonts-noto-core fonts-noto-cjk`
118
+ - Alpine: `apk add font-noto font-noto-cjk font-noto-cjk-extra` (the `-extra` package carries Noto Serif CJK)
119
+ - macOS: `brew install --cask font-noto-sans font-noto-serif font-noto-sans-mono font-noto-sans-jp font-noto-serif-jp font-noto-sans-cjk font-noto-serif-cjk font-noto-sans-mono-cjk-jp` (macOS itself ships Noto only for a few rare scripts)
120
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).
121
+ Arabic, Hebrew, Devanagari, Thai and Khmer need their own packages, and emoji need the **monochrome** [Noto Emoji](https://fonts.google.com/noto/specimen/Noto+Emoji) colour emoji fonts are not drawn by this pipeline:
122
122
 
123
- Scripts outside Latin and CJK need their own Noto package, or they render as tofu boxes. Since v1.8.0 the gem names these families explicitly (`Noto Sans Arabic`, `Noto Naskh Arabic`, `Noto Sans/Serif Hebrew`, `Devanagari`, `Thai`, `Khmer`) instead of leaving them to the system fallback, so install them to get the intended shapes:
124
-
125
- - Debian/Ubuntu: `apt install fonts-noto-core` already covers them; on minimal images add `fonts-noto` for the full set
123
+ - Debian/Ubuntu: `fonts-noto-core` covers the scripts; on minimal images add `fonts-noto` for the full set
126
124
  - Alpine: `apk add font-noto-arabic font-noto-naskh-arabic font-noto-hebrew font-noto-devanagari font-noto-thai font-noto-khmer`
125
+ - macOS: the same families are available as `font-noto-*` casks
127
126
 
128
- Emoji need the **monochrome** [Noto Emoji](https://fonts.google.com/noto/specimen/Noto+Emoji); colour emoji fonts (`NotoColorEmoji`, shipped by Alpine's `font-noto-emoji` and Debian's `fonts-noto-color-emoji`) are measured but not drawn by the librsvg/Cairo pipeline, so emoji then fall back to whatever outline font happens to cover them.
127
+ See [Fonts](https://yohasebe.github.io/rsyntaxtree/documentation#install-fonts-for-svg) in the documentation for which family is used for what, how to substitute your own, and the macOS caveats.
129
128
 
130
129
  ## Installation
131
130
 
data/bin/rsyntaxtree CHANGED
@@ -173,8 +173,8 @@ data = RSyntaxTree::FormatConverter.to_bracket(data) if data
173
173
  begin
174
174
  RSyntaxTree::RSGenerator.check_data(data)
175
175
  rescue RSTError => e
176
- puts e
177
- exit
176
+ warn e
177
+ exit 1
178
178
  end
179
179
 
180
180
  begin
@@ -188,10 +188,10 @@ begin
188
188
  output = rsg.send(draw_method)
189
189
  File.binwrite(filepath, output)
190
190
  rescue RSTError => e
191
- puts e
192
- exit
191
+ warn e
192
+ exit 1
193
193
  rescue StandardError => e
194
- p e
195
- puts "Error: something unexpected occurred"
196
- exit
194
+ warn "Error: something unexpected occurred"
195
+ warn "#{e.class}: #{e.message}"
196
+ exit 1
197
197
  end
@@ -376,7 +376,8 @@ module RSyntaxTree
376
376
  # being compressed narrower than the level right below it (an inversion
377
377
  # that reads as a needle-thin top over flat lower branches); branch
378
378
  # angles then stay comparable between adjacent levels. 1.0 = a pair is
379
- # never tighter than the widest pair among its own children.
379
+ # never tighter than the widest pair among its own children. Applied in
380
+ # the :ordered nest mode only; see tidy_compress.
380
381
  TIDY_LEVEL_BALANCE = 1.0
381
382
 
382
383
  # Base multiplier for the minimum clearance between adjacent subtrees.
@@ -554,16 +555,21 @@ module RSyntaxTree
554
555
  end
555
556
  end
556
557
 
557
- # Level-balance floor (nest mode only): keep the pair at least a
558
+ # Level-balance floor (:ordered only): keep the pair at least a
558
559
  # fraction of the widest child-level spread found inside its own
559
560
  # two subtrees. Nesting can tuck an upper pair far narrower than
560
561
  # the level right below it — an inversion that reads as a
561
- # needle-thin top over flat lower branches. Without nesting the
562
- # leaf-span guard already prevents such inversions, and applying
563
- # the floor there would only forfeit legitimate compression.
562
+ # needle-thin top over flat lower branches.
563
+ #
564
+ # :none does not need it, since the leaf-span guard already
565
+ # prevents such inversions. :free deliberately goes without: it is
566
+ # the end of the scale where density outranks even branch angles,
567
+ # and with the floor in place it compressed no further than
568
+ # :ordered on all but a handful of trees.
569
+ #
564
570
  # Compression is a negative delta (the right subtree moves left),
565
571
  # so the floor bounds delta from below.
566
- if @tidy_nest != :none && delta.negative?
572
+ if @tidy_nest == :ordered && delta.negative?
567
573
  dist = (right_child.horizontal_indent + right_child.content_width / 2.0) -
568
574
  (left_child.horizontal_indent + left_child.content_width / 2.0)
569
575
  below = [left_child, right_child].map { |c| child_spread(c) }.compact.max
@@ -29,18 +29,36 @@ SCRIPT_FAMILIES_SANS = ["Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans Devan
29
29
  # Arabic behind it for systems that ship one but not the other.
30
30
  SCRIPT_FAMILIES_SERIF = ["Noto Naskh Arabic", "Noto Sans Arabic", "Noto Serif Hebrew", "Noto Serif Devanagari", "Noto Serif Thai", "Noto Serif Khmer"].freeze
31
31
 
32
+ # Monochrome emoji faces only. Colour emoji fonts carry their glyphs as bitmap
33
+ # or COLR tables, which Pango happily measures but librsvg does not draw, so a
34
+ # colour font in this list would give a figure whose emoji are blank or blobbed.
35
+ #
36
+ # This holds only where Pango resolves through fontconfig. On macOS it goes
37
+ # through CoreText, which answers every emoji codepoint with Apple Color Emoji
38
+ # whatever the chain asks for; emoji figures have to be generated elsewhere.
32
39
  EMOJI_FAMILIES = ["OpenMoji", "OpenMoji Color", "OpenMoji Black", "Noto Emoji"].freeze
33
40
 
41
+ # Mathematical alphanumerics (U+1D400–) label heads such as the little v of vP.
42
+ # Neither Noto Sans nor Noto Serif covers the block, so without these entries
43
+ # the glyphs came from whatever the machine happened to offer — Noto Sans Math
44
+ # on Alpine, DejaVu Serif on Debian/Ubuntu, STIX Two Math on macOS. Noto Sans
45
+ # Math is the only Noto face that covers the block and it is a sans design, so
46
+ # the serif style asks for a serif source first. Listed after the script
47
+ # families: Noto Sans Math also claims the Arabic block without joining rules,
48
+ # and must never be reached before Noto Sans Arabic.
49
+ MATH_FAMILIES_SANS = ["Noto Sans Math"].freeze
50
+ MATH_FAMILIES_SERIF = ["DejaVu Serif", "Noto Sans Math"].freeze
51
+
34
52
  FONT_FAMILIES = {
35
- sans: (["Noto Sans", "Noto Sans JP", "Noto Sans CJK JP"] + SCRIPT_FAMILIES_SANS + EMOJI_FAMILIES + ["sans-serif"]).freeze,
36
- serif: (["Noto Serif", "Noto Serif JP", "Noto Serif CJK JP"] + SCRIPT_FAMILIES_SERIF + EMOJI_FAMILIES + ["serif"]).freeze,
53
+ sans: (["Noto Sans", "Noto Sans JP", "Noto Sans CJK JP"] + SCRIPT_FAMILIES_SANS + MATH_FAMILIES_SANS + EMOJI_FAMILIES + ["sans-serif"]).freeze,
54
+ serif: (["Noto Serif", "Noto Serif JP", "Noto Serif CJK JP"] + SCRIPT_FAMILIES_SERIF + MATH_FAMILIES_SERIF + EMOJI_FAMILIES + ["serif"]).freeze,
37
55
  # Noto ships no monospaced faces for these scripts, so the mono style borrows
38
56
  # the proportional ones rather than dropping to the generic fallback.
39
- mono: (["Noto Sans Mono SemiCondensed", "Noto Sans Mono", "Noto Sans JP", "Noto Sans Mono CJK JP"] + SCRIPT_FAMILIES_SANS + EMOJI_FAMILIES + ["monospace"]).freeze,
57
+ mono: (["Noto Sans Mono", "Noto Sans JP", "Noto Sans Mono CJK JP"] + SCRIPT_FAMILIES_SANS + MATH_FAMILIES_SANS + EMOJI_FAMILIES + ["monospace"]).freeze,
40
58
  # The cjk style puts a full-coverage CJK family first, for text that mixes
41
59
  # Han, Hangul and kana. Latin falls back to the same Noto faces the sans
42
60
  # style uses. (Before 1.8.0 this was WQY Zen Hei.)
43
- cjk: (["Noto Sans CJK JP", "Noto Sans", "Noto Sans JP"] + SCRIPT_FAMILIES_SANS + EMOJI_FAMILIES + ["sans-serif"]).freeze
61
+ cjk: (["Noto Sans CJK JP", "Noto Sans", "Noto Sans JP"] + SCRIPT_FAMILIES_SANS + MATH_FAMILIES_SANS + EMOJI_FAMILIES + ["sans-serif"]).freeze
44
62
  }.freeze
45
63
 
46
64
  module FontFamily
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RSyntaxTree
4
- VERSION = "1.8.1"
4
+ VERSION = "1.8.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsyntaxtree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoichiro Hasebe