Class: Fontist::Import::Google::Models::Metadata

Inherits:
Lutaml::Model::Serializable
  • Object
show all
Defined in:
lib/fontist/import/google/models/metadata.rb

Overview

Rich domain model for Google Fonts metadata from METADATA.pb

This class represents complete font family metadata with:

  • Validation methods

  • Business logic for font classification

  • Query methods for font properties

  • Transformation methods for formula generation

Examples:

Basic usage

 = Metadata.new(name: "Roboto", designer: "Google")
.valid? # => true
.variable_font? # => false

With validation

 = Metadata.new(name: "")
.validate! # raises ValidationError

Loading from file

 = Metadata.from_file("/path/to/METADATA.pb")

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_content(content) ⇒ Metadata

Load metadata from content string

Parameters:

  • content (String)

    METADATA.pb file content

Returns:

Raises:

  • (ParseError)

    if content cannot be parsed



84
85
86
87
# File 'lib/fontist/import/google/models/metadata.rb', line 84

def self.from_content(content)
  unibuf_message = Unibuf.parse_textproto(content)
  MetadataAdapter.adapt(unibuf_message)
end

.from_file(file_path) ⇒ Metadata

Load metadata from METADATA.pb file

Parameters:

  • file_path (String)

    Path to METADATA.pb file

Returns:

Raises:

  • (ParseError)

    if file cannot be parsed



74
75
76
77
# File 'lib/fontist/import/google/models/metadata.rb', line 74

def self.from_file(file_path)
  unibuf_message = Unibuf.parse_textproto_file(file_path)
  MetadataAdapter.adapt(unibuf_message)
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Compare with another metadata object

Parameters:

  • other (Metadata)

    other metadata object

Returns:

  • (Boolean)

    true if same family



404
405
406
407
408
# File 'lib/fontist/import/google/models/metadata.rb', line 404

def ==(other)
  return false unless other.is_a?(Metadata)

  name == other.name && designer == other.designer
end

#axis_countInteger

Get number of variable font axes

Returns:

  • (Integer)

    count of axes (0 for static fonts)



193
194
195
# File 'lib/fontist/import/google/models/metadata.rb', line 193

def axis_count
  axes_array.count
end

#axis_tagsArray<String>

Get all variable font axis tags

Returns:

  • (Array<String>)

    array of axis tags (e.g., [“wght”, “wdth”])



179
180
181
# File 'lib/fontist/import/google/models/metadata.rb', line 179

def axis_tags
  axes_array.map(&:tag)
end

#bold_fontFontFileMetadata?

Get bold font

Returns:



260
261
262
# File 'lib/fontist/import/google/models/metadata.rb', line 260

def bold_font
  find_font(style: "normal", weight: 700)
end

#complete?Boolean

Check if metadata is complete (has all optional fields filled)

Returns:

  • (Boolean)

    true if has source, axes, languages, etc.



152
153
154
155
156
# File 'lib/fontist/import/google/models/metadata.rb', line 152

def complete?
  !source.nil? &&
    !subsets.nil? && !subsets.empty? &&
    (!variable_font? || !axes.nil?)
end

#filenamesArray<String>

Get all font filenames

Returns:

  • (Array<String>)

    array of font filenames



172
173
174
# File 'lib/fontist/import/google/models/metadata.rb', line 172

def filenames
  fonts_array.map(&:filename)
end

#find_axis(tag) ⇒ AxisMetadata?

Find axis by tag

Parameters:

  • tag (String)

    axis tag (e.g., “wght”, “wdth”)

Returns:



298
299
300
# File 'lib/fontist/import/google/models/metadata.rb', line 298

def find_axis(tag)
  axes_array.find { |a| a.tag == tag }
end

#find_font(style:, weight:) ⇒ FontFileMetadata?

Find font by style and weight

Parameters:

  • style (String)

    font style (“normal”, “italic”)

  • weight (Integer)

    font weight (100-900)

Returns:



246
247
248
# File 'lib/fontist/import/google/models/metadata.rb', line 246

def find_font(style:, weight:)
  fonts_array.find { |f| f.style == style && f.weight == weight }
end

#font_countInteger

Get number of font files

Returns:

  • (Integer)

    count of font files



186
187
188
# File 'lib/fontist/import/google/models/metadata.rb', line 186

