Class: LocoMotion::Icons::Scanner
- Inherits:
-
Object
- Object
- LocoMotion::Icons::Scanner
- Defined in:
- lib/loco_motion/icons/scanner.rb
Overview
Scans application source for static icon references so
loco_motion:icons:sync can vendor only the icons actually used — the
icon analogue of Tailwind scanning your templates for class names.
It is intentionally a plain regex scan (no Ruby evaluation), so it is
fully deterministic: the same source always yields the same set. It
recognizes the loco_icon helper and the universal
icon: / left_icon: / right_icon: / middle_icon: options, whether
the name is a string ("home") or a symbol (:home). The library and
variant come from the token itself — [library:]name[/variant] (see
Reference) — so a reference is self-contained and the
scan never has to guess from other arguments that may be on another line.
Like Tailwind, it cannot see dynamically-built names
(loco_icon("bars-#{n}"), icon: some_var) — those belong in
Configuration#icon_safelist.
Documentation text is not scanned: the body of a HAML filter block
(:markdown prose, :plain code samples inside doc_code, and
friends) is rendered as text, never executed as Ruby, so a backticked
icon: "home/solid" in a guide is not a usage. The exceptions are the
code filters (:ruby / :erb) and #{...} interpolation inside any
filter — both of those do execute and are scanned normally.
Constant Summary collapse
- HELPER =
The qualified token in a
loco_icon("foo")call. %r{\bloco_icon\s*\(?\s*(["'])([a-z0-9][a-z0-9:/-]*)\1}- KWARG =
A token passed via icon:/left_icon:/right_icon:/middle_icon: (also covers
loco_icon(icon: "foo")). Longest keys first soicondoes not win insideleft_icon. %r{\b(?:left_icon|right_icon|middle_icon|icon)\s*:\s*(["'])([a-z0-9][a-z0-9:/-]*)\1}- HELPER_SYMBOL =
The symbol forms —
loco_icon(:home)andicon: :home. A bare Ruby symbol can't contain-,/, or:, so these only ever name a single simple icon (tokens / hyphenated names must be strings). /\bloco_icon\s*\(?\s*:([a-z0-9][a-z0-9_]*)\b/- KWARG_SYMBOL =
/\b(?:left_icon|right_icon|middle_icon|icon)\s*:\s*:([a-z0-9][a-z0-9_]*)\b/- TEXT_FILTER =
A HAML filter header (
:markdown,:plain, ...) whose indented block is text, not code.:rubyand:erbblocks hold executable code, so they are excluded here and scanned like ordinary lines. /\A(\s*):(?!ruby\b|erb\b)\w+\s*\z/- INTERPOLATION =
An interpolated segment inside filter text — the one part of a filter block that executes as Ruby.
/\#\{([^}]*)\}/
Instance Method Summary collapse
-
#initialize(paths:, root:, default_library:) ⇒ Scanner
constructor
A new instance of Scanner.
-
#references ⇒ Array<Hash>
Unique references, each
{ library:, variant:, name: }(variantisnilwhen unspecified, meaning "the library's default"), sorted for stable output.
Constructor Details
Instance Method Details
#references ⇒ Array<Hash>
Returns Unique references, each
{ library:, variant:, name: } (variant is nil when unspecified,
meaning "the library's default"), sorted for stable output.
73 74 75 76 77 78 79 80 81 |
# File 'lib/loco_motion/icons/scanner.rb', line 73 def references refs = {} files.each do |file| each_reference(file) { |ref| refs[ref] ||= ref } end refs.values.sort_by { |r| [r[:library], r[:variant].to_s, r[:name]] } end |