fontist 3.0.28 → 3.0.30

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +148 -0
  3. data/fontist.gemspec +4 -3
  4. data/lib/fontist/cache/store.rb +13 -6
  5. data/lib/fontist/cli.rb +106 -6
  6. data/lib/fontist/css/google_family.rb +50 -0
  7. data/lib/fontist/css/local.rb +157 -0
  8. data/lib/fontist/css/styles.rb +79 -0
  9. data/lib/fontist/css.rb +110 -0
  10. data/lib/fontist/errors.rb +3 -0
  11. data/lib/fontist/font_file.rb +2 -1
  12. data/lib/fontist/font_finder.rb +15 -2
  13. data/lib/fontist/font_installer.rb +97 -94
  14. data/lib/fontist/font_operations/convert.rb +55 -0
  15. data/lib/fontist/font_operations/extract.rb +53 -0
  16. data/lib/fontist/font_operations/instance.rb +92 -0
  17. data/lib/fontist/font_operations/pack.rb +49 -0
  18. data/lib/fontist/font_operations/subset.rb +68 -0
  19. data/lib/fontist/font_operations.rb +25 -0
  20. data/lib/fontist/format_spec.rb +35 -0
  21. data/lib/fontist/formula.rb +33 -5
  22. data/lib/fontist/formula_picker.rb +27 -8
  23. data/lib/fontist/from_file_cache.rb +4 -0
  24. data/lib/fontist/helpers.rb +1 -1
  25. data/lib/fontist/import/convert_formulas.rb +1 -1
  26. data/lib/fontist/import/google/data_sources/base.rb +3 -3
  27. data/lib/fontist/import/google/data_sources/github.rb +28 -0
  28. data/lib/fontist/import/google/formula_builders/formula_builder_v5.rb +30 -57
  29. data/lib/fontist/import/google/models/font_family.rb +7 -4
  30. data/lib/fontist/import/google/variable_font_source.rb +105 -0
  31. data/lib/fontist/import/google.rb +1 -0
  32. data/lib/fontist/import/helpers/hash_helper.rb +1 -1
  33. data/lib/fontist/import/sil_importer.rb +18 -5
  34. data/lib/fontist/import/v4_to_v5_migrator.rb +1 -1
  35. data/lib/fontist/import/windows.rb +13 -2
  36. data/lib/fontist/import_cli.rb +19 -0
  37. data/lib/fontist/index_cli.rb +1 -1
  38. data/lib/fontist/indexes/index_mixin.rb +4 -4
  39. data/lib/fontist/json.rb +76 -0
  40. data/lib/fontist/manifest.rb +63 -0
  41. data/lib/fontist/resource.rb +6 -1
  42. data/lib/fontist/validate_cli.rb +1 -1
  43. data/lib/fontist/version.rb +1 -1
  44. data/lib/fontist/yaml_backend.rb +18 -5
  45. data/lib/fontist.rb +3 -0
  46. metadata +17 -19
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fontist
4
+ module Import
5
+ module Google
6
+ # The real variable font files of a family as published in the
7
+ # google/fonts repository (METADATA.pb `fonts` entries whose filename
8
+ # carries an axis list, e.g. "Roboto[wdth,wght].ttf").
9
+ #
10
+ # The Google Fonts API only serves static per-weight instances, so these
11
+ # files are the only genuine variable sources. Google publishes them as
12
+ # TTF only.
13
+ class VariableFontSource
14
+ RAW_BASE = "https://raw.githubusercontent.com/google/fonts"
15
+ AXIS_LIST = /\[([^\]]+)\]/
16
+
17
+ attr_reader :directory, :commit, :files, :axes
18
+
19
+ # @param directory [String] repo-relative family dir, e.g. "ofl/roboto"
20
+ # @param commit [String] google/fonts commit SHA the URLs are pinned to
21
+ # @param files [Array<Models::FontFileMetadata>] METADATA.pb fonts
22
+ # @param axes [Array<Models::AxisMetadata>] METADATA.pb axes
23
+ def self.from_metadata(metadata, directory:, commit:)
24
+ files = Array(metadata.fonts).select do |font|
25
+ font.filename.to_s.match?(AXIS_LIST)
26
+ end
27
+ return nil if files.empty? || commit.to_s.empty?
28
+
29
+ new(directory: directory, commit: commit, files: files,
30
+ axes: Array(metadata.axes))
31
+ end
32
+
33
+ def initialize(directory:, commit:, files:, axes:)
34
+ @directory = directory
35
+ @commit = commit
36
+ @files = files
37
+ @axes = axes
38
+ end
39
+
40
+ def urls
41
+ files.map { |file| url_for(file.filename) }
42
+ end
43
+
44
+ # Axis tags in METADATA.pb order, limited to those the files carry.
45
+ def axis_tags
46
+ present = files.flat_map { |file| tags_in(file.filename) }.uniq
47
+ declared = axes.map(&:tag)
48
+ (declared & present) + (present - declared)
49
+ end
50
+
51
+ # Resource entry for a v5 formula (TTF only).
52
+ def resource(family_name)
53
+ {
54
+ "source" => "google",
55
+ "family" => family_name,
56
+ "files" => urls,
57
+ "urls" => urls,
58
+ "format" => "ttf",
59
+ "variable_axes" => axis_tags,
60
+ }
61
+ end
62
+
63
+ # One style per variable file, described by METADATA.pb.
64
+ def styles
65
+ files.map { |file| style_for(file) }
66
+ end
67
+
68
+ private
69
+
70
+ def style_for(file)
71
+ names_of(file).merge(
72
+ "font" => file.filename,
73
+ "formats" => ["ttf"],
74
+ "variable_font" => true,
75
+ "variable_axes" => tags_in(file.filename),
76
+ "source_resource" => "ttf_variable",
77
+ ).compact
78
+ end
79
+
80
+ def names_of(file)
81
+ {
82
+ "family_name" => file.name,
83
+ "type" => file.style.to_s == "italic" ? "Italic" : "Regular",
84
+ "full_name" => file.full_name,
85
+ "post_script_name" => file.post_script_name,
86
+ "copyright" => file.copyright,
87
+ }
88
+ end
89
+
90
+ def tags_in(filename)
91
+ filename[AXIS_LIST, 1].to_s.split(",")
92
+ end
93
+
94
+ def url_for(filename)
95
+ # Brackets stay literal: the installer matches style files against
96
+ # the URL basename, which must equal the downloaded file name.
97
+ encoded = filename.gsub(/[^A-Za-z0-9._,\-\[\]]/) do |char|
98
+ char.bytes.map { |b| format("%%%02X", b) }.join
99
+ end
100
+ "#{RAW_BASE}/#{commit}/#{directory}/#{encoded}"
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -7,6 +7,7 @@ module Fontist
7
7
  autoload :MetadataAdapter, "#{__dir__}/google/metadata_adapter"
