fontist 3.0.0 → 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 +4 -4
- data/.github/workflows/discover-fonts.yml +76 -0
- data/.github/workflows/rake.yml +103 -8
- data/.rubocop_todo.yml +179 -139
- data/TODO.audit-docs.md +164 -0
- data/TODO.improve-docs.md +114 -0
- data/TODO.upgrade-excavate.md +107 -0
- data/docs/guide/formulas.md +37 -1
- data/docs/guide/how-it-works.md +13 -0
- data/docs/guide/platforms/windows.md +67 -0
- data/fontist.gemspec +2 -2
- data/lib/fontist/cache/store.rb +1 -1
- data/lib/fontist/cli.rb +2 -1
- data/lib/fontist/errors.rb +24 -3
- data/lib/fontist/extract.rb +1 -0
- data/lib/fontist/font.rb +2 -2
- data/lib/fontist/font_finder.rb +1 -2
- data/lib/fontist/font_installer.rb +16 -14
- data/lib/fontist/format_matcher.rb +4 -2
- data/lib/fontist/format_spec.rb +1 -1
- data/lib/fontist/formula.rb +15 -3
- data/lib/fontist/formula_picker.rb +5 -3
- data/lib/fontist/import/create_formula.rb +5 -0
- data/lib/fontist/import/formula_builder.rb +10 -1
- data/lib/fontist/import/google/data_sources/github.rb +4 -4
- data/lib/fontist/import/google/font_database.rb +8 -8
- data/lib/fontist/import/google/formula_builders/formula_builder_v4.rb +1 -1
- data/lib/fontist/import/google/formula_builders/formula_builder_v5.rb +9 -3
- data/lib/fontist/import/google/metadata_adapter.rb +6 -6
- data/lib/fontist/import/google/models/font_family.rb +1 -1
- data/lib/fontist/import/import_display.rb +5 -5
- data/lib/fontist/import/macos_importer.rb +1 -1
- data/lib/fontist/import/upgrade_formulas.rb +1 -3
- data/lib/fontist/import/v4_to_v5_migrator.rb +2 -1
- data/lib/fontist/import/windows/fod_capabilities.yml +654 -0
- data/lib/fontist/import/windows/windows_license.txt +4 -0
- data/lib/fontist/import/windows.rb +162 -0
- data/lib/fontist/import.rb +3 -1
- data/lib/fontist/import_source.rb +1 -0
- data/lib/fontist/indexes/directory_snapshot.rb +2 -2
- data/lib/fontist/indexes/incremental_scanner.rb +2 -2
- data/lib/fontist/indexes.rb +8 -4
- data/lib/fontist/macos/catalog/asset.rb +2 -2
- data/lib/fontist/macos_import_source.rb +0 -1
- data/lib/fontist/repo.rb +1 -1
- data/lib/fontist/resource.rb +5 -1
- data/lib/fontist/resources/windows_fod_resource.rb +51 -0
- data/lib/fontist/resources.rb +1 -0
- data/lib/fontist/system_index.rb +5 -5
- data/lib/fontist/utils/downloader.rb +8 -3
- data/lib/fontist/utils/system.rb +19 -2
- data/lib/fontist/validation.rb +1 -1
- data/lib/fontist/validator.rb +2 -2
- data/lib/fontist/version.rb +1 -1
- data/lib/fontist/windows_fod_metadata.rb +83 -0
- data/lib/fontist/windows_import_source.rb +54 -0
- data/lib/fontist.rb +4 -1
- data/script/generate_windows_formulas.rb +24 -0
- data/script/validate_windows_fod_ci.rb +175 -0
- metadata +17 -6
data/TODO.audit-docs.md
ADDED
|
@@ -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`
|
data/docs/guide/formulas.md
CHANGED
|
@@ -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
|
data/docs/guide/how-it-works.md
CHANGED
|
@@ -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
|
|
@@ -78,6 +78,73 @@ fontist install "Roboto" --location=system
|
|
|
78
78
|
|
|
79
79
|
---
|
|
80
80
|
|
|
81
|
+
## Windows Features on Demand (FOD) Fonts
|
|
82
|
+
|
|
83
|
+
Windows includes supplementary fonts that aren't pre-installed but can be enabled through **Features on Demand** (FOD). These include fonts for Japanese, Korean, Arabic, Pan-European, and other scripts.
|
|
84
|
+
|
|
85
|
+
### What Are FOD Fonts?
|
|
86
|
+
|
|
87
|
+
Windows FOD fonts are installed using `Add-WindowsCapability`, which downloads font packages from Windows Update. Fontist automates this process — when a formula specifies `source: windows_fod`, Fontist calls the appropriate PowerShell command to install the capability.
|
|
88
|
+
|
|
89
|
+
### Installing FOD Fonts
|
|
90
|
+
|
|
91
|
+
```powershell
|
|
92
|
+
# Install a specific supplemental font
|
|
93
|
+
fontist install "Meiryo"
|
|
94
|
+
|
|
95
|
+
# Install Pan-European supplemental fonts
|
|
96
|
+
fontist install "Arial Nova"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Fontist checks whether the capability is already installed. If not, it runs:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
Add-WindowsCapability -Online -Name 'Language.Fonts.Jpan~~~und-JPAN~0.0.1.0'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Requirements
|
|
106
|
+
|
|
107
|
+
| Requirement | Details |
|
|
108
|
+
|-------------|---------|
|
|
109
|
+
| Windows version | Windows 10 or later |
|
|
110
|
+
| Internet connection | Required (fonts download from Windows Update) |
|
|
111
|
+
| Administrator | Required on Windows 10 for system-wide installation |
|
|
112
|
+
| WSUS/SCCM | Must not block Features on Demand |
|
|
113
|
+
|
|
114
|
+
### Available FOD Fonts
|
|
115
|
+
|
|
116
|
+
Fontist includes metadata for all Windows FOD font capabilities. Some common ones:
|
|
117
|
+
|
|
118
|
+
| Capability | Fonts Included |
|
|
119
|
+
|------------|---------------|
|
|
120
|
+
| Japanese Supplemental Fonts | Meiryo, MS Gothic, MS Mincho |
|
|
121
|
+
| Korean Supplemental Fonts | Batang, Dotum, Gulim |
|
|
122
|
+
| Arabic Script Supplemental Fonts | Sakkal Majalla, Simplified Arabic |
|
|
123
|
+
| Pan-European Supplemental Fonts | Arial Nova, Georgia Pro, Gill Sans Nova |
|
|
124
|
+
| Traditional Chinese Supplemental Fonts | MingLiU, DFKai-SB |
|
|
125
|
+
|
|
126
|
+
### FOD Font Installation Flow
|
|
127
|
+
|
|
128
|
+
1. Fontist looks up the font in the formula index
|
|
129
|
+
2. Checks if the Windows FOD capability is already installed via `Get-WindowsCapability`
|
|
130
|
+
3. If not installed, runs `Add-WindowsCapability` to download and install it
|
|
131
|
+
4. Returns paths to the installed font files in `C:\Windows\Fonts`
|
|
132
|
+
|
|
133
|
+
### Troubleshooting FOD Installation
|
|
134
|
+
|
|
135
|
+
If you see a `WindowsFodInstallError`:
|
|
136
|
+
|
|
137
|
+
1. **No internet connection** — FOD fonts require Windows Update access
|
|
138
|
+
2. **Insufficient permissions** — Run as Administrator on Windows 10
|
|
139
|
+
3. **WSUS/SCCM policy** — Your organization may block FOD downloads; contact your IT administrator
|
|
140
|
+
4. **Capability not found** — The capability name may differ on your Windows version; run `Get-WindowsCapability -Online -Name 'Language.Fonts.*'` to list available capabilities
|
|
141
|
+
|
|
142
|
+
::: info Platform Restriction
|
|
143
|
+
Windows FOD fonts are only installable on Windows. Fontist will raise a `PlatformMismatchError` if you attempt to install them on macOS or Linux.
|
|
144
|
+
:::
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
81
148
|
## Windows-Specific Considerations
|
|
82
149
|
|
|
83
150
|
### File Locking
|
data/fontist.gemspec
CHANGED
|
@@ -31,11 +31,11 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
|
|
32
32
|
spec.add_dependency "down", "~> 5.0"
|
|
33
33
|
spec.add_dependency "excavate", "~> 1.0", ">= 1.0.3"
|
|
34
|
-
spec.add_dependency "fontisan", "~> 0.2", ">= 0.2.
|
|
34
|
+
spec.add_dependency "fontisan", "~> 0.2", ">= 0.2.16"
|
|
35
35
|
spec.add_dependency "fuzzy_match", "~> 2.1"
|
|
36
36
|
spec.add_dependency "git", "> 1.0"
|
|
37
37
|
spec.add_dependency "json", "~> 2.0"
|
|
38
|
-
spec.add_dependency "lutaml-model", "~> 0.
|
|
38
|
+
spec.add_dependency "lutaml-model", "~> 0.8.0"
|
|
39
39
|
spec.add_dependency "marcel", "~> 1.0"
|
|
40
40
|
spec.add_dependency "nokogiri", "~> 1.0"
|
|
41
41
|
spec.add_dependency "octokit", "~> 4.0"
|
data/lib/fontist/cache/store.rb
CHANGED
data/lib/fontist/cli.rb
CHANGED
|
@@ -338,7 +338,8 @@ module Fontist
|
|
|
338
338
|
"Uses `fnmatch` patterns."
|
|
339
339
|
option :name_prefix, desc: "Prefix to add to all font family names, " \
|
|
340
340
|
"e.g. 'Wine ' for compatibility fonts"
|
|
341
|
-
option :schema_version, type: :numeric, default: 5,
|
|
341
|
+
option :schema_version, type: :numeric, default: 5,
|
|
342
|
+
desc: "Formula schema version (default: 5)"
|
|
342
343
|
def create_formula(url)
|
|
343
344
|
handle_class_options(options)
|
|
344
345
|
name = Fontist::Import::CreateFormula.new(url, options).call
|
data/lib/fontist/errors.rb
CHANGED
|
@@ -159,9 +159,30 @@ module Fontist
|
|
|
159
159
|
|
|
160
160
|
def build_message(font_name)
|
|
161
161
|
"Font '#{font_name}' is only available for: #{@required_platforms.join(', ')}. " \
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
"Your current platform is: #{@current_platform}. " \
|
|
163
|
+
"This font is licensed exclusively for the specified platform(s) and " \
|
|
164
|
+
"cannot be installed on your system."
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
class WindowsFodInstallError < GeneralError
|
|
169
|
+
attr_reader :capability_name
|
|
170
|
+
|
|
171
|
+
def initialize(capability_name, stderr_output = nil)
|
|
172
|
+
@capability_name = capability_name
|
|
173
|
+
super(build_message(capability_name, stderr_output))
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
private
|
|
177
|
+
|
|
178
|
+
def build_message(cap_name, stderr)
|
|
179
|
+
msg = "Failed to install Windows font capability '#{cap_name}'."
|
|
180
|
+
msg += "\n#{stderr}" if stderr && !stderr.strip.empty?
|
|
181
|
+
msg += "\n\nPossible causes:" \
|
|
182
|
+
"\n - No internet connection (Windows Update required)" \
|
|
183
|
+
"\n - Insufficient permissions (admin required on Windows 10)" \
|
|
184
|
+
"\n - WSUS/SCCM policy blocking Features on Demand"
|
|
185
|
+
msg
|
|
165
186
|
end
|
|
166
187
|
end
|
|
167
188
|
|
data/lib/fontist/extract.rb
CHANGED
data/lib/fontist/font.rb
CHANGED
|
@@ -338,9 +338,9 @@ module Fontist
|
|
|
338
338
|
all_fonts = [fontist_fonts, user_fonts, system_fonts].compact.flatten
|
|
339
339
|
return unless all_fonts && !all_fonts.empty?
|
|
340
340
|
|
|
341
|
-
uninstalled_paths = all_fonts.
|
|
341
|
+
uninstalled_paths = all_fonts.filter_map do |font|
|
|
342
342
|
uninstall_font_at_location(font.path)
|
|
343
|
-
end
|
|
343
|
+
end
|
|
344
344
|
|
|
345
345
|
return if uninstalled_paths.empty?
|
|
346
346
|
|
data/lib/fontist/font_finder.rb
CHANGED
|
@@ -75,7 +75,7 @@ module Fontist
|
|
|
75
75
|
def extract_resource_names(formula)
|
|
76
76
|
return [] unless formula.resources
|
|
77
77
|
|
|
78
|
-
Array(formula.resources).
|
|
78
|
+
Array(formula.resources).filter_map(&:name)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def build_font_match(formula, name, resource)
|
|
@@ -123,7 +123,6 @@ module Fontist
|
|
|
123
123
|
matcher = FormatMatcher.new(@format_spec)
|
|
124
124
|
matcher.filter_resources(resources)
|
|
125
125
|
end
|
|
126
|
-
|
|
127
126
|
end
|
|
128
127
|
|
|
129
128
|
# Result object for font matches
|