fontist 3.0.35 → 3.0.37
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/release.yml +10 -0
- data/.github/workflows/tebako-pack.yml +219 -45
- data/README.adoc +64 -0
- data/docs/.vitepress/config.ts +2 -1
- data/docs/cli/convert.md +38 -0
- data/docs/cli/index.md +1 -0
- data/lib/fontist/cli.rb +14 -1
- data/lib/fontist/convert_cli.rb +88 -0
- data/lib/fontist/font.rb +21 -3
- data/lib/fontist/system_index.rb +4 -1
- data/lib/fontist/validation.rb +1 -1
- data/lib/fontist/validator.rb +1 -2
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist.rb +1 -0
- data/packaging/nfpm.yaml +33 -0
- data/script/tebako/entry.rb +90 -0
- data/script/tebako/package-smoke.sh +33 -0
- data/script/tebako/package.sh +23 -0
- data/script/tebako/press.sh +36 -0
- data/script/tebako/smoke.sh +25 -0
- data/script/tebako/stage.sh +39 -0
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85b1409d941968bcf69c2058ab3e3ffac4138279bf6c262d670206590dd8e557
|
|
4
|
+
data.tar.gz: f025af9d9214504168b1612f7f42f3142afdadb9112e9283022fe92378665000
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c13e6cca540bd6f5e2ed3bd203bad3b4dad7db56824d34e36b511331b6a9bd5b5178ecf7fc6717318d54981950c33536ae3dfc6eafc82e4ceaf771f3b08fbdb
|
|
7
|
+
data.tar.gz: f1a3542fcda412f62e763cb38d9484028ddc65585eba3d6c9cb982eea8ef80656672769fc898a5b4266ef7419adadcf7e592200f4d7c8c9845505ddf13ec4f58
|
|
@@ -28,3 +28,13 @@ jobs:
|
|
|
28
28
|
next_version: ${{ github.event.inputs.next_version }}
|
|
29
29
|
secrets:
|
|
30
30
|
rubygems-api-key: ${{ secrets.FONTIST_CI_RUBYGEMS_API_KEY }}
|
|
31
|
+
|
|
32
|
+
# Self-contained executables and .deb/.rpm packages for the new version,
|
|
33
|
+
# attached to its GitHub Release (fontist/fontist#463).
|
|
34
|
+
packages:
|
|
35
|
+
needs: release
|
|
36
|
+
permissions:
|
|
37
|
+
contents: write
|
|
38
|
+
uses: ./.github/workflows/tebako-pack.yml
|
|
39
|
+
with:
|
|
40
|
+
publish: true
|
|
@@ -1,65 +1,239 @@
|
|
|
1
1
|
name: tebako-pack
|
|
2
2
|
|
|
3
|
+
# Packs fontist into one self-contained executable per platform with
|
|
4
|
+
# tebako v2, wraps the Linux ones into .deb/.rpm packages, checks both on
|
|
5
|
+
# machines with no Ruby, and attaches them to the GitHub Release when given
|
|
6
|
+
# a tag.
|
|
7
|
+
|
|
3
8
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
# Called by release.yml once the gem is out. Its releases are created with
|
|
10
|
+
# GITHUB_TOKEN, and GitHub starts no workflow from such an event, so a
|
|
11
|
+
# `release: published` trigger here would never fire.
|
|
12
|
+
workflow_call:
|
|
13
|
+
inputs:
|
|
14
|
+
publish:
|
|
15
|
+
type: boolean
|
|
16
|
+
default: true
|
|
6
17
|
workflow_dispatch:
|
|
18
|
+
inputs:
|
|
19
|
+
tag:
|
|
20
|
+
description: Release tag to build and attach to (empty = build only)
|
|
21
|
+
required: false
|
|
22
|
+
default: ''
|
|
23
|
+
pull_request:
|
|
24
|
+
paths:
|
|
25
|
+
- .github/workflows/tebako-pack.yml
|
|
26
|
+
- script/tebako/**
|
|
27
|
+
- packaging/**
|
|
7
28
|
|
|
8
29
|
permissions:
|
|
9
30
|
contents: read
|
|
10
|
-
packages: write
|
|
11
31
|
|
|
12
32
|
concurrency:
|
|
13
|
-
group: '${{ github.workflow }}-${{ github.
|
|
33
|
+
group: '${{ github.workflow }}-${{ github.head_ref || github.ref_name }}'
|
|
14
34
|
cancel-in-progress: true
|
|
15
35
|
|
|
16
36
|
env:
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# has better performance
|
|
23
|
-
TEBAKO_RUBY_VER: 3.1.4
|
|
37
|
+
# Ruby the packed fontist runs on: a version tebako ships a runtime for
|
|
38
|
+
# (tebako press rejects the rest).
|
|
39
|
+
PACKAGE_RUBY_VERSION: 3.3.12
|
|
40
|
+
TEBAKO_VERSION: 2.8.68
|
|
41
|
+
NFPM_VERSION: 2.48.0
|
|
24
42
|
|
|
25
43
|
jobs:
|
|
44
|
+
resolve:
|
|
45
|
+
name: resolve tag
|
|
46
|
+
runs-on: ubuntu-24.04
|
|
47
|
+
outputs:
|
|
48
|
+
tag: ${{ steps.tag.outputs.tag }}
|
|
49
|
+
steps:
|
|
50
|
+
# After release.yml the default branch carries the released version.
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
with:
|
|
53
|
+
ref: ${{ github.event.repository.default_branch }}
|
|
54
|
+
|
|
55
|
+
- id: tag
|
|
56
|
+
env:
|
|
57
|
+
GH_TOKEN: ${{ github.token }}
|
|
58
|
+
CALLED: ${{ github.event_name != 'workflow_dispatch' && github.event_name != 'pull_request' && inputs.publish }}
|
|
59
|
+
INPUT_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || '' }}
|
|
60
|
+
run: |
|
|
61
|
+
if [ "$CALLED" = true ]; then
|
|
62
|
+
tag="v$(sed -n 's/.*VERSION = "\(.*\)".*/\1/p' lib/fontist/version.rb)"
|
|
63
|
+
else
|
|
64
|
+
tag="$INPUT_TAG"
|
|
65
|
+
fi
|
|
66
|
+
if [ -n "$tag" ]; then
|
|
67
|
+
# Only a version tag that is a published release of this repo.
|
|
68
|
+
if ! printf '%s' "$tag" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
69
|
+
echo "not a release tag: $tag" >&2
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
gh release view "$tag" --repo "$GITHUB_REPOSITORY" --json tagName >/dev/null
|
|
73
|
+
fi
|
|
74
|
+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
75
|
+
echo "building ${tag:-$GITHUB_SHA}"
|
|
76
|
+
|
|
26
77
|
pack:
|
|
27
|
-
name:
|
|
78
|
+
name: pack ${{ matrix.name }}
|
|
79
|
+
needs: resolve
|
|
28
80
|
runs-on: ${{ matrix.os }}
|
|
29
81
|
strategy:
|
|
30
82
|
fail-fast: false
|
|
31
|
-
# macos-11 runner is deadly slow because brew is not supported on this version anymore
|
|
32
|
-
# so it is practically impossible to use it for tests anymore
|
|
33
83
|
matrix:
|
|
34
|
-
|
|
84
|
+
include:
|
|
85
|
+
# Linux is packed on the oldest runner so the result runs on older
|
|
86
|
+
# glibc distros too.
|
|
87
|
+
- { os: ubuntu-22.04, triplet: linux-gnu-x86_64, name: linux-x86_64 }
|
|
88
|
+
- { os: ubuntu-22.04-arm, triplet: linux-gnu-arm64, name: linux-arm64 }
|
|
89
|
+
- { os: macos-15, triplet: macos-arm64, name: macos-arm64 }
|
|
90
|
+
- { os: macos-15-intel, triplet: macos-x86_64, name: macos-x86_64 }
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@v4
|
|
93
|
+
with:
|
|
94
|
+
fetch-depth: 0
|
|
95
|
+
|
|
96
|
+
# A release build packs the validated release tag, not the dispatching
|
|
97
|
+
# commit (release.yml bumps the version after this run's commit).
|
|
98
|
+
- name: Check out the release tag
|
|
99
|
+
if: needs.resolve.outputs.tag != ''
|
|
100
|
+
env:
|
|
101
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
102
|
+
run: git checkout --detach "refs/tags/$TAG"
|
|
103
|
+
|
|
104
|
+
- uses: ruby/setup-ruby@v1
|
|
105
|
+
with:
|
|
106
|
+
ruby-version: '3.3'
|
|
107
|
+
|
|
108
|
+
- name: Press
|
|
109
|
+
env:
|
|
110
|
+
GH_TOKEN: ${{ github.token }}
|
|
111
|
+
run: script/tebako/press.sh "${{ matrix.triplet }}" "out/fontist-${{ matrix.name }}"
|
|
112
|
+
|
|
113
|
+
# Uploaded before the smoke test so a failing binary can be fetched
|
|
114
|
+
# and inspected.
|
|
115
|
+
- uses: actions/upload-artifact@v4
|
|
116
|
+
with:
|
|
117
|
+
name: fontist-${{ matrix.name }}
|
|
118
|
+
path: out/fontist-${{ matrix.name }}
|
|
119
|
+
if-no-files-found: error
|
|
120
|
+
|
|
121
|
+
# Only the system directories and git stay on PATH, so the Ruby set up
|
|
122
|
+
# above is out of reach. (macOS keeps a system ruby in /usr/bin; the
|
|
123
|
+
# fresh distro containers in package-smoke are the no-Ruby-at-all
|
|
124
|
+
# check.) fontist's git gem needs git >= 2.43, newer than Apple's, so
|
|
125
|
+
# the runner's own git is kept.
|
|
126
|
+
- name: Smoke test without the build Ruby
|
|
127
|
+
run: |
|
|
128
|
+
git_dir="$(dirname "$(command -v git)")"
|
|
129
|
+
env -i HOME="$HOME" PATH="$git_dir:/usr/bin:/bin:/usr/sbin:/sbin" \
|
|
130
|
+
script/tebako/smoke.sh "out/fontist-${{ matrix.name }}"
|
|
131
|
+
|
|
132
|
+
packages:
|
|
133
|
+
name: deb and rpm
|
|
134
|
+
needs: [ resolve, pack ]
|
|
135
|
+
runs-on: ubuntu-24.04
|
|
35
136
|
steps:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
137
|
+
- uses: actions/checkout@v4
|
|
138
|
+
with:
|
|
139
|
+
fetch-depth: 0
|
|
140
|
+
|
|
141
|
+
# A release build packs the validated release tag, not the dispatching
|
|
142
|
+
# commit (release.yml bumps the version after this run's commit).
|
|
143
|
+
- name: Check out the release tag
|
|
144
|
+
if: needs.resolve.outputs.tag != ''
|
|
145
|
+
env:
|
|
146
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
147
|
+
run: git checkout --detach "refs/tags/$TAG"
|
|
148
|
+
|
|
149
|
+
- uses: actions/download-artifact@v4
|
|
150
|
+
with:
|
|
151
|
+
pattern: fontist-linux-*
|
|
152
|
+
path: out
|
|
153
|
+
merge-multiple: true
|
|
154
|
+
|
|
155
|
+
- name: Install nfpm
|
|
156
|
+
env:
|
|
157
|
+
GH_TOKEN: ${{ github.token }}
|
|
158
|
+
run: |
|
|
159
|
+
gh release download "v${NFPM_VERSION}" --repo goreleaser/nfpm --dir /tmp/nfpm \
|
|
160
|
+
--pattern "nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" --pattern checksums.txt
|
|
161
|
+
(cd /tmp/nfpm && sha256sum --ignore-missing -c checksums.txt)
|
|
162
|
+
tar -xzf "/tmp/nfpm/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" -C /tmp/nfpm nfpm
|
|
163
|
+
sudo install /tmp/nfpm/nfpm /usr/local/bin/nfpm
|
|
164
|
+
|
|
165
|
+
- name: Build packages
|
|
166
|
+
run: |
|
|
167
|
+
script/tebako/package.sh amd64 out/fontist-linux-x86_64 pkg
|
|
168
|
+
script/tebako/package.sh arm64 out/fontist-linux-arm64 pkg
|
|
169
|
+
|
|
170
|
+
- uses: actions/upload-artifact@v4
|
|
171
|
+
with:
|
|
172
|
+
name: fontist-linux-packages
|
|
173
|
+
path: pkg/*
|
|
174
|
+
if-no-files-found: error
|
|
175
|
+
|
|
176
|
+
package-smoke:
|
|
177
|
+
name: install on ${{ matrix.image }} ${{ matrix.arch }}
|
|
178
|
+
needs: [ resolve, packages ]
|
|
179
|
+
runs-on: ${{ matrix.runner }}
|
|
180
|
+
container: ${{ matrix.image }}
|
|
181
|
+
strategy:
|
|
182
|
+
fail-fast: false
|
|
183
|
+
matrix:
|
|
184
|
+
# Distros whose git meets the git gem's >= 2.43; older ones refuse
|
|
185
|
+
# the package on its git dependency.
|
|
186
|
+
image: [ 'ubuntu:24.04', 'debian:13', 'fedora:latest', 'rockylinux:9' ]
|
|
187
|
+
arch: [ amd64 ]
|
|
188
|
+
runner: [ ubuntu-24.04 ]
|
|
189
|
+
include:
|
|
190
|
+
- { image: 'ubuntu:24.04', arch: arm64, runner: ubuntu-24.04-arm }
|
|
191
|
+
steps:
|
|
192
|
+
# Only the smoke scripts are used here, so the dispatching commit is
|
|
193
|
+
# enough (these containers have no git to check out a tag with).
|
|
194
|
+
- uses: actions/checkout@v4
|
|
195
|
+
|
|
196
|
+
- uses: actions/download-artifact@v4
|
|
197
|
+
with:
|
|
198
|
+
name: fontist-linux-packages
|
|
199
|
+
path: pkg
|
|
200
|
+
|
|
201
|
+
- name: Keep only this architecture
|
|
202
|
+
run: |
|
|
203
|
+
if [ "${{ matrix.arch }}" = amd64 ]; then
|
|
204
|
+
find pkg \( -name '*arm64*' -o -name '*aarch64*' \) -delete
|
|
205
|
+
else
|
|
206
|
+
find pkg \( -name '*amd64*' -o -name '*x86_64*' \) -delete
|
|
207
|
+
fi
|
|
208
|
+
ls -l pkg
|
|
209
|
+
|
|
210
|
+
- name: Install, use, remove
|
|
211
|
+
run: script/tebako/package-smoke.sh pkg
|
|
212
|
+
|
|
213
|
+
publish:
|
|
214
|
+
name: attach to release
|
|
215
|
+
if: needs.resolve.outputs.tag != ''
|
|
216
|
+
needs: [ resolve, pack, package-smoke ]
|
|
217
|
+
runs-on: ubuntu-24.04
|
|
218
|
+
permissions:
|
|
219
|
+
contents: write
|
|
220
|
+
steps:
|
|
221
|
+
- uses: actions/download-artifact@v4
|
|
222
|
+
with:
|
|
223
|
+
path: dist
|
|
224
|
+
merge-multiple: true
|
|
225
|
+
|
|
226
|
+
- name: Name executables by version and upload
|
|
227
|
+
env:
|
|
228
|
+
GH_TOKEN: ${{ github.token }}
|
|
229
|
+
TAG: ${{ needs.resolve.outputs.tag }}
|
|
230
|
+
run: |
|
|
231
|
+
version="${TAG#v}"
|
|
232
|
+
cd dist
|
|
233
|
+
for name in linux-x86_64 linux-arm64 macos-arm64 macos-x86_64; do
|
|
234
|
+
mv "fontist-$name" "fontist-$version-$name"
|
|
235
|
+
done
|
|
236
|
+
# Executables and .rpm files are fontist-*, .deb files fontist_*.
|
|
237
|
+
sha256sum fontist-* fontist_* > SHA256SUMS
|
|
238
|
+
gh release upload "$TAG" --repo "$GITHUB_REPOSITORY" --clobber \
|
|
239
|
+
fontist-* fontist_* SHA256SUMS
|
data/README.adoc
CHANGED
|
@@ -42,6 +42,56 @@ And then execute:
|
|
|
42
42
|
bundle install
|
|
43
43
|
----
|
|
44
44
|
|
|
45
|
+
=== Install without Ruby
|
|
46
|
+
|
|
47
|
+
Each release on the
|
|
48
|
+
https://github.com/fontist/fontist/releases[GitHub Releases] page has a
|
|
49
|
+
self-contained `fontist` executable. It does not need a Ruby installation.
|
|
50
|
+
Linux and macOS are supported.
|
|
51
|
+
|
|
52
|
+
Download the file for your system, check it, and make it executable. The
|
|
53
|
+
names are `fontist-<version>-linux-x86_64`, `-linux-arm64`, `-macos-arm64`
|
|
54
|
+
and `-macos-x86_64`.
|
|
55
|
+
|
|
56
|
+
[source,sh]
|
|
57
|
+
----
|
|
58
|
+
curl -LO https://github.com/fontist/fontist/releases/download/v<version>/fontist-<version>-linux-x86_64
|
|
59
|
+
curl -LO https://github.com/fontist/fontist/releases/download/v<version>/SHA256SUMS
|
|
60
|
+
sha256sum --ignore-missing -c SHA256SUMS # on macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
|
|
61
|
+
chmod +x fontist-<version>-linux-x86_64
|
|
62
|
+
./fontist-<version>-linux-x86_64 version
|
|
63
|
+
----
|
|
64
|
+
|
|
65
|
+
The executables are not signed. On macOS, remove the quarantine flag before
|
|
66
|
+
the first run:
|
|
67
|
+
|
|
68
|
+
[source,sh]
|
|
69
|
+
----
|
|
70
|
+
xattr -d com.apple.quarantine ./fontist-<version>-macos-arm64
|
|
71
|
+
----
|
|
72
|
+
|
|
73
|
+
Each run prints a notice from the packager that the executable is unsigned.
|
|
74
|
+
It is harmless.
|
|
75
|
+
|
|
76
|
+
fontist needs git 2.43 or newer to fetch formulas. The git that ships with
|
|
77
|
+
macOS is older, so install a current one first (for example
|
|
78
|
+
`brew install git`).
|
|
79
|
+
|
|
80
|
+
On Debian and Ubuntu, install the `.deb` package. On Fedora and RHEL, install
|
|
81
|
+
the `.rpm` package. Both put `fontist` in `/usr/bin` and depend on git 2.43 or
|
|
82
|
+
newer, which Ubuntu 24.04, Debian 13, Fedora and RHEL 9 provide.
|
|
83
|
+
|
|
84
|
+
[source,sh]
|
|
85
|
+
----
|
|
86
|
+
sudo apt install ./fontist_<version>_amd64.deb
|
|
87
|
+
sudo dnf install ./fontist-<version>-1.x86_64.rpm
|
|
88
|
+
----
|
|
89
|
+
|
|
90
|
+
For ARM64, use `_arm64.deb` and `.aarch64.rpm`.
|
|
91
|
+
|
|
92
|
+
This build uses the same home directory as the gem (`~/.fontist`, or
|
|
93
|
+
`FONTIST_PATH` if set), so the two can be used side by side.
|
|
94
|
+
|
|
45
95
|
=== Fetch formulas
|
|
46
96
|
|
|
47
97
|
After installation, please fetch formulas via the `fontist` command:
|
|
@@ -363,6 +413,20 @@ Keeps only the glyphs for those characters. Options can be combined with
|
|
|
363
413
|
fontist pack family.ttc Regular.ttf Bold.ttf
|
|
364
414
|
----
|
|
365
415
|
|
|
416
|
+
==== Transform a font file you already have
|
|
417
|
+
|
|
418
|
+
`fontist convert` runs the same operations on a local file, without
|
|
419
|
+
installing anything. Each output is written next to the source unless
|
|
420
|
+
`--output` (or `--output-dir`) is given, and the source is never overwritten.
|
|
421
|
+
|
|
422
|
+
[source,sh]
|
|
423
|
+
----
|
|
424
|
+
fontist convert format Lato-Regular.ttf woff2
|
|
425
|
+
fontist convert extract NotoSansCJK.ttc --index 1 --output-dir out
|
|
426
|
+
fontist convert instance "Roboto[wdth,wght].ttf" wght=300,wdth=90
|
|
427
|
+
fontist convert subset Lato-Regular.ttf --unicodes "U+0020-007E" --text "é"
|
|
428
|
+
----
|
|
429
|
+
|
|
366
430
|
==== Ruby API
|
|
367
431
|
|
|
368
432
|
[source,ruby]
|
data/docs/.vitepress/config.ts
CHANGED
|
@@ -204,6 +204,7 @@ export default defineConfig({
|
|
|
204
204
|
{ text: "repo", link: "/cli/repo" },
|
|
205
205
|
{ text: "fontconfig", link: "/cli/fontconfig" },
|
|
206
206
|
{ text: "import", link: "/cli/import" },
|
|
207
|
+
{ text: "convert", link: "/cli/convert" },
|
|
207
208
|
{ text: "index", link: "/cli/index-cmd" },
|
|
208
209
|
{ text: "create-formula", link: "/cli/create-formula" },
|
|
209
210
|
],
|
|
@@ -247,7 +248,7 @@ export default defineConfig({
|
|
|
247
248
|
],
|
|
248
249
|
|
|
249
250
|
footer: {
|
|
250
|
-
message: `Fontist is <a href="https://
|
|
251
|
+
message: `Fontist is <a href="https://www.ribose.com/">riboseopen</a>`,
|
|
251
252
|
copyright: `Copyright © 2026 Ribose Group Inc. All rights reserved.`,
|
|
252
253
|
},
|
|
253
254
|
},
|
data/docs/cli/convert.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# fontist convert
|
|
2
|
+
|
|
3
|
+
Transform a font file you already have, using [Fontisan](https://github.com/fontist/fontisan). Nothing is installed.
|
|
4
|
+
|
|
5
|
+
## Syntax
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
fontist convert format FONT_FILE FORMAT [--output FILE]
|
|
9
|
+
fontist convert extract COLLECTION --index N [--output-dir DIR]
|
|
10
|
+
fontist convert instance FONT_FILE AXES [--output FILE]
|
|
11
|
+
fontist convert subset FONT_FILE [--unicodes LIST] [--text TEXT] [--output FILE]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Subcommands
|
|
15
|
+
|
|
16
|
+
| Subcommand | Description |
|
|
17
|
+
|------------|-------------|
|
|
18
|
+
| `format` | Convert to `ttf`, `otf`, `woff` or `woff2` |
|
|
19
|
+
| `extract` | Write one member of a TTC/OTC collection as a standalone font |
|
|
20
|
+
| `instance` | Write a static instance of a variable font at the given axis values |
|
|
21
|
+
| `subset` | Keep only the glyphs for the given characters |
|
|
22
|
+
|
|
23
|
+
By default each output is written next to the source: `Lato.woff2`, `Font-wght300.ttf`, `Lato-subset.ttf`. A command never overwrites its source font.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
fontist convert format Lato-Regular.ttf woff2
|
|
29
|
+
fontist convert extract NotoSansCJK.ttc --index 1 --output-dir out
|
|
30
|
+
fontist convert instance "Roboto[wdth,wght].ttf" wght=300,wdth=90
|
|
31
|
+
fontist convert subset Lato-Regular.ttf --unicodes "U+0020-007E" --text "é"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Axis tags and values are checked against the font: an unknown axis or a value outside its range fails with an error.
|
|
35
|
+
|
|
36
|
+
## Related Commands
|
|
37
|
+
|
|
38
|
+
- [fontist install](/cli/install) - The same operations while installing (`--format`, `--collection-index`, `--instance`, `--subset-*`)
|
data/docs/cli/index.md
CHANGED
|
@@ -23,6 +23,7 @@ Complete command-line interface reference for Fontist.
|
|
|
23
23
|
| [`fontist repo`](/cli/repo) | Custom repositories |
|
|
24
24
|
| [`fontist fontconfig`](/cli/fontconfig) | Fontconfig integration |
|
|
25
25
|
| [`fontist import`](/cli/import) | Import fonts |
|
|
26
|
+
| [`fontist convert`](/cli/convert) | Convert, extract, instance or subset a font file |
|
|
26
27
|
| [`fontist index`](/cli/index-cmd) | System font index |
|
|
27
28
|
| [`fontist create-formula`](/cli/create-formula) | Create formulas |
|
|
28
29
|
|
data/lib/fontist/cli.rb
CHANGED
|
@@ -33,6 +33,7 @@ module Fontist
|
|
|
33
33
|
Fontist::Errors::CollectionIndexError => [STATUS_UNKNOWN_ERROR],
|
|
34
34
|
Fontist::Errors::UnsupportedTranscodeError => [STATUS_UNKNOWN_ERROR],
|
|
35
35
|
Fontist::Errors::SourceNotFoundError => [STATUS_UNKNOWN_ERROR],
|
|
36
|
+
Fontist::Errors::InstanceError => [STATUS_UNKNOWN_ERROR],
|
|
36
37
|
Fontist::Errors::SizeLimitError => [
|
|
37
38
|
STATUS_SIZE_LIMIT_ERROR,
|
|
38
39
|
:append,
|
|
@@ -470,6 +471,10 @@ module Fontist
|
|
|
470
471
|
desc "config SUBCOMMAND ...ARGS", "Manage fontist config"
|
|
471
472
|
subcommand "config", Fontist::ConfigCLI
|
|
472
473
|
|
|
474
|
+
desc "convert SUBCOMMAND ...ARGS",
|
|
475
|
+
"Convert, extract, instance or subset a font file"
|
|
476
|
+
subcommand "convert", Fontist::ConvertCLI
|
|
477
|
+
|
|
473
478
|
desc "cache SUBCOMMAND ...ARGS", "Manage fontist cache"
|
|
474
479
|
subcommand "cache", Fontist::CacheCLI
|
|
475
480
|
|
|
@@ -559,7 +564,7 @@ module Fontist
|
|
|
559
564
|
styles.each do |style, installed|
|
|
560
565
|
opts = []
|
|
561
566
|
opts << "manual" if formula.manual?
|
|
562
|
-
opts << (installed
|
|
567
|
+
opts << install_label(installed)
|
|
563
568
|
msg = " #{style.type} (#{opts.join(', ')})"
|
|
564
569
|
|
|
565
570
|
if installed
|
|
@@ -573,6 +578,14 @@ module Fontist
|
|
|
573
578
|
end
|
|
574
579
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
575
580
|
|
|
581
|
+
def install_label(status)
|
|
582
|
+
case status
|
|
583
|
+
when true then "installed"
|
|
584
|
+
when false then "not installed"
|
|
585
|
+
else "installed (system)"
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
576
589
|
def print_find_results(results)
|
|
577
590
|
if results.empty?
|
|
578
591
|
Fontist.ui.say("No fonts found matching criteria")
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Fontist
|
|
2
|
+
# `fontist convert ...`: Fontisan operations on font files the user
|
|
3
|
+
# already has, without installing anything.
|
|
4
|
+
class ConvertCLI < Thor
|
|
5
|
+
include CLI::ClassOptions
|
|
6
|
+
|
|
7
|
+
desc "format FONT_FILE FORMAT",
|
|
8
|
+
"Convert FONT_FILE to FORMAT (ttf, otf, woff, woff2)"
|
|
9
|
+
option :output, aliases: :o,
|
|
10
|
+
desc: "Output file (default: FONT_FILE, new extension)"
|
|
11
|
+
def to_format(source, target)
|
|
12
|
+
default = replace_ext(source, ".#{target.to_s.downcase}")
|
|
13
|
+
write_font do
|
|
14
|
+
output = output_for(source, default)
|
|
15
|
+
FontOperations::Convert.call(source, target, output)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
map "format" => :to_format
|
|
19
|
+
|
|
20
|
+
desc "extract COLLECTION", "Write one member of a TTC/OTC collection"
|
|
21
|
+
option :index, type: :numeric, required: true,
|
|
22
|
+
desc: "Zero-based member index"
|
|
23
|
+
option :output_dir, desc: "Output directory (default: next to COLLECTION)"
|
|
24
|
+
def extract(collection)
|
|
25
|
+
dir = options[:output_dir] || File.dirname(collection)
|
|
26
|
+
write_font do
|
|
27
|
+
FontOperations::Extract.call(collection, index: options[:index],
|
|
28
|
+
output_dir: dir)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
desc "instance FONT_FILE AXES",
|
|
33
|
+
"Write a static instance of a variable font (e.g. wght=300,wdth=90)"
|
|
34
|
+
option :output, aliases: :o,
|
|
35
|
+
desc: "Output file (default: FONT_FILE named after AXES)"
|
|
36
|
+
def instance(source, axes)
|
|
37
|
+
write_font do
|
|
38
|
+
coords = FontOperations::Instance.parse(axes)
|
|
39
|
+
name = FontOperations::Instance.file_name(File.basename(source), coords)
|
|
40
|
+
default = File.join(File.dirname(source), name)
|
|
41
|
+
FontOperations::Instance.call(source, output_for(source, default),
|
|
42
|
+
coordinates: coords)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
desc "subset FONT_FILE", "Keep only the glyphs for the given characters"
|
|
47
|
+
option :unicodes, desc: "Codepoints to keep (e.g. 'U+0020-007E,U+00E9')"
|
|
48
|
+
option :text, desc: "Characters to keep"
|
|
49
|
+
option :output, aliases: :o,
|
|
50
|
+
desc: "Output file (default: FONT_FILE with -subset)"
|
|
51
|
+
def subset(source)
|
|
52
|
+
default = replace_ext(source, "-subset#{File.extname(source)}")
|
|
53
|
+
write_font do
|
|
54
|
+
FontOperations::Subset.call(source, output_for(source, default),
|
|
55
|
+
unicodes: options[:unicodes],
|
|
56
|
+
text: options[:text])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def write_font
|
|
63
|
+
handle_class_options(options)
|
|
64
|
+
path = yield
|
|
65
|
+
Fontist.ui.success("Written to #{path}")
|
|
66
|
+
CLI::STATUS_SUCCESS
|
|
67
|
+
rescue Errors::GeneralError => e
|
|
68
|
+
Fontist.ui.error(e.message)
|
|
69
|
+
CLI::STATUS_UNKNOWN_ERROR
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The given --output, or +default+; never the source itself.
|
|
73
|
+
def output_for(source, default)
|
|
74
|
+
output = options[:output] || default
|
|
75
|
+
if File.expand_path(output) == File.expand_path(source)
|
|
76
|
+
raise FontOperations::Error,
|
|
77
|
+
"Output would overwrite #{source}. Give a different --output."
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
output
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def replace_ext(path, suffix)
|
|
84
|
+
File.join(File.dirname(path),
|
|
85
|
+
File.basename(path, File.extname(path)) + suffix)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/lib/fontist/font.rb
CHANGED
|
@@ -446,8 +446,9 @@ module Fontist
|
|
|
446
446
|
def list_styles(formulas)
|
|
447
447
|
map_to_hash(formulas) do |formula|
|
|
448
448
|
map_to_hash(requested_fonts(formula.all_fonts)) do |font|
|
|
449
|
+
external = external_paths_by_type(font)
|
|
449
450
|
map_to_hash(font.styles) do |style|
|
|
450
|
-
installed(style)
|
|
451
|
+
installed(style, external)
|
|
451
452
|
end
|
|
452
453
|
end
|
|
453
454
|
end
|
|
@@ -465,8 +466,25 @@ module Fontist
|
|
|
465
466
|
end
|
|
466
467
|
end
|
|
467
468
|
|
|
468
|
-
|
|
469
|
-
|
|
469
|
+
# A font found only outside the fontist directory reports its paths
|
|
470
|
+
# instead of true, so callers can tell the copies fontist cannot
|
|
471
|
+
# update or remove from the managed ones.
|
|
472
|
+
def installed(style, external)
|
|
473
|
+
return true if path(style)
|
|
474
|
+
|
|
475
|
+
external.fetch(style.type.to_s.downcase, false)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
# One index lookup per font name, grouped by lower-cased style type.
|
|
479
|
+
def external_paths_by_type(font)
|
|
480
|
+
entries = SystemFont.find_styles(font.name) || []
|
|
481
|
+
entries.reject { |entry| in_fontist_dir?(entry.path) }
|
|
482
|
+
.group_by { |entry| entry.type.to_s.downcase }
|
|
483
|
+
.transform_values { |group| group.map(&:path) }
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def in_fontist_dir?(path)
|
|
487
|
+
path.start_with?(Fontist.fonts_path.to_s)
|
|
470
488
|
end
|
|
471
489
|
|
|
472
490
|
def raise_non_supported_font
|
data/lib/fontist/system_index.rb
CHANGED
|
@@ -403,8 +403,11 @@ module Fontist
|
|
|
403
403
|
end
|
|
404
404
|
|
|
405
405
|
def index_changed?
|
|
406
|
+
# Verified first: a location that holds no fonts leaves the index
|
|
407
|
+
# empty after its rebuild, and treating empty as unbuilt would rescan
|
|
408
|
+
# the disk on every lookup. Installs reach the index via add_font.
|
|
409
|
+
return false if @index_check_done # already verified in this session
|
|
406
410
|
return true if fonts.nil? || fonts.empty?
|
|
407
|
-
return false if @index_check_done # Skip if already verified in this session
|
|
408
411
|
|
|
409
412
|
# Quick check: if index was scanned recently, trust it
|
|
410
413
|
if recently_scanned?
|
data/lib/fontist/validation.rb
CHANGED
data/lib/fontist/validator.rb
CHANGED
data/lib/fontist/version.rb
CHANGED
data/lib/fontist.rb
CHANGED
|
@@ -82,6 +82,7 @@ module Fontist
|
|
|
82
82
|
autoload :CLI, "#{__dir__}/fontist/cli"
|
|
83
83
|
autoload :CacheCLI, "#{__dir__}/fontist/cache_cli"
|
|
84
84
|
autoload :ConfigCLI, "#{__dir__}/fontist/config_cli"
|
|
85
|
+
autoload :ConvertCLI, "#{__dir__}/fontist/convert_cli"
|
|
85
86
|
autoload :FontconfigCLI, "#{__dir__}/fontist/fontconfig_cli"
|
|
86
87
|
autoload :ImportCLI, "#{__dir__}/fontist/import_cli"
|
|
87
88
|
autoload :IndexCLI, "#{__dir__}/fontist/index_cli"
|
data/packaging/nfpm.yaml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Linux packages that wrap the tebako-packed fontist executable.
|
|
2
|
+
# Built by script/tebako/package.sh, which sets ARCH, VERSION and BINARY.
|
|
3
|
+
name: fontist
|
|
4
|
+
arch: ${ARCH}
|
|
5
|
+
platform: linux
|
|
6
|
+
version: ${VERSION}
|
|
7
|
+
section: utils
|
|
8
|
+
priority: optional
|
|
9
|
+
maintainer: Ribose Inc. <open.source@ribose.com>
|
|
10
|
+
description: |
|
|
11
|
+
Install openly-licensed fonts on Windows, Linux and Mac.
|
|
12
|
+
Self-contained build: no Ruby installation is needed.
|
|
13
|
+
vendor: Ribose Inc.
|
|
14
|
+
homepage: https://www.fontist.org
|
|
15
|
+
license: BSD-2-Clause
|
|
16
|
+
|
|
17
|
+
# fontist clones its formula repository with git, and its git gem (~> 6.0)
|
|
18
|
+
# refuses a host git older than 2.43. Debian and Ubuntu version git with
|
|
19
|
+
# epoch 1 (1:2.43.0-1), RPM distros do not, hence one dependency per packager.
|
|
20
|
+
overrides:
|
|
21
|
+
deb:
|
|
22
|
+
depends:
|
|
23
|
+
- git (>= 1:2.43)
|
|
24
|
+
rpm:
|
|
25
|
+
depends:
|
|
26
|
+
- git >= 2.43
|
|
27
|
+
|
|
28
|
+
contents:
|
|
29
|
+
- src: ${BINARY}
|
|
30
|
+
dst: /usr/bin/fontist
|
|
31
|
+
expand: true # nfpm leaves ${BINARY} in src alone without this
|
|
32
|
+
file_info:
|
|
33
|
+
mode: 0755
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Entry point of the tebako-packed fontist (copied to bin/fontist by
|
|
5
|
+
# script/tebako/stage.sh).
|
|
6
|
+
#
|
|
7
|
+
# tebako installs the locked dependencies as gems inside the package; only
|
|
8
|
+
# fontist itself sits at a path, so it goes on the load path directly.
|
|
9
|
+
# bundler/setup is not used: bundler chdirs into path gems, and the packed
|
|
10
|
+
# filesystem refuses that.
|
|
11
|
+
#
|
|
12
|
+
# Libraries loaded through FFI (yeptris, leptris, ...) are opened with the
|
|
13
|
+
# host's dlopen, which cannot see inside the package. Each one is copied
|
|
14
|
+
# once to a host cache keyed by its content, and FFI is handed that copy.
|
|
15
|
+
|
|
16
|
+
# The packed gems are the only gems this program may see. rubygems also
|
|
17
|
+
# searches the host's GEM_HOME, GEM_PATH and user gem dir (~/.gem/ruby/<abi>),
|
|
18
|
+
# so a Ruby manager such as rvm, or a `gem install --user-install`, would
|
|
19
|
+
# shadow the locked gems. Pin rubygems to the package's gem dir before
|
|
20
|
+
# anything is required.
|
|
21
|
+
packed_gem_dir = Gem.default_dir
|
|
22
|
+
ENV.delete("GEM_HOME")
|
|
23
|
+
ENV.delete("GEM_PATH")
|
|
24
|
+
Gem.use_paths(packed_gem_dir, [packed_gem_dir])
|
|
25
|
+
|
|
26
|
+
require "digest"
|
|
27
|
+
require "fileutils"
|
|
28
|
+
require "ffi"
|
|
29
|
+
|
|
30
|
+
module FontistPackedNativeLibraries
|
|
31
|
+
PACKAGE_ROOT = "/__tfs__/"
|
|
32
|
+
|
|
33
|
+
def self.cache_root
|
|
34
|
+
home = ENV["FONTIST_PATH"] || File.join(Dir.home, ".fontist")
|
|
35
|
+
File.join(home, "tebako-native")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.host_path(name)
|
|
39
|
+
return name unless name.is_a?(String) && name.start_with?(PACKAGE_ROOT)
|
|
40
|
+
return name unless File.file?(name)
|
|
41
|
+
|
|
42
|
+
bytes = File.binread(name)
|
|
43
|
+
dir = File.join(cache_root, Digest::SHA256.hexdigest(bytes)[0, 16])
|
|
44
|
+
target = File.join(dir, File.basename(name))
|
|
45
|
+
write_once(target, bytes) unless File.file?(target)
|
|
46
|
+
target
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.write_once(target, bytes)
|
|
50
|
+
FileUtils.mkdir_p(File.dirname(target))
|
|
51
|
+
partial = "#{target}.#{Process.pid}.partial"
|
|
52
|
+
File.binwrite(partial, bytes)
|
|
53
|
+
File.chmod(0o755, partial)
|
|
54
|
+
File.rename(partial, target)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# An Array argument is a list of alternatives (the first that loads wins),
|
|
58
|
+
# so the nesting is kept: only the names inside are rewritten.
|
|
59
|
+
def self.rewrite(name)
|
|
60
|
+
name.is_a?(Array) ? name.map { |n| rewrite(n) } : host_path(name)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def ffi_lib(*names)
|
|
64
|
+
super(*names.map { |name| FontistPackedNativeLibraries.rewrite(name) })
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
FFI::Library.prepend(FontistPackedNativeLibraries)
|
|
69
|
+
|
|
70
|
+
# leptris also opens libleptris from its compiled extension, which consults
|
|
71
|
+
# LEPTRIS_LIB_PATH and then package paths the host cannot open. Two copies
|
|
72
|
+
# of the library loaded side by side crash it, so both loaders are pointed
|
|
73
|
+
# at the same host copy. yeptris reads YEPTRIS_LIB_PATH the same way.
|
|
74
|
+
{
|
|
75
|
+
"leptris" => %w[LEPTRIS_LIB_PATH libleptris],
|
|
76
|
+
"yeptris" => %w[YEPTRIS_LIB_PATH libyeptris],
|
|
77
|
+
}.each do |gem_name, (variable, basename)|
|
|
78
|
+
next if ENV[variable]
|
|
79
|
+
|
|
80
|
+
spec = Gem::Specification.find_all_by_name(gem_name).max_by(&:version)
|
|
81
|
+
next unless spec
|
|
82
|
+
|
|
83
|
+
library = Dir.glob(
|
|
84
|
+
File.join(spec.full_gem_path, "**", "#{basename}.{dylib,so,dll}"),
|
|
85
|
+
).min
|
|
86
|
+
ENV[variable] = FontistPackedNativeLibraries.host_path(library) if library
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
$LOAD_PATH.unshift(File.expand_path("../vendor/fontist/lib", __dir__))
|
|
90
|
+
load File.expand_path("../vendor/fontist/exe/fontist", __dir__)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install a fontist .deb or .rpm on a fresh distro, use it, then remove it.
|
|
3
|
+
# Runs inside a distro container (see .github/workflows/tebako-pack.yml).
|
|
4
|
+
#
|
|
5
|
+
# script/tebako/package-smoke.sh <package-dir>
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
dir="${1:?usage: package-smoke.sh <package-dir>}"
|
|
9
|
+
# apt reads a bare relative path as a package name; give it an absolute one.
|
|
10
|
+
dir="$(cd "$dir" && pwd)"
|
|
11
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
|
|
13
|
+
if command -v apt-get >/dev/null; then
|
|
14
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
15
|
+
apt-get update -qq
|
|
16
|
+
apt-get install -y -qq ca-certificates "$dir"/fontist_*.deb
|
|
17
|
+
remove() { apt-get remove -y -qq fontist; }
|
|
18
|
+
else
|
|
19
|
+
dnf install -y -q "$dir"/fontist-*.rpm
|
|
20
|
+
remove() { dnf remove -y -q fontist; }
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if command -v ruby >/dev/null; then
|
|
24
|
+
echo "package-smoke: this image has no business carrying ruby" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
"$here/smoke.sh" "$(command -v fontist)"
|
|
28
|
+
remove
|
|
29
|
+
if command -v fontist >/dev/null; then
|
|
30
|
+
echo "package-smoke: fontist still on PATH after removal" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
echo "package-smoke: ok"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wrap a packed Linux fontist executable into .deb and .rpm packages.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/package.sh <amd64|arm64> <fontist-executable> <out-dir>
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
usage="usage: package.sh <amd64|arm64> <fontist-executable> <out-dir>"
|
|
8
|
+
arch="${1:?$usage}"
|
|
9
|
+
binary="${2:?$usage}"
|
|
10
|
+
out="${3:?$usage}"
|
|
11
|
+
|
|
12
|
+
root="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
13
|
+
version="$(sed -n 's/.*VERSION = "\(.*\)".*/\1/p' "$root/lib/fontist/version.rb")"
|
|
14
|
+
|
|
15
|
+
mkdir -p "$out"
|
|
16
|
+
BINARY="$(cd "$(dirname "$binary")" && pwd)/$(basename "$binary")"
|
|
17
|
+
export ARCH="$arch" VERSION="$version" BINARY
|
|
18
|
+
|
|
19
|
+
for packager in deb rpm; do
|
|
20
|
+
nfpm package --config "$root/packaging/nfpm.yaml" \
|
|
21
|
+
--packager "$packager" --target "$out"
|
|
22
|
+
done
|
|
23
|
+
ls -l "$out"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Press fontist into one self-contained executable with tebako v2.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/press.sh <tebako-triplet> <output-path>
|
|
5
|
+
#
|
|
6
|
+
# <tebako-triplet> is the tebako release asset suffix: linux-gnu-x86_64,
|
|
7
|
+
# linux-gnu-arm64, macos-arm64 or macos-x86_64. Needs gh, ruby and bundler.
|
|
8
|
+
# GH_TOKEN (or GITHUB_TOKEN) keeps tebako's runtime lookups clear of the
|
|
9
|
+
# anonymous GitHub API limit.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
triplet="${1:?usage: press.sh <tebako-triplet> <output-path>}"
|
|
13
|
+
output="${2:?usage: press.sh <tebako-triplet> <output-path>}"
|
|
14
|
+
|
|
15
|
+
tebako_version="${TEBAKO_VERSION:-2.8.68}"
|
|
16
|
+
ruby_version="${PACKAGE_RUBY_VERSION:-3.3.12}"
|
|
17
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
18
|
+
work="$(mktemp -d)"
|
|
19
|
+
trap 'rm -rf "$work"' EXIT
|
|
20
|
+
|
|
21
|
+
export GITHUB_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
|
|
22
|
+
|
|
23
|
+
asset="tebako-${tebako_version}-${triplet}"
|
|
24
|
+
gh release download "v${tebako_version}" --repo tamatebako/tebako \
|
|
25
|
+
--pattern "${asset}" --pattern "${asset}.sha256" --dir "$work"
|
|
26
|
+
(cd "$work" && shasum -a 256 -c "${asset}.sha256")
|
|
27
|
+
chmod +x "$work/$asset"
|
|
28
|
+
|
|
29
|
+
stage="$("$here/stage.sh" "$work/stage")"
|
|
30
|
+
|
|
31
|
+
mkdir -p "$(dirname "$output")"
|
|
32
|
+
output="$(cd "$(dirname "$output")" && pwd)/$(basename "$output")"
|
|
33
|
+
|
|
34
|
+
# tebako appends a trailer to the executable: never strip the result.
|
|
35
|
+
"$work/$asset" press --root "$stage" --entry-point bin/fontist \
|
|
36
|
+
--output "$output" --mode self-contained -R "$ruby_version"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Check that a packed (or installed) fontist works on its own.
|
|
3
|
+
#
|
|
4
|
+
# script/tebako/smoke.sh <fontist-executable>
|
|
5
|
+
#
|
|
6
|
+
# Uses a throwaway FONTIST_PATH so it never touches a real ~/.fontist.
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
fontist="${1:?usage: smoke.sh <fontist-executable>}"
|
|
10
|
+
font="${SMOKE_FONT:-Overpass}"
|
|
11
|
+
|
|
12
|
+
home="$(mktemp -d)"
|
|
13
|
+
trap 'rm -rf "$home"' EXIT
|
|
14
|
+
export FONTIST_PATH="$home"
|
|
15
|
+
|
|
16
|
+
"$fontist" version
|
|
17
|
+
"$fontist" install --accept-all-licenses "$font"
|
|
18
|
+
|
|
19
|
+
if ! find "$home/fonts" -type f | grep -q .; then
|
|
20
|
+
echo "smoke: no font file landed under $home/fonts" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
"$fontist" list "$font" | tee "$home/list.txt"
|
|
24
|
+
grep -qi "installed" "$home/list.txt"
|
|
25
|
+
echo "smoke: ok"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build a Gemfile-rooted app around the fontist gem, the layout tebako v2
|
|
3
|
+
# presses (it refuses a root that is itself a gem source tree).
|
|
4
|
+
#
|
|
5
|
+
# script/tebako/stage.sh <stage-dir>
|
|
6
|
+
#
|
|
7
|
+
# The gem is built from this checkout, unpacked with a static gemspec (the
|
|
8
|
+
# repository gemspec lists files with `git ls-files`, which needs .git), and
|
|
9
|
+
# referenced by path, so the packed fontist is exactly this checkout's code.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
stage="${1:?usage: stage.sh <stage-dir>}"
|
|
13
|
+
root="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
14
|
+
|
|
15
|
+
rm -rf "$stage"
|
|
16
|
+
mkdir -p "$stage/vendor" "$stage/bin"
|
|
17
|
+
stage="$(cd "$stage" && pwd)"
|
|
18
|
+
|
|
19
|
+
(cd "$root" && gem build fontist.gemspec --output "$stage/fontist.gem" >/dev/null)
|
|
20
|
+
# Unpacked directory naming differs across rubygems versions; take the one
|
|
21
|
+
# child of a fresh directory instead of guessing it.
|
|
22
|
+
unpacked="$(mktemp -d)"
|
|
23
|
+
gem unpack "$stage/fontist.gem" --target "$unpacked" >/dev/null
|
|
24
|
+
mv "$unpacked"/*/ "$stage/vendor/fontist"
|
|
25
|
+
rmdir "$unpacked"
|
|
26
|
+
gem spec "$stage/fontist.gem" --ruby > "$stage/vendor/fontist/fontist.gemspec"
|
|
27
|
+
rm "$stage/fontist.gem"
|
|
28
|
+
|
|
29
|
+
cat > "$stage/Gemfile" <<'GEMFILE'
|
|
30
|
+
source "https://rubygems.org"
|
|
31
|
+
|
|
32
|
+
gem "fontist", path: "vendor/fontist"
|
|
33
|
+
GEMFILE
|
|
34
|
+
|
|
35
|
+
cp "$root/script/tebako/entry.rb" "$stage/bin/fontist"
|
|
36
|
+
chmod +x "$stage/bin/fontist"
|
|
37
|
+
|
|
38
|
+
(cd "$stage" && bundle lock >/dev/null)
|
|
39
|
+
echo "$stage"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fontist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.37
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-11-
|
|
11
|
+
date: 2026-11-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: down
|
|
@@ -277,6 +277,7 @@ files:
|
|
|
277
277
|
- docs/api/manifest.md
|
|
278
278
|
- docs/cli/cache.md
|
|
279
279
|
- docs/cli/config.md
|
|
280
|
+
- docs/cli/convert.md
|
|
280
281
|
- docs/cli/create-formula.md
|
|
281
282
|
- docs/cli/exit-codes.md
|
|
282
283
|
- docs/cli/fontconfig.md
|
|
@@ -343,6 +344,7 @@ files:
|
|
|
343
344
|
- lib/fontist/collection_file.rb
|
|
344
345
|
- lib/fontist/config.rb
|
|
345
346
|
- lib/fontist/config_cli.rb
|
|
347
|
+
- lib/fontist/convert_cli.rb
|
|
346
348
|
- lib/fontist/css.rb
|
|
347
349
|
- lib/fontist/css/google_family.rb
|
|
348
350
|
- lib/fontist/css/local.rb
|
|
@@ -515,9 +517,16 @@ files:
|
|
|
515
517
|
- lib/fontist/yaml/yeptris_adapter.rb
|
|
516
518
|
- lib/fontist/yaml_backend.rb
|
|
517
519
|
- lib/tasks/system_fonts.rake
|
|
520
|
+
- packaging/nfpm.yaml
|
|
518
521
|
- script/capture_system_fonts
|
|
519
522
|
- script/download_system_indexes
|
|
520
523
|
- script/generate_windows_formulas.rb
|
|
524
|
+
- script/tebako/entry.rb
|
|
525
|
+
- script/tebako/package-smoke.sh
|
|
526
|
+
- script/tebako/package.sh
|
|
527
|
+
- script/tebako/press.sh
|
|
528
|
+
- script/tebako/smoke.sh
|
|
529
|
+
- script/tebako/stage.sh
|
|
521
530
|
- script/validate_windows_fod_ci.rb
|
|
522
531
|
homepage: https://github.com/fontist/fontist
|
|
523
532
|
licenses:
|