8
8
  autoload :MetadataParser, "#{__dir__}/google/metadata_parser"
9
9
  autoload :Models, "#{__dir__}/google/models"
10
+ autoload :VariableFontSource, "#{__dir__}/google/variable_font_source"
10
11
 
11
12
  DEFAULT_MAX_COUNT = 100
12
13
 
@@ -4,7 +4,7 @@ module Fontist
4
4
  module HashHelper
5
5
  class << self
6
6
  def stringify_keys(hash)
7
- JSON.parse(hash.to_json)
7
+ Fontist::JSON.parse(Fontist::JSON.dump(hash))
8
8
  end
9
9
  end
10
10
  end
@@ -5,6 +5,9 @@ module Fontist
5
5
  module Import
6
6
  class SilImporter
7
7
  ROOT = "https://software.sil.org/fonts/".freeze
8
+ CARD_LINK_SELECTOR = "a.inner-card".freeze
9
+ CARD_TITLE_SELECTOR = ".title-text".freeze
10
+ LEGACY_LINK_SELECTOR = "table.products div.title > a".freeze
8
11
 
9
12
  def initialize(options = {})
10
13
  @output_path = options[:output_path]
@@ -99,7 +102,7 @@ module Fontist
99
102
  end
100
103
 
101
104
  def process_single_font(link, current, total)
102
- family_name = link.content
105
+ family_name = link_name(link)
103
106
 
104
107
  # Display progress
