fontisan 0.2.17 → 0.2.23

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.
Files changed (249) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/.rubocop_todo.yml +86 -86
  4. data/CHANGELOG.md +12 -2
  5. data/README.adoc +53 -1
  6. data/docs/.vitepress/config.ts +68 -8
  7. data/docs/.vitepress/theme/style.css +570 -272
  8. data/docs/CONVERSION_GUIDE.adoc +31 -8
  9. data/docs/EXTRACT_TTC_MIGRATION.md +1 -1
  10. data/docs/WOFF_WOFF2_FORMATS.adoc +53 -0
  11. data/docs/api/conversion-options.md +37 -14
  12. data/docs/cli/audit.md +337 -0
  13. data/docs/cli/convert.md +20 -1
  14. data/docs/cli/index.md +31 -0
  15. data/docs/guide/color.md +1 -1
  16. data/docs/guide/conversion/options.md +32 -3
  17. data/docs/guide/conversion/ttf-otf.md +1 -1
  18. data/docs/guide/conversion/type1.md +1 -1
  19. data/docs/guide/conversion/web.md +91 -32
  20. data/docs/guide/conversion.md +6 -5
  21. data/docs/guide/formats/woff.md +35 -11
  22. data/docs/guide/index.md +2 -2
  23. data/docs/guide/migrations/extract-ttc.md +1 -1
  24. data/docs/guide/quick-start.md +4 -4
  25. data/docs/guide/type1.md +4 -4
  26. data/docs/guide/woff.md +19 -17
  27. data/docs/index.md +2 -0
  28. data/docs/lychee.toml +5 -1
  29. data/docs/package.json +1 -1
  30. data/docs/public/robots.txt +4 -0
  31. data/docs/scripts/post-build.mjs +81 -0
  32. data/lib/fontisan/base_collection.rb +23 -9
  33. data/lib/fontisan/binary/structures.rb +0 -2
  34. data/lib/fontisan/binary.rb +11 -0
  35. data/lib/fontisan/cldr/aggregator.rb +33 -0
  36. data/lib/fontisan/cldr/cache_manager.rb +110 -0
  37. data/lib/fontisan/cldr/config.rb +59 -0
  38. data/lib/fontisan/cldr/download_error.rb +9 -0
  39. data/lib/fontisan/cldr/downloader.rb +79 -0
  40. data/lib/fontisan/cldr/error.rb +8 -0
  41. data/lib/fontisan/cldr/index.rb +64 -0
  42. data/lib/fontisan/cldr/index_builder.rb +72 -0
  43. data/lib/fontisan/cldr/unicode_set_parser.rb +189 -0
  44. data/lib/fontisan/cldr/unknown_version_error.rb +9 -0
  45. data/lib/fontisan/cldr/version_resolver.rb +91 -0
  46. data/lib/fontisan/cldr.rb +23 -0
  47. data/lib/fontisan/cli/cldr_cli.rb +85 -0
  48. data/lib/fontisan/cli.rb +31 -2
  49. data/lib/fontisan/collection/builder.rb +0 -4
  50. data/lib/fontisan/collection/dfont_builder.rb +0 -4
  51. data/lib/fontisan/collection/shared_logic.rb +0 -2
  52. data/lib/fontisan/collection/writer.rb +0 -3
  53. data/lib/fontisan/collection.rb +15 -0
  54. data/lib/fontisan/commands/base_command.rb +0 -3
  55. data/lib/fontisan/commands/convert_command.rb +25 -20
  56. data/lib/fontisan/commands/dump_table_command.rb +0 -3
  57. data/lib/fontisan/commands/export_command.rb +0 -4
  58. data/lib/fontisan/commands/features_command.rb +0 -3
  59. data/lib/fontisan/commands/instance_command.rb +0 -5
  60. data/lib/fontisan/commands/ls_command.rb +0 -6
  61. data/lib/fontisan/commands/optical_size_command.rb +0 -3
  62. data/lib/fontisan/commands/pack_command.rb +0 -5
  63. data/lib/fontisan/commands/scripts_command.rb +0 -2
  64. data/lib/fontisan/commands/subset_command.rb +0 -3
  65. data/lib/fontisan/commands/unicode_command.rb +0 -3
  66. data/lib/fontisan/commands/unpack_command.rb +0 -7
  67. data/lib/fontisan/commands/validate_command.rb +0 -8
  68. data/lib/fontisan/commands/variable_command.rb +0 -3
  69. data/lib/fontisan/commands.rb +26 -0
  70. data/lib/fontisan/config/cldr.yml +22 -0
  71. data/lib/fontisan/config/conversion_matrix.yml +38 -0
  72. data/lib/fontisan/constants.rb +19 -0
  73. data/lib/fontisan/conversion_options.rb +30 -19
  74. data/lib/fontisan/converters/cff_table_builder.rb +0 -3
  75. data/lib/fontisan/converters/collection_converter.rb +0 -8
  76. data/lib/fontisan/converters/conversion_strategy.rb +161 -46
  77. data/lib/fontisan/converters/format_converter.rb +143 -32
  78. data/lib/fontisan/converters/glyf_table_builder.rb +0 -2
  79. data/lib/fontisan/converters/outline_converter.rb +0 -19
  80. data/lib/fontisan/converters/outline_extraction.rb +0 -5
  81. data/lib/fontisan/converters/outline_optimizer.rb +0 -5
  82. data/lib/fontisan/converters/svg_generator.rb +0 -4
  83. data/lib/fontisan/converters/table_copier.rb +0 -2
  84. data/lib/fontisan/converters/type1_converter.rb +0 -11
  85. data/lib/fontisan/converters/woff2_encoder.rb +49 -20
  86. data/lib/fontisan/converters/woff_writer.rb +211 -282
  87. data/lib/fontisan/converters.rb +21 -0
  88. data/lib/fontisan/dfont_collection.rb +29 -10
  89. data/lib/fontisan/export/exporter.rb +0 -6
  90. data/lib/fontisan/export/transformers/font_to_ttx.rb +0 -9
  91. data/lib/fontisan/export/transformers/head_transformer.rb +0 -2
  92. data/lib/fontisan/export/transformers/hhea_transformer.rb +0 -2
  93. data/lib/fontisan/export/transformers/maxp_transformer.rb +0 -2
  94. data/lib/fontisan/export/transformers/name_transformer.rb +0 -2
  95. data/lib/fontisan/export/transformers/os2_transformer.rb +0 -2
  96. data/lib/fontisan/export/transformers/post_transformer.rb +0 -2
  97. data/lib/fontisan/export/transformers.rb +17 -0
  98. data/lib/fontisan/export.rb +13 -0
  99. data/lib/fontisan/font_loader.rb +14 -19
  100. data/lib/fontisan/font_writer.rb +0 -1
  101. data/lib/fontisan/formatters.rb +9 -0
  102. data/lib/fontisan/hints/hint_converter.rb +0 -1
  103. data/lib/fontisan/hints/postscript_hint_applier.rb +0 -9
  104. data/lib/fontisan/hints/postscript_hint_extractor.rb +0 -2
  105. data/lib/fontisan/hints/truetype_hint_extractor.rb +0 -2
  106. data/lib/fontisan/hints.rb +19 -0
  107. data/lib/fontisan/metrics_calculator.rb +0 -2
  108. data/lib/fontisan/models/all_scripts_features_info.rb +0 -1
  109. data/lib/fontisan/models/cldr/language_coverage.rb +31 -0
  110. data/lib/fontisan/models/cldr.rb +12 -0
  111. data/lib/fontisan/models/collection_brief_info.rb +0 -1
  112. data/lib/fontisan/models/collection_info.rb +0 -2
  113. data/lib/fontisan/models/collection_list_info.rb +0 -1
  114. data/lib/fontisan/models/collection_validation_report.rb +0 -2
  115. data/lib/fontisan/models/color_glyph.rb +0 -1
  116. data/lib/fontisan/models/font_report.rb +0 -1
  117. data/lib/fontisan/models/ttx/tables.rb +21 -0
  118. data/lib/fontisan/models/ttx/ttfont.rb +0 -8
  119. data/lib/fontisan/models/ttx.rb +14 -0
  120. data/lib/fontisan/models.rb +47 -0
  121. data/lib/fontisan/open_type_collection.rb +6 -5
  122. data/lib/fontisan/open_type_font.rb +8 -2
  123. data/lib/fontisan/open_type_font_extensions.rb +9 -9
  124. data/lib/fontisan/optimizers/pattern_analyzer.rb +0 -1
  125. data/lib/fontisan/optimizers.rb +14 -0
  126. data/lib/fontisan/outline_extractor.rb +0 -2
  127. data/lib/fontisan/parsers/dfont_parser.rb +0 -1
  128. data/lib/fontisan/parsers.rb +10 -0
  129. data/lib/fontisan/pipeline/format_detector.rb +29 -102
  130. data/lib/fontisan/pipeline/output_writer.rb +11 -9
  131. data/lib/fontisan/pipeline/strategies/instance_strategy.rb +0 -4
  132. data/lib/fontisan/pipeline/strategies/named_strategy.rb +0 -4
  133. data/lib/fontisan/pipeline/strategies/preserve_strategy.rb +0 -2
  134. data/lib/fontisan/pipeline/strategies.rb +16 -0
  135. data/lib/fontisan/pipeline/transformation_pipeline.rb +0 -7
  136. data/lib/fontisan/pipeline/variation_resolver.rb +0 -7
  137. data/lib/fontisan/pipeline.rb +14 -0
  138. data/lib/fontisan/sfnt_font.rb +29 -14
  139. data/lib/fontisan/sfnt_table.rb +0 -4
  140. data/lib/fontisan/subset/builder.rb +0 -6
  141. data/lib/fontisan/subset.rb +13 -0
  142. data/lib/fontisan/svg/font_generator.rb +0 -4
  143. data/lib/fontisan/svg/glyph_generator.rb +0 -2
  144. data/lib/fontisan/svg.rb +12 -0
  145. data/lib/fontisan/tables/cbdt.rb +0 -1
  146. data/lib/fontisan/tables/cblc.rb +0 -1
  147. data/lib/fontisan/tables/cff/charset.rb +0 -1
  148. data/lib/fontisan/tables/cff/charstring.rb +0 -1
  149. data/lib/fontisan/tables/cff/charstring_rebuilder.rb +0 -4
  150. data/lib/fontisan/tables/cff/charstrings_index.rb +0 -3
  151. data/lib/fontisan/tables/cff/dict.rb +0 -1
  152. data/lib/fontisan/tables/cff/encoding.rb +0 -1
  153. data/lib/fontisan/tables/cff/header.rb +0 -2
  154. data/lib/fontisan/tables/cff/hint_operation_injector.rb +0 -2
  155. data/lib/fontisan/tables/cff/index.rb +0 -1
  156. data/lib/fontisan/tables/cff/private_dict.rb +0 -2
  157. data/lib/fontisan/tables/cff/private_dict_writer.rb +0 -2
  158. data/lib/fontisan/tables/cff/table_builder.rb +0 -6
  159. data/lib/fontisan/tables/cff/top_dict.rb +0 -2
  160. data/lib/fontisan/tables/cff.rb +23 -15
  161. data/lib/fontisan/tables/cff2/charstring_parser.rb +0 -2
  162. data/lib/fontisan/tables/cff2/table_builder.rb +0 -11
  163. data/lib/fontisan/tables/cff2/table_reader.rb +0 -2
  164. data/lib/fontisan/tables/cff2.rb +13 -14
  165. data/lib/fontisan/tables/cmap.rb +24 -2
  166. data/lib/fontisan/tables/cmap_table.rb +0 -3
  167. data/lib/fontisan/tables/colr.rb +0 -1
  168. data/lib/fontisan/tables/cpal.rb +0 -1
  169. data/lib/fontisan/tables/cvar.rb +0 -2
  170. data/lib/fontisan/tables/fvar.rb +0 -1
  171. data/lib/fontisan/tables/glyf/compound_glyph_resolver.rb +0 -2
  172. data/lib/fontisan/tables/glyf/glyph_builder.rb +0 -3
  173. data/lib/fontisan/tables/glyf.rb +0 -6
  174. data/lib/fontisan/tables/glyf_table.rb +0 -3
  175. data/lib/fontisan/tables/gpos.rb +0 -2
  176. data/lib/fontisan/tables/gsub.rb +0 -2
  177. data/lib/fontisan/tables/gvar.rb +0 -2
  178. data/lib/fontisan/tables/head.rb +0 -2
  179. data/lib/fontisan/tables/head_table.rb +0 -3
  180. data/lib/fontisan/tables/hhea.rb +0 -2
  181. data/lib/fontisan/tables/hhea_table.rb +0 -3
  182. data/lib/fontisan/tables/hmtx.rb +0 -2
  183. data/lib/fontisan/tables/hmtx_table.rb +0 -3
  184. data/lib/fontisan/tables/hvar.rb +0 -3
  185. data/lib/fontisan/tables/loca.rb +0 -2
  186. data/lib/fontisan/tables/loca_table.rb +0 -3
  187. data/lib/fontisan/tables/maxp.rb +0 -2
  188. data/lib/fontisan/tables/maxp_table.rb +0 -3
  189. data/lib/fontisan/tables/mvar.rb +0 -3
  190. data/lib/fontisan/tables/name.rb +0 -2
  191. data/lib/fontisan/tables/name_table.rb +0 -3
  192. data/lib/fontisan/tables/os2_table.rb +0 -3
  193. data/lib/fontisan/tables/post_table.rb +0 -3
  194. data/lib/fontisan/tables/sbix.rb +0 -1
  195. data/lib/fontisan/tables/svg.rb +0 -1
  196. data/lib/fontisan/tables/variation_common.rb +0 -1
  197. data/lib/fontisan/tables/vvar.rb +0 -3
  198. data/lib/fontisan/tables.rb +55 -0
  199. data/lib/fontisan/true_type_collection.rb +6 -14
  200. data/lib/fontisan/true_type_font.rb +8 -2
  201. data/lib/fontisan/true_type_font_extensions.rb +9 -9
  202. data/lib/fontisan/type1/afm_generator.rb +0 -4
  203. data/lib/fontisan/type1/conversion_options.rb +0 -2
  204. data/lib/fontisan/type1/encodings.rb +0 -2
  205. data/lib/fontisan/type1/generator.rb +0 -8
  206. data/lib/fontisan/type1/pfa_generator.rb +0 -3
  207. data/lib/fontisan/type1/pfb_generator.rb +0 -5
  208. data/lib/fontisan/type1/pfm_generator.rb +0 -4
  209. data/lib/fontisan/type1.rb +42 -69
  210. data/lib/fontisan/type1_font.rb +40 -11
  211. data/lib/fontisan/utilities/checksum_calculator.rb +0 -1
  212. data/lib/fontisan/utilities.rb +10 -0
  213. data/lib/fontisan/utils.rb +10 -0
  214. data/lib/fontisan/validation/collection_validator.rb +0 -2
  215. data/lib/fontisan/validation.rb +9 -0
  216. data/lib/fontisan/validators/basic_validator.rb +0 -2
  217. data/lib/fontisan/validators/font_book_validator.rb +0 -2
  218. data/lib/fontisan/validators/opentype_validator.rb +0 -2
  219. data/lib/fontisan/validators/profile_loader.rb +0 -5
  220. data/lib/fontisan/validators/validator.rb +0 -2
  221. data/lib/fontisan/validators/web_font_validator.rb +0 -2
  222. data/lib/fontisan/validators.rb +14 -0
  223. data/lib/fontisan/variable/delta_applicator.rb +0 -4
  224. data/lib/fontisan/variable/instancer.rb +0 -3
  225. data/lib/fontisan/variable/static_font_builder.rb +0 -3
  226. data/lib/fontisan/variable.rb +16 -0
  227. data/lib/fontisan/variation/blend_applier.rb +0 -2
  228. data/lib/fontisan/variation/cache.rb +0 -2
  229. data/lib/fontisan/variation/converter.rb +0 -3
  230. data/lib/fontisan/variation/data_extractor.rb +0 -2
  231. data/lib/fontisan/variation/delta_applier.rb +0 -5
  232. data/lib/fontisan/variation/inspector.rb +0 -1
  233. data/lib/fontisan/variation/instance_generator.rb +0 -6
  234. data/lib/fontisan/variation/instance_writer.rb +0 -5
  235. data/lib/fontisan/variation/metrics_adjuster.rb +0 -4
  236. data/lib/fontisan/variation/optimizer.rb +0 -3
  237. data/lib/fontisan/variation/parallel_generator.rb +0 -3
  238. data/lib/fontisan/variation/subsetter.rb +0 -4
  239. data/lib/fontisan/variation/tuple_variation_header.rb +0 -2
  240. data/lib/fontisan/variation/variable_svg_generator.rb +0 -3
  241. data/lib/fontisan/variation/variation_context.rb +0 -3
  242. data/lib/fontisan/variation/variation_preserver.rb +0 -3
  243. data/lib/fontisan/variation.rb +31 -0
  244. data/lib/fontisan/version.rb +1 -1
  245. data/lib/fontisan/woff2.rb +13 -0
  246. data/lib/fontisan/woff2_font.rb +31 -9
  247. data/lib/fontisan/woff_font.rb +31 -2
  248. data/lib/fontisan.rb +121 -196
  249. metadata +46 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42bca448396aff910f6d3c92ac31bfa68afdbb85b6f9217d996d73cdbb62af5c