def font_count
  fonts_array.count
end

#font_stylesArray<String>

Get all font styles

Returns:

  • (Array<String>)

    unique font styles



274
275
276
# File 'lib/fontist/import/google/models/metadata.rb', line 274

def font_styles
  fonts_array.map(&:style).uniq
end

#font_weightsArray<Integer>

Get all font weights

Returns:

  • (Array<Integer>)

    unique font weights



281
282
283
# File 'lib/fontist/import/google/models/metadata.rb', line 281

def font_weights
  fonts_array.map(&:weight).uniq.sort
end

#has_italics?Boolean

Check if has italic variants

Returns:

  • (Boolean)

    true if has any italic fonts



288
289
290
# File 'lib/fontist/import/google/models/metadata.rb', line 288

def has_italics?
  fonts_array.any? { |f| f.style == "italic" }
end

#has_registry_overrides?Boolean

Check if has registry overrides

Returns:

  • (Boolean)

    true if has any overrides



357
358
359
# File 'lib/fontist/import/google/models/metadata.rb', line 357

def has_registry_overrides?
  !registry_default_overrides.nil? && !registry_default_overrides.empty?
end

#hashInteger

Hash code for using as hash key

Returns:

  • (Integer)

    hash code



413
414
415
# File 'lib/fontist/import/google/models/metadata.rb', line 413

def hash
  [name, designer].hash
end

#italic_fontFontFileMetadata?

Get italic font

Returns:



267
268
269
# File 'lib/fontist/import/google/models/metadata.rb', line 267

def italic_font
  find_font(style: "italic", weight: 400)
end

#language_countInteger

Get number of supported languages

Returns:

  • (Integer)

    count of languages



200
201
202
# File 'lib/fontist/import/google/models/metadata.rb', line 200

def language_count
  languages_array.count
end

#license_nameString

Get license name

Returns:

  • (String)

    human-readable license name



230
231
232
233
234
235
236
237
# File 'lib/fontist/import/google/models/metadata.rb', line 230

def license_name
  case license
  when "OFL" then "SIL Open Font License"
  when "APACHE" then "Apache License 2.0"
  when "UFL" then "Ubuntu Font License"
  else license
  end
end

#minimal?Boolean

Check if metadata is minimal (only required fields)

Returns:

  • (Boolean)

    true if only has required fields



161
162
163
164
165
# File 'lib/fontist/import/google/models/metadata.rb', line 161

def minimal?
  source.nil? &&
    (subsets.nil? || subsets.empty?) &&
    (languages.nil? || languages.empty?)
end

#noto_font?Boolean

Check if font is a Noto font

Returns:

  • (Boolean)

    true if is_noto flag is set or name starts with “Noto”



145
146
147
# File 'lib/fontist/import/google/models/metadata.rb', line 145

def noto_font?
  is_noto == true || name&.start_with?("Noto")
end

#open_license?Boolean

Check if license is open source

Returns:

  • (Boolean)

    true if OFL or Apache license



216
217
218
# File 'lib/fontist/import/google/models/metadata.rb', line 216

def open_license?
  %w[OFL APACHE].include?(license)
end

#registry_override(axis_tag) ⇒ Float?

Get registry default override for axis

Parameters:

  • axis_tag (String)

    axis tag

Returns:

  • (Float, nil)

    override value or nil



348
349
350
351
352
# File 'lib/fontist/import/google/models/metadata.rb', line 348

def registry_override(axis_tag)
  return nil unless registry_default_overrides

  registry_default_overrides[axis_tag]
end

#regular_fontFontFileMetadata?

Get regular/normal font

Returns:



253
254
255
# File 'lib/fontist/import/google/models/metadata.rb', line 253

def regular_font
  find_font(style: "normal", weight: 400)
end

#requires_license_agreement?Boolean

Check if license requires acceptance

Returns:

  • (Boolean)

    true if UFL or other non-open license



223
224
225
# File 'lib/fontist/import/google/models/metadata.rb', line 223

def requires_license_agreement?
  !open_license?
end

#slant_axisAxisMetadata?

Get slant axis

Returns:



319
320
321
# File 'lib/fontist/import/google/models/metadata.rb', line 319

def slant_axis
  find_axis("slnt")
end

#static_font?Boolean

Check if this is a static font