105
108
  ImportDisplay.progress(current, total, family_name) if @verbose
@@ -257,7 +260,8 @@ module Fontist
257
260
  end
258
261
 
259
262
  def empty_result
260
- { successful: 0, failed: 0, errors: [], duration: 0 }
263
+ { successful: 0, failed: 0, errors: [], duration: 0,
264
+ no_fonts_found: true }
261
265
  end
262
266
 
263
267
  def build_results(duration)
@@ -274,12 +278,21 @@ module Fontist
274
278
  def font_links
275
279
  html = URI.parse(ROOT).open("User-Agent" => Fontist::Utils::UserAgent.random_user_agent).read
276
280
  document = Nokogiri::HTML.parse(html)
277
- document.css("table.products div.title > a")
281
+ links = document.css(CARD_LINK_SELECTOR)
282
+ links = document.css(LEGACY_LINK_SELECTOR) if links.empty?
283
+ links
284
+ end
285
+
286
+ # Font name of a product link. Cards on the current site also carry a
287
+ # description, so the name is taken from the card title only.
288
+ def link_name(link)
289
+ title = link.at_css(CARD_TITLE_SELECTOR)
290
+ (title || link).text.strip
278
291
  end
279
292
 
280
293
  def filter_by_name(links)
281
294
  links.select do |link|
282
- link.content.downcase.include?(@font_name.downcase)
295
+ link_name(link).downcase.include?(@font_name.downcase)
283
296
  end
284
297
  end
285
298
 
@@ -342,7 +355,7 @@ module Fontist
342
355
  end
343
356
 
344
357
  def find_archive_url_by_page_link(link)
345
- family_name = link.content
358
+ family_name = link_name(link)
346
359
 
347
360
  # Skip known index pages that just link to other fonts
348
361
  if index_page?(family_name)
@@ -95,7 +95,7 @@ module Fontist
95
95
  def load_yaml_without_aliases(path)
96
96
  data = YAML.safe_load(File.read(path), aliases: true,
97
97
  permitted_classes: [Date])
98
- JSON.parse(JSON.generate(data))
98
+ Fontist::JSON.parse(Fontist::JSON.dump(data))
99
99
  end
100
100
 
101
101
  def file_has_yaml_aliases?(path)
@@ -53,7 +53,7 @@ module Fontist
53
53
  def base_attrs(description)
54
54
  {
55
55
  schema_version: 5,
56
- name: description,
56
+ name: formula_name(description),
57
57
  description: "#{description} for Windows",
58
58
  homepage: HOMEPAGE,
59
59
  platforms: ["windows"],
@@ -119,7 +119,7 @@ module Fontist
119
119
  end
120
120
 
121
121
  def formula_path(description)
122
- filename = "#{normalize_key(description)}.yml"
122
+ filename = "#{formula_key(description)}.yml"
123
123
  formula_dir.join(filename)
124
124
  end
125
125
 
@@ -135,6 +135,17 @@ module Fontist
135
135
  end
136
136
  end
137
137
 
138
+ # Formula names keep to letters, digits and spaces, so the file key the
139
+ # formulas repository derives from them (lowercase, spaces as
140
+ # underscores) needs no shell escaping in its CI.
141
+ def formula_name(description)
142
+ description.tr("-", " ").delete("^A-Za-z0-9 ").squeeze(" ").strip
143
+ end
144
+
145
+ def formula_key(description)
146
+ formula_name(description).downcase.tr(" ", "_")
147
+ end
148
+
138
149
  def normalize_key(name)
139
150
  name.downcase.gsub(/[^a-z0-9]+/, "_").gsub(/^_|_$/, "")
140
151
  end
@@ -122,6 +122,24 @@ module Fontist
122
122
  CLI::STATUS_UNKNOWN_ERROR
123
123
  end
124
124
 
125
+ desc "windows", "Import Windows font extension packs (Features on Demand)"
126
+ option :output_path,
127
+ type: :string,
128
+ desc: "Output directory for generated formulas " \
129
+ "(default: formulas/windows)"
130
+
131
+ def windows
132
+ handle_class_options(options)
133
+ require_relative "import/windows"
134
+
135
+ Import::Windows.new(formulas_dir: options[:output_path]).call
136
+
137
+ CLI::STATUS_SUCCESS
138
+ rescue StandardError => e
139
+ Fontist.ui.error("Import error: #{e.message}")
140
+ CLI::STATUS_UNKNOWN_ERROR
141
+ end
142
+
125
143
  desc "sil", "Import formulas from SIL International"
126
144
  option :output_path,
127
145
  type: :string,
@@ -158,6 +176,7 @@ module Fontist
158
176
  )