4
- data.tar.gz: 8e3a5ad55f4c4ba9ac4430caa9447b07ef317840559b84b936cc57791470ee3b
3
+ metadata.gz: f84b59fae400f9db9dd05b2ddebce11bedb865138026f7a3a6d1b7ce0b3d8f2a
4
+ data.tar.gz: 563b27ed9dc91412fb83d7769a72a0d618109e3a6394236c7648524a60ad4fb6
5
5
  SHA512:
6
- metadata.gz: de88ca7106b4934b37c0060f76f41b7972c0092a798c860cbc37795357ffdbce11089ae556f461c490c1fdd43ab48bc97ba3f1d90687abfb95fbea14d42259a7
7
- data.tar.gz: 2aa4ccdca9901b1ce95eb442238530d86f24a52eae0e3eebfbd23470f3c614858b905adac85fa198fd6d3e8b66f3b6b762015575adff30bafbccd0c5c99115c7
6
+ metadata.gz: 7f2d94e40b9444414113ebf842a4a84e2188199829b4caf8b9e707bea6bca89c07b5e11fa04ba2f4aff1ce7ea658004385a5e2ae2ae4b4d4094d5bb90c4d5345
7
+ data.tar.gz: becf5ccba115f938caeb23d29e3cc0685edc9e0cb8452f8b1ed8b7e76cc8e742adcf3f9d1f5c8b1f01c1631fcb28a4ff2305068ce6b9677ef339d8f5fb4765b9
data/.rubocop.yml CHANGED
@@ -114,3 +114,9 @@ Layout/LineEndStringConcatenationIndentation:
114
114
  # Bitwise AND checks with != 0 are clearer for font bitmasks
