Class: Abqari::AssetPipeline
- Inherits:
-
Object
- Object
- Abqari::AssetPipeline
- Defined in:
- lib/abqari/asset_pipeline.rb
Constant Summary collapse
- OUTPUT_SUBDIR =
'assets'- HASH_LENGTH =
10- BUNDLE_LOGICAL =
'css/bundle.css'- THEME_NAME_RE =
A theme name is a directory name under themes/ and nothing more. The strict pattern is load-bearing: the name is joined into filesystem paths in several places (here, ArtifactWriter, Renderer), so without it
theme: ../somethingwalks and publishes arbitrary directories. Same containment class the symlink guards enforce. /\A[a-z0-9_-]+\z/.freeze
- MINIFY_KINDS =
Extensions that get minified before fingerprinting (production only — dev keeps sources readable for devtools).
{ '.css' => :css, '.js' => :js }.freeze
- NO_COMMON_THEMES =
Themes that bring their own structural CSS. Mirror of the
_head.html.erbconditional that skips_common.css. %w[bootstrap none].freeze
Instance Method Summary collapse
-
#initialize(site) ⇒ AssetPipeline
constructor
A new instance of AssetPipeline.
- #path_for(name) ⇒ Object
- #process ⇒ Object
- #theme_name ⇒ Object
-
#validate_theme! ⇒ Object
Fail fast — called at the top of Site#build, BEFORE the output dir is wiped, so a config typo aborts with one clear message instead of N per-page "Unknown asset: css/app.css" failures (or, for a traversal-shaped name, a walk of whatever the path resolves to).
Constructor Details
#initialize(site) ⇒ AssetPipeline
Returns a new instance of AssetPipeline.
25 26 27 28 29 |
# File 'lib/abqari/asset_pipeline.rb', line 25 def initialize(site) @site = site @paths = {} @sources = {} end |
Instance Method Details
#path_for(name) ⇒ Object
61 62 63 |
# File 'lib/abqari/asset_pipeline.rb', line 61 def path_for(name) @paths[name] || raise(ArgumentError, "Unknown asset: #{name}. Add it to app/assets/ or themes/#{theme_name}/.") end |
#process ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/abqari/asset_pipeline.rb', line 31 def process validate_theme! # Processing order matters — later passes overwrite earlier ones # on logical-path conflict (same filename). # # Within a category (theme vs app/assets), engine first, site # second — so a site can override a theme file or a structural # CSS asset just by dropping its own version at the same path. # # Between categories, themes lose to app/assets (preserving the # original semantic: `_common.css` and `site.css` win over # theme-bundled CSS on conflict). Hence the order: # 1. engine theme → 2. site theme # 3. engine assets → 4. site assets # # A theme's `public/` subtree is NOT an asset source — it's the # verbatim passthrough tree ArtifactWriter#copy_public ships to # the site root (e.g. the vendored Bootstrap dist). Walking it # here used to fingerprint ~700 KB of dead, unreferenced copies # into `_site/assets/public/`. [engine_theme_dir, site_theme_dir].uniq.each do |dir| process_dir(dir, skip_public: true) if dir && Dir.exist?(dir) end [engine_app_assets, site_app_assets].uniq.each do |dir| process_dir(dir) if dir && Dir.exist?(dir) end build_css_bundle end |
#theme_name ⇒ Object
65 66 67 |
# File 'lib/abqari/asset_pipeline.rb', line 65 def theme_name @site.config['theme'] || SiteConfig::DEFAULTS['theme'] end |
#validate_theme! ⇒ Object
Fail fast — called at the top of Site#build, BEFORE the output dir is wiped, so a config typo aborts with one clear message instead of N per-page "Unknown asset: css/app.css" failures (or, for a traversal-shaped name, a walk of whatever the path resolves to).
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/abqari/asset_pipeline.rb', line 74 def validate_theme! name = theme_name.to_s return if name == 'none' unless name.match?(THEME_NAME_RE) raise PathSafe::Error, "invalid theme name #{name.inspect}: must match #{THEME_NAME_RE.inspect} " \ "(lowercase letters, digits, '-', '_'), or 'none'" end unless Dir.exist?(File.join(@site.engine_root, 'themes', name)) || Dir.exist?(File.join(@site.site_root, 'themes', name)) raise "unknown theme #{name.inspect} — no themes/#{name}/ in the site or the engine. " \ "Available: #{available_theme_names.join(', ')}, or 'none'" end return if theme_app_css_candidates.any? { |f| File.file?(f) } raise "theme #{name.inspect} has no css/app.css — looked in " \ "themes/#{name}/css/ (site and engine) and app/assets/css/ (site). " \ 'Every theme needs one, even if empty; it anchors the CSS bundle.' end |