1
0
mirror of https://github.com/discourse/discourse.git synced 2025-03-15 11:01:14 +00:00

DEV: Introduce postcss for autoprefix and light-dark() polyfill ()

Introduces PostCSS at the end of our CSS compilation pipeline. For now,
just adds autoprefixer and light-dark polyfill.
This commit is contained in:
David Taylor
2025-02-20 14:40:27 +00:00
committed by GitHub
parent 1b33a9900f
commit 087e8e4bdb
11 changed files with 273 additions and 44 deletions

@ -47,14 +47,16 @@ esbuild
.build({
logLevel: "warning",
bundle: true,
minify: true,
minify: false,
alias: {
util: "./node_modules/@zxing/text-encoding",
path: "path-browserify",
"source-map-js": "source-map-js",
},
define: {
process: `{ "env": { "EMBER_ENV": "production" } }`,
banner: {
js: `var process = { "env": { "EMBER_ENV": "production" }, "cwd": () => "/" };`,
},
external: ["fs", "path"],
external: [],
entryPoints: ["./transpiler.js"],
plugins: [wasmPlugin],
})

@ -8,7 +8,9 @@
"keywords": [],
"dependencies": {
"@babel/standalone": "^7.26.9",
"@csstools/postcss-light-dark-function": "^2.0.7",
"@zxing/text-encoding": "^0.9.0",
"autoprefixer": "^10.4.20",
"babel-plugin-ember-template-compilation": "^2.3.0",
"content-tag": "^3.1.1",
"decorator-transforms": "^2.3.0",
@ -20,6 +22,9 @@
"handlebars": "^4.7.8",
"path-browserify": "^1.0.1",
"polyfill-crypto.getrandomvalues": "^1.0.0",
"postcss": "^8.5.3",
"postcss-js": "^4.0.1",
"source-map-js": "^1.2.1",
"terser": "^5.39.0"
},
"engines": {

@ -0,0 +1,49 @@
/* eslint-disable no-bitwise */
// Simple, fast hashing function (djb2)
const hashString = (str) => {
let hash = 5381;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) + hash + str.charCodeAt(i);
hash = hash >>> 0; // Convert to unsigned 32-bit integer
}
return hash.toString(16).slice(0, 8);
};
/**
* Adds a hash of the current file as a prefix to variables
* introduced by the light-dark polyfill. This ensures that
* usage across different files cannot conflict.
*/
const namespacesToPrefix = ["--csstools-light-dark-toggle-"];
export default function postcssVariablePrefixer() {
let hash;
return {
postcssPlugin: "postcss-var-prefixer",
prepare(result) {
hash = hashString(result.root.source.input.css);
},
Declaration(declaration) {
const prop = declaration.prop;
for (const prefix of namespacesToPrefix) {
if (declaration.prop.startsWith(prefix)) {
declaration.prop = `--${hash}-${prop.slice(2)}`;
}
if (declaration.value.includes(prefix)) {
declaration.value = declaration.value.replaceAll(
prefix,
`--${hash}-${prefix.slice(2)}`
);
}
}
},
};
}
postcssVariablePrefixer.postcss = true;

@ -0,0 +1,44 @@
import postcssLightDark from "@csstools/postcss-light-dark-function";
import autoprefixer from "autoprefixer";
import postcss from "postcss";
import { browsers } from "../discourse/config/targets";
import postcssVariablePrefixer from "./postcss-variable-prefixer";
const postCssProcessor = postcss([
autoprefixer({
overrideBrowserslist: browsers,
}),
postcssLightDark,
postcssVariablePrefixer(),
]);
let lastPostcssError, lastPostcssResult;
globalThis.postCss = async function (css, map, sourcemapFile) {
try {
const rawResult = await postCssProcessor.process(css, {
from: "input.css",
to: "output.css",
map: {
prev: map,
inline: false,
absolute: false,
annotation: sourcemapFile,
},
});
lastPostcssResult = [rawResult.css, rawResult.map?.toString()];
} catch (e) {
lastPostcssError = e;
}
};
globalThis.getPostCssResult = function () {
const error = lastPostcssError;
const result = lastPostcssResult;
lastPostcssError = lastPostcssResult = null;
if (error) {
throw error;
}
return result;
};

