fontist 3.0.1 → 3.0.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: afb1c6bc21c216e16a0a2bb42de770866575bbf424bd8d3d49bf99d5eec80cb5
4
- data.tar.gz: 5d72a4edb96a6f39e2d058cbe312d392f62e50d73bdfbf8a168b82492155e9b4
3
+ metadata.gz: b68f4d4d083a0e2f73df389c0698800b4a4d519428cbf59ddd98f493630a3342
4
+ data.tar.gz: 76cc6dd8420deb15d8b5fd872e17550c4b31dc31585834f2290a0e3f36d130ba
5
5
  SHA512:
6
- metadata.gz: 77746091e20120805c19eb0a912c3f0a9eb101d88522afc4dd3cc45902922ce301bcf8aa909b23bb6ef664c615fb648dc5990e314a36227c774cfa63d0714e09
7
- data.tar.gz: 7b900979917db2a7b973c9541bb2be9ff6b1dac5016128f9e082763136f648f0647a3519868efb6fa665b9d094d8377981cb6d7f3101f33262d8ea898c5e3718
6
+ metadata.gz: 72c687e0c3c81823d1e0edf131f9af115564e5d7b60b296d84dad7c297e5ea6e8f5fd6995f18961b6a6d048fb630eeba1e74d7beb942bad0abf97b9922112435
7
+ data.tar.gz: 57c8dde9259414c129e83c5fea0b7d50b2970c0062a756ffd9f8dbf91738508c154e0372f7b4a9d30139abb17d650a98954db0cc8764bd8871c7c5611221e4f9
@@ -69,6 +69,8 @@ jobs:
69
69
  version: [2022, 2025]
70
70
  fail-fast: false
71
71
  steps:
72
+ - uses: actions/checkout@v6
73
+
72
74
  - name: List ALL Windows Fonts
73
75
  shell: pwsh
74
76
  run: |
@@ -78,6 +80,80 @@ jobs:
78
80
  Write-Host "=== Total Count ==="