115
115
  Style/BitwisePredicate:
116
116
  Enabled: false
117
+
118
+ # Allow short math-conventional parameter names in font geometry code.
119
+ # Point#x / Point#y are domain-standard coordinate names; renaming to
120
+ # x_coord/y_coord adds noise without aiding readers.
121
+ Naming/MethodParameterName:
122
+ AllowedNames: ["x", "y", "cp", "gid", "n"]
data/.rubocop_todo.yml CHANGED
@@ -1,68 +1,91 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-02 04:07:39 UTC using RuboCop version 1.86.1.
3
+ # on 2026-06-29 07:08:46 UTC using RuboCop version 1.86.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 1
10
- # This cop supports safe autocorrection (--autocorrect).
11
- Gemspec/RequireMFA:
12
- Exclude:
13
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
14
-
15
9
  # Offense count: 2
16
10
  Gemspec/RequiredRubyVersion:
17
11
  Exclude:
18
12
  - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
19
13
  - 'fontisan.gemspec'
20
14
 
21
- # Offense count: 1
15
+ # Offense count: 21
22
16
  # This cop supports safe autocorrection (--autocorrect).
23
- Layout/EmptyLines:
17
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
18
+ # SupportedStyles: with_first_argument, with_fixed_indentation
19
+ Layout/ArgumentAlignment:
20
+ Exclude:
21
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
22
+ - 'lib/fontisan/hints.rb'
23
+ - 'lib/fontisan/models.rb'
24
+ - 'lib/fontisan/pipeline.rb'
25
+ - 'lib/fontisan/pipeline/strategies.rb'
26
+ - 'lib/fontisan/tables.rb'
27
+ - 'lib/fontisan/tables/cff.rb'
28
+ - 'spec/fontisan/cldr/config_spec.rb'
29
+ - 'spec/fontisan/cldr/unicode_set_parser_spec.rb'
30
+ - 'spec/fontisan/cli/cldr_cli_spec.rb'
31
+
32
+ # Offense count: 2
33
+ # This cop supports safe autocorrection (--autocorrect).
34
+ # Configuration parameters: EnforcedStyleAlignWith.
35
+ # SupportedStylesAlignWith: either, start_of_block, start_of_line
36
+ Layout/BlockAlignment:
24
37
  Exclude:
25
- - 'lib/fontisan/loading_modes.rb'
38
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
39
+ - 'spec/fontisan/cldr/index_spec.rb'
26
40
 
27
- # Offense count: 4
41
+ # Offense count: 2
28
42
  # This cop supports safe autocorrection (--autocorrect).
29
- # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
30
- Layout/ExtraSpacing:
43
+ Layout/BlockEndNewline:
31
44
  Exclude:
32
- - 'docs/node_modules/speakingurl/lib/speakingurl-rails.rb'
33
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
45
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
46
+ - 'spec/fontisan/cldr/index_spec.rb'
34
47
 
35
- # Offense count: 1
48
+ # Offense count: 2
36
49
  # This cop supports safe autocorrection (--autocorrect).
37
- # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
38
- # SupportedHashRocketStyles: key, separator, table
39
- # SupportedColonStyles: key, separator, table
40
- # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
41
- Layout/HashAlignment:
50
+ Layout/EmptyLines:
42
51
  Exclude:
43
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
52
+ - 'lib/fontisan/cli.rb'
53
+
54
+ # Offense count: 4
55
+ # This cop supports safe autocorrection (--autocorrect).
56
+ # Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
57
+ # SupportedStylesAlignWith: start_of_line, relative_to_receiver
58
+ Layout/IndentationWidth:
59
+ Exclude:
60
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
61
+ - 'spec/fontisan/cldr/index_spec.rb'
44
62
 