@ -31,6 +31,7 @@ import { minify as terserMinify } from "terser";
import RawHandlebars from "discourse/lib/raw-handlebars";
import { WidgetHbsCompiler } from "discourse-widget-hbs/lib/widget-hbs-compiler";
globalThis.crypto = { getRandomValues };
import "./postcss";
import { browsers } from "../discourse/config/targets";
const thisFallbackPlugin = EmberThisFallback._buildPlugin({

@ -2,6 +2,8 @@
// It is compiled to CSS separately from the rest of the app.
// The source variables come from color_transformations.scss and variables.scss
:root {
color-scheme: #{schemeType()};
--scheme-type: #{schemeType()};
--primary: #{$primary};
--secondary: #{$secondary};

@ -185,5 +185,15 @@ class DiscourseJsProcessor
def terser(tree, opts)
self.class.v8_call("minify", tree, opts, fetch_result_call: "getMinifyResult")
end
def post_css(css:, map:, source_map_file:)
self.class.v8_call(
"postCss",
css,
map,
source_map_file,
fetch_result_call: "getPostCssResult",
)
end
end
end

@ -60,13 +60,20 @@ module Stylesheet
result = engine.render
source_map = engine.source_map
source_map.force_encoding("UTF-8")
result, source_map =
DiscourseJsProcessor::Transpiler.new.post_css(
css: result,
map: source_map,
source_map_file: source_map_file,
)
if options[:rtl]
require "rtlcss"
[Rtlcss.flip_css(result), nil]
else
source_map = engine.source_map
source_map.force_encoding("UTF-8")
[result, source_map]
end
end

@ -8,7 +8,7 @@ end
class Stylesheet::Manager
# Bump this number to invalidate all stylesheet caches (e.g. if you change something inside the compiler)
BASE_COMPILER_VERSION = 2
BASE_COMPILER_VERSION = 3
# Add any dependencies here which should automatically cause a global cache invalidation.
BASE_CACHE_KEY = "#{BASE_COMPILER_VERSION}::#{DiscourseFonts::VERSION}"

167
pnpm-lock.yaml generated

@ -36,7 +36,7 @@ importers:
version: 7.25.9(@babel/core@7.26.9)
'@discourse/lint-configs':
specifier: ^2.5.0
version: 2.5.0(ember-template-lint@6.1.0)(eslint@9.20.1)(postcss@8.5.1)(prettier@2.8.8)(stylelint@16.14.1(typescript@5.6.3))
version: 2.5.0(ember-template-lint@6.1.0)(eslint@9.20.1)(postcss@8.5.3)(prettier@2.8.8)(stylelint@16.14.1(typescript@5.6.3))
'@discourse/moment-timezone-names-translations':
specifier: ^1.0.0
version: 1.0.0
@ -1015,9 +1015,15 @@ importers:
'@babel/standalone':
specifier: ^7.26.9
version: 7.26.9
'@csstools/postcss-light-dark-function':
specifier: ^2.0.7
version: 2.0.7(postcss@8.5.3)
'@zxing/text-encoding':
specifier: ^0.9.0
version: 0.9.0
autoprefixer:
specifier: ^10.4.20
version: 10.4.20(postcss@8.5.3)
babel-plugin-ember-template-compilation:
specifier: ^2.3.0
version: 2.3.0
@ -1051,6 +1057,15 @@ importers:
polyfill-crypto.getrandomvalues:
specifier: ^1.0.0
version: 1.0.0
postcss:
specifier: ^8.5.3
version: 8.5.3
postcss-js:
specifier: ^4.0.1
version: 4.0.1(postcss@8.5.3)
source-map-js:
specifier: ^1.2.1
version: 1.2.1
terser:
specifier: ^5.39.0
version: 5.39.0
@ -1694,12 +1709,30 @@ packages:
'@csstools/css-parser-algorithms': ^3.0.4
'@csstools/css-tokenizer': ^3.0.3
'@csstools/postcss-light-dark-function@2.0.7':
resolution: {integrity: sha512-ZZ0rwlanYKOHekyIPaU+sVm3BEHCe+Ha0/px+bmHe62n0Uc1lL34vbwrLYn6ote8PHlsqzKeTQdIejQCJ05tfw==}
engines: {node: '>=18'}
peerDependencies:
postcss: ^8.4
'@csstools/postcss-progressive-custom-properties@4.0.0':
resolution: {integrity: sha512-XQPtROaQjomnvLUSy/bALTR5VCtTVUFwYs1SblvYgLSeTo2a/bMNwUwo2piXw5rTv/FEYiy5yPSXBqg9OKUx7Q==}
engines: {node: '>=18'}
peerDependencies:
postcss: ^8.4
'@csstools/selector-specificity@5.0.0':
resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==}
engines: {node: '>=18'}
peerDependencies:
postcss-selector-parser: ^7.0.0
'@csstools/utilities@2.0.0':
resolution: {integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==}
engines: {node: '>=18'}
peerDependencies:
postcss: ^8.4
'@dabh/diagnostics@2.0.3':
resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==}
@ -3106,6 +3139,13 @@ packages:
engines: {node: '>= 4.5.0'}
hasBin: true
autoprefixer@10.4.20:
resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
autosize@6.0.1:
resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==}
@ -3517,6 +3557,10 @@ packages:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
camelcase-css@2.0.1:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'}
camelize@1.0.1:
resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
@ -5045,6 +5089,9 @@ packages:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
fragment-cache@0.2.1:
resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==}
engines: {node: '>=0.10.0'}
@ -6603,6 +6650,10 @@ packages:
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
engines: {node: '>=0.10.0'}
normalize-range@0.1.2:
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
engines: {node: '>=0.10.0'}
npm-bundled@3.0.1:
resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
@ -6995,6 +7046,12 @@ packages:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
postcss-js@4.0.1:
resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
engines: {node: ^12 || ^14 || >= 16}
peerDependencies:
postcss: ^8.4.21
postcss-media-query-parser@0.2.3:
resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
@ -7048,8 +7105,8 @@ packages:
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
postcss@8.5.1:
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
postcss@8.5.3:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
preact@10.23.2:
@ -9537,10 +9594,27 @@ snapshots:
'@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
'@csstools/css-tokenizer': 3.0.3
'@csstools/postcss-light-dark-function@2.0.7(postcss@8.5.3)':
dependencies:
'@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
'@csstools/css-tokenizer': 3.0.3
'@csstools/postcss-progressive-custom-properties': 4.0.0(postcss@8.5.3)
'@csstools/utilities': 2.0.0(postcss@8.5.3)
postcss: 8.5.3
'@csstools/postcss-progressive-custom-properties@4.0.0(postcss@8.5.3)':
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
'@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.0.0)':
dependencies:
postcss-selector-parser: 7.0.0
'@csstools/utilities@2.0.0(postcss@8.5.3)':
dependencies:
postcss: 8.5.3
'@dabh/diagnostics@2.0.3':
dependencies:
colorspace: 1.1.4
@ -9551,7 +9625,7 @@ snapshots:
'@discourse/itsatrap@2.0.10': {}
'@discourse/lint-configs@2.5.0(ember-template-lint@6.1.0)(eslint@9.20.1)(postcss@8.5.1)(prettier@2.8.8)(stylelint@16.14.1(typescript@5.6.3))':
'@discourse/lint-configs@2.5.0(ember-template-lint@6.1.0)(eslint@9.20.1)(postcss@8.5.3)(prettier@2.8.8)(stylelint@16.14.1(typescript@5.6.3))':
dependencies:
'@babel/core': 7.26.9(supports-color@8.1.1)
'@babel/eslint-parser': 7.26.8(@babel/core@7.26.9)(eslint@9.20.1)
@ -9569,7 +9643,7 @@ snapshots:
prettier-plugin-ember-template-tag: 0.3.2
stylelint: 16.14.1(typescript@5.6.3)
stylelint-config-standard: 37.0.0(stylelint@16.14.1(typescript@5.6.3))
stylelint-config-standard-scss: 14.0.0(postcss@8.5.1)(stylelint@16.14.1(typescript@5.6.3))
stylelint-config-standard-scss: 14.0.0(postcss@8.5.3)(stylelint@16.14.1(typescript@5.6.3))
typescript: 5.7.3
transitivePeerDependencies:
- '@typescript-eslint/parser'
@ -11269,6 +11343,16 @@ snapshots:
atob@2.1.2: {}
autoprefixer@10.4.20(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
caniuse-lite: 1.0.30001699
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
postcss: 8.5.3
postcss-value-parser: 4.2.0
autosize@6.0.1: {}
available-typed-arrays@1.0.7:
@ -12004,6 +12088,8 @@ snapshots:
callsites@3.1.0: {}
camelcase-css@2.0.1: {}
camelize@1.0.1: {}
can-symlink@1.0.0:
@ -12343,13 +12429,13 @@ snapshots:
css-loader@5.2.7(webpack@5.98.0(@swc/core@1.10.18)(esbuild@0.25.0)):
dependencies:
icss-utils: 5.1.0(postcss@8.5.1)
icss-utils: 5.1.0(postcss@8.5.3)
loader-utils: 2.0.4
postcss: 8.5.1
postcss-modules-extract-imports: 3.1.0(postcss@8.5.1)
postcss-modules-local-by-default: 4.0.5(postcss@8.5.1)
postcss-modules-scope: 3.2.0(postcss@8.5.1)
postcss-modules-values: 4.0.0(postcss@8.5.1)
postcss: 8.5.3
postcss-modules-extract-imports: 3.1.0(postcss@8.5.3)
postcss-modules-local-by-default: 4.0.5(postcss@8.5.3)
postcss-modules-scope: 3.2.0(postcss@8.5.3)
postcss-modules-values: 4.0.0(postcss@8.5.3)
postcss-value-parser: 4.2.0
schema-utils: 3.3.0
semver: 7.7.1
@ -14051,6 +14137,8 @@ snapshots:
forwarded@0.2.0: {}
fraction.js@4.3.7: {}
fragment-cache@0.2.1:
dependencies:
map-cache: 0.2.2
@ -14558,9 +14646,9 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
icss-utils@5.1.0(postcss@8.5.1):
icss-utils@5.1.0(postcss@8.5.3):
dependencies:
postcss: 8.5.1
postcss: 8.5.3
ieee754@1.2.1: {}
@ -15744,6 +15832,8 @@ snapshots:
normalize-path@3.0.0: {}
normalize-range@0.1.2: {}
npm-bundled@3.0.1:
dependencies:
npm-normalize-package-bin: 3.0.1
@ -16154,38 +16244,43 @@ snapshots:
possible-typed-array-names@1.1.0: {}
postcss-js@4.0.1(postcss@8.5.3):
dependencies:
camelcase-css: 2.0.1
postcss: 8.5.3
postcss-media-query-parser@0.2.3: {}
postcss-modules-extract-imports@3.1.0(postcss@8.5.1):
postcss-modules-extract-imports@3.1.0(postcss@8.5.3):
dependencies:
postcss: 8.5.1
postcss: 8.5.3
postcss-modules-local-by-default@4.0.5(postcss@8.5.1):
postcss-modules-local-by-default@4.0.5(postcss@8.5.3):
dependencies:
icss-utils: 5.1.0(postcss@8.5.1)
postcss: 8.5.1
icss-utils: 5.1.0(postcss@8.5.3)
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-value-parser: 4.2.0
postcss-modules-scope@3.2.0(postcss@8.5.1):
postcss-modules-scope@3.2.0(postcss@8.5.3):
dependencies:
postcss: 8.5.1
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-modules-values@4.0.0(postcss@8.5.1):
postcss-modules-values@4.0.0(postcss@8.5.3):
dependencies:
icss-utils: 5.1.0(postcss@8.5.1)
postcss: 8.5.1
icss-utils: 5.1.0(postcss@8.5.3)
postcss: 8.5.3
postcss-resolve-nested-selector@0.1.6: {}
postcss-safe-parser@7.0.1(postcss@8.5.1):
postcss-safe-parser@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.1
postcss: 8.5.3
postcss-scss@4.0.9(postcss@8.5.1):
postcss-scss@4.0.9(postcss@8.5.3):
dependencies:
postcss: 8.5.1
postcss: 8.5.3
postcss-selector-parser@6.1.2:
dependencies:
@ -16199,7 +16294,7 @@ snapshots:
postcss-value-parser@4.2.0: {}
postcss@8.5.1:
postcss@8.5.3:
dependencies:
nanoid: 3.3.8
picocolors: 1.1.1
@ -17238,14 +17333,14 @@ snapshots:
styled_string@0.0.1: {}
stylelint-config-recommended-scss@14.1.0(postcss@8.5.1)(stylelint@16.14.1(typescript@5.6.3)):
stylelint-config-recommended-scss@14.1.0(postcss@8.5.3)(stylelint@16.14.1(typescript@5.6.3)):
dependencies:
postcss-scss: 4.0.9(postcss@8.5.1)
postcss-scss: 4.0.9(postcss@8.5.3)
stylelint: 16.14.1(typescript@5.6.3)
stylelint-config-recommended: 14.0.1(stylelint@16.14.1(typescript@5.6.3))
stylelint-scss: 6.10.1(stylelint@16.14.1(typescript@5.6.3))
optionalDependencies:
postcss: 8.5.1
postcss: 8.5.3
stylelint-config-recommended@14.0.1(stylelint@16.14.1(typescript@5.6.3)):
dependencies:
@ -17255,13 +17350,13 @@ snapshots:
dependencies:
stylelint: 16.14.1(typescript@5.6.3)
stylelint-config-standard-scss@14.0.0(postcss@8.5.1)(stylelint@16.14.1(typescript@5.6.3)):
stylelint-config-standard-scss@14.0.0(postcss@8.5.3)(stylelint@16.14.1(typescript@5.6.3)):
dependencies:
stylelint: 16.14.1(typescript@5.6.3)
stylelint-config-recommended-scss: 14.1.0(postcss@8.5.1)(stylelint@16.14.1(typescript@5.6.3))
stylelint-config-recommended-scss: 14.1.0(postcss@8.5.3)(stylelint@16.14.1(typescript@5.6.3))
stylelint-config-standard: 36.0.1(stylelint@16.14.1(typescript@5.6.3))
optionalDependencies:
postcss: 8.5.1
postcss: 8.5.3
stylelint-config-standard@36.0.1(stylelint@16.14.1(typescript@5.6.3)):
dependencies:
@ -17314,9 +17409,9 @@ snapshots:
micromatch: 4.0.8
normalize-path: 3.0.0
picocolors: 1.1.1
postcss: 8.5.1
postcss: 8.5.3
postcss-resolve-nested-selector: 0.1.6
postcss-safe-parser: 7.0.1(postcss@8.5.1)
postcss-safe-parser: 7.0.1(postcss@8.5.3)
postcss-selector-parser: 7.0.0
postcss-value-parser: 4.2.0
resolve-from: 5.0.0

@ -231,5 +231,19 @@ RSpec.describe Stylesheet::Compiler do
css, _ = Stylesheet::Compiler.compile("a{right:1px}", "test.scss", rtl: true)
expect(css).to eq("a{left:1px}")
end
it "runs through postcss" do
css, map = Stylesheet::Compiler.compile(<<~SCSS, "test.scss")
@media (min-resolution: 2dppx) {
body {
background-color: light-dark(white, black);
}
}
SCSS
expect(css).to include("-webkit-min-device-pixel-ratio")
expect(css).to include("csstools-light-dark-toggle")
expect(map.size).to be > 10
end
end
end