diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index fa3ccba14128aa..9e2af19e6255c5 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -225,7 +225,7 @@ Note if an inline config is provided, Vite will not search for other PostCSS con Specify options to pass to CSS pre-processors. The file extensions are used as keys for the options. The supported options for each preprocessors can be found in their respective documentation: -- `sass`/`scss` - top level option `api: "legacy" | "modern"` (default `"legacy"`) allows switching which sass API to use. [Options (legacy)](https://sass-lang.com/documentation/js-api/interfaces/LegacyStringOptions), [Options (modern)](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/). +- `sass`/`scss` - top level option `api: "legacy" | "modern" | "modern-compiler"` (default `"legacy"`) allows switching which sass API to use. For the best performance, it's recommended to use `api: "modern-compiler"` with `sass-embedded` package. [Options (legacy)](https://sass-lang.com/documentation/js-api/interfaces/LegacyStringOptions), [Options (modern)](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/). - `less` - [Options](https://lesscss.org/usage/#less-options). - `styl`/`stylus` - Only [`define`](https://stylus-lang.com/docs/js.html#define-name-node) is supported, which can be passed as an object. @@ -244,7 +244,7 @@ export default defineConfig({ }, }, scss: { - api: 'modern', // or "legacy" + api: 'modern-compiler', // or "modern", "legacy" importers: [ // ... ], diff --git a/docs/guide/features.md b/docs/guide/features.md index 75940b8d17310c..9998387dae46b0 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -257,7 +257,7 @@ That said, Vite does provide built-in support for `.scss`, `.sass`, `.less`, `.s ```bash # .scss and .sass -npm add -D sass +npm add -D sass-embedded # or sass # .less npm add -D less diff --git a/packages/vite/package.json b/packages/vite/package.json index 8f98fe74adf109..787fc688a89913 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -142,6 +142,7 @@ "rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-license": "^3.5.2", "sass": "^1.77.8", + "sass-embedded": "^1.77.8", "sirv": "^2.0.4", "source-map-support": "^0.5.21", "strip-ansi": "^7.1.0", @@ -157,6 +158,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -168,6 +170,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 4fc5619e615d81..26ba17c192f84e 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -2,6 +2,7 @@ import fs from 'node:fs' import fsp from 'node:fs/promises' import path from 'node:path' import { createRequire } from 'node:module' +import { fileURLToPath, pathToFileURL } from 'node:url' import glob from 'fast-glob' import postcssrc from 'postcss-load-config' import type { @@ -1945,7 +1946,9 @@ type StylePreprocessorOptions = { } type SassStylePreprocessorOptions = StylePreprocessorOptions & - Omit, 'data' | 'file' | 'outFile'> + Omit, 'data' | 'file' | 'outFile'> & { + api?: 'legacy' | 'modern' | 'modern-compiler' + } type StylusStylePreprocessorOptions = StylePreprocessorOptions & { define?: Record @@ -1990,11 +1993,11 @@ export interface StylePreprocessorResults { } const loadedPreprocessorPath: Partial< - Record + Record > = {} function loadPreprocessorPath( - lang: PreprocessLang | PostCssDialectLang, + lang: PreprocessLang | PostCssDialectLang | 'sass-embedded', root: string, ): string { const cached = loadedPreprocessorPath[lang] @@ -2020,6 +2023,24 @@ function loadPreprocessorPath( } } +function loadSassPackage(root: string): { + name: 'sass' | 'sass-embedded' + path: string +} { + // try sass-embedded before sass + try { + const path = loadPreprocessorPath('sass-embedded', root) + return { name: 'sass-embedded', path } + } catch (e1) { + try { + const path = loadPreprocessorPath(PreprocessLang.sass, root) + return { name: 'sass', path } + } catch (e2) { + throw e1 + } + } +} + let cachedSss: any function loadSss(root: string) { if (cachedSss) return cachedSss @@ -2277,6 +2298,81 @@ const makeModernScssWorker = ( return worker } +// this is mostly a copy&paste of makeModernScssWorker +// however sharing code between two is hard because +// makeModernScssWorker above needs function inlined for worker. +const makeModernCompilerScssWorker = ( + resolvers: CSSAtImportResolvers, + alias: Alias[], + _maxWorkers: number | undefined, +) => { + let compiler: Sass.AsyncCompiler | undefined + + const worker: Awaited> = { + async run(sassPath, data, options) { + // need pathToFileURL for windows since import("D:...") fails + // https://github.com/nodejs/node/issues/31710 + const sass: typeof Sass = (await import(pathToFileURL(sassPath).href)) + .default + compiler ??= await sass.initAsyncCompiler() + + const sassOptions = { ...options } as Sass.StringOptions<'async'> + sassOptions.url = pathToFileURL(options.filename) + sassOptions.sourceMap = options.enableSourcemap + + const internalImporter: Sass.Importer<'async'> = { + async canonicalize(url, context) { + const importer = context.containingUrl + ? fileURLToPath(context.containingUrl) + : options.filename + const resolved = await resolvers.sass(url, cleanScssBugUrl(importer)) + return resolved ? pathToFileURL(resolved) : null + }, + async load(canonicalUrl) { + const ext = path.extname(canonicalUrl.pathname) + let syntax: Sass.Syntax = 'scss' + if (ext === '.sass') { + syntax = 'indented' + } else if (ext === '.css') { + syntax = 'css' + } + const result = await rebaseUrls( + fileURLToPath(canonicalUrl), + options.filename, + alias, + '$', + resolvers.sass, + ) + const contents = + result.contents ?? (await fsp.readFile(result.file, 'utf-8')) + return { contents, syntax } + }, + } + sassOptions.importers = [ + ...(sassOptions.importers ?? []), + internalImporter, + ] + + const result = await compiler.compileStringAsync(data, sassOptions) + return { + css: result.css, + map: result.sourceMap ? JSON.stringify(result.sourceMap) : undefined, + stats: { + includedFiles: result.loadedUrls + .filter((url) => url.protocol === 'file:') + .map((url) => fileURLToPath(url)), + }, + } satisfies ScssWorkerResult + }, + async stop() { + compiler?.dispose() + compiler = undefined + }, + } + + return worker +} + type ScssWorkerResult = { css: string map?: string | undefined @@ -2295,14 +2391,19 @@ const scssProcessor = ( } }, async process(source, root, options, resolvers) { - const sassPath = loadPreprocessorPath(PreprocessLang.sass, root) + const sassPackage = loadSassPackage(root) + // TODO: change default in v6 + // options.api ?? sassPackage.name === "sass-embedded" ? "modern-compiler" : "modern"; + const api = options.api ?? 'legacy' if (!workerMap.has(options.alias)) { workerMap.set( options.alias, - options.api === 'modern' - ? makeModernScssWorker(resolvers, options.alias, maxWorkers) - : makeScssWorker(resolvers, options.alias, maxWorkers), + api === 'modern-compiler' + ? makeModernCompilerScssWorker(resolvers, options.alias, maxWorkers) + : api === 'modern' + ? makeModernScssWorker(resolvers, options.alias, maxWorkers) + : makeScssWorker(resolvers, options.alias, maxWorkers), ) } const worker = workerMap.get(options.alias)! @@ -2320,7 +2421,7 @@ const scssProcessor = ( } try { const result = await worker.run( - sassPath, + sassPackage.path, data, optionsWithoutAdditionalData, ) diff --git a/playground/css/__tests__/sass-modern-compiler/sass-modern-compiler.spec.ts b/playground/css/__tests__/sass-modern-compiler/sass-modern-compiler.spec.ts new file mode 100644 index 00000000000000..90a9b9774d3ebc --- /dev/null +++ b/playground/css/__tests__/sass-modern-compiler/sass-modern-compiler.spec.ts @@ -0,0 +1 @@ +import '../css.spec' diff --git a/playground/css/vite.config-sass-modern-compiler.js b/playground/css/vite.config-sass-modern-compiler.js new file mode 100644 index 00000000000000..9759d58506f597 --- /dev/null +++ b/playground/css/vite.config-sass-modern-compiler.js @@ -0,0 +1,31 @@ +import { defineConfig } from 'vite' +import baseConfig from './vite.config.js' + +export default defineConfig({ + ...baseConfig, + css: { + ...baseConfig.css, + preprocessorOptions: { + ...baseConfig.css.preprocessorOptions, + scss: { + api: 'modern-compiler', + additionalData: `$injectedColor: orange;`, + importers: [ + { + canonicalize(url) { + return url === 'virtual-dep' + ? new URL('custom-importer:virtual-dep') + : null + }, + load() { + return { + contents: ``, + syntax: 'scss', + } + }, + }, + ], + }, + }, + }, +}) diff --git a/playground/vitestGlobalSetup.ts b/playground/vitestGlobalSetup.ts index 193c47b6047eac..d97dec019d411e 100644 --- a/playground/vitestGlobalSetup.ts +++ b/playground/vitestGlobalSetup.ts @@ -47,6 +47,11 @@ export async function setup({ provide }: GlobalSetupContext): Promise { path.resolve(tempDir, 'css__sass-modern'), { recursive: true }, ) + await fs.cp( + path.resolve(tempDir, 'css'), + path.resolve(tempDir, 'css__sass-modern-compiler'), + { recursive: true }, + ) } export async function teardown(): Promise { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4e44fb6d1cd420..4a5658d194cd8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -382,6 +382,9 @@ importers: sass: specifier: ^1.77.8 version: 1.77.8 + sass-embedded: + specifier: ^1.77.8 + version: 1.77.8 sirv: specifier: ^2.0.4 version: 2.0.4(patch_hash=amdes53ifqfntejkflpaq5ifce) @@ -2273,6 +2276,9 @@ packages: resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} engines: {node: '>=6.9.0'} + '@bufbuild/protobuf@1.10.0': + resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} + '@cloudflare/workerd-darwin-64@1.20240718.0': resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} engines: {node: '>=16'} @@ -3866,6 +3872,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-builder@0.2.0: + resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -6005,6 +6014,9 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -6015,6 +6027,125 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sass-embedded-android-arm64@1.77.8: + resolution: {integrity: sha512-EmWHLbEx0Zo/f/lTFzMeH2Du+/I4RmSRlEnERSUKQWVp3aBSO04QDvdxfFezgQ+2Yt/ub9WMqBpma9P/8MPsLg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [android] + hasBin: true + + sass-embedded-android-arm@1.77.8: + resolution: {integrity: sha512-GpGL7xZ7V1XpFbnflib/NWbM0euRzineK0iwoo31/ntWKAXGj03iHhGzkSiOwWSFcXgsJJi3eRA5BTmBvK5Q+w==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [android] + hasBin: true + + sass-embedded-android-ia32@1.77.8: + resolution: {integrity: sha512-+GjfJ3lDezPi4dUUyjQBxlNKXNa+XVWsExtGvVNkv1uKyaOxULJhubVo2G6QTJJU0esJdfeXf5Ca5/J0ph7+7w==} + engines: {node: '>=14.0.0'} + cpu: [ia32] + os: [android] + hasBin: true + + sass-embedded-android-x64@1.77.8: + resolution: {integrity: sha512-YZbFDzGe5NhaMCygShqkeCWtzjhkWxGVunc7ULR97wmxYPQLPeVyx7XFQZc84Aj0lKAJBJS4qRZeqphMqZEJsQ==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [android] + hasBin: true + + sass-embedded-darwin-arm64@1.77.8: + resolution: {integrity: sha512-aifgeVRNE+i43toIkDFFJc/aPLMo0PJ5s5hKb52U+oNdiJE36n65n2L8F/8z3zZRvCa6eYtFY2b7f1QXR3B0LA==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [darwin] + hasBin: true + + sass-embedded-darwin-x64@1.77.8: + resolution: {integrity: sha512-/VWZQtcWIOek60Zj6Sxk6HebXA1Qyyt3sD8o5qwbTgZnKitB1iEBuNunyGoAgMNeUz2PRd6rVki6hvbas9hQ6w==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [darwin] + hasBin: true + + sass-embedded-linux-arm64@1.77.8: + resolution: {integrity: sha512-6iIOIZtBFa2YfMsHqOb3qake3C9d/zlKxjooKKnTSo+6g6z+CLTzMXe1bOfayb7yxeenElmFoK1k54kWD/40+g==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + hasBin: true + + sass-embedded-linux-arm@1.77.8: + resolution: {integrity: sha512-2edZMB6jf0whx3T0zlgH+p131kOEmWp+I4wnKj7ZMUeokiY4Up05d10hSvb0Q63lOrSjFAWu6P5/pcYUUx8arQ==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + hasBin: true + + sass-embedded-linux-ia32@1.77.8: + resolution: {integrity: sha512-63GsFFHWN5yRLTWiSef32TM/XmjhCBx1DFhoqxmj+Yc6L9Z1h0lDHjjwdG6Sp5XTz5EmsaFKjpDgnQTP9hJX3Q==} + engines: {node: '>=14.0.0'} + cpu: [ia32] + os: [linux] + hasBin: true + + sass-embedded-linux-musl-arm64@1.77.8: + resolution: {integrity: sha512-j8cgQxNWecYK+aH8ESFsyam/Q6G+9gg8eJegiRVpA9x8yk3ykfHC7UdQWwUcF22ZcuY4zegrjJx8k+thsgsOVA==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [linux] + + sass-embedded-linux-musl-arm@1.77.8: + resolution: {integrity: sha512-nFkhSl3uu9btubm+JBW7uRglNVJ8W8dGfzVqh3fyQJKS1oyBC3vT3VOtfbT9YivXk28wXscSHpqXZwY7bUuopA==} + engines: {node: '>=14.0.0'} + cpu: [arm] + os: [linux] + + sass-embedded-linux-musl-ia32@1.77.8: + resolution: {integrity: sha512-oWveMe+8TFlP8WBWPna/+Ec5TV0CE+PxEutyi0ltSruBds2zxRq9dPVOqrpPcDN9QUx50vNZC0Afgch0aQEd0g==} + engines: {node: '>=14.0.0'} + cpu: [ia32] + os: [linux] + + sass-embedded-linux-musl-x64@1.77.8: + resolution: {integrity: sha512-2NtRpMXHeFo9kaYxuZ+Ewwo39CE7BTS2JDfXkTjZTZqd8H+8KC53eBh516YQnn2oiqxSiKxm7a6pxbxGZGwXOQ==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + + sass-embedded-linux-x64@1.77.8: + resolution: {integrity: sha512-ND5qZLWUCpOn7LJfOf0gLSZUWhNIysY+7NZK1Ctq+pM6tpJky3JM5I1jSMplNxv5H3o8p80n0gSm+fcjsEFfjQ==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [linux] + hasBin: true + + sass-embedded-win32-arm64@1.77.8: + resolution: {integrity: sha512-7L8zT6xzEvTYj86MvUWnbkWYCNQP+74HvruLILmiPPE+TCgOjgdi750709BtppVJGGZSs40ZuN6mi/YQyGtwXg==} + engines: {node: '>=14.0.0'} + cpu: [arm64] + os: [win32] + hasBin: true + + sass-embedded-win32-ia32@1.77.8: + resolution: {integrity: sha512-7Buh+4bP0WyYn6XPbthkIa3M2vtcR8QIsFVg3JElVlr+8Ng19jqe0t0SwggDgbMX6AdQZC+Wj4F1BprZSok42A==} + engines: {node: '>=14.0.0'} + cpu: [ia32] + os: [win32] + hasBin: true + + sass-embedded-win32-x64@1.77.8: + resolution: {integrity: sha512-rZmLIx4/LLQm+4GW39sRJW0MIlDqmyV0fkRzTmhFP5i/wVC7cuj8TUubPHw18rv2rkHFfBZKZJTCkPjCS5Z+SA==} + engines: {node: '>=14.0.0'} + cpu: [x64] + os: [win32] + hasBin: true + + sass-embedded@1.77.8: + resolution: {integrity: sha512-WGXA6jcaoBo5Uhw0HX/s6z/sl3zyYQ7ZOnLOJzqwpctFcFmU4L07zn51e2VSkXXFpQZFAdMZNqOGz/7h/fvcRA==} + engines: {node: '>=16.0.0'} + sass@1.77.8: resolution: {integrity: sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==} engines: {node: '>=14.0.0'} @@ -6274,6 +6405,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -6551,6 +6686,9 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + varint@6.0.0: + resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -7720,6 +7858,8 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 + '@bufbuild/protobuf@1.10.0': {} + '@cloudflare/workerd-darwin-64@1.20240718.0': optional: true @@ -9187,6 +9327,8 @@ snapshots: node-releases: 2.0.14 update-browserslist-db: 1.1.0(browserslist@4.23.2) + buffer-builder@0.2.0: {} + buffer-from@1.1.2: {} builtin-modules@3.3.0: {} @@ -11602,6 +11744,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + rxjs@7.8.1: + dependencies: + tslib: 2.6.3 + sade@1.8.1: dependencies: mri: 1.2.0 @@ -11610,6 +11756,84 @@ snapshots: safer-buffer@2.1.2: {} + sass-embedded-android-arm64@1.77.8: + optional: true + + sass-embedded-android-arm@1.77.8: + optional: true + + sass-embedded-android-ia32@1.77.8: + optional: true + + sass-embedded-android-x64@1.77.8: + optional: true + + sass-embedded-darwin-arm64@1.77.8: + optional: true + + sass-embedded-darwin-x64@1.77.8: + optional: true + + sass-embedded-linux-arm64@1.77.8: + optional: true + + sass-embedded-linux-arm@1.77.8: + optional: true + + sass-embedded-linux-ia32@1.77.8: + optional: true + + sass-embedded-linux-musl-arm64@1.77.8: + optional: true + + sass-embedded-linux-musl-arm@1.77.8: + optional: true + + sass-embedded-linux-musl-ia32@1.77.8: + optional: true + + sass-embedded-linux-musl-x64@1.77.8: + optional: true + + sass-embedded-linux-x64@1.77.8: + optional: true + + sass-embedded-win32-arm64@1.77.8: + optional: true + + sass-embedded-win32-ia32@1.77.8: + optional: true + + sass-embedded-win32-x64@1.77.8: + optional: true + + sass-embedded@1.77.8: + dependencies: + '@bufbuild/protobuf': 1.10.0 + buffer-builder: 0.2.0 + immutable: 4.0.0 + rxjs: 7.8.1 + supports-color: 8.1.1 + varint: 6.0.0 + optionalDependencies: + sass-embedded-android-arm: 1.77.8 + sass-embedded-android-arm64: 1.77.8 + sass-embedded-android-ia32: 1.77.8 + sass-embedded-android-x64: 1.77.8 + sass-embedded-darwin-arm64: 1.77.8 + sass-embedded-darwin-x64: 1.77.8 + sass-embedded-linux-arm: 1.77.8 + sass-embedded-linux-arm64: 1.77.8 + sass-embedded-linux-ia32: 1.77.8 + sass-embedded-linux-musl-arm: 1.77.8 + sass-embedded-linux-musl-arm64: 1.77.8 + sass-embedded-linux-musl-ia32: 1.77.8 + sass-embedded-linux-musl-x64: 1.77.8 + sass-embedded-linux-x64: 1.77.8 + sass-embedded-win32-arm64: 1.77.8 + sass-embedded-win32-ia32: 1.77.8 + sass-embedded-win32-x64: 1.77.8 + sass@1.77.8: dependencies: chokidar: 3.6.0(patch_hash=bckcfsslxcffppz65mxcq6naau) @@ -11886,6 +12110,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} systemjs@6.15.1: {} @@ -12186,6 +12414,8 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + varint@6.0.0: {} + vary@1.1.2: {} vfile-message@4.0.2: