mirror of
https://github.com/discourse/discourse.git
synced 2024-12-02 01:53:43 +08:00
6e522e4aad
This PR is a major change to Sass compilation in Discourse. The new version of sass-ruby moves to dart-sass putting we back on the supported version of Sass. It does so while keeping compatibility with the existing method signatures, so minimal change is needed in Discourse for this change. This moves us From: - sassc 2.0.1 (Feb 2019) - libsass 3.5.2 (May 2018) To: - dart-sass 1.58 This update applies the following breaking changes: > > These breaking changes are coming soon or have recently been released: > > [Functions are stricter about which units they allow](https://sass-lang.com/documentation/breaking-changes/function-units) beginning in Dart Sass 1.32.0. > > [Selectors with invalid combinators are invalid](https://sass-lang.com/documentation/breaking-changes/bogus-combinators) beginning in Dart Sass 1.54.0. > > [/ is changing from a division operation to a list separator](https://sass-lang.com/documentation/breaking-changes/slash-div) beginning in Dart Sass 1.33.0. > > [Parsing the special syntax of @-moz-document will be invalid](https://sass-lang.com/documentation/breaking-changes/moz-document) beginning in Dart Sass 1.7.2. > > [Compound selectors could not be extended](https://sass-lang.com/documentation/breaking-changes/extend-compound) in Dart Sass 1.0.0 and Ruby Sass 4.0.0. SCSS files have been migrated automatically using `sass-migrator division app/assets/stylesheets/**/*.scss`
225 lines
7.0 KiB
Ruby
225 lines
7.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "stylesheet/compiler"
|
|
|
|
RSpec.describe Stylesheet::Compiler do
|
|
describe "compilation" do
|
|
Dir["#{Rails.root.join("app/assets/stylesheets")}/*.scss"].each do |path|
|
|
next if path =~ /ember_cli/
|
|
|
|
path = File.basename(path, ".scss")
|
|
|
|
it "can compile '#{path}' css" do
|
|
css, _map = Stylesheet::Compiler.compile_asset(path)
|
|
expect(css.length).to be > 500
|
|
end
|
|
end
|
|
end
|
|
|
|
context "with a theme" do
|
|
let!(:theme) { Fabricate(:theme) }
|
|
let!(:upload) do
|
|
UploadCreator.new(file_from_fixtures("logo.png"), "logo.png").create_for(
|
|
Discourse.system_user.id,
|
|
)
|
|
end
|
|
let!(:upload_theme_field) do
|
|
ThemeField.create!(
|
|
theme: theme,
|
|
target_id: 0,
|
|
name: "primary",
|
|
upload: upload,
|
|
value: "",
|
|
type_id: ThemeField.types[:theme_upload_var],
|
|
)
|
|
end
|
|
let!(:stylesheet_theme_field) do
|
|
ThemeField.create!(
|
|
theme: theme,
|
|
target_id: 0,
|
|
name: "scss",
|
|
value: "body { background: $primary }",
|
|
type_id: ThemeField.types[:scss],
|
|
)
|
|
end
|
|
before { stylesheet_theme_field.save! }
|
|
|
|
it "theme stylesheet should be able to access theme asset variables" do
|
|
css, _map =
|
|
Stylesheet::Compiler.compile_asset(
|
|
"desktop_theme",
|
|
theme_id: theme.id,
|
|
theme_variables: theme.scss_variables,
|
|
)
|
|
expect(css).to include(upload.url)
|
|
end
|
|
|
|
context "with a plugin" do
|
|
let :plugin1 do
|
|
plugin1 = Plugin::Instance.new
|
|
plugin1.path = "#{Rails.root}/spec/fixtures/plugins/my_plugin/plugin.rb"
|
|
plugin1.register_css "body { background: $primary }"
|
|
plugin1
|
|
end
|
|
|
|
let :plugin2 do
|
|
plugin2 = Plugin::Instance.new
|
|
plugin2.path = "#{Rails.root}/spec/fixtures/plugins/scss_plugin/plugin.rb"
|
|
plugin2
|
|
end
|
|
|
|
before do
|
|
Discourse.plugins << plugin1
|
|
Discourse.plugins << plugin2
|
|
plugin1.activate!
|
|
plugin2.activate!
|
|
Stylesheet::Importer.register_imports!
|
|
end
|
|
|
|
after do
|
|
Discourse.plugins.delete plugin1
|
|
Discourse.plugins.delete plugin2
|
|
Stylesheet::Importer.register_imports!
|
|
DiscoursePluginRegistry.reset!
|
|
end
|
|
|
|
it "does not include theme variables in plugins" do
|
|
css, _map = Stylesheet::Compiler.compile_asset("my_plugin", theme_id: theme.id)
|
|
expect(css).not_to include(upload.url)
|
|
expect(css).to include("background:")
|
|
end
|
|
|
|
it "supports SCSS imports" do
|
|
css, _map = Stylesheet::Compiler.compile_asset("scss_plugin", theme_id: theme.id)
|
|
|
|
expect(css).to include("border-color:red")
|
|
expect(css).to include("fill:green")
|
|
expect(css).to include("line-height:1.2em")
|
|
expect(css).to include("border-color:#c00")
|
|
end
|
|
end
|
|
end
|
|
|
|
it "supports absolute-image-url" do
|
|
scss = Stylesheet::Importer.new({}).prepended_scss
|
|
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
|
|
css, _map = Stylesheet::Compiler.compile(scss, "test.scss")
|
|
|
|
expect(css).to include('url("http://test.localhost/images/favicons/github.png")')
|
|
expect(css).not_to include("absolute-image-url")
|
|
end
|
|
|
|
it "supports absolute-image-url in subfolder" do
|
|
set_subfolder "/subfo"
|
|
scss = Stylesheet::Importer.new({}).prepended_scss
|
|
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
|
|
css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")
|
|
|
|
expect(css).to include('url("http://test.localhost/subfo/images/favicons/github.png")')
|
|
expect(css).not_to include("absolute-image-url")
|
|
end
|
|
|
|
it "supports absolute-image-url with CDNs" do
|
|
set_cdn_url "https://awesome.com"
|
|
scss = Stylesheet::Importer.new({}).prepended_scss
|
|
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
|
|
css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")
|
|
|
|
expect(css).to include('url("https://awesome.com/images/favicons/github.png")')
|
|
expect(css).not_to include("absolute-image-url")
|
|
end
|
|
|
|
it "supports absolute-image-url in plugins" do
|
|
set_cdn_url "https://awesome.com"
|
|
scss = Stylesheet::Importer.new({}).prepended_scss
|
|
scss +=
|
|
".body{background-image: absolute-image-url('/plugins/discourse-special/images/somefile.png');}"
|
|
css, _map = Stylesheet::Compiler.compile(scss, "discourse-special.scss")
|
|
|
|
expect(css).to include(
|
|
'url("https://awesome.com/plugins/discourse-special/images/somefile.png")',
|
|
)
|
|
expect(css).not_to include("absolute-image-url")
|
|
end
|
|
|
|
context "with a color scheme" do
|
|
it "returns the default color definitions when no color scheme is specified" do
|
|
css, _map = Stylesheet::Compiler.compile_asset("color_definitions")
|
|
expect(css).to include("--header_background:")
|
|
expect(css).to include("--primary:")
|
|
end
|
|
|
|
it "returns color definitions for a custom color scheme" do
|
|
cs =
|
|
Fabricate(
|
|
:color_scheme,
|
|
name: "Stylish",
|
|
color_scheme_colors: [
|
|
Fabricate(:color_scheme_color, name: "header_primary", hex: "88af8e"),
|
|
Fabricate(:color_scheme_color, name: "header_background", hex: "f8745c"),
|
|
],
|
|
)
|
|
|
|
css, _map = Stylesheet::Compiler.compile_asset("color_definitions", color_scheme_id: cs.id)
|
|
|
|
expect(css).to include("--header_background: #f8745c")
|
|
expect(css).to include("--header_primary: #88af8e")
|
|
expect(css).to include("--header_background-rgb: 248, 116, 92")
|
|
end
|
|
|
|
context "with a plugin" do
|
|
before do
|
|
plugin = Plugin::Instance.new
|
|
plugin.path = "#{Rails.root}/spec/fixtures/plugins/color_definition/plugin.rb"
|
|
Discourse.plugins << plugin
|
|
plugin.activate!
|
|
end
|
|
|
|
after do
|
|
Discourse.plugins.pop
|
|
DiscoursePluginRegistry.reset!
|
|
end
|
|
|
|
it "includes color definitions from plugins" do
|
|
css, _map = Stylesheet::Compiler.compile_asset("color_definitions")
|
|
|
|
expect(css).to include("--plugin-color")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "indexes" do
|
|
it "include all SCSS files in their respective folders" do
|
|
refs = []
|
|
|
|
Dir
|
|
.glob(Rails.root.join("app/assets/stylesheets/**/*/"))
|
|
.each do |dir|
|
|
Dir
|
|
.glob("#{dir}_index.scss")
|
|
.each do |indexfile|
|
|
contents = File.read indexfile
|
|
|
|
files = Dir["#{dir}*.scss"]
|
|
files -= Dir["#{dir}_index.scss"]
|
|
files.each do |path|
|
|
filename = File.basename(path, ".scss")
|
|
if !contents.match(/@import "#{filename}";/)
|
|
refs << "#{filename} import missing in #{indexfile}"
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
expect(refs).to eq([])
|
|
end
|
|
end
|
|
|
|
describe ".compile" do
|
|
it "produces RTL CSS when rtl option is given" do
|
|
css, _ = Stylesheet::Compiler.compile("a{right:1px}", "test.scss", rtl: true)
|
|
expect(css).to eq("a{left:1px}")
|
|
end
|
|
end
|
|
end
|