fontist 3.0.10 → 3.0.11

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: e0b0e99691434acdede0ea1ef18c07f326e07b0a62b57fd5cae59c218e3991e5
4
- data.tar.gz: 23c928be6bf6344d49f2e9bc93b36c038b3d3ee0d9e388a62ef4427862ad739f
3
+ metadata.gz: 8be7d98f9f421275a9d89981c7519a92dc76da79c37f9a600b0ae7af89a2fe90
4
+ data.tar.gz: 7a83154879381549601dbe394abb263d1f6044e327570beece2879a00a023eb4
5
5
  SHA512:
6
- metadata.gz: e28c80e58cef62db2b64280a1168e840a83849dd99e233f28b25b63f6b1719bfb368d3d72d6880a9c37026ed5d91cf96f0b74cf53188a3bb7ba52fe4894eb5ca
7
- data.tar.gz: 25a14d68e16d69f3378480e55ab232f60fcae8b727633ba542944bfed4a2fbb6f192b9ac00f49baacbb937270db4ba1c67082c0e6e8402c16a6b88ae2d1f1030
6
+ metadata.gz: 9313ca1bfaac860c55067e71810715c40d2967d064900b3d9e26a8a5b84f32614eed57cfd4fb9c64d7c67ebb1ce7bf4fd05a06ba208fa35c6735dc903687927d
7
+ data.tar.gz: 76f717efb9f83ad90cea7286a47599ac90c423382909c8c503ed07b8e7e42252c28fefdb486f17ad6185b4dc5b8d3792e4c8e74914c31affeaae9b7012532be7
@@ -18,14 +18,6 @@ function pathToUrl(relativePath: string): string {
18
18
 
19
19
  // https://vitepress.dev/reference/site-config
20
20
  export default defineConfig({
21
- // Register custom components
22
- vite: {
23
- resolve: {
24
- alias: {
25
- "@components": fileURLToPath(new URL("../components", import.meta.url)),
26
- },
27
- },
28
- },
29
21
  lang: "en-US",
30
22
 
31
23
  // https://vitepress.dev/guide/routing#generating-clean-url
@@ -23,6 +23,7 @@ fontist create-formula URL [options]
23
23
  | `--subdir` | string | Subdirectory to extract fonts from |
24
24
  | `--file-pattern` | string | File pattern to match (e.g., "*.otf") |
25
25
  | `--name-prefix` | string | Prefix for font family names |
26
+ | `--schema-version N | numeric | Formula schema version (default: 5) |
26
27
 
27
28
  ## Examples
28
29
 
data/docs/cli/index.md CHANGED
@@ -18,12 +18,12 @@ Complete command-line interface reference for Fontist.
18
18
  | Command | Description |
19
19
  |---------|-------------|
20
20
  | [`fontist manifest`](/cli/manifest) | Manifest management |
21
- | [`fontist index`](/cli/index-cmd) | System font index |
22
21
  | [`fontist cache`](/cli/cache) | Cache management |
23
22
  | [`fontist config`](/cli/config) | Configuration |
24
23
  | [`fontist repo`](/cli/repo) | Custom repositories |
25
24
  | [`fontist fontconfig`](/cli/fontconfig) | Fontconfig integration |
26
25
  | [`fontist import`](/cli/import) | Import fonts |
26
+ | [`fontist index`](/cli/index-cmd) | System font index |
27
27
  | [`fontist create-formula`](/cli/create-formula) | Create formulas |
28
28
 
29
29
  ## Global Options
@@ -32,11 +32,12 @@ These options work with all commands:
32
32
 
33
33
  | Option | Description |
34
34
  |--------|-------------|
35
- | `--quiet` | Suppress output |
36
- | `--verbose` | Enable verbose output |
37
- | `--debug` | Enable debug output |
38
- | `--color` | Force colored output |
39
- | `--no-color` | Disable colored output |
35
+ | `--preferred-family` | Use preferred family when available |
36
+ | `--quiet` `-q` | Suppress output |
37
+ | `--verbose` `-v` | Enable verbose output |
38
+ | `--no-cache` `-c` | Avoid using cache during download
39
+ | `--[no-]interactive` `-i` | Interactive mode (default: true) |
40
+ | `--formulas-path PATH` | Path to formulas |
40
41
 
41
42
  ## Environment Variables
42
43
 
data/docs/cli/install.md CHANGED
@@ -16,13 +16,58 @@ fontist install FONT... [options]
16
16
 
17
17
  ## Options
18
18
 
19
- <CliOptions command="install" />
19
+ | Option | Alias | Type | Description |
20
+ |--------|-------|------|-------------|
21
+ | `--force` | `-f` | boolean | Install even if already installed in system |
22
+ | `--formula` | `-F` | boolean | Install whole formula instead of a font |
23
+ | `--accept-all-licenses` | `-a` | boolean | Accept all license agreements |
24
+ | `--hide-licenses` | `-h` | boolean | Hide license texts |
25
+ | `--no-progress` | `-p` | boolean | Hide download progress |
26
+ | `--version` | `-V` | string | Specify particular version of a font |
27
+ | `--smallest` | `-s` | boolean | Install the smallest font by file size if several |
28
+ | `--newest` | `-n` | boolean | Install the newest version of a font if several |
29
+ | `--size-limit` | `-S` | numeric | Specify upper limit for file size of a formula to be installed (default: 500 MB) |
30
+ | `--update-fontconfig` | `-u` | boolean | Update fontconfig |
31
+ | `--location` | `-l` | string | Install location: `fontist` (default), `user`, `system` |
32
+ | `--format FORMAT` | | string | Font format to install (ttf, otf, woff, woff2, ttc, otc). If format not available, will transcode from available formats
33
+ | `--variable-axes` | | string | Variable axes to match (comma-separated, e.g., 'wght,wdth') |
34
+ | `--prefer-variable` | | boolean | Prefer variable fonts over static fonts |
35
+ | `--prefer-format FORMAT` | | string | Preferred format when multiple available
36
+ | `--transcode-path PATH` | | string | Directory to save transcoded fonts (default: same as install location)
37
+ | `--keep-original` | | boolean | Keep original font after transcoding. (default: true)
38
+ | `--collection-index N` | | numeric | Extract specific font from TTC/OTC collection (0-indexed)
39
+
40
+
20
41
 
21
42
  ## Examples
22
43
 
23
- <CliExamples command="install" />
44
+ ### Common uses
45
+
46
+ ```sh
47
+ # Install a single font
48
+ fontist install "Roboto"
49
+
50
+ # Install multiple fonts
51
+ fontist install "Fira Code" "Open Sans"
52
+
53
+ # Force reinstall
54
+ fontist install "Roboto" --force
55
+
56
+ # Install to user directory
57
+ fontist install "Roboto" --location user
58
+
59
+ # Accept licenses automatically (for CI)
60
+ fontist install "Roboto" --accept-all-licenses --hide-licenses
61
+
62
+ # Install a specific version
63
+ fontist install "Roboto" --version 2.0
64
+
65
+ # Install whole formula
66
+ fontist install "Roboto" --formula
67
+ ```
68
+
24
69
 
25
- ## Multi-font Installation
70
+ ### Multi-font Installation
26
71
 
27
72
  You can install multiple fonts at once:
28
73
 
@@ -35,7 +80,7 @@ When installing multiple fonts, Fontist will:
35
80
  - Report successes and failures separately
36
81
  - Return appropriate exit code based on results
37
82
 
38
- ## Install Locations
83
+ ### Install Locations
39
84
 
40
85
  The `--location` option controls where fonts are installed:
41
86
 
@@ -7,7 +7,7 @@
7
7
  "devDependencies": {
8
8
  "@types/node": "^22.15.0",
9
9
  "prettier": "^3.8.1",
10
- "typescript": "^5.9.3",
10
+ "typescript": "^5.9.0",
11
11
  "vitepress": "^1.6.4"
12
12
  }
13
13
  },
@@ -2050,9 +2050,9 @@
2050
2050
  "license": "ISC"
2051
2051
  },
2052
2052
  "node_modules/postcss": {
2053
- "version": "8.5.8",
2054
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
2055
- "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
2053
+ "version": "8.5.13",
2054
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz",
2055
+ "integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==",
2056
2056
  "dev": true,
2057
2057
  "funding": [
2058
2058
  {
data/lib/fontist/cli.rb CHANGED
@@ -23,7 +23,7 @@ module Fontist
23
23
  STATUS_FORMULA_NOT_FOUND = 13
24
24
  STATUS_FONTCONFIG_NOT_FOUND = 14
25
25
  STATUS_FONTCONFIG_FILE_NOT_FOUND = 15
26
- STATUS_FONTIST_VERSION_ERROR = 15
26
+ STATUS_FONTIST_VERSION_ERROR = 17
27
27
  STATUS_INVALID_CONFIG_ATTRIBUTE = 16
28
28
 
29
29
  ERROR_TO_STATUS = {
@@ -125,7 +125,7 @@ module Fontist
125
125
  desc "sil", "Import formulas from SIL International"
126
126
  option :output_path,
127
127
  type: :string,
128
- desc: "Output directory for generated formulas (default: ~/.fontist/versions/v4/formulas/Formulas/sil)"
128
+ desc: "Output directory for generated formulas (default: ~/.fontist/versions/v5/formulas/Formulas/sil)"
129
129
  option :font_name,
130
130
  type: :string, aliases: :f,
131
131
  desc: "Import specific font by name (optional)"
@@ -1,6 +1,16 @@
1
+ require "time"
2
+
1
3
  module Fontist
2
4
  module Utils
3
5
  class Downloader
6
+ RATE_LIMITED_HTTP_STATUS = 429
7
+ BACKOFF = {
8
+ rate_limited: [10, 20, 40, 60, 90].freeze,
9
+ transient: [2, 4].freeze,
10
+ }.freeze
11
+ MAX_RETRY_AFTER = 120
12
+ JITTER_RATIO = 0.25
13
+
4
14
  class << self
5
15
  def download(*args)
6
16
  new(*args).download
@@ -22,6 +32,7 @@ module Fontist
22
32
  @verbose = progress_bar == :verbose
23
33
  @use_content_length = use_content_length
24
34
  @cache = Cache.new(cache_path: cache_path)
35
+ @tries = Hash.new(0)
25
36
  end
26
37
 
27
38
  def download
@@ -91,32 +102,85 @@ module Fontist
91
102
  end
92
103
 
93
104
  def download_file
94
- @tries ||= 0
95
- @tries += 1
96
105
  print_download_start if @verbose
97
106
  do_download_file
98
107
  rescue Down::Error => e
99
- retry if retry_download?
108
+ retry if retry_download?(e)
100
109
 
101
110
  raise Fontist::Errors::InvalidResourceError,
102
111
  "Invalid URL: #{@file}. Error: #{e.inspect}."
103
112
  end
104
113
 
105
- def retry_download?
106
- return false unless @tries < max_retries
114
+ def retry_download?(error)
115
+ response = http_response(error)
116
+ requested = retry_after(response)
117
+ backing_off = requested || rate_limited?(response)
118
+ kind = backing_off ? :rate_limited : :transient
119
+ delays = BACKOFF.fetch(kind)
120
+ attempt = (@tries[kind] += 1)
121
+ return false if attempt > delays.length
107
122
 
108
- sleep(backoff_time(@tries))
123
+ wait(kind, requested || jitter(delays[attempt - 1]))
109
124
  true
110
125
  end
111
126
 
112
- def max_retries
113
- @max_retries ||= 3
127
+ def wait(kind, seconds)
128
+ reason = if kind == :rate_limited
129
+ "Server asked us to slow down"
130
+ else
131
+ "Download failed"
132
+ end
133
+
134
+ Fontist.ui.say("#{reason}. Retrying in #{seconds}s...")
135
+ sleep(seconds)
136
+ end
137
+
138
+ # Spread retrying clients apart so they do not all return at once.
139
+ # Rounding the bound rather than the draw keeps the smallest delays
140
+ # spread too. Drawing first and rounding after loses them: a two second
141
+ # delay scales to half a second, and any fraction of that rounds to
142
+ # nothing, so every client would return at exactly two seconds.
143
+ def jitter(seconds)
144
+ seconds + rand(0..(seconds * JITTER_RATIO).round)
145
+ end
146
+
147
+ # down attaches the response to status errors, but its redirect errors
148
+ # pass `response:` as a keyword to a keyword-less initializer (5.4.2), so
149
+ # those carry a Hash instead. Requiring both methods we go on to use drops
150
+ # the Hash, and drops any backend we could not read a status or header
151
+ # from, which then falls back to the transient policy.
152
+ def http_response(error)
153
+ return unless error.is_a?(Down::ResponseError)
154
+
155
+ response = error.response
156
+ response if response.respond_to?(:code) && response.respond_to?(:[])
157
+ end
158
+
159
+ def rate_limited?(response)
160
+ response && response.code.to_i == RATE_LIMITED_HTTP_STATUS
114
161
  end
115
162
 
116
- def backoff_time(attempt)
117
- # Exponential backoff: 2^attempt seconds, max 30 seconds
118
- # 1st retry: 2s, 2nd: 4s, 3rd: 8s
119
- [2**attempt, 30].min
163
+ # nil unless the server asked for a wait we can use.
164
+ def retry_after(response)
165
+ return unless response
166
+
167
+ seconds = retry_after_seconds(response["Retry-After"])
168
+ [seconds, MAX_RETRY_AFTER].min if seconds&.positive?
169
+ end
170
+
171
+ # RFC 7231 allows delta-seconds or an HTTP date. Most responses carry no
172
+ # header at all and most that do use digits, so both leave before the
173
+ # date parse, which is the only branch that needs a rescue. A date
174
+ # already past gives a negative delay, which the caller drops the same
175
+ # way it drops a zero.
176
+ def retry_after_seconds(value)
177
+ header = value.to_s.strip
178
+ return if header.empty?
179
+ return header.to_i if header.match?(/\A\d+\z/)
180
+
181
+ (Time.httpdate(header) - Time.now).round
182
+ rescue ArgumentError
183
+ nil
120
184
  end
121
185
 
122
186
  def print_download_start
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "3.0.10".freeze
2
+ VERSION = "3.0.11".freeze
3
3
  end
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.10
4
+ version: 3.0.11
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-07-03 00:00:00.000000000 Z
11
+ date: 2026-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -279,9 +279,6 @@ files:
279
279
  - TODO.upgrade-excavate.md
280
280
  - docs/.gitignore
281
281
  - docs/.vitepress/config.ts
282
- - docs/.vitepress/data/cli-commands.json
283
- - docs/.vitepress/data/exit-codes.json
284
- - docs/.vitepress/data/features.json
285
282
  - docs/.vitepress/theme/components/HeroCodeBlock.vue
286
283
  - docs/.vitepress/theme/components/WithinHero.vue
287
284
  - docs/.vitepress/theme/index.ts
@@ -308,10 +305,6 @@ files:
308
305
  - docs/cli/uninstall.md
309
306
  - docs/cli/update.md
310
307
  - docs/cli/version.md
311
- - docs/components/CliCommand.vue
312
- - docs/components/CliExamples.vue
313
- - docs/components/CliOptions.vue
314
- - docs/components/ExitCodes.vue
315
308
  - docs/guide/ci.md
316
309
  - docs/guide/concepts/fonts.md
317
310
  - docs/guide/concepts/formats.md
@@ -1,461 +0,0 @@
1
- {
2
- "install": {
3
- "description": "Install one or more fonts",
4
- "syntax": "fontist install FONT... [options]",
5
- "arguments": [
6
- { "name": "FONT", "description": "One or more font names to install", "required": true, "variadic": true }
7
- ],
8
- "options": [
9
- { "name": "force", "alias": "f", "type": "boolean", "description": "Install even if already installed in system" },
10
- { "name": "formula", "alias": "F", "type": "boolean", "description": "Install whole formula instead of a font" },
11
- { "name": "accept-all-licenses", "alias": "a", "type": "boolean", "description": "Accept all license agreements" },
12
- { "name": "hide-licenses", "alias": "h", "type": "boolean", "description": "Hide license texts" },
13
- { "name": "no-progress", "alias": "p", "type": "boolean", "description": "Hide download progress" },
14
- { "name": "version", "alias": "V", "type": "string", "description": "Specify particular version of a font" },
15
- { "name": "smallest", "alias": "s", "type": "boolean", "description": "Install the smallest font by file size if several" },
16
- { "name": "newest", "alias": "n", "type": "boolean", "description": "Install the newest version of a font if several" },
17
- { "name": "size-limit", "alias": "S", "type": "numeric", "description": "Specify upper limit for file size of a formula to be installed (default is 500 MB)" },
18
- { "name": "update-fontconfig", "alias": "u", "type": "boolean", "description": "Update fontconfig" },
19
- { "name": "location", "alias": "l", "type": "string", "enum": ["fontist", "user", "system"], "description": "Install location: fontist (default), user, system" }
20
- ],
21
- "examples": [
22
- { "description": "Install a single font", "command": "fontist install \"Roboto\"" },
23
- { "description": "Install multiple fonts", "command": "fontist install \"Fira Code\" \"Open Sans\"" },
24
- { "description": "Force reinstall", "command": "fontist install \"Roboto\" --force" },
25
- { "description": "Install to user directory", "command": "fontist install \"Roboto\" --location user" },
26
- { "description": "Accept licenses automatically (for CI)", "command": "fontist install \"Roboto\" --accept-all-licenses --hide-licenses" },
27
- { "description": "Install a specific version", "command": "fontist install \"Roboto\" --version 2.0" },
28
- { "description": "Install whole formula", "command": "fontist install \"Roboto\" --formula" }
29
- ],
30
- "related": ["uninstall", "list", "status"]
31
- },
32
- "uninstall": {
33
- "description": "Uninstall font by font or formula name",
34
- "syntax": "fontist uninstall FONT",
35
- "aliases": ["remove"],
36
- "arguments": [
37
- { "name": "FONT", "description": "Font or formula name to uninstall", "required": true }
38
- ],
39
- "options": [],
40
- "examples": [
41
- { "description": "Uninstall a font", "command": "fontist uninstall \"Roboto\"" },
42
- { "description": "Using the remove alias", "command": "fontist remove \"Roboto\"" }
43
- ],
44
- "related": ["install", "status"]
45
- },
46
- "status": {
47
- "description": "Show paths of installed fonts",
48
- "syntax": "fontist status [FONT]",
49
- "arguments": [
50
- { "name": "FONT", "description": "Optional font name to filter results", "required": false }
51
- ],
52
- "options": [],
53
- "examples": [
54
- { "description": "Show all installed fonts", "command": "fontist status" },
55
- { "description": "Show paths for a specific font", "command": "fontist status \"Open Sans\"" }
56
- ],
57
- "related": ["list", "install"]
58
- },
59
- "list": {
60
- "description": "List installation status of fonts in fontist",
61
- "syntax": "fontist list [FONT]",
62
- "arguments": [
63
- { "name": "FONT", "description": "Optional font name to filter results", "required": false }
64
- ],
65
- "options": [],
66
- "examples": [
67
- { "description": "List all fonts and their status", "command": "fontist list" },
68
- { "description": "Check status of a specific font", "command": "fontist list \"Fira Mono\"" }
69
- ],
70
- "related": ["status", "install"]
71
- },
72
- "update": {
73
- "description": "Update formulas from the repository",
74
- "syntax": "fontist update",
75
- "arguments": [],
76
- "options": [],
77
- "examples": [
78
- { "description": "Update all formulas", "command": "fontist update" }
79
- ],
80
- "related": ["version"]
81
- },
82
- "version": {
83
- "description": "Show fontist version and formulas repository information",
84
- "syntax": "fontist version",
85
- "arguments": [],
86
- "options": [],
87
- "examples": [
88
- { "description": "Show version information", "command": "fontist version" }
89
- ],
90
- "related": ["update"]
91
- },
92
- "create-formula": {
93
- "description": "Create a new formula with fonts from a URL",
94
- "syntax": "fontist create-formula URL [options]",
95
- "arguments": [
96
- { "name": "URL", "description": "URL to download fonts from", "required": true }
97
- ],
98
- "options": [
99
- { "name": "name", "alias": null, "type": "string", "description": "Font name, e.g., 'Times New Roman'" },
100
- { "name": "mirror", "alias": null, "type": "array", "description": "Mirror URLs (can be repeated)" },
101
- { "name": "subdir", "alias": null, "type": "string", "description": "Subdirectory to take fonts from, e.g., 'fonts/static_otf'" },
102
- { "name": "file-pattern", "alias": null, "type": "string", "description": "File pattern to match, e.g., '*.otf'" },
103
- { "name": "name-prefix", "alias": null, "type": "string", "description": "Prefix to add to all font family names" }
104
- ],
105
- "examples": [
106
- { "description": "Create a formula from a font archive", "command": "fontist create-formula https://example.com/fonts.zip --name \"Custom Font\"" },
107
- { "description": "Create formula with subdirectory filter", "command": "fontist create-formula https://example.com/fonts.zip --subdir \"fonts/otf\"" }
108
- ],
109
- "related": []
110
- },
111
- "rebuild-index": {
112
- "description": "Rebuild formula index (used by formulas maintainers)",
113
- "syntax": "fontist rebuild-index",
114
- "arguments": [],
115
- "options": [],
116
- "examples": [
117
- { "description": "Rebuild the formula index", "command": "fontist rebuild-index" }
118
- ],
119
- "related": []
120
- },
121
- "macos-catalogs": {
122
- "description": "List available macOS font catalogs",
123
- "syntax": "fontist macos-catalogs",
124
- "arguments": [],
125
- "options": [],
126
- "examples": [
127
- { "description": "List available macOS font catalogs", "command": "fontist macos-catalogs" }
128
- ],
129
- "related": ["import macos"]
130
- },
131
- "manifest": {
132
- "description": "Manage font manifests",
133
- "syntax": "fontist manifest SUBCOMMAND ...ARGS",
134
- "subcommands": {
135
- "install": {
136
- "description": "Install fonts from a manifest file (YAML)",
137
- "syntax": "fontist manifest install MANIFEST [options]",
138
- "arguments": [
139
- { "name": "MANIFEST", "description": "Path to manifest YAML file", "required": true }
140
- ],
141
- "options": [
142
- { "name": "accept-all-licenses", "alias": "a", "type": "boolean", "description": "Accept all license agreements" },
143
- { "name": "hide-licenses", "alias": "h", "type": "boolean", "description": "Hide license texts" },
144
- { "name": "location", "alias": "l", "type": "string", "enum": ["fontist", "user", "system"], "description": "Install location: fontist (default), user, system" }
145
- ],
146
- "examples": [
147
- { "description": "Install fonts from manifest", "command": "fontist manifest install fonts.yml" },
148
- { "description": "Install with auto-accept licenses", "command": "fontist manifest install fonts.yml --accept-all-licenses --hide-licenses" }
149
- ]
150
- },
151
- "locations": {
152
- "description": "Get locations of fonts from a manifest file",
153
- "syntax": "fontist manifest locations MANIFEST [options]",
154
- "arguments": [
155
- { "name": "MANIFEST", "description": "Path to manifest YAML file", "required": true }
156
- ],
157
- "options": [
158
- { "name": "show-timing", "alias": "t", "type": "boolean", "description": "Show timing information for manifest resolution" }
159
- ],
160
- "examples": [
161
- { "description": "Get font locations from manifest", "command": "fontist manifest locations fonts.yml" }
162
- ]
163
- }
164
- }
165
- },
166
- "repo": {
167
- "description": "Manage custom font repositories",
168
- "syntax": "fontist repo SUBCOMMAND ...ARGS",
169
- "subcommands": {
170
- "setup": {
171
- "description": "Setup a custom fontist repo and fetch its formulas",
172
- "syntax": "fontist repo setup NAME URL",
173
- "arguments": [
174
- { "name": "NAME", "description": "Name for the repository", "required": true },
175
- { "name": "URL", "description": "Git repository URL", "required": true }
176
- ],
177
- "options": [],
178
- "examples": [
179
- { "description": "Setup a custom repository", "command": "fontist repo setup my-fonts https://github.com/user/font-formulas" }
180
- ]
181
- },
182
- "update": {
183
- "description": "Update formulas in a fontist repo",
184
- "syntax": "fontist repo update NAME",
185
- "arguments": [
186
- { "name": "NAME", "description": "Name of the repository", "required": true }
187
- ],
188
- "options": [],
189
- "examples": [
190
- { "description": "Update a custom repository", "command": "fontist repo update my-fonts" }
191
- ]
192
- },
193
- "remove": {
194
- "description": "Remove a fontist repo",
195
- "syntax": "fontist repo remove NAME",
196
- "arguments": [
197
- { "name": "NAME", "description": "Name of the repository", "required": true }
198
- ],
199
- "options": [],
200
- "examples": [
201
- { "description": "Remove a custom repository", "command": "fontist repo remove my-fonts" }
202
- ]
203
- },
204
- "list": {
205
- "description": "List all fontist repos",
206
- "syntax": "fontist repo list",
207
- "arguments": [],
208
- "options": [],
209
- "examples": [
210
- { "description": "List all repositories", "command": "fontist repo list" }
211
- ]
212
- },
213
- "info": {
214
- "description": "Show information about a repo",
215
- "syntax": "fontist repo info NAME",
216
- "arguments": [
217
- { "name": "NAME", "description": "Name of the repository", "required": true }
218
- ],
219
- "options": [],
220
- "examples": [
221
- { "description": "Get info about a repository", "command": "fontist repo info my-fonts" }
222
- ]
223
- }
224
- }
225
- },
226
- "import": {
227
- "description": "Import fonts from external sources",
228
- "syntax": "fontist import SUBCOMMAND ...ARGS",
229
- "subcommands": {
230
- "google": {
231
- "description": "Import Google fonts",
232
- "syntax": "fontist import google [options]",
233
- "arguments": [],
234
- "options": [
235
- { "name": "source-path", "alias": null, "type": "string", "description": "Path to checked-out google/fonts repository" },
236
- { "name": "output-path", "alias": null, "type": "string", "description": "Output path for generated formulas (default: ./Formulas/google)" },
237
- { "name": "font-name", "alias": "f", "type": "string", "description": "Import specific font family by name" },
238
- { "name": "force", "alias": null, "type": "boolean", "description": "Overwrite existing formulas" },
239
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Enable verbose output" },
240
- { "name": "import-cache", "alias": null, "type": "string", "description": "Directory for import cache (default: ~/.fontist/import_cache)" }
241
- ],
242
- "examples": [
243
- { "description": "Import all Google fonts", "command": "fontist import google" },
244
- { "description": "Import specific font", "command": "fontist import google --font-name \"Roboto\"" }
245
- ]
246
- },
247
- "macos": {
248
- "description": "Import macOS supplementary fonts",
249
- "syntax": "fontist import macos [options]",
250
- "arguments": [],
251
- "options": [
252
- { "name": "plist", "alias": null, "type": "string", "description": "Path to macOS font catalog XML" },
253
- { "name": "output-path", "alias": null, "type": "string", "description": "Output directory for generated formulas (default: formulas/macos)" },
254
- { "name": "font-name", "alias": "f", "type": "string", "description": "Import specific font by name" },
255
- { "name": "force", "alias": null, "type": "boolean", "description": "Overwrite existing formulas" },
256
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Enable verbose output" }
257
- ],
258
- "examples": [
259
- { "description": "Import macOS fonts", "command": "fontist import macos --plist /path/to/catalog.xml" }
260
- ]
261
- },
262
- "sil": {
263
- "description": "Import formulas from SIL International",
264
- "syntax": "fontist import sil [options]",
265
- "arguments": [],
266
- "options": [
267
- { "name": "output-path", "alias": null, "type": "string", "description": "Output directory for generated formulas" },
268
- { "name": "font-name", "alias": "f", "type": "string", "description": "Import specific font by name" },
269
- { "name": "force", "alias": null, "type": "boolean", "description": "Overwrite existing formulas" },
270
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Enable verbose output" }
271
- ],
272
- "examples": [
273
- { "description": "Import SIL fonts", "command": "fontist import sil" }
274
- ]
275
- }
276
- }
277
- },
278
- "fontconfig": {
279
- "description": "Manage fontconfig configuration",
280
- "syntax": "fontist fontconfig SUBCOMMAND ...ARGS",
281
- "subcommands": {
282
- "update": {
283
- "description": "Update fontconfig configuration to use fontist fonts",
284
- "syntax": "fontist fontconfig update",
285
- "arguments": [],
286
- "options": [],
287
- "examples": [
288
- { "description": "Update fontconfig", "command": "fontist fontconfig update" }
289
- ]
290
- },
291
- "remove": {
292
- "description": "Remove fontist file from fontconfig configuration",
293
- "syntax": "fontist fontconfig remove [options]",
294
- "arguments": [],
295
- "options": [
296
- { "name": "force", "alias": "f", "type": "boolean", "description": "Proceed even if file does not exist" }
297
- ],
298
- "examples": [
299
- { "description": "Remove fontconfig integration", "command": "fontist fontconfig remove" }
300
- ]
301
- }
302
- }
303
- },
304
- "config": {
305
- "description": "Manage fontist configuration",
306
- "syntax": "fontist config SUBCOMMAND ...ARGS",
307
- "subcommands": {
308
- "show": {
309
- "description": "Show values of the current config",
310
- "syntax": "fontist config show",
311
- "arguments": [],
312
- "options": [],
313
- "examples": [
314
- { "description": "Show current config", "command": "fontist config show" }
315
- ]
316
- },
317
- "set": {
318
- "description": "Set a config attribute to a value",
319
- "syntax": "fontist config set KEY VALUE",
320
- "arguments": [
321
- { "name": "KEY", "description": "Config key to set", "required": true },
322
- { "name": "VALUE", "description": "Value to set", "required": true }
323
- ],
324
- "options": [],
325
- "examples": [
326
- { "description": "Set fonts path", "command": "fontist config set fonts_path /var/myfonts" }
327
- ]
328
- },
329
- "delete": {
330
- "description": "Delete a config attribute (reset to default)",
331
- "syntax": "fontist config delete KEY",
332
- "arguments": [
333
- { "name": "KEY", "description": "Config key to delete", "required": true }
334
- ],
335
- "options": [],
336
- "examples": [
337
- { "description": "Reset fonts path to default", "command": "fontist config delete fonts_path" }
338
- ]
339
- },
340
- "keys": {
341
- "description": "Print all available config attributes",
342
- "syntax": "fontist config keys",
343
- "arguments": [],
344
- "options": [],
345
- "examples": [
346
- { "description": "List available config keys", "command": "fontist config keys" }
347
- ]
348
- }
349
- },
350
- "config_keys": [
351
- { "key": "fonts_path", "default": "~/.fontist/fonts", "description": "Where to put font files" },
352
- { "key": "open_timeout", "default": "60", "description": "HTTP open timeout in seconds" },
353
- { "key": "read_timeout", "default": "60", "description": "HTTP read timeout in seconds" }
354
- ]
355
- },
356
- "cache": {
357
- "description": "Manage fontist cache",
358
- "syntax": "fontist cache SUBCOMMAND ...ARGS",
359
- "subcommands": {
360
- "clear": {
361
- "description": "Clear fontist download cache",
362
- "syntax": "fontist cache clear",
363
- "arguments": [],
364
- "options": [],
365
- "examples": [
366
- { "description": "Clear download cache", "command": "fontist cache clear" }
367
- ]
368
- },
369
- "clear-import": {
370
- "description": "Clear import cache",
371
- "syntax": "fontist cache clear-import [options]",
372
- "arguments": [],
373
- "options": [
374
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Show detailed output" }
375
- ],
376
- "examples": [
377
- { "description": "Clear import cache", "command": "fontist cache clear-import" }
378
- ]
379
- },
380
- "info": {
381
- "description": "Show cache information",
382
- "syntax": "fontist cache info",
383
- "arguments": [],
384
- "options": [],
385
- "examples": [
386
- { "description": "Show cache size and location", "command": "fontist cache info" }
387
- ]
388
- }
389
- }
390
- },
391
- "index": {
392
- "description": "Manage system font index",
393
- "syntax": "fontist index SUBCOMMAND ...ARGS",
394
- "subcommands": {
395
- "rebuild": {
396
- "description": "Rebuild system font index from scratch (cold build)",
397
- "syntax": "fontist index rebuild [options]",
398
- "arguments": [],
399
- "options": [
400
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Show detailed progress and statistics" },
401
- { "name": "output", "alias": "o", "type": "string", "description": "Save index to specified path (for inspection)" }
402
- ],
403
- "examples": [
404
- { "description": "Rebuild system font index", "command": "fontist index rebuild" },
405
- { "description": "Rebuild with verbose output", "command": "fontist index rebuild --verbose" }
406
- ]
407
- },
408
- "update": {
409
- "description": "Update system font index incrementally",
410
- "syntax": "fontist index update [options]",
411
- "arguments": [],
412
- "options": [
413
- { "name": "verbose", "alias": "v", "type": "boolean", "description": "Show detailed progress and statistics" }
414
- ],
415
- "examples": [
416
- { "description": "Update system font index", "command": "fontist index update" }
417
- ]
418
- },
419
- "info": {
420
- "description": "Show system font index information",
421
- "syntax": "fontist index info",
422
- "arguments": [],
423
- "options": [],
424
- "examples": [
425
- { "description": "Show index info", "command": "fontist index info" }
426
- ]
427
- },
428
- "path": {
429
- "description": "Show the system font index file path",
430
- "syntax": "fontist index path",
431
- "arguments": [],
432
- "options": [],
433
- "examples": [
434
- { "description": "Show index file path", "command": "fontist index path" }
435
- ]
436
- },
437
- "list": {
438
- "description": "List all system fonts from the index",
439
- "syntax": "fontist index list [options]",
440
- "arguments": [],
441
- "options": [
442
- { "name": "format", "alias": null, "type": "string", "default": "yaml", "description": "Output format: yaml or json" },
443
- { "name": "limit", "alias": null, "type": "numeric", "description": "Limit number of fonts to display" }
444
- ],
445
- "examples": [
446
- { "description": "List all system fonts", "command": "fontist index list" },
447
- { "description": "List as JSON", "command": "fontist index list --format json" }
448
- ]
449
- },
450
- "clear": {
451
- "description": "Delete system font index (will be rebuilt on next use)",
452
- "syntax": "fontist index clear",
453
- "arguments": [],
454
- "options": [],
455
- "examples": [
456
- { "description": "Clear system font index", "command": "fontist index clear" }
457
- ]
458
- }
459
- }
460
- }
461
- }
@@ -1,21 +0,0 @@
1
- {
2
- "codes": [
3
- { "code": 0, "name": "SUCCESS", "description": "Command completed successfully" },
4
- { "code": 1, "name": "UNKNOWN_ERROR", "description": "Unknown or unexpected error" },
5
- { "code": 2, "name": "NON_SUPPORTED_FONT_ERROR", "description": "Font is not supported by fontist" },
6
- { "code": 3, "name": "MISSING_FONT_ERROR", "description": "Font could not be found on the system or in formulas" },
7
- { "code": 4, "name": "LICENSING_ERROR", "description": "License agreement required but not accepted" },
8
- { "code": 5, "name": "MANIFEST_COULD_NOT_BE_FOUND_ERROR", "description": "Manifest file not found at specified path" },
9
- { "code": 6, "name": "MANIFEST_COULD_NOT_BE_READ_ERROR", "description": "Manifest file could not be read (invalid YAML or permissions)" },
10
- { "code": 7, "name": "FONT_INDEX_CORRUPTED", "description": "Font index file is corrupted and needs to be rebuilt" },
11
- { "code": 8, "name": "REPO_NOT_FOUND", "description": "Repository not found" },
12
- { "code": 9, "name": "MAIN_REPO_NOT_FOUND", "description": "Main formulas repository not found" },
13
- { "code": 10, "name": "REPO_COULD_NOT_BE_UPDATED", "description": "Repository could not be updated (network or git error)" },
14
- { "code": 11, "name": "MANUAL_FONT_ERROR", "description": "Manual font installation required (font cannot be downloaded)" },
15
- { "code": 12, "name": "SIZE_LIMIT_ERROR", "description": "Formula exceeds size limit. Use --size-limit, --newest, or --smallest options" },
16
- { "code": 13, "name": "FORMULA_NOT_FOUND", "description": "Formula not found for the requested font" },
17
- { "code": 14, "name": "FONTCONFIG_NOT_FOUND", "description": "Fontconfig is not installed or not found" },
18
- { "code": 15, "name": "FONTCONFIG_FILE_NOT_FOUND", "description": "Fontconfig configuration file not found" },
19
- { "code": 16, "name": "INVALID_CONFIG_ATTRIBUTE", "description": "Invalid configuration attribute specified" }
20
- ]
21
- }
@@ -1,44 +0,0 @@
1
- {
2
- "features": [
3
- {
4
- "title": "Cross-Platform",
5
- "icon": "🌐",
6
- "description": "Same commands work identically on Windows, macOS, and Linux. No platform-specific paths to remember."
7
- },
8
- {
9
- "title": "Formula-Based",
10
- "icon": "📦",
11
- "description": "3000+ fonts available through community-maintained formulas with automatic download and license handling."
12
- },
13
- {
14
- "title": "Manifest Support",
15
- "icon": "📋",
16
- "description": "Define font requirements in YAML for reproducible installations across environments."
17
- },
18
- {
19
- "title": "CI/CD Ready",
20
- "icon": "🔄",
21
- "description": "Perfect for automated environments with non-interactive installation and GitHub Action available."
22
- },
23
- {
24
- "title": "System Font Detection",
25
- "icon": "🔍",
26
- "description": "Detects and indexes fonts already installed on your system. No redundant downloads."
27
- },
28
- {
29
- "title": "Multiple Locations",
30
- "icon": "📁",
31
- "description": "Install to fontist directory, user fonts, or system fonts. Flexible for different use cases."
32
- },
33
- {
34
- "title": "Fontconfig Integration",
35
- "icon": "⚡",
36
- "description": "Optional fontconfig integration for seamless font discovery in Linux environments."
37
- },
38
- {
39
- "title": "Custom Repositories",
40
- "icon": "🔗",
41
- "description": "Add private formula repositories for internal or custom fonts."
42
- }
43
- ]
44
- }
@@ -1,77 +0,0 @@
1
- <script setup>
2
- import { computed } from 'vue'
3
- const props = defineProps({
4
- command: { type: String, required: true }
5
- })
6
- import commands from '../.vitepress/data/cli-commands.json'
7
- const cmd = computed(() => commands[props.command])
8
- </script>
9
-
10
- <template>
11
- <div v-if="cmd" class="cli-command">
12
- <p class="description">{{ cmd.description }}</p>
13
- <pre class="syntax"><code>{{ cmd.syntax }}</code></pre>
14
-
15
- <h3 v-if="cmd.arguments && cmd.arguments.length">Arguments</h3>
16
- <table v-if="cmd.arguments && cmd.arguments.length">
17
- <thead><tr><th>Name</th><th>Required</th><th>Description</th></tr></thead>
18
- <tbody>
19
- <tr v-for="arg in cmd.arguments" :key="arg.name">
20
- <td><code>{{ arg.name }}</code></td>
21
- <td>{{ arg.required ? 'Yes' : 'No' }}</td>
22
- <td>{{ arg.description }}</td>
23
- </tr>
24
- </tbody>
25
- </table>
26
-
27
- <h3 v-if="cmd.options && cmd.options.length">Options</h3>
28
- <table v-if="cmd.options && cmd.options.length">
29
- <thead><tr><th>Option</th><th>Alias</th><th>Type</th><th>Description</th></tr></thead>
30
- <tbody>
31
- <tr v-for="opt in cmd.options" :key="opt.name">
32
- <td><code>--{{ opt.name }}</code></td>
33
- <td><code v-if="opt.alias">-{{ opt.alias }}</code></td>
34
- <td>{{ opt.type }}</td>
35
- <td>{{ opt.description }}</td>
36
- </tr>
37
- </tbody>
38
- </table>
39
-
40
- <h3 v-if="cmd.examples && cmd.examples.length">Examples</h3>
41
- <div v-if="cmd.examples && cmd.examples.length" class="examples">
42
- <div v-for="example in cmd.examples" :key="example.command" class="example">
43
- <p>{{ example.description }}</p>
44
- <pre><code>{{ example.command }}</code></pre>
45
- </div>
46
- </div>
47
-
48
- <p v-if="cmd.related && cmd.related.length" class="related">
49
- <strong>Related:</strong>
50
- <span v-for="rel in cmd.related" :key="rel">
51
- <a :href="`/cli/${rel}`">{{ rel }}</a>{{ rel !== cmd.related[cmd.related.length-1] ? ', ' : '' }}
52
- </span>
53
- </p>
54
- </div>
55
- </template>
56
-
57
- <style scoped>
58
- .cli-command .syntax {
59
- margin: 1rem 0;
60
- }
61
- .example {
62
- margin: 0.5rem 0;
63
- }
64
- .example p {
65
- margin: 0;
66
- font-weight: 500;
67
- }
68
- .example pre {
69
- margin: 0.25rem 0;
70
- padding: 0.75rem;
71
- background: var(--vp-code-block-bg);
72
- border-radius: 4px;
73
- }
74
- .related {
75
- margin-top: 1.5rem;
76
- }
77
- </style>
@@ -1,17 +0,0 @@
1
- <script setup>
2
- import { computed } from 'vue'
3
- const props = defineProps({
4
- command: { type: String, required: true }
5
- })
6
- import commands from '../.vitepress/data/cli-commands.json'
7
- const cmd = computed(() => commands[props.command])
8
- </script>
9
-
10
- <template>
11
- <div v-if="cmd && cmd.examples">
12
- <div v-for="example in cmd.examples" :key="example.command" class="example">
13
- <p>{{ example.description }}</p>
14
- <pre><code>{{ example.command }}</code></pre>
15
- </div>
16
- </div>
17
- </template>
@@ -1,26 +0,0 @@
1
- <script setup>
2
- import { computed } from 'vue'
3
- const props = defineProps({
4
- command: { type: String, required: true }
5
- })
6
- import commands from '../.vitepress/data/cli-commands.json'
7
- const cmd = computed(() => commands[props.command])
8
- </script>
9
-
10
- <template>
11
- <div v-if="cmd">
12
- <table>
13
- <thead>
14
- <tr><th>Option</th><th>Alias</th><th>Type</th><th>Description</th></tr>
15
- </thead>
16
- <tbody>
17
- <tr v-for="opt in cmd.options" :key="opt.name">
18
- <td><code>--{{ opt.name }}</code></td>
19
- <td><code v-if="opt.alias">-{{ opt.alias }}</code></td>
20
- <td>{{ opt.type }}</td>
21
- <td>{{ opt.description }}</td>
22
- </tr>
23
- </tbody>
24
- </table>
25
- </div>
26
- </template>
@@ -1,18 +0,0 @@
1
- <script setup>
2
- import exitCodes from '../.vitepress/data/exit-codes.json'
3
- </script>
4
-
5
- <template>
6
- <table>
7
- <thead>
8
- <tr><th>Code</th><th>Name</th><th>Description</th></tr>
9
- </thead>
10
- <tbody>
11
- <tr v-for="code in exitCodes.codes" :key="code.code">
12
- <td><code>{{ code.code }}</code></td>
13
- <td>{{ code.name }}</td>
14
- <td>{{ code.description }}</td>
15
- </tr>
16
- </tbody>
17
- </table>
18
- </template>