79
81
  (Get-ChildItem -Path "C:\Windows\Fonts\" -Include *.ttf,*.ttc,*.otf -Recurse).Count
80
82
 
83
+ - name: List FOD font capabilities
84
+ shell: pwsh
85
+ run: |
86
+ Write-Host "=== Windows FOD Font Capabilities ==="
87
+ $caps = Get-WindowsCapability -Online -Name "Language.Fonts.*"
88
+ $caps | Format-Table -AutoSize Name, State
89
+ Write-Host ""
90
+ Write-Host "=== Summary ==="
91
+ $installed = ($caps | Where-Object { $_.State -eq "Installed" }).Count
92
+ $notPresent = ($caps | Where-Object { $_.State -eq "NotPresent" }).Count
93
+ $staged = ($caps | Where-Object { $_.State -eq "Staged" }).Count
94
+ Write-Host "Installed: $installed"
95
+ Write-Host "NotPresent: $notPresent"
96
+ Write-Host "Staged: $staged"
97
+ Write-Host "Total: $($caps.Count)"
98
+ Write-Host ""
99
+ Write-Host "=== Saving results ==="
100
+ New-Item -ItemType Directory -Force -Path artifacts | Out-Null
101
+ $caps | Select-Object Name, State | ConvertTo-Csv -NoTypeInformation | Out-File -FilePath artifacts/fod-capabilities.csv
102
+ $caps | ConvertTo-Json | Out-File -FilePath artifacts/fod-capabilities.json
103
+ Write-Host "Saved to artifacts/fod-capabilities.csv and artifacts/fod-capabilities.json"
104
+
105
+ - name: Cross-check FOD capabilities with our YAML
106
+ shell: pwsh
107
+ run: |
108
+ Write-Host "=== Cross-checking fod_capabilities.yml against live Windows ==="
109
+
110
+ # Get live capabilities from Windows
111
+ $liveCaps = Get-WindowsCapability -Online -Name "Language.Fonts.*"
112
+ $liveNames = $liveCaps | ForEach-Object { $_.Name }
113
+
114
+ # Parse our YAML capability names (simple text extraction)
115
+ $yamlPath = "lib/fontist/import/windows/fod_capabilities.yml"
116
+ $yamlContent = Get-Content $yamlPath -Raw
117
+ $yamlNames = [regex]::Matches($yamlContent, '^\s+"([^"]+)":', [System.Text.RegularExpressions.RegexOptions]::Multiline) |
118
+ ForEach-Object { $_.Groups[1].Value }
119
+
120
+ Write-Host ""
121
+ Write-Host "Live capabilities: $($liveNames.Count)"
122
+ Write-Host "YAML capabilities: $($yamlNames.Count)"
123
+ Write-Host ""
124
+
125
+ # Find matches
126
+ $matched = $yamlNames | Where-Object { $liveNames -contains $_ }
127
+ Write-Host "=== Matched ($($matched.Count)) ==="
128
+ $matched | ForEach-Object { Write-Host " OK: $_" }
129
+
130
+ # Find missing from our YAML (present on Windows but not in our file)
131
+ $missingFromYaml = $liveNames | Where-Object { $yamlNames -notcontains $_ }
132
+ if ($missingFromYaml.Count -gt 0) {
133
+ Write-Host ""
134
+ Write-Host "=== Missing from our YAML ($($missingFromYaml.Count)) ==="
135
+ $missingFromYaml | ForEach-Object { Write-Host " MISSING: $_" }
136
+ }
137
+
138
+ # Find extra in our YAML (in our file but not on Windows)
139
+ $extraInYaml = $yamlNames | Where-Object { $liveNames -notcontains $_ }
140
+ if ($extraInYaml.Count -gt 0) {
141
+ Write-Host ""
142
+ Write-Host "=== Extra in our YAML ($($extraInYaml.Count)) ==="
143
+ $extraInYaml | ForEach-Object { Write-Host " EXTRA: $_" }
144
+ }
145
+
146
+ Write-Host ""
147
+ Write-Host "=== Cross-check complete ==="
148
+
149
+ - name: Upload FOD capability results
150
+ if: always()
151
+ uses: actions/upload-artifact@v4
152
+ with:
153
+ name: windows-fod-capabilities-${{ matrix.version }}
154
+ path: artifacts/
155
+ if-no-files-found: warn
156
+
81
157
  discover-linux:
82
158
  name: Linux fonts
83
159
  runs-on: ubuntu-latest
@@ -214,6 +214,104 @@ jobs:
214
214
  echo " Test Complete"
215
215
  echo "========================================================================="
216
216
 
217
+ - name: Test Windows FOD font installation
218
+ if: startsWith(matrix.os, 'windows')
219
+ continue-on-error: true
220
+ shell: pwsh
221
+ run: |
222
+ Write-Host "========================================================================="
223
+ Write-Host " Windows FOD (Features on Demand) Font Installation Test"
224
+ Write-Host "========================================================================="
225
+ Write-Host ""
226
+ Write-Host "Platform: Windows $(([System.Environment]::OSVersion.Version).ToString())"
227
+ Write-Host "Runner: ${{ matrix.os }}"
228
+ Write-Host ""
229
+
230
+ Write-Host "--- Step 1: Generate Windows FOD Formulas into formulas repo ---"
231
+ $formulasRepo = bundle exec ruby -e "require 'fontist'; puts Fontist.formulas_path"
232
+ $formulasRepo = $formulasRepo.Trim()
233
+ $windowsDir = Join-Path $formulasRepo "windows"
234
+ Write-Host "Formulas path: $formulasRepo"
235
+ Write-Host "Generating FOD formulas into: $windowsDir"
236
+ bundle exec ruby script/generate_windows_formulas.rb $windowsDir
237
+ $formulaCount = (Get-ChildItem -Path $windowsDir -Filter "*.yml" -ErrorAction SilentlyContinue).Count
238
+ Write-Host "Generated $formulaCount formula files"
239
+ Write-Host ""
240
+
241
+ Write-Host "--- Step 2: Rebuild formula index to include FOD formulas ---"
242
+ bundle exec ruby -e "require 'fontist'; Fontist::Index.rebuild; puts 'Formula index rebuilt'; f = Fontist::Formula.find('Arial Nova'); puts f ? 'Verified: Arial Nova found -> ' + f.name : 'WARNING: Arial Nova NOT found in index'"
243
+ if ($LASTEXITCODE -ne 0) {
244
+ Write-Host "WARNING: Formula index rebuild failed with exit code $LASTEXITCODE"
245
+ }
246
+ Write-Host ""
247
+
248
+ Write-Host "--- Step 2b: Verify formula index ---"
249
+ $indexPath = bundle exec ruby -e "require 'fontist'; puts Fontist.formula_index_path"
250
+ $indexPath = $indexPath.Trim()
251
+ Write-Host "Formula index path: $indexPath"
252
+ if (Test-Path $indexPath) {
253
+ $lineCount = (Get-Content $indexPath).Count
254
+ Write-Host "Formula index exists: $lineCount lines"
255
+ Write-Host "First 20 lines:"
256
+ Get-Content $indexPath -Head 20
257
+ } else {
258
+ Write-Host "WARNING: Formula index file does NOT exist at $indexPath"
259
+ }
260
+ Write-Host ""
261
+
262
+ Write-Host "--- Step 2c: Verify formula files on disk ---"
263
+ $formulasDir = bundle exec ruby -e "require 'fontist'; puts Fontist.formulas_path"
264
+ $formulasDir = $formulasDir.Trim()
265
+ Write-Host "Formulas directory: $formulasDir"
266
+ if (Test-Path $formulasDir) {
267
+ $ymlFiles = Get-ChildItem -Path $formulasDir -Filter "*.yml" -Recurse
268
+ Write-Host "Total .yml files: $($ymlFiles.Count)"
269
+ $ymlFiles | Select-Object -First 30 | ForEach-Object { Write-Host " $($_.FullName)" }
270
+ } else {
271
+ Write-Host "WARNING: Formulas directory does NOT exist"
272
+ }
273
+ Write-Host ""
274
+
275
+ Write-Host "--- Step 3: List FOD Font Capabilities ---"
276
+ $caps = Get-WindowsCapability -Online -Name "Language.Fonts.*"
277
+ $installed = ($caps | Where-Object { $_.State -eq "Installed" })
278
+ $notPresent = ($caps | Where-Object { $_.State -eq "NotPresent" })
279
+ Write-Host "Installed: $($installed.Count)"
280
+ Write-Host "NotPresent: $($notPresent.Count)"
281
+ Write-Host "Total: $($caps.Count)"
282
+ Write-Host ""
283
+
284
+ Write-Host "--- Step 4: Run Cross-Check Validation ---"
285
+ bundle exec ruby script/validate_windows_fod_ci.rb
286
+ Write-Host ""
287
+
288
+ Write-Host "--- Step 5: Install Plantagenet Cherokee via fontist (small FOD) ---"
289
+ Write-Host "Running: fontist install 'Plantagenet Cherokee' --accept-all-licenses"
290
+ bundle exec fontist install "Plantagenet Cherokee" --accept-all-licenses
291
+ if ($LASTEXITCODE -eq 0) {
292
+ Write-Host "fontist install succeeded"
293
+ } else {
294
+ Write-Host "WARNING: fontist install exited with code $LASTEXITCODE"
295
+ }
296
+ Write-Host ""
297
+
298
+ Write-Host "--- Step 6: Verify Plantagenet Cherokee via fontist list ---"
299
+ bundle exec fontist list "Plantagenet Cherokee"
300
+ Write-Host ""
301
+
302
+ Write-Host "--- Step 7: Verify font file on disk ---"
303
+ $path = Join-Path "C:\Windows\Fonts" "Plantc.ttf"
304
+ if (Test-Path $path) {
305
+ Write-Host " OK: Plantc.ttf"
306
+ } else {
307
+ Write-Host " MISSING: Plantc.ttf"
308
+ }
309
+ Write-Host ""
310
+
311
+ Write-Host "========================================================================="
312
+ Write-Host " Test Complete"
313
+ Write-Host "========================================================================="
314
+
217
315
  - name: Upload system index as artifact
218
316
  if: always()
219
317
  uses: actions/upload-artifact@v4
@@ -237,17 +335,14 @@ jobs:
237
335
 
238
336
  steps:
239
337
  - name: Setup packages
240
- run: pacman -Syu --noconfirm git binutils gcc autoconf make libffi libyaml gmp
338
+ run: |
339
+ pacman -Syu --noconfirm git binutils gcc autoconf make libffi libyaml gmp ruby ruby-stdlib
241
340
 
242
341
  - uses: actions/checkout@v4
243
342
 
244
- - uses: asdf-vm/actions/install@v3
245
- with:
246
- tool_versions: ruby ${{ needs.prepare.outputs.default-ruby-version }}
247
-
248
343
  - run: |
249
- gem install bundler
250
- bundle install
344
+ gem install --no-document --user-install bundler
345
+ PATH="$(ruby -e 'puts Gem.user_dir')/bin:$PATH" bundle install
251
346
 
252
347
  - name: Test
253
- run: bundle exec rake
348
+ run: PATH="$(ruby -e 'puts Gem.user_dir')/bin:$PATH" bundle exec rake
@@ -0,0 +1,164 @@
1
+ # TODO: Documentation Audit
2
+
3
+ ## Purpose
4
+ Audit all Fontist Ruby gem functionality to ensure complete documentation coverage.
5
+
6
+ ## Reference Files
7
+ - docs/guide/how-it-works.md
8
+ - docs/api/
9
+ - docs/cli/
10
+ - docs/guide/concepts/
11
+
12
+ **Last Updated:** 2026-03-10
13
+
14
+ ---
15
+
16
+ ## ✅ COMPLETED
17
+
18
+ ### 1. Configuration Priority System
19
+ Documented in `/guide/how-it-works.md`
20
+
21
+ **Priority Order (Highest to Lowest):**
22
+
23
+ | Priority | Source | Example | Notes |
24
+ |----------|--------|---------|-------|
25
+ | 1 | ENV VAR | `FONTIST_PATH=/custom` | Always wins |
26
+ | 2 | Config file | `~/.fontist/config.yml` | Persistent settings |
27
+ | 3 | CLI option | `--location user` | Per-command override |
28
+ | 4 | Ruby API | `Fontist.preferred_family = true` | Programmatic |
29
+ | 5 | Default | Built-in defaults | Fallback |
30
+
31
+ ### 2. Installation Locations
32
+ Documented in `/guide/how-it-works.md`
33
+
34
+ | Type | Path | Managed? | Use Case |
35
+ |------|------|----------|----------|
36
+ | fontist | `~/.fontist/fonts/{formula}/` | ✅ Yes | Default, isolated |
37
+ | user | `~/Library/Fonts/fontist/` (macOS) | ✅ Yes | User-wide access |
38
+ | system | `/Library/Fonts/fontist/` (macOS) | ✅ Yes | All users |
39
+
40
+ ### 3. Font Indexes
41
+ Documented in `/guide/how-it-works.md`
42
+
43
+ - Formula Index: Maps font names → formula files
44
+ - System Index: OS-installed fonts
45
+ - Fontist Index: Fonts installed via Fontist
46
+ - User Index: User-installed fonts
47
+
48
+ ### 4. Formula Repository
49
+ Documented in `/guide/formulas.md`
50
+
51
+ - Location: `~/.fontist/versions/v4/formulas/`
52
+ - Git clone from `https://github.com/fontist/formulas.git`
53
+ - Auto-updates via `fontist update`
54
+ - Private repos via `fontist repo`
55
+
56
+ ### 5. CLI Commands
57
+ All documented in `/docs/cli/`
58
+
59
+ ### 6. Ruby API Classes
60
+ All documented in `/docs/api/`
61
+
62
+ ---
63
+
64
+ ## 🔄 IN PROGRESS
65
+
66
+ - [ ] Add configuration priority table to how-it-works.md
67
+ - [ ] Add managed vs non-managed location explanation
68
+ - [ ] Document all ENV variables in reference page
69
+
70
+ ---
71
+
72
+ ## Configuration Reference
73
+
74
+ ### All Configuration Settings
75
+
76
+ | Setting | ENV VAR | Config Key | CLI Option | Default |
77
+ |---------|---------|------------|------------|---------|
78
+ | Base path | `FONTIST_PATH` | - | - | `~/.fontist` |
79
+ | Fonts path | - | `fonts_path` | - | `~/.fontist/fonts` |
80
+ | Formulas path | `FONTIST_FORMULAS_PATH` | - | `--formulas-path` | (auto) |
81
+ | Install location | `FONTIST_INSTALL_LOCATION` | `fonts_install_location` | `--location` | `fontist` |
82
+ | User fonts path | `FONTIST_USER_FONTS_PATH` | `user_fonts_path` | - | Platform default |
83
+ | System fonts path | `FONTIST_SYSTEM_FONTS_PATH` | `system_fonts_path` | - | Platform default |
84
+ | Preferred family | - | `preferred_family` | `--preferred-family` | `false` |
85
+ | No cache | - | - | `--no-cache` | `false` |
86
+ | Quiet mode | - | - | `--quiet` | `false` |
87
+ | Verbose | - | - | `--verbose` | `false` |
88
+ | Open timeout | - | `open_timeout` | - | `60` |
89
+ | Read timeout | - | `read_timeout` | - | `60` |
90
+ | Google Fonts key | `GOOGLE_FONTS_API_KEY` | `google_fonts_key` | - | `nil` |
91
+ | Import cache | `FONTIST_IMPORT_CACHE` | - | - | `~/.fontist/import_cache` |
92
+
93
+ ---
94
+
95
+ ## Environment Variables Reference
96
+
97
+ | Variable | Description | Default |
98
+ |----------|-------------|---------|
99
+ | `FONTIST_PATH` | Base directory for all Fontist data | `~/.fontist` |
100
+ | `FONTIST_FORMULAS_PATH` | Custom formulas directory | (auto) |
101
+ | `FONTIST_INSTALL_LOCATION` | Default install location (`fontist`, `user`, `system`) | `fontist` |
102
+ | `FONTIST_USER_FONTS_PATH` | Custom user fonts path | Platform default |
103
+ | `FONTIST_SYSTEM_FONTS_PATH` | Custom system fonts path | Platform default |
104
+ | `FONTIST_IMPORT_CACHE` | Import cache directory | `~/.fontist/import_cache` |
105
+ | `FONTIST_NO_MIRRORS` | Disable formula index mirrors | `false` |
106
+ | `GOOGLE_FONTS_API_KEY` | Google Fonts API key | (none) |
107
+
108
+ ---
109
+
110
+ ## Managed vs Non-Managed Locations
111
+
112
+ ### Managed Locations (Fontist controls)
113
+ - `~/.fontist/fonts/` - Always managed
114
+ - `~/Library/Fonts/fontist/` - Managed subdirectory
115
+ - `/Library/Fonts/fontist/` - Managed subdirectory
116
+
117
+ **Behavior:** Safe to replace existing fonts
118
+
119
+ ### Non-Managed Locations (custom paths via ENV)
120
+ - `FONTIST_USER_FONTS_PATH=~/Library/Fonts` → installs directly
121
+ - `FONTIST_SYSTEM_FONTS_PATH=/Library/Fonts` → installs directly
122
+
123
+ **Behavior:** Uses unique filenames (`-fontist` suffix) to avoid conflicts
124
+
125
+ ---
126
+
127
+ ## Directory Structure
128
+
129
+ ```
130
+ ~/.fontist/
131
+ ├── fonts/ # Installed font files
132
+ │ └── {formula-key}/
133
+ │ └── *.ttf
134
+ ├── versions/
135
+ │ └── v4/
136
+ │ ├── formulas/ # Git clone of formulas repo
137
+ │ │ └── Formulas/
138
+ │ │ ├── roboto.yml
139
+ │ │ └── private/ # Custom formula repos
140
+ │ ├── formula_index.default_family.yml
141
+ │ ├── formula_index.preferred_family.yml
142
+ │ └── filename_index.yml
143
+ ├── config.yml # User configuration
144
+ ├── downloads/ # Temporary downloads
145
+ ├── import_cache/ # Imported font cache
146
+ ├── system_index.default_family.yml # System fonts index
147
+ ├── fontist_index.default_family.yml # Fontist fonts index
148
+ └── user_index.default_family.yml # User fonts index
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Remaining Minor Gaps
154
+
155
+ - [ ] Document import system (`fontist import`) internals
156
+ - [ ] Document cache system internals
157
+ - [ ] Document formula picker algorithm
158
+ - [ ] Document locking mechanism (for concurrent operations)
159
+
160
+ ---
161
+
162
+ ## Status: Nearly Complete
163
+ **Priority:** High
164
+ **Notes:** Core functionality documented, minor gaps remain
@@ -0,0 +1,114 @@
1
+ # Fontist Documentation Improvement Plan
2
+
3
+ **Goal:** Achieve 100% documentation coverage of README.adoc content in docs/
4
+
5
+ **Status:** ✅ Complete
6
+
7
+ ---
8
+
9
+ ## Phase 1: Platform-Specific Guides (Critical)
10
+
11
+ ### 1.1 Create macOS Platform Guide
12
+ - [x] Create `/docs/guide/platforms/macos.md`
13
+ - [x] Document supplementary fonts framework
14
+ - [x] Document framework versioning (Font3-Font8)
15
+ - [x] Document platform tags (`macos-fontX`)
16
+ - [x] Document version compatibility checking
17
+ - [x] Include macOS version → framework table
18
+ - [x] Add link to Fontist blog post
19
+
20
+ ### 1.2 Create Windows Platform Guide
21
+ - [x] Create `/docs/guide/platforms/windows.md`
22
+ - [x] Document Windows font management differences
23
+ - [x] Document Windows font locations
24
+ - [x] Document file locking considerations
25
+ - [x] Document path handling
26
+ - [x] Document registry integration
27
+ - [x] Document administrator privileges
28
+ - [x] Include platform compatibility table
29
+
30
+ ---
31
+
32
+ ## Phase 2: Installation Improvements
33
+
34
+ ### 2.1 Update Installation Guide
35
+ - [x] Add detailed dependency table (json, brotli, seven-zip, libmspack, ffi-libarchive-binary)
36
+ - [x] Add Windows RubyInstaller DevKit steps (`ridk install`)
37
+ - [x] Add Git as prerequisite for update/repo commands
38
+ - [x] Add note about native extension compilation
39
+
40
+ ---
41
+
42
+ ## Phase 3: Formula Advanced Features
43
+
44
+ ### 3.1 Update Formulas Guide
45
+ - [x] Add `override:` key documentation (already present)
46
+ - [x] Add Frutiger fonts example (already present)
47
+ - [x] Add HTTP authentication for private repos (already present)
48
+ - [x] Add authorization headers example (already present)
49
+ - [x] Add token scope requirements (already present)
50
+
51
+ ### 3.2 Update create-formula CLI
52
+ - [x] Add `--name-prefix` option with example (already documented)
53
+
54
+ ---
55
+
56
+ ## Phase 4: How It Works Improvements
57
+
58
+ ### 4.1 Update How It Works Guide
59
+ - [x] Add managed vs non-managed locations section (already present)
60
+ - [x] Add font discovery behavior explanation (already present)
61
+ - [x] Add import cache environment variables (already present)
62
+
63
+ ---
64
+
65
+ ## Phase 5: Maintainer Documentation (Clearly Marked)
66
+
67
+ ### 5.1 Create Maintainer Import Guide
68
+ - [x] Create `/docs/guide/maintainer/index.md`
69
+ - [x] Create `/docs/guide/maintainer/import.md`
70
+ - [x] Mark as "Maintainer Only" clearly
71
+ - [x] Document `fontist import google` command
72
+ - [x] Document Google Fonts API integration
73
+ - [x] Document import source architecture
74
+ - [x] Document versioned filenames
75
+ - [x] Document import cache Ruby API
76
+
77
+ ### 5.2 Update CLI Import Reference
78
+ - [x] Add `fontist import google` to `/docs/cli/import.md` (already present)
79
+ - [x] Add maintainer-only notice
80
+
81
+ ---
82
+
83
+ ## Phase 6: Navigation Updates
84
+
85
+ ### 6.1 Update VitePress Config
86
+ - [x] Add Platforms section to Guide sidebar
87
+ - [x] Add Maintainer section to Guide sidebar (collapsed)
88
+ - [x] Update navigation as needed
89
+
90
+ ---
91
+
92
+ ## Phase 7: Verification
93
+
94
+ ### 7.1 Build and Test
95
+ - [x] Run `npm run build` to verify no errors
96
+ - [x] Run lychee link checker (manual verification with curl - lychee crashed)
97
+ - [x] Verify all new pages are accessible
98
+ - [x] Cross-check against README.adoc
99
+
100
+ ---
101
+
102
+ ## Progress Tracking
103
+
104
+ | Phase | Status | Items Done | Items Total |
105
+ |-------|--------|------------|-------------|
106
+ | 1. Platform Guides | ✅ Complete | 14 | 14 |
107
+ | 2. Installation | ✅ Complete | 4 | 4 |
108
+ | 3. Formula Features | ✅ Complete | 7 | 7 |
109
+ | 4. How It Works | ✅ Complete | 3 | 3 |
110
+ | 5. Maintainer Docs | ✅ Complete | 10 | 10 |
111
+ | 6. Navigation | ✅ Complete | 3 | 3 |
112
+ | 7. Verification | ✅ Complete | 4 | 4 |
113
+
114
+ **Total Progress: 45/45 items (100%)**
@@ -0,0 +1,107 @@
1
+ # TODO: Fix Excavate Memory Leaks and Upgrade Fontist
2
+
3
+ ## Problem
4
+ Fontist CI tests pass but fail at the end with:
5
+ ```
6
+ failed to allocate memory (NoMemoryError)
7
+ ```
8
+
9
+ This happens after repeated archive extractions during test runs.
10
+
11
+ ## Root Cause Analysis
12
+ Memory leaks in Excavate gem due to:
13
+ 1. Temp directories not cleaned up on errors
14
+ 2. Incorrect `ensure`/`rescue` order in `extract_and_replace` method
15
+
16
+ ## Remaining Work
17
+
18
+ ### 1. Fix Excavate Gem (in /Users/mulgogi/src/fontist/excavate)
19
+
20
+ #### archive.rb - Fix `extract_and_replace` method (lines 217-229)
21
+ Current broken code has `ensure` BEFORE `rescue` which is invalid Ruby syntax:
22
+ ```ruby
23
+ def extract_and_replace(archive)
24
+ target = Dir.mktmpdir
25
+ extract_recursively(archive, target)
26
+ replace_archive_with_contents(archive, target)
27
+ ensure # <-- WRONG: ensure must come AFTER rescue
28
+ FileUtils.rm_rf(target)
29
+ rescue StandardError # <-- This causes syntax error
30
+ raise unless TYPES.key?(normalized_extension(archive))
31
+ end
32
+ ```
33
+
34
+ Fix - swap order so `rescue` comes before `ensure`:
35
+ ```ruby
36
+ def extract_and_replace(archive)
37
+ target = Dir.mktmpdir
38
+ extract_recursively(archive, target)
39
+ replace_archive_with_contents(archive, target)
40
+ rescue StandardError
41
+ raise unless TYPES.key?(normalized_extension(archive))
42
+ ensure
43
+ FileUtils.rm_rf(target)
44
+ end
45
+ ```
46
+
47
+ ### 2. Run Excavate Tests
48
+ ```bash
49
+ cd /Users/mulgogi/src/fontist/excavate
50
+ bundle exec rspec
51
+ ```
52
+ All 65 tests should pass.
53
+
54
+ ### 3. Bump Excavate Version
55
+ Edit `/Users/mulgogi/src/fontist/excavate/lib/excavate/version.rb`:
56
+ ```ruby
57
+ VERSION = "1.0.3"
58
+ ```
59
+
60
+ ### 4. Commit and Push Excavate
61
+ ```bash
62
+ cd /Users/mulgogi/src/fontist/excavate
63
+ git add -A
64
+ git commit -m "fix: prevent memory leaks by ensuring proper resource cleanup
65
+
66
+ - Fix extract_and_replace to use correct rescue/ensure order
67
+ - Add ensure block to extract_by_filter for temp dir cleanup"
68
+ git push origin main
69
+ ```
70
+
71
+ ### 5. Release Excavate Gem
72
+ ```bash
73
+ cd /Users/mulgogi/src/fontist/excavate
74
+ # Tag and push to rubygems
75
+ git tag v1.0.3
76
+ git push --tags
77
+ gem build excavate.gemspec
78
+ gem push excavate-1.0.3.gem
79
+ ```
80
+
81
+ ### 6. Update Fontist to Use New Excavate
82
+ ```bash
83
+ cd /Users/mulgogi/src/fontist/fontist
84
+ # Update Gemfile.lock to use excavate >= 1.0.3
85
+ bundle update excavate
86
+ ```
87
+
88
+ ### 7. Run Fontist Tests
89
+ ```bash
90
+ cd /Users/mulgogi/src/fontist/fontist
91
+ bundle exec rspec
92
+ ```
93
+ Tests should pass WITHOUT the `NoMemoryError` at the end.
94
+
95
+ ### 8. Create PR and Merge
96
+ - Create PR in fontist repository
97
+ - Reference issue #451
98
+ - Merge after CI passes
99
+
100
+ ## Files Modified
101
+
102
+ ### Excavate
103
+ - `lib/excavate/archive.rb` - Fix `extract_and_replace` method
104
+
105
+ ## Notes
106
+ - Do NOT add `ensure` blocks with `reader&.close` to extractors - the Omnizip readers don't have a `close` method
107
+ - The fix is simple: correct the `rescue`/`ensure` order in `extract_and_replace`
@@ -26,7 +26,7 @@ The main formula repository is [fontist/formulas](https://github.com/fontist/for
26
26
  - Google Fonts (Roboto, Open Sans, etc.)
27
27
  - SIL Fonts
28
28
  - macOS system fonts
29
- - Windows fonts
29
+ - Windows fonts (including Windows Features on Demand)
30
30
  - Many other open source fonts
31
31
 
32
32
  ### Local Storage
@@ -257,6 +257,42 @@ fontist create-formula https://dl.winehq.org/wine/source/10.x/wine-10.18.tar.xz
257
257
 
258
258
  This generates a formula where all fonts have names prefixed with "Wine ", making it clear these are Wine compatibility fonts rather than the original Microsoft fonts.
259
259
 
260
+ ### Windows Features on Demand (FOD) Formulas
261
+
262
+ Windows FOD formulas use `source: windows_fod` to install fonts via PowerShell's `Add-WindowsCapability`. These formulas don't have download URLs — instead, they specify a Windows capability name:
263
+
264
+ ```yaml
265
+ schema_version: 5
266
+ name: Japanese Supplemental Fonts
267
+ platforms:
268
+ - windows
269
+ resources:
270
+ japanese_supplemental_fonts:
271
+ source: windows_fod
272
+ capability_name: "Language.Fonts.Jpan~~~und-JPAN~0.0.1.0"
273
+ fonts:
274
+ - name: Meiryo
275
+ styles:
276
+ - family_name: Meiryo
277
+ type: Regular
278
+ font: Meiryo.ttc
279
+ import_source:
280
+ type: windows
281
+ capability_name: "Language.Fonts.Jpan~~~und-JPAN~0.0.1.0"
282
+ min_windows_version: "10.0"
283
+ ```
284
+
285
+ Key fields for Windows FOD formulas:
286
+
287
+ | Field | Description |
288
+ |-------|-------------|
289
+ | `resources.*.source` | Must be `windows_fod` |
290
+ | `resources.*.capability_name` | The Windows FOD capability identifier (e.g., `Language.Fonts.Jpan~~~und-JPAN~0.0.1.0`) |
291
+ | `import_source.type` | Must be `windows` |
292
+ | `import_source.min_windows_version` | Minimum Windows version required (default: `10.0`) |
293
+
294
+ These formulas are restricted to the `windows` platform. Attempting to install them on macOS or Linux raises a `PlatformMismatchError`.
295
+
260
296
  ## Related
261
297
 
262
298
  - [How Fontist Works](/guide/how-it-works) - Internal architecture and indexes
@@ -291,6 +291,19 @@ When you run `fontist install "Open Sans"`:
291
291
  └─────────────────────────────────────────────────────────────┘
292
292
  ```
293
293
 
294
+ ### Resource Dispatch
295
+
296
+ Fontist selects a download strategy based on the formula's `source` field:
297
+
298
+ | Source | Resource Class | Behavior |
299
+ |--------|---------------|----------|
300
+ | `google` | `GoogleResource` | Downloads from Google Fonts API |
301
+ | `apple_cdn` | `AppleCDNResource` | Downloads from Apple CDN |
302
+ | `windows_fod` | `WindowsFodResource` | Installs via PowerShell `Add-WindowsCapability` |
303
+ | (default) | `ArchiveResource` | Downloads and extracts archive via excavate |
304
+
305
+ For Windows FOD fonts, the flow differs from archives — instead of downloading a file, Fontist checks if the Windows capability is installed and installs it via PowerShell if needed. Font files are then read from `C:\Windows\Fonts`.
306
+
294
307
  ---
295
308
 
296
309
  ## Index Management