45
- # Offense count: 1585
63
+ # Offense count: 1641
46
64
  # This cop supports safe autocorrection (--autocorrect).
47
65
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
48
66
  # URISchemes: http, https
49
67
  Layout/LineLength:
50
68
  Enabled: false
51
69
 
52
- # Offense count: 5
70
+ # Offense count: 21
53
71
  # This cop supports safe autocorrection (--autocorrect).
54
- # Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals.
55
- # SupportedStylesForExponentOperator: space, no_space
56
- # SupportedStylesForRationalLiterals: space, no_space
57
- Layout/SpaceAroundOperators:
58
- Exclude:
59
- - 'docs/node_modules/speakingurl/lib/speakingurl-rails.rb'
60
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
72
+ # Configuration parameters: AllowInHeredoc.
73
+ Layout/TrailingWhitespace:
74
+ Exclude:
75
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
76
+ - 'lib/fontisan/hints.rb'
77
+ - 'lib/fontisan/models.rb'
78
+ - 'lib/fontisan/pipeline.rb'
79
+ - 'lib/fontisan/pipeline/strategies.rb'
80
+ - 'lib/fontisan/tables.rb'
81
+ - 'lib/fontisan/tables/cff.rb'
82
+ - 'spec/fontisan/cldr/config_spec.rb'
83
+ - 'spec/fontisan/cldr/unicode_set_parser_spec.rb'
84
+ - 'spec/fontisan/cli/cldr_cli_spec.rb'
61
85
 
62
- # Offense count: 3
86
+ # Offense count: 2
63
87
  Lint/CopDirectiveSyntax:
64
88
  Exclude:
65
- - 'lib/fontisan/converters/woff_writer.rb'
66
89
  - 'lib/fontisan/woff2_font.rb'
67
90
  - 'spec/fontisan/variation/cache_spec.rb'
68
91
 
@@ -114,28 +137,18 @@ Lint/MissingSuper:
114
137
  - 'lib/fontisan/commands/validate_command.rb'
115
138
  - 'lib/fontisan/tables/cff2/table_builder.rb'
116
139
 
117
- # Offense count: 4
118
- # This cop supports safe autocorrection (--autocorrect).
119
- Lint/RedundantRequireStatement:
120
- Exclude:
121
- - 'lib/fontisan/commands/features_command.rb'
122
- - 'lib/fontisan/commands/scripts_command.rb'
123
- - 'lib/fontisan/loading_modes.rb'
124
- - 'lib/fontisan/variation/optimizer.rb'
125
-
126
140
  # Offense count: 1
127
141
  Lint/StructNewOverride:
128
142
  Exclude:
129
143
  - 'lib/fontisan/optimizers/pattern_analyzer.rb'
130
144
 
131
- # Offense count: 8
145
+ # Offense count: 7
132
146
  # This cop supports safe autocorrection (--autocorrect).
133
147
  # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
134
148
  # NotImplementedExceptions: NotImplementedError
135
149
  Lint/UnusedMethodArgument:
136
150
  Exclude:
137
151
  - 'lib/fontisan.rb'
138
- - 'lib/fontisan/font_loader.rb'
139
152
  - 'lib/fontisan/tables/cff2/private_dict_blend_handler.rb'
140
153
  - 'lib/fontisan/utilities/brotli_wrapper.rb'
141
154
  - 'lib/fontisan/variation/table_accessor.rb'
@@ -148,12 +161,12 @@ Lint/UselessConstantScoping:
148
161
  - 'lib/fontisan/conversion_options.rb'
149
162
  - 'lib/fontisan/type1/charstrings.rb'
150
163
 
151
- # Offense count: 549
164
+ # Offense count: 557
152
165
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
153
166
  Metrics/AbcSize:
154
167
  Enabled: false
155
168
 
156
- # Offense count: 33
169
+ # Offense count: 31
157
170
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
158
171
  # AllowedMethods: refine
159
172
  Metrics/BlockLength:
@@ -171,38 +184,32 @@ Metrics/CollectionLiteralLength:
171
184
  - 'lib/fontisan/type1/agl.rb'
172
185
  - 'lib/fontisan/type1/encodings.rb'
173
186
 
174
- # Offense count: 301
187
+ # Offense count: 308
175
188
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
176
189
  Metrics/CyclomaticComplexity:
177
190
  Enabled: false
178
191
 
179
- # Offense count: 842
192
+ # Offense count: 849
180
193
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
181
194
  Metrics/MethodLength:
182
195
  Max: 135
183
196
 
184
- # Offense count: 22
197
+ # Offense count: 24
185
198
  # Configuration parameters: CountKeywordArgs.
186
199
  Metrics/ParameterLists:
187
200
  Max: 39
188
201
  MaxOptionalParameters: 4
189
202
 
190
- # Offense count: 229
203
+ # Offense count: 231
191
204
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
192
205
  Metrics/PerceivedComplexity:
193
206
  Enabled: false
194
207
 
195
- # Offense count: 24
208
+ # Offense count: 166
196
209
  # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
197
210
  # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