159
177
 
160
178
  result = importer.call
179
+ return CLI::STATUS_UNKNOWN_ERROR if result[:no_fonts_found]
161
180
 
162
181
  # Report results only in non-verbose mode (verbose mode already has rich summary)
163
182
  unless options[:verbose]
@@ -205,7 +205,7 @@ module Fontist
205
205
  case options[:format].downcase
206
206
  when "json"
207
207
  require "json"
208
- puts JSON.pretty_generate(fonts_data)
208
+ puts Fontist::JSON.pretty(fonts_data)
209
209
  when "yaml"
210
210
  require "yaml"
211
211
  puts YAML.dump(fonts_data)
@@ -103,13 +103,13 @@ module Fontist
103
103
  return entries if entries
104
104
 
105
105
  parse_sidecar_entries(sidecar_path)
106
- rescue JSON::ParserError, TypeError
106
+ rescue Fontist::JSON::ParseError, TypeError
107
107
  nil
108
108
  end
109
109
 
110
110
  def rebuild_sidecar_entries
111
111
  entries_hash = from_file(path).entries_hash
112
- File.write("#{path}.json", JSON.dump("entries" => entries_hash))
112
+ File.write("#{path}.json", Fontist::JSON.dump("entries" => entries_hash))
113
113
  entries_hash
114
114
  end
115
115
 
@@ -135,7 +135,7 @@ module Fontist
135
135
  # as read-only
136
136
  def parse_sidecar_entries(sidecar_path)
137
137
  mtime = File.mtime(sidecar_path)
138
- entries = JSON.parse(File.read(sidecar_path))["entries"]
138
+ entries = Fontist::JSON.parse(File.read(sidecar_path))["entries"]
139
139
 
140
140
  sidecar_cache_mutex.synchronize do
141
141
  sidecar_cache[sidecar_path] = { mtime: mtime, entries: entries }
@@ -244,7 +244,7 @@ module Fontist
244
244
 
245
245
  def write_lookup_sidecar(file_path)
246
246
  File.write("#{file_path}.json",
247
- JSON.dump("entries" => entries_hash))
247
+ Fontist::JSON.dump("entries" => entries_hash))
248
248
  end
249
249
 
250
250
  # key -> formula paths, in the sidecar's JSON-friendly shape
@@ -0,0 +1,76 @@
1
+ require "yeptris"
2
+ require "yeptris/json"
3
+
4
+ module Fontist
5
+ # JSON encoding and decoding through yeptris's native engine, replacing
6
+ # the json gem as fontist's JSON backend. The yeptris parser and
7
+ # generator produce and accept the same plain Ruby structures as the
8
+ # json gem (string keys, arrays, scalars), so this module is a
9
+ # drop-in surface; call sites rescue the module's error classes
10
+ # instead of JSON::ParserError and JSON::GeneratorError.
11
+ module JSON
12
+ class Error < StandardError; end
13
+ class ParseError < Error; end
14
+ class DumpError < Error; end
15
+
16
+ class << self
17
+ def parse(source)
18
+ unless source.is_a?(String)
19
+ raise ParseError,
20
+ "cannot parse #{source.class}"
21
+ end
22
+
23
+ Yeptris::JSON.load(source)
24
+ rescue Yeptris::Error, TypeError => e
25
+ raise ParseError, e.message
26
+ end
27
+
28
+ def dump(object)
29
+ Yeptris::JSON.dump(object)
30
+ rescue Yeptris::Error, TypeError => e
31
+ raise DumpError, e.message
32
+ end
33
+
34
+ # Two-space-indented JSON for human-facing CLI output; yeptris's
35
+ # generator is compact-only, so the indentation is applied here
36
+ def pretty(object)
37
+ pretty_value(object, 0)
38
+ end
39
+
40
+ private
41
+
42
+ def pretty_value(value, depth)
43
+ case value
44
+ when Hash then pretty_object(value, depth)
45
+ when Array then pretty_array(value, depth)
46
+ else dump(value)
47
+ end
48
+ end
49
+
50
+ def pretty_object(hash, depth)
51
+ return "{}" if hash.empty?
52
+
53
+ inner = hash.map do |key, value|
54
+ "#{indent(depth + 1)}#{dump(key.to_s)}: #{pretty_value(value,
55
+ depth + 1)}"
56
+ end
57
+
58
+ "{\n#{inner.join(",\n")}\n#{indent(depth)}}"
59
+ end
60
+
61
+ def pretty_array(array, depth)
62
+ return "[]" if array.empty?
63
+
64
+ inner = array.map do |value|
65
+ "#{indent(depth + 1)}#{pretty_value(value, depth + 1)}"
66
+ end
67
+
68
+ "[\n#{inner.join(",\n")}\n#{indent(depth)}]"
69
+ end
70
+
71
+ def indent(depth)
72
+ " " * depth
73
+ end
74
+ end
75
+ end
76
+ end
@@ -18,6 +18,12 @@ module Fontist
18
18
  # Collection options
