Class: Ucode::Audit::Emitter::FaceDirectory

Inherits:
Object
  • Object
show all
Defined in:
lib/ucode/audit/emitter/face_directory.rb

Overview

Top-level Mode 2 orchestrator. Walks an AuditReport (or a list of reports for a collection, or a library summary) and emits the full directory tree per 03-directory-output-spec.md.

Owns the chunk-emitter composition: callers never touch IndexEmitter / BlockEmitter / etc. directly. The chunk emitters themselves stay single-purpose (one chunk kind each) and take an explicit face_dir Pathname — they don't know whether the face lives at output/font_audit/<label>/ or under a collection subdir.

Three entry points:

- {#emit_face}       — one standalone face
- {#emit_collection} — one TTC source (N sibling faces)
- {#emit_library}    — directory-mode (M face labels)

Idempotency is delegated to each chunk emitter via Repo::AtomicWrites; re-running the same audit produces zero writes on the second pass.

Instance Method Summary collapse

Constructor Details

#initialize(output_root:, verbose: false, with_glyphs: false, glyph_resolver: GlyphEmitter::DEFAULT_RESOLVER, database: nil, emit_browser: false, universal_set_root: nil, with_missing_glyph_pages: false) ⇒ FaceDirectory

Returns a new instance of FaceDirectory.

Parameters:

  • output_root (String, Pathname)

    top-level output root (e.g. "output"). The library root is <output_root>/font_audit.

  • verbose (Boolean) (defaults to: false)

    emit codepoints/.json per block

  • with_glyphs (Boolean) (defaults to: false)

    emit glyphs/U+XXXX.svg per covered cp

  • glyph_resolver (Proc(Integer) -) (defaults to: GlyphEmitter::DEFAULT_RESOLVER)

    String, nil] SVG source for GlyphEmitter; defaults to a proc that returns nil (no glyphs emitted). Replaced by the canonical 4-tier resolver (TODO 20) when ready.

  • database (Ucode::Database, nil) (defaults to: nil)

    baseline UCD lookup for CodepointEmitter enrichment

  • emit_browser (Boolean) (defaults to: false)

    also write the self-contained HTML browsers — <face_dir>/index.html per face and <library_root>/index.html for library mode. Default false.

  • universal_set_root (String, Pathname, nil) (defaults to: nil)

    root of a co-located universal-set build. When present and emit_browser: is true, the face browser advertises glyph paths in its overview JSON so missing-codepoint chips can render the universal-set glyph at runtime.

  • with_missing_glyph_pages (Boolean) (defaults to: false)

    emit one standalone <face_dir>/missing/<BLOCK>.html per touched block with missing codepoints. Requires emit_browser: and a reachable universal_set_root: (silently no-ops otherwise).



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ucode/audit/emitter/face_directory.rb', line 63

def initialize(output_root:, verbose: false, with_glyphs: false,
               glyph_resolver: GlyphEmitter::DEFAULT_RESOLVER,
               database: nil, emit_browser: false,
               universal_set_root: nil, with_missing_glyph_pages: false)
  @output_root = output_root
  @verbose = verbose
  @with_glyphs = with_glyphs
  @emit_browser = emit_browser
  @database = database
  @universal_set_root = universal_set_root
  @with_missing_glyph_pages = with_missing_glyph_pages
  @index_emitter = IndexEmitter.new
  @block_emitter = BlockEmitter.new
  @plane_emitter = PlaneEmitter.new
  @script_emitter = ScriptEmitter.new
  @codepoint_emitter = CodepointEmitter.new
  @glyph_emitter = GlyphEmitter.new(glyph_resolver: glyph_resolver)
  @collection_emitter = CollectionEmitter.new
  @library_emitter = LibraryEmitter.new
end

Instance Method Details

#emit_collection(source_label:, reports:) ⇒ Array<String>

Returns per-face subdirectory names.

Parameters:

Returns:

  • (Array<String>)

    per-face subdirectory names



94
95
96
97
# File 'lib/ucode/audit/emitter/face_directory.rb', line 94

def emit_collection(source_label:, reports:)
  @collection_emitter.emit(@output_root, source_label, reports,
                           face_directory: self)
end

#emit_collection_face(source_label:, face_index:, report:) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Hook called by CollectionEmitter to write one face under a collection root. Computes the per-face subdirectory name from the face_index so the source order is preserved on disk.

Parameters:

Returns:

  • (String)

    the per-face subdirectory name (e.g. "00-Mona")



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ucode/audit/emitter/face_directory.rb', line 119

def emit_collection_face(source_label:, face_index:, report:)
  face_label = format("%<idx>02d-%<label>s",
                      idx: face_index,
                      label: sanitize(report.postscript_name))
  emit_face_at(
    Paths.collection_face_dir(@output_root, source_label, face_index,
                              sanitize(report.postscript_name)),
    report,
  )
  face_label
end

#emit_face(label:, report:) ⇒ Pathname

Returns the per-face directory written.

Parameters:

Returns:

  • (Pathname)

    the per-face directory written



87
88
89
# File 'lib/ucode/audit/emitter/face_directory.rb', line 87

def emit_face(label:, report:)
  emit_face_at(Paths.face_dir(@output_root, label), report)
end

#emit_face_at(face_dir, report) ⇒ Pathname

Write one face's full chunk tree under an explicit face_dir.

Public entry point for callers that compute their own face_dir (e.g. Release::Emitter builds the release tree at <release_root>/audit/<slug>/<face>/). Callers that want the default library-mode layout should use #emit_face.

Parameters:

Returns:

  • (Pathname)

    the face directory written



141
142
143
144
145
146
147
148
149
150
# File 'lib/ucode/audit/emitter/face_directory.rb', line 141

def emit_face_at(face_dir, report)
  @index_emitter.emit(face_dir, report, universal_set_root: @universal_set_root)
  report.blocks.each { |b| @block_emitter.emit(face_dir, b) }
  report.plane_summaries.each { |p| @plane_emitter.emit(face_dir, p) }
  report.scripts.each { |s| @script_emitter.emit(face_dir, s) }
  emit_codepoints(face_dir, report) if @verbose
  emit_glyphs(face_dir, report)     if @with_glyphs
  emit_browsers(face_dir, report)   if @emit_browser
  face_dir
end

#emit_library(summary:) ⇒ Boolean

Returns true if library index was written.

Parameters:

Returns:

  • (Boolean)

    true if library index was written



101
102
103
104
105
106
107
108
# File 'lib/ucode/audit/emitter/face_directory.rb', line 101

def emit_library(summary:)
  summary.per_face_reports.each do |report|
    emit_face(label: face_label(report), report: report)
  end
  written = @library_emitter.emit(@output_root, summary)
  emit_library_browser(summary) if @emit_browser
  written
end