198
211
  Naming/MethodParameterName:
199
- Exclude:
200
- - 'lib/fontisan/optimizers/subroutine_optimizer.rb'
201
- - 'lib/fontisan/tables/cff2/blend_operator.rb'
202
- - 'lib/fontisan/tables/glyf/curve_converter.rb'
203
- - 'lib/fontisan/type1/seac_expander.rb'
204
- - 'lib/fontisan/type1/ttf_to_type1_converter.rb'
205
- - 'lib/fontisan/variation/optimizer.rb'
212
+ Enabled: false
206
213
 
207
214
  # Offense count: 13
208
215
  # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
@@ -241,7 +248,7 @@ Naming/VariableName:
241
248
  - 'lib/fontisan/type1/pfm_generator.rb'
242
249
  - 'lib/fontisan/type1/pfm_parser.rb'
243
250
 
244
- # Offense count: 113
251
+ # Offense count: 111
245
252
  # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
246
253
  # SupportedStyles: snake_case, normalcase, non_integer
247
254
  # AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
@@ -264,7 +271,7 @@ RSpec/AnyInstance:
264
271
  RSpec/ContextWording:
265
272
  Enabled: false
266
273
 
267
- # Offense count: 27
274
+ # Offense count: 28
268
275
  # Configuration parameters: IgnoredMetadata.
269
276
  RSpec/DescribeClass:
270
277
  Enabled: false
@@ -280,7 +287,7 @@ RSpec/DescribeMethod:
280
287
  - 'spec/fontisan/type1/seac_expander_spec.rb'
281
288
  - 'spec/fontisan/type1_real_fonts_spec.rb'
282
289
 
283
- # Offense count: 1428
290
+ # Offense count: 1458
284
291
  # Configuration parameters: CountAsOne.
285
292
  RSpec/ExampleLength:
286
293
  Max: 66
@@ -357,11 +364,11 @@ RSpec/MultipleDescribes:
357
364
  - 'spec/fontisan/utils/thread_pool_spec.rb'
358
365
  - 'spec/fontisan/variation/cache_spec.rb'
359
366
 
360
- # Offense count: 1855
367
+ # Offense count: 1902
361
368
  RSpec/MultipleExpectations:
362
369
  Max: 19
363
370
 
364
- # Offense count: 152
371
+ # Offense count: 154
365
372
  # Configuration parameters: AllowSubject.
366
373
  RSpec/MultipleMemoizedHelpers:
367
374
  Max: 13
@@ -389,7 +396,7 @@ RSpec/RepeatedExample:
389
396
  - 'spec/fontisan/metrics_calculator_spec.rb'
390
397
  - 'spec/fontisan/tables/os2_spec.rb'
391
398
 
392
- # Offense count: 22
399
+ # Offense count: 23
393
400
  # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
394
401
  # SupportedInflectors: default, active_support
395
402
  RSpec/SpecFilePathFormat:
@@ -425,6 +432,18 @@ Security/Open:
425
432
  Exclude:
426
433
  - 'Rakefile'
427
434
 
435
+ # Offense count: 2
436
+ # This cop supports safe autocorrection (--autocorrect).
437
+ # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
438
+ # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
439
+ # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
440
+ # FunctionalMethods: let, let!, subject, watch
441
+ # AllowedMethods: lambda, proc, it
442
+ Style/BlockDelimiters:
443
+ Exclude:
444
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
445
+ - 'spec/fontisan/cldr/index_spec.rb'
446
+
428
447
  # Offense count: 6
429
448
  # This cop supports safe autocorrection (--autocorrect).
430
449
  Style/ComparableClamp:
@@ -442,13 +461,6 @@ Style/EmptyElse:
442
461
  Exclude:
443
462
  - 'lib/fontisan/type1/seac_expander.rb'
444
463
 
445
- # Offense count: 2
446
- # This cop supports safe autocorrection (--autocorrect).
447
- Style/ExpandPathArguments:
448
- Exclude:
449
- - 'docs/node_modules/speakingurl/lib/speakingurl-rails.rb'
450
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
451
-
452
464
  # Offense count: 11
453
465
  # This cop supports safe autocorrection (--autocorrect).
454
466
  # Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
@@ -466,14 +478,11 @@ Style/HashLikeCase:
466
478
  - 'lib/fontisan/commands/unpack_command.rb'
467
479
  - 'lib/fontisan/models/validation_report.rb'
468
480
 
469
- # Offense count: 1
481
+ # Offense count: 9
470
482
  # This cop supports safe autocorrection (--autocorrect).
471
- # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
472
- # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
473
- # SupportedShorthandSyntax: always, never, either, consistent, either_consistent
474
- Style/HashSyntax:
483
+ Style/MultilineIfModifier:
475
484
  Exclude:
476
- - 'docs/node_modules/speakingurl/lib/speakingurl-rails.rb'
485
+ - 'lib/fontisan/cldr/unicode_set_parser.rb'
477
486
 
478
487
  # Offense count: 1
479
488
  # Configuration parameters: AllowedMethods.
@@ -481,12 +490,3 @@ Style/HashSyntax:
481
490
  Style/OptionalBooleanParameter:
482
491
  Exclude:
483
492
  - 'lib/fontisan/conversion_options.rb'