19
19
  attribute :collection_index, :integer
20
20
 
21
+ # Font operations (subsetting, conversion failure handling)
22
+ attribute :subset_unicodes, :string
23
+ attribute :subset_text, :string
24
+ attribute :fallback_to_original, :boolean, default: false
25
+ attribute :instance, :string
26
+
21
27
  # Build FormatSpec from attributes
22
28
  def format_spec
23
29
  FormatSpec.new(
@@ -27,6 +33,10 @@ module Fontist
27
33
  transcode_path: transcode_path,
28
34
  keep_original: keep_original,
29
35
  collection_index: collection_index,
36
+ subset_unicodes: subset_unicodes,
37
+ subset_text: subset_text,
38
+ fallback_to_original: fallback_to_original,
39
+ instance: instance,
30
40
  )
31
41
  end
32
42
 
@@ -129,6 +139,57 @@ module Fontist
129
139
  }
130
140
  end
131
141
 
142
+ # Font options a manifest entry can carry next to its styles:
143
+ #
144
+ # Roboto:
145
+ # styles: [Regular, Bold]
146
+ # format: woff2
147
+ #
148
+ # The plain form `Roboto: [Regular, Bold]` stays valid.
149
+ FONT_OPTIONS = %w[format variable_axes prefer_variable transcode_path
150
+ keep_original collection_index subset_unicodes
151
+ subset_text fallback_to_original instance].freeze
152
+
153
+ def self.from_yaml(content, options = {})
154
+ data = YAML.safe_load(content)
155
+ return super unless data.is_a?(Hash) && data.values.any?(Hash)
156
+
157
+ plain, font_options = split_font_options(data)
158
+ super(plain.to_yaml, options).tap do |manifest|
159
+ manifest.apply_font_options(font_options)
160
+ end
161
+ end
162
+
163
+ def self.split_font_options(data)
164
+ font_options = {}
165
+ plain = data.to_h do |name, value|
166
+ next [name, value] unless value.is_a?(Hash)
167
+
168
+ font_options[name] = font_options_of(name, value)
169
+ [name, value["styles"] || value[:styles]]
170
+ end
171
+ [plain, font_options]
172
+ end
173
+
174
+ def self.font_options_of(name, value)
175
+ value = value.transform_keys(&:to_s)
176
+ unknown = value.keys - FONT_OPTIONS - ["styles"]
177
+ unless unknown.empty?
178
+ raise Fontist::Errors::ManifestCouldNotBeReadError,
179
+ "Unknown option(s) for '#{name}': #{unknown.join(', ')}"
180
+ end
181
+
182
+ value.slice(*FONT_OPTIONS)
183
+ end
184
+
185
+ def apply_font_options(font_options)
186
+ Array(fonts).each do |font|
187
+ font_options.fetch(font.name, {}).each do |key, value|
188
+ font.public_send(:"#{key}=", value)
189
+ end
190
+ end
191
+ end
192
+
132
193
  def self.from_file(path, locations: false)