Returns:

  • (Boolean)

    true if has no variable font axes



138
139
140
# File 'lib/fontist/import/google/models/metadata.rb', line 138

def static_font?
  !variable_font?
end

#subset_countInteger

Get number of supported subsets

Returns:

  • (Integer)

    count of subsets



207
208
209
# File 'lib/fontist/import/google/models/metadata.rb', line 207

def subset_count
  subsets_array.count
end

#to_formula_hashHash

Convert to hash for formula generation

Returns:

  • (Hash)

    hash representation suitable for formulas



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/fontist/import/google/models/metadata.rb', line 366

def to_formula_hash
  {
    name: name,
    designer: designer,
    license: license,
    license_url: source&.repository_url,
    open_license: open_license?,
    category: category,
    date_added: date_added,
    fonts: fonts_array.map(&:to_h),
    subsets: subsets_array,
    axes: axes_array.map(&:to_h),
    source: source&.to_h,
    registry_default_overrides: registry_default_overrides,
    languages: languages_array,
    primary_script: primary_script,
  }
end

#to_sString

Convert to display format

Returns:

  • (String)

    human-readable representation



388
389
390
391
392
393
394
395
396
# File 'lib/fontist/import/google/models/metadata.rb', line 388

def to_s
  parts = ["#{name} by #{designer}"]
  parts << "(Variable Font)" if variable_font?
  parts << "(Noto)" if noto_font?
  parts << "- #{font_count} files"
  parts << "- #{axis_count} axes" if variable_font?
  parts << "- #{language_count} languages" if language_count.positive?
  parts.join(" ")
end

#valid?Boolean

Check if metadata is valid

Returns:

  • (Boolean)

    true if valid, false otherwise



105
106
107
# File 'lib/fontist/import/google/models/metadata.rb', line 105

def valid?
  validation_errors.empty?
end

#validate!true

Validate metadata completeness and correctness

Returns:

  • (true)

    if valid

Raises:



95
96
97
98
99
100
# File 'lib/fontist/import/google/models/metadata.rb', line 95

def validate!
  errors = validation_errors
  raise ValidationError, errors.join(", ") unless errors.empty?

  true
end

#validation_errorsArray<String>

Get all validation errors

Returns:

  • (Array<String>)

    array of error messages



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/fontist/import/google/models/metadata.rb', line 112

def validation_errors
  errors = []
  errors << "name is required" if name.nil? || name.empty?
  errors << "designer is required" if designer.nil? || designer.empty?
  errors << "license is required" if license.nil? || license.empty?
  errors << "category is required" if category.nil? || category.empty?
  errors << "date_added is required" if date_added.nil? || date_added.empty?
  errors << "at least one font file is required" if fonts.nil? || fonts_array.empty?
  errors << "invalid license type" unless valid_license?
  errors << "invalid category" unless valid_category?
  errors << "invalid date format" unless valid_date_format?
  errors
end

#variable_font?Boolean

Check if this is a variable font

Returns:

  • (Boolean)

    true if has variable font axes



131
132
133
# File 'lib/fontist/import/google/models/metadata.rb', line 131

def variable_font?
  !axes.nil? && !axes_array.empty?
end

#variable_slant?Boolean

Check if has slant/italic axis

Returns:

  • (Boolean)

    true if has slnt axis



340
341
342
# File 'lib/fontist/import/google/models/metadata.rb', line 340

def variable_slant?
  !slant_axis.nil?
end

#variable_weight?Boolean

Check if has weight axis

Returns:

  • (Boolean)

    true if has wght axis



326
327
328
# File 'lib/fontist/import/google/models/metadata.rb', line 326

def variable_weight?
  !weight_axis.nil?
end

#variable_width?Boolean

Check if has width axis

Returns:

  • (Boolean)

    true if has wdth axis



333
334
335
# File 'lib/fontist/import/google/models/metadata.rb', line 333

def variable_width?
  !width_axis.nil?
end

#weight_axisAxisMetadata?

Get weight axis

Returns:



305
306
307
# File 'lib/fontist/import/google/models/metadata.rb', line 305

def weight_axis
  find_axis("wght")
end

#width_axisAxisMetadata?

Get width axis

Returns:



312
313
314
# File 'lib/fontist/import/google/models/metadata.rb', line 312

def width_axis
  find_axis("wdth")
end