484
-
485
- # Offense count: 7
486
- # This cop supports safe autocorrection (--autocorrect).
487
- # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
488
- # SupportedStyles: single_quotes, double_quotes
489
- Style/StringLiterals:
490
- Exclude:
491
- - 'docs/node_modules/speakingurl/lib/speakingurl-rails.rb'
492
- - 'docs/node_modules/speakingurl/speakingurl-rails.gemspec'
data/CHANGELOG.md CHANGED
@@ -7,7 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Added
10
+ ### Removed
11
+
12
+ - Audit subsystem (`Fontisan::Audit`, `Fontisan::Commands::Audit*`,
13
+ `Formatters::AuditTextRenderer` / `AuditDiffTextRenderer` /
14
+ `LibrarySummaryTextRenderer`, `Models::Audit::*`) — moved to ucode.
15
+ Never had external consumers.
16
+ - UCD/UCDXML subsystem (`Fontisan::Ucd`, `config/ucd.yml`) — moved to
17
+ ucode. Never released in a published gem version.
18
+ - `fontisan audit` and `fontisan ucd` CLI subcommands.
19
+
20
+ ### Added (documentation)
11
21
  - Comprehensive documentation for WOFF/WOFF2 format support
12
22
  - Color fonts documentation (COLR/CPAL, sbix, SVG tables)
13
23
  - Font validation framework documentation
@@ -16,7 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
26
  - Updated font hinting documentation
17
27
  - Enhanced README with all v0.2.1-v0.2.7 features
18
28
 
19
- ### Changed
29
+ ### Changed (documentation)
20
30
  - Improved documentation organization with dedicated feature guides
21
31
  - Added more examples for command-line and Ruby API usage
22
32
 
data/README.adoc CHANGED
@@ -61,6 +61,7 @@ Color fonts and collections::
61
61
  * Font collection validation with per-font reporting (see link:docs/COLLECTION_VALIDATION.adoc[Collection Validation Guide])
62
62
 
63
63
  Font analysis and information::
64
+ * Comprehensive per-face font metadata extraction (replaces `otfinfo`) covering identity, style, metrics, codepoint coverage, licensing, hinting, color capabilities, variable-font detail, and OpenType layout features
64
65
  * Bidirectional font hint conversion (see link:docs/FONT_HINTING.adoc[Font Hinting Guide])
65
66
  * Extract comprehensive font metadata (name, version, designer, license, etc.)
66
67
  * Brief mode for fast font indexing (5x faster, metadata-only loading)
@@ -99,11 +100,20 @@ Font engineering::
99
100
 
100
101
  Export and interfaces::
101
102
  * TTX/YAML/JSON export (complete)
102
- * Command-line interface with 18 commands
103
+ * Command-line interface with 19 commands
103
104
  * Ruby library API for programmatic access
104
105
  * Structured output in YAML, JSON, and text formats
105
106
 
106
107
 
108
+ == Font audit
109
+
110
+ [NOTE]
111
+ ====
112
+ The `audit` and `ucd` subsystems have moved to the `ucode` gem. See
113
+ the `ucode` documentation for the equivalent commands.
114
+ ====
115
+
116
+
107
117
  == Font information
108
118
 
109
119
  === General
@@ -2133,11 +2143,33 @@ Generating options (control how the output font is written):
2133
2143
  * `--optimize-tables` - Enable table optimization
2134
2144
  * `--decompose-on-output` - Decompose composites in output
2135
2145
 
2146
+ WOFF compression knobs (apply to `--to woff` only):
2147
+
2148
+ * `--zlib-level=N` - zlib level (0–9, default 6)
2149
+ * `--uncompressed` - store tables uncompressed (legal per WOFF 1.0 §5.1)
2150
+ * `--compression-threshold=N` - skip compression for tables smaller than N bytes
2151
+
2152
+ WOFF2 compression knobs (apply to `--to woff2` only):
2153
+
2154
+ * `--brotli-quality=N` - Brotli quality (0–11, default 11)
2155
+ * `--transform-tables` / `--no-transform-tables` - apply glyf/loca + hmtx transformations
2156
+
2157
+ The format selection (`--to woff` vs `--to woff2`) **is** the algorithm
2158
+ choice: WOFF mandates zlib, WOFF2 mandates Brotli. Passing a knob that
2159
+ doesn't apply to the requested target exits 1 with a clear error.
2160
+
2136
2161
  [source,shell]
2137
2162
  ----
2138
2163
  # Convert with autohinting and optimization
2139
2164
  fontisan convert font.ttf --to otf --output font.otf \
2140
2165
  --autohint --hinting-mode auto --optimize-tables
2166
+
2167
+ # Smallest WOFF2 (max Brotli + table transforms)
2168
+ fontisan convert font.ttf --to woff2 --output font.woff2 \
2169
+ --brotli-quality 11 --transform-tables
2170
+
2171
+ # WOFF for IE 9+ legacy reach (max zlib)
2172
+ fontisan convert font.ttf --to woff --output font.woff --zlib-level 9
2141
2173
  ----
2142
2174
 
2143
2175
  For detailed information on all available options and conversion scenarios,
@@ -2206,6 +2238,26 @@ tables = converter.convert(font, options: options)
2206
2238
  ====
2207
2239
 
2208
2240
 
2241
+ .One-shot conversion via Fontisan.convert
2242
+ [example]
2243
+ ====
2244
+ [source,ruby]
2245
+ ----
2246
+ require 'fontisan'
2247
+
2248
+ # TTF → WOFF2 (modern browsers)
2249
+ Fontisan.convert('font.ttf', to: :woff2, output: 'font.woff2',
2250
+ brotli_quality: 11, transform_tables: true)
2251
+
2252
+ # TTF → WOFF (IE 9+ legacy reach, max zlib)
2253
+ Fontisan.convert('font.ttf', to: :woff, output: 'font.woff', zlib_level: 9)
2254
+
2255
+ # WOFF stored uncompressed (legal per WOFF 1.0 §5.1; useful for tooling)
2256
+ Fontisan.convert('font.ttf', to: :woff, output: 'font.woff', uncompressed: true)
2257
+ ----
2258
+ ====
2259
+
2260
+
2209
2261
  == Round-Trip validation