133
194
  Fontist.ui.debug("Manifest: #{path}")
134
195
 
@@ -159,8 +220,10 @@ module Fontist
159
220
 
160
221
  def self.from_hash(data, options = {})
161
222
  locations = options.delete(:locations) || false
223
+ data, font_options = split_font_options(data) if data.is_a?(Hash)
162
224
 
163
225
  model = super
226
+ model.apply_font_options(font_options) if font_options
164
227
 
165
228
  # Use performance optimizations for faster manifest compilation
166
229
  with_performance_optimizations do
@@ -6,7 +6,12 @@ module Fontist
6
6
  attribute :name, :string
7
7
  attribute :source, :string
8
8
  attribute :urls, :string, collection: true
9
- attribute :sha256, :string, collection: true
9
+ # Declared scalar: the corpus writes one digest per resource almost
10
+ # everywhere, and consumers render it verbatim. A handful of
11
+ # resources pair one digest with each mirror URL and write a list;
12
+ # a scalar-typed attribute keeps both forms as written instead of
13
+ # normalizing every single digest into a one-element Array.
14
+ attribute :sha256, :string
10
15
  attribute :file_size, :integer
11
16
  attribute :family, :string
12
17
  attribute :files, :string, collection: true
@@ -189,7 +189,7 @@ module Fontist
189
189
 
190
190
  def output_json_report(report, output_file)
191
191
  require "json"
192
- json_content = JSON.pretty_generate(report.to_hash)
192
+ json_content = Fontist::JSON.pretty(report.to_hash)
193
193
 
194
194
  if output_file
195
195
  File.write(output_file, json_content)
@@ -1,3 +1,3 @@
1
1
  module Fontist
2
- VERSION = "3.0.28".freeze
2
+ VERSION = "3.0.30".freeze
3
3
  end
@@ -14,13 +14,26 @@ module Fontist
14
14
  ENABLED_VALUE = "yeptris"
15
15
 
16
16
  class << self
17
- # Returns the activated adapter class, or nil when the standard
18
- # engine stays in place (flag unset, or yeptris unavailable)
17
+ # Pins the YAML adapter explicitly: lutaml-model auto-selects
18
+ # yeptris for a format whenever the yeptris gem is in the bundle,
19
+ # which would silently switch YAML parsing and dumping (and its
20
+ # line-wrap behavior) for every model in the process. The yeptris
21
+ # YAML engine activates only when explicitly enabled with
22
+ # FONTIST_YAML=yeptris; otherwise the standard Psych engine is
23
+ # pinned, because the yeptris x86_64-linux and Windows builds
24
+ # currently mis-parse some plain scalars as single-element Arrays
25
+ # (leptris/yeptris#863). Flip the default once that parity fix
26
+ # lands.
27
+ #
28
+ # Returns the activated adapter class.
19
29
  def activate!
20
- return nil unless enabled?
21
- return nil unless yeptris_available?
30
+ adapter =
31
+ if enabled? && yeptris_available?
32
+ Yaml::YeptrisAdapter
33
+ else
34
+ Lutaml::Yaml::Adapter::StandardAdapter
35
+ end
22
36
 
23
- adapter = Yaml::YeptrisAdapter
24
37
  Lutaml::Model::AdapterResolver.set_adapter_class(:yaml, adapter)
25
38
 
26
39
  adapter
data/lib/fontist.rb CHANGED
@@ -17,6 +17,8 @@ require_relative "fontist/yaml_backend"
17
17
  module Fontist
18
18
  # Core classes
19
19
  autoload :Config, "#{__dir__}/fontist/config"
20
+ autoload :Css, "#{__dir__}/fontist/css"
21
+ autoload :JSON, "#{__dir__}/fontist/json"
20
22
  autoload :Font, "#{__dir__}/fontist/font"
21
23
  autoload :FontCollection, "#{__dir__}/fontist/font_collection"
22
24
  autoload :FontFile, "#{__dir__}/fontist/font_file"
@@ -25,6 +27,7 @@ module Fontist
25
27
  autoload :FontPath, "#{__dir__}/fontist/font_path"
26
28
  autoload :FontStyle, "#{__dir__}/fontist/font_style"
