Module: RubyUIAdmin::TailwindSource
- Defined in:
- lib/ruby_ui_admin/tailwind_source.rb
Overview
Extracts the Tailwind class candidates used by the admin's Phlex views into a single file the
host app can @source from its Tailwind build. This solves the "gem path changes per
environment" problem: instead of pointing @source at the gem's .rb files (whose absolute
path differs between dev/CI/deploy), the host writes the class inventory into its OWN tree (a
stable, relative path) and re-runs on upgrade. It scans the same literals Tailwind would, so the
generated utilities match the previous @source "<gem>/**/*.rb" approach.
Driven by rake ruby_ui_admin:tailwind_source.
Constant Summary collapse
- VIEWS_GLOB =
"app/components/ruby_ui_admin/**/*.rb"
Class Method Summary collapse
-
.class_candidates ⇒ Object
All class candidates across the engine's view files, deduped and sorted.
-
.class_token?(token) ⇒ Boolean
Heuristic: a Tailwind utility candidate.
-
.extract(ruby_source) ⇒ Object
Pulls Tailwind-ish class tokens out of a chunk of Ruby source: every double-quoted string literal (and heredoc
CLASSESbody) is split into tokens, with#{…}interpolations dropped so the literal fragments around them survive. -
.html ⇒ Object
The scannable file body (valid HTML so any Tailwind extractor picks it up).
-
.write(dest) ⇒ Object
Writes the inventory to
destand returns the path.
Class Method Details
.class_candidates ⇒ Object
All class candidates across the engine's view files, deduped and sorted.
20 21 22 23 24 |
# File 'lib/ruby_ui_admin/tailwind_source.rb', line 20 def class_candidates Dir[RubyUIAdmin::Engine.root.join(VIEWS_GLOB)].sort .flat_map { |file| extract(File.read(file)) } .uniq.sort end |
.class_token?(token) ⇒ Boolean
Heuristic: a Tailwind utility candidate. Must start with a letter (optionally !/- for
important/negative) and may carry variants/values (hover:, /10, [356px]). Requiring a
letter start drops embedded SVG path coordinates (e.g. 0-7.07l-1.72), which start with a
digit and would otherwise be scanned as junk — no real Tailwind utility starts with a digit.
46 47 48 |
# File 'lib/ruby_ui_admin/tailwind_source.rb', line 46 def class_token?(token) token.match?(%r{\A!?-?[a-z][a-z0-9:_/\[\]().,%#-]*\z}) end |
.extract(ruby_source) ⇒ Object
Pulls Tailwind-ish class tokens out of a chunk of Ruby source: every double-quoted string
literal (and heredoc CLASSES body) is split into tokens, with #{…} interpolations dropped
so the literal fragments around them survive. Non-class words are filtered out by
class_token?. Only double quotes are scanned — the views write every class: with them, and
scanning single quotes would let stray apostrophes in comments span across real code.
31 32 33 34 35 36 37 38 39 40 |
# File 'lib/ruby_ui_admin/tailwind_source.rb', line 31 def extract(ruby_source) strings = ruby_source.scan(/"([^"]*)"/).flatten strings += ruby_source.scan(/<<~?CLASSES\n(.*?)\n\s*CLASSES/m).flatten strings .map { |string| string.gsub(/#\{[^}]*\}/, " ") } .flat_map { |string| string.split(/\s+/) } .select { |token| class_token?(token) } .uniq end |
.html ⇒ Object
The scannable file body (valid HTML so any Tailwind extractor picks it up).
51 52 53 54 55 56 |
# File 'lib/ruby_ui_admin/tailwind_source.rb', line 51 def html <<~HTML <!-- Generated by `rake ruby_ui_admin:tailwind_source`. Do not edit — re-run after upgrading ruby_ui_admin. --> <div class="#{class_candidates.join(" ")}"></div> HTML end |
.write(dest) ⇒ Object
Writes the inventory to dest and returns the path.
59 60 61 62 63 |
# File 'lib/ruby_ui_admin/tailwind_source.rb', line 59 def write(dest) FileUtils.mkdir_p(File.dirname(dest)) File.write(dest, html) dest end |