# frozen_string_literal: true
module Proscenium
module Phlex::ResolveCssModules
extend ActiveSupport::Concern
class_methods do
attr_accessor :side_load_cache
end
def before_template
self.class.side_load_cache ||= Set.new
super
end
# Resolve and side load any CSS modules in the "class" attributes, where a CSS module is a class
# name beginning with a `@`. The class name is resolved to a CSS module name based on the file
# system path of the Phlex class, and any CSS file is side loaded.
#
# For example, the following will side load the CSS module file at
# app/components/user/component.module.css, and add the CSS Module name `user_name` to the
#
.
#
# # app/components/user/component.rb
# class User::Component < Proscenium::Phlex
# def template
# div class: :@user_name do
# 'Joel Moss'
# end
# end
# end
#
# Additionally, any class name containing a `/` is resolved as a CSS module path. Allowing you
# to use the same syntax as a CSS module, but without the need to manually import the CSS file.
#
# For example, the following will side load the CSS module file at /lib/users.module.css, and
# add the CSS Module name `name` to the
.
#
# class User::Component < Proscenium::Phlex
# def template
# div class: '/lib/users@name' do
# 'Joel Moss'
# end
# end
# end
#
# The given class name should be underscored, and the resulting CSS module name will be
# `camelCased` with a lower case first character.
#
# @raise [Proscenium::CssModule::Resolver::NotFound] If a CSS module file is not found for the
# Phlex class file path.
def process_attributes(**attributes)
if attributes.key?(:class) && (attributes[:class] = tokens(attributes[:class])).include?('@')
resolver = CssModule::ClassNamesResolver.new(attributes[:class], path)
self.class.side_load_cache.merge resolver.stylesheets
attributes[:class] = resolver.class_names
end
attributes
end
def after_template
super
self.class.side_load_cache&.each { |path| SideLoad.append! path, :css }
end
end
end