27
29
  autoload :Fontconfig, "#{__dir__}/fontist/fontconfig"
30
+ autoload :FontOperations, "#{__dir__}/fontist/font_operations"
28
31
  autoload :FormatSpec, "#{__dir__}/fontist/format_spec"
29
32
  autoload :Formula, "#{__dir__}/fontist/formula"
30
33
  autoload :FormulaCollection, "#{__dir__}/fontist/formula"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fontist
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.28
4
+ version: 3.0.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: '0.4'
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: 0.4.9
56
+ version: 0.4.47
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
@@ -63,7 +63,7 @@ dependencies:
63
63
  version: '0.4'
64
64
  - - ">="
65
65
  - !ruby/object:Gem::Version
66
- version: 0.4.9
66
+ version: 0.4.47
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: fuzzy_match
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -92,20 +92,6 @@ dependencies:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
94
  version: '6.0'
95
- - !ruby/object:Gem::Dependency
96
- name: json
97
- requirement: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - "~>"
100
- - !ruby/object:Gem::Version
101
- version: '2.0'
102
- type: :runtime
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - "~>"
107
- - !ruby/object:Gem::Version
108
- version: '2.0'
109
95
  - !ruby/object:Gem::Dependency
110
96
  name: lutaml-model
111
97
  requirement: !ruby/object:Gem::Requirement
@@ -154,14 +140,14 @@ dependencies:
154
140
  requirements:
155
141
  - - "~>"
156
142
  - !ruby/object:Gem::Version
157
- version: '4.0'
143
+ version: '10.0'
158
144
  type: :runtime
159
145
  prerelease: false
160
146
  version_requirements: !ruby/object:Gem::Requirement
161
147
  requirements:
162
148
  - - "~>"
163
149
  - !ruby/object:Gem::Version
164
- version: '4.0'
150
+ version: '10.0'
165
151
  - !ruby/object:Gem::Dependency
166
152
  name: paint
167
153
  requirement: !ruby/object:Gem::Requirement
@@ -357,6 +343,10 @@ files:
357
343
  - lib/fontist/collection_file.rb
358
344
  - lib/fontist/config.rb
359
345
  - lib/fontist/config_cli.rb
346
+ - lib/fontist/css.rb
347
+ - lib/fontist/css/google_family.rb
348
+ - lib/fontist/css/local.rb
349
+ - lib/fontist/css/styles.rb
360
350
  - lib/fontist/errors.rb
361
351
  - lib/fontist/exclude.yml
362
352
  - lib/fontist/extract.rb
@@ -366,6 +356,12 @@ files:
366
356
  - lib/fontist/font_finder.rb
367
357
  - lib/fontist/font_installer.rb
368
358
  - lib/fontist/font_model.rb
359
+ - lib/fontist/font_operations.rb
360
+ - lib/fontist/font_operations/convert.rb
361
+ - lib/fontist/font_operations/extract.rb
362
+ - lib/fontist/font_operations/instance.rb
363
+ - lib/fontist/font_operations/pack.rb
364
+ - lib/fontist/font_operations/subset.rb
369
365
  - lib/fontist/font_path.rb
370
366
  - lib/fontist/font_style.rb
371
367
  - lib/fontist/fontconfig.rb
@@ -414,6 +410,7 @@ files:
414
410
  - lib/fontist/import/google/models/font_variant.rb
415
411
  - lib/fontist/import/google/models/metadata.rb
416
412
  - lib/fontist/import/google/models/source_metadata.rb
413
+ - lib/fontist/import/google/variable_font_source.rb
417
414
  - lib/fontist/import/google_fonts_importer.rb
418
415
  - lib/fontist/import/google_import.rb
419
416
  - lib/fontist/import/helpers.rb
@@ -462,6 +459,7 @@ files:
462
459
  - lib/fontist/install_locations/fontist_location.rb
463
460
  - lib/fontist/install_locations/system_location.rb
464
461
  - lib/fontist/install_locations/user_location.rb
462
+ - lib/fontist/json.rb
465
463
  - lib/fontist/macos.rb
466
464
  - lib/fontist/macos/catalog.rb
467
465
  - lib/fontist/macos/catalog/asset.rb