2210
2262
 
2211
2263
  === General
@@ -1,4 +1,19 @@
1
- import { defineConfig } from "vitepress";
1
+ import { defineConfig, type HeadConfig } from "vitepress";
2
+
3
+ const SITE_ORIGIN = "https://www.fontist.org";
4
+ const BASE_PATH = "/fontisan/";
5
+ const DEFAULT_DESCRIPTION =
6
+ "The most comprehensive font processing library for Ruby — 100% Pure Ruby, no Python, no C++, no C# dependencies.";
7
+ const DEFAULT_OG_IMAGE = `${SITE_ORIGIN}/og-image.png`;
8
+
9
+ // Map a page's source path to its canonical public URL (origin + base + clean path).
10
+ function pathToUrl(relativePath: string): string {
11
+ const bare = relativePath.replace(/\.md$/, "").replace(/\\/g, "/");
12
+ if (bare === "index") return `${SITE_ORIGIN}${BASE_PATH}`;
13
+ if (bare.endsWith("/index"))
14
+ return `${SITE_ORIGIN}${BASE_PATH}${bare.slice(0, -6)}/`;
15
+ return `${SITE_ORIGIN}${BASE_PATH}${bare}`;
16
+ }
2
17
 
3
18
  // https://vitepress.dev/reference/site-config
4
19
  export default defineConfig({
@@ -7,12 +22,29 @@ export default defineConfig({
7
22
  // https://vitepress.dev/guide/routing#generating-clean-url
8
23
  cleanUrls: true,
9
24
 
25
+ // Exclude standalone guide stubs that collide with directory routes.
26
+ // Both guide/<name>.md and guide/<name>/index.md exist for these three
27
+ // (hinting, validation, conversion); the directory version is the canonical
28
+ // one (sidebar-linked, richer content). Excluding the standalone stub from
29
+ // the build resolves the duplicate-route collision while keeping the source
30
+ // files in the repo.
31
+ srcExclude: [
32
+ "guide/hinting.md",
33
+ "guide/validation.md",
34
+ "guide/conversion.md",
35
+ ],
36
+
10
37
  title: "Fontisan",
11
38
  description:
12
39
  "The most comprehensive font processing library for Ruby — 100% Pure Ruby, no Python, no C++, no C# dependencies.",
13
40
 
14
41
  lastUpdated: true,
15
42
 
43
+ // https://vitepress.dev/reference/site-config#sitemap
44
+ sitemap: {
45
+ hostname: SITE_ORIGIN,
46
+ },
47
+
16
48
  // Base path for deployment (e.g., /fontisan/ for fontist.org/fontisan/)
17
49
  base: process.env.BASE_PATH || "/fontisan/",
18
50
 
@@ -29,19 +61,40 @@ export default defineConfig({
29
61
  ],
30
62
  ["link", { rel: "manifest", href: "/site.webmanifest" }],
31
63
  ["meta", { property: "og:type", content: "website" }],
32
- ["meta", { property: "og:title", content: "Fontisan" }],
64
+ ["link", { rel: "preconnect", href: "https://fonts.googleapis.com" }],
65
+ ["link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "" }],
33
66
  [
34
- "meta",
67
+ "link",
35
68
  {
36
- property: "og:description",
37
- content:
38
- "The most comprehensive font processing library for Ruby — 100% Pure Ruby.",
69
+ rel: "stylesheet",
70
+ href: "https://fonts.googleapis.com/css2?family=Spectral:ital,opsz,wght@0,7..72,200..800;1,7..72,200..800&family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@300;400;500;600&display=swap",
39
71
  },
40
72
  ],
41
- ["meta", { property: "og:image", content: "/logo-full.svg" }],
42
- ["meta", { name: "twitter:card", content: "summary_large_image" }],
43
73
  ],
44
74
 
75
+ // Per-page og:* and twitter:* tags are derived from each page's frontmatter.
76
+ // https://vitepress.dev/reference/site-config#transformhead
77
+ transformHead(ctx) {
78
+ const { pageData } = ctx;
79
+ const url = pathToUrl(pageData.relativePath);
80
+ const title = pageData.title || "Fontisan";
81
+ const description = pageData.description || DEFAULT_DESCRIPTION;
82
+ const image = pageData.frontmatter.image || DEFAULT_OG_IMAGE;
83
+
84
+ const tags: HeadConfig[] = [
85
+ ["meta", { property: "og:title", content: title }],
86
+ ["meta", { property: "og:description", content: description }],
87
+ ["meta", { property: "og:url", content: url }],
88
+ ["meta", { property: "og:image", content: image }],
89
+ ["meta", { name: "twitter:card", content: "summary_large_image" }],
90
+ ["meta", { name: "twitter:title", content: title }],
91
+ ["meta", { name: "twitter:description", content: description }],
92
+ ["meta", { name: "twitter:image", content: image }],
93
+ ];
94
+
95
+ return tags;
96
+ },
97
+
45
98
  // https://vitepress.dev/reference/default-theme-config
46
99
  themeConfig: {
47
100
  logo: "/logo-full.svg",
@@ -210,6 +263,13 @@ export default defineConfig({
210
263
  { text: "Overview", link: "/cli/" },
211
264
  ],
212
265
  },
266
+ {
267
+ text: "Font Audit",
268
+ collapsed: true,
269
+ items: [
270
+ { text: "audit", link: "/cli/audit" },
271
+ ],
272
+ },
213
273
  {
214
274
  text: "Font Information",
215
275
  collapsed: true,