Class: Fontico::Lockfile
- Inherits:
-
Object
- Object
- Fontico::Lockfile
- Defined in:
- lib/fontico/lockfile.rb
Overview
icons.lock pins two things that must never drift:
codepoints — append-only. Adding an icon must not renumber the others,
or every glyph in the built font moves and the committed
artifact churns whole-file on each addition. Codepoints of
removed icons are retired, never reissued.
bodies — the normalised SVG for each icon, so builds are
reproducible and run offline. The Iconify API serves
*latest*; without this an icon can change shape between
two builds of the same manifest.
Constant Summary collapse
- PUA_START =
0xE001- FORMAT =
1
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
- #body(name) ⇒ Object
- #codepoint_for(name) ⇒ Object
- #entry(name) ⇒ Object
- #fresh?(name, source) ⇒ Boolean
-
#initialize(path) ⇒ Lockfile
constructor
A new instance of Lockfile.
- #multicolor?(name) ⇒ Boolean
-
#retire_missing!(names) ⇒ Object
Names present in the lock but absent from the manifest keep their codepoint reserved so it is never handed to a different icon.
- #save! ⇒ Object
- #store(name, source:, body:, multicolor: false, warnings: []) ⇒ Object
-
#warnings(name) ⇒ Object
Replayed on cached builds so a hard failure keeps being reported until the source file is actually fixed.
Constructor Details
#initialize(path) ⇒ Lockfile
Returns a new instance of Lockfile.
24 25 26 27 28 29 30 |
# File 'lib/fontico/lockfile.rb', line 24 def initialize(path) @path = path data = File.exist?(path) ? (YAML.safe_load_file(path) || {}) : {} @codepoints = data["codepoints"] || {} @retired = data["retired"] || {} @entries = data["icons"] || {} end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
22 23 24 |
# File 'lib/fontico/lockfile.rb', line 22 def path @path end |
Instance Method Details
#body(name) ⇒ Object
62 |
# File 'lib/fontico/lockfile.rb', line 62 def body(name) = entry(name)&.fetch("body", nil) |
#codepoint_for(name) ⇒ Object
32 33 34 |
# File 'lib/fontico/lockfile.rb', line 32 def codepoint_for(name) @codepoints[name] ||= next_free end |
#entry(name) ⇒ Object
36 |
# File 'lib/fontico/lockfile.rb', line 36 def entry(name) = @entries[name] |
#fresh?(name, source) ⇒ Boolean
58 59 60 |
# File 'lib/fontico/lockfile.rb', line 58 def fresh?(name, source) entry(name)&.fetch("source", nil) == source && entry(name)["body"] end |
#multicolor?(name) ⇒ Boolean
63 |
# File 'lib/fontico/lockfile.rb', line 63 def multicolor?(name) = !!entry(name)&.fetch("multicolor", false) |
#retire_missing!(names) ⇒ Object
Names present in the lock but absent from the manifest keep their codepoint reserved so it is never handed to a different icon.
51 52 53 54 55 56 |
# File 'lib/fontico/lockfile.rb', line 51 def retire_missing!(names) (@codepoints.keys - names).each do |gone| @retired[gone] = @codepoints.delete(gone) @entries.delete(gone) end end |
#save! ⇒ Object
69 70 71 72 73 74 75 76 |
# File 'lib/fontico/lockfile.rb', line 69 def save! File.write(@path, { "format" => FORMAT, "codepoints" => @codepoints.sort.to_h, "retired" => @retired.sort.to_h, "icons" => @entries.sort.to_h }.to_yaml) end |
#store(name, source:, body:, multicolor: false, warnings: []) ⇒ Object
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/fontico/lockfile.rb', line 38 def store(name, source:, body:, multicolor: false, warnings: []) @entries[name] = { "source" => source, "digest" => Digest::SHA256.hexdigest(body)[0, 16], "multicolor" => multicolor, "warnings" => warnings, "body" => body } codepoint_for(name) end |
#warnings(name) ⇒ Object
Replayed on cached builds so a hard failure keeps being reported until the source file is actually fixed.
67 |
# File 'lib/fontico/lockfile.rb', line 67 def warnings(name) = entry(name)&.fetch("warnings", nil) || [] |