DEV: Let themes extend color definitions (#10429)

Themes can now declare custom colors that get compiled in core's color definitions stylesheet, thus allowing themes to better support dark/light color schemes. 

For example, if you need your theme to use tertiary for an element in a light color scheme and quaternary in a dark scheme, you can add the following SCSS to your theme's `color_definitions.scss` file: 

```
:root {
  --mytheme-tertiary-or-quaternary: #{dark-light-choose($tertiary, $quaternary)};
}
```

And then use the `--mytheme-tertiary-or-quaternary` variable as the color property of that element. You can also use this file to add color variables that use SCSS color transformation functions (lighten, darken, saturate, etc.) without compromising your theme's compatibility with different color schemes.
This commit is contained in:
Penar Musaraj
2020-08-18 13:02:13 -04:00
committed by GitHub
parent 16e7744ab5
commit 882b0aac19
15 changed files with 101 additions and 37 deletions

View File

@ -23,6 +23,10 @@ class Stylesheet::Manager
cache.hash.keys.select { |k| k =~ /theme/ }.each { |k| cache.delete(k) }
end
def self.clear_color_scheme_cache!
cache.hash.keys.select { |k| k =~ /color_definitions/ }.each { |k| cache.delete(k) }
end
def self.clear_core_cache!(targets)
cache.hash.keys.select { |k| k =~ /#{targets.join('|')}/ }.each { |k| cache.delete(k) }
end
@ -94,13 +98,14 @@ class Stylesheet::Manager
end
def self.color_scheme_stylesheet_details(color_scheme_id = nil, media, theme_id)
theme_id = theme_id || SiteSetting.default_theme_id
color_scheme = begin
ColorScheme.find(color_scheme_id)
rescue
# don't load fallback when requesting dark color scheme
return false if media != "all"
theme_id = theme_id || SiteSetting.default_theme_id
Theme.find_by_id(theme_id)&.color_scheme || ColorScheme.base
end
@ -108,13 +113,14 @@ class Stylesheet::Manager
target = COLOR_SCHEME_STYLESHEET.to_sym
current_hostname = Discourse.current_hostname
cache_key = color_scheme_cache_key(color_scheme)
cache_key = color_scheme_cache_key(color_scheme, theme_id)
stylesheets = cache[cache_key]
return stylesheets if stylesheets.present?
stylesheet = { color_scheme_id: color_scheme&.id }
builder = self.new(target, nil, color_scheme)
builder = self.new(target, theme_id, color_scheme)
builder.compile unless File.exists?(builder.stylesheet_fullpath)
href = builder.stylesheet_path(current_hostname)
@ -132,20 +138,16 @@ class Stylesheet::Manager
%[<link href="#{href}" media="#{media}" rel="stylesheet"/>].html_safe
end
def self.color_scheme_cache_key(color_scheme)
def self.color_scheme_cache_key(color_scheme, theme_id = nil)
color_scheme_name = Slug.for(color_scheme.name) + color_scheme&.id.to_s
"#{COLOR_SCHEME_STYLESHEET}_#{color_scheme_name}_#{Discourse.current_hostname}"
end
def self.color_scheme_cache_clear(color_scheme)
cache_key = color_scheme_cache_key(color_scheme)
cache[cache_key] = nil
theme_string = theme_id ? "_theme#{theme_id}" : ""
"#{COLOR_SCHEME_STYLESHEET}_#{color_scheme_name}#{theme_string}_#{Discourse.current_hostname}"
end
def self.precompile_css
themes = Theme.where('user_selectable OR id = ?', SiteSetting.default_theme_id).pluck(:id, :name)
themes = Theme.where('user_selectable OR id = ?', SiteSetting.default_theme_id).pluck(:id, :name, :color_scheme_id)
themes << nil
themes.each do |id, name|
themes.each do |id, name, color_scheme_id|
[:desktop, :mobile, :desktop_rtl, :mobile_rtl, :desktop_theme, :mobile_theme, :admin].each do |target|
theme_id = id || SiteSetting.default_theme_id
next if target =~ THEME_REGEX && theme_id == -1
@ -156,17 +158,13 @@ class Stylesheet::Manager
builder.compile(force: true)
cache[cache_key] = nil
end
end
cs_ids = Theme.where('user_selectable OR id = ?', SiteSetting.default_theme_id).pluck(:color_scheme_id)
ColorScheme.where(id: cs_ids).each do |cs|
target = COLOR_SCHEME_STYLESHEET
STDERR.puts "precompile target: #{target} #{cs.name}"
scheme = ColorScheme.find_by_id(color_scheme_id) || ColorScheme.base
STDERR.puts "precompile target: #{COLOR_SCHEME_STYLESHEET} #{name} (#{scheme.name})"
builder = self.new(target, nil, cs)
builder = self.new(COLOR_SCHEME_STYLESHEET, id, scheme)
builder.compile(force: true)
cache_key = color_scheme_cache_key(cs)
cache[cache_key] = nil
clear_color_scheme_cache!
end
nil
@ -349,8 +347,6 @@ class Stylesheet::Manager
end
def theme_digest
scss = ""
if [:mobile_theme, :desktop_theme].include?(@target)
scss_digest = theme.resolve_baked_field(:common, :scss)
scss_digest += theme.resolve_baked_field(@target.to_s.sub("_theme", ""), :scss)
@ -401,7 +397,8 @@ class Stylesheet::Manager
category_updated = Category.where("uploaded_background_id IS NOT NULL").pluck(:updated_at).map(&:to_i).sum
if cs || category_updated > 0
Digest::SHA1.hexdigest "#{RailsMultisite::ConnectionManagement.current_db}-#{cs&.id}-#{cs&.version}-#{Stylesheet::Manager.last_file_updated}-#{category_updated}"
theme_color_defs = theme&.resolve_baked_field(:common, :color_definitions)
Digest::SHA1.hexdigest "#{RailsMultisite::ConnectionManagement.current_db}-#{cs&.id}-#{cs&.version}-#{theme_color_defs}-#{Stylesheet::Manager.last_file_updated}-#{category_updated}"
else
digest_string = "defaults-#{Stylesheet::Manager.last_file_updated}"