diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4f92d032c7a..6e818e69c47 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -50,7 +50,6 @@ pnpm-lock.yaml # Loaders -/crates/rspack_loader_sass @web-infra-dev/rspack-dx /crates/rspack_loader_swc @web-infra-dev/rspack-dx # Plugins diff --git a/Cargo.lock b/Cargo.lock index b165b756e04..9680f798943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -368,12 +368,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" - [[package]] name = "cargo-rst" version = "0.1.0" @@ -2135,29 +2129,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "psm" version = "0.1.21" @@ -2464,7 +2435,6 @@ dependencies = [ "rspack_ids", "rspack_loader_react_refresh", "rspack_loader_runner", - "rspack_loader_sass", "rspack_loader_swc", "rspack_napi_shared", "rspack_plugin_asset", @@ -2529,7 +2499,6 @@ dependencies = [ "rspack_ids", "rspack_loader_react_refresh", "rspack_loader_runner", - "rspack_loader_sass", "rspack_loader_swc", "rspack_napi_shared", "rspack_plugin_asset", @@ -2751,25 +2720,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rspack_loader_sass" -version = "0.1.0" -dependencies = [ - "async-trait", - "indexmap 1.9.3", - "itertools", - "once_cell", - "regex", - "rspack_core", - "rspack_error", - "rspack_loader_runner", - "rspack_testing", - "sass-embedded", - "serde", - "str_indices", - "tokio", -] - [[package]] name = "rspack_loader_swc" version = "0.1.0" @@ -3355,7 +3305,6 @@ dependencies = [ "rspack_fs", "rspack_ids", "rspack_loader_runner", - "rspack_loader_sass", "rspack_loader_swc", "rspack_plugin_asset", "rspack_plugin_css", @@ -3464,25 +3413,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "sass-embedded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043fea16ac00f7132b50dce6094873fee0d328bd43c0f552faeb33d989d97b77" -dependencies = [ - "atty", - "crossbeam-channel", - "dashmap", - "parking_lot 0.12.1", - "prost", - "regex", - "rustc-hash", - "serde", - "serde_json", - "url", - "urlencoding", -] - [[package]] name = "schemars" version = "0.8.12" @@ -5517,7 +5447,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] diff --git a/crates/rspack_binding_options/Cargo.toml b/crates/rspack_binding_options/Cargo.toml index 58ed9ad45dc..5d67c434cce 100644 --- a/crates/rspack_binding_options/Cargo.toml +++ b/crates/rspack_binding_options/Cargo.toml @@ -14,7 +14,6 @@ rspack_identifier = { path = "../rspack_identifier" } rspack_ids = { path = "../rspack_ids" } rspack_loader_react_refresh = { path = "../rspack_loader_react_refresh" } rspack_loader_runner = { path = "../rspack_loader_runner" } -rspack_loader_sass = { path = "../rspack_loader_sass" } rspack_loader_swc = { path = "../rspack_loader_swc" } rspack_napi_shared = { path = "../rspack_napi_shared" } rspack_plugin_asset = { path = "../rspack_plugin_asset" } diff --git a/crates/rspack_binding_options/src/options/raw_module/mod.rs b/crates/rspack_binding_options/src/options/raw_module/mod.rs index 2d5e62a5846..cc0b2826229 100644 --- a/crates/rspack_binding_options/src/options/raw_module/mod.rs +++ b/crates/rspack_binding_options/src/options/raw_module/mod.rs @@ -15,7 +15,6 @@ use rspack_core::{ }; use rspack_error::{internal_error, miette::IntoDiagnostic}; use rspack_loader_react_refresh::REACT_REFRESH_LOADER_IDENTIFIER; -use rspack_loader_sass::SASS_LOADER_IDENTIFIER; use rspack_loader_swc::SWC_LOADER_IDENTIFIER; use rspack_napi_shared::threadsafe_function::{ThreadsafeFunction, ThreadsafeFunctionCallMode}; use rspack_napi_shared::{get_napi_env, NapiResultExt}; @@ -26,14 +25,6 @@ pub use self::js_loader::*; use crate::RawResolveOptions; pub fn get_builtin_loader(builtin: &str, options: Option<&str>) -> BoxLoader { - if builtin.starts_with(SASS_LOADER_IDENTIFIER) { - return Arc::new(rspack_loader_sass::SassLoader::new( - serde_json::from_str(options.unwrap_or("{}")).unwrap_or_else(|e| { - panic!("Could not parse builtin:sass-loader options: {options:?}, error: {e:?}") - }), - )); - } - if builtin.starts_with(SWC_LOADER_IDENTIFIER) { return Arc::new( rspack_loader_swc::SwcLoader::new( diff --git a/crates/rspack_binding_values/Cargo.toml b/crates/rspack_binding_values/Cargo.toml index 60a2e89b128..db33ac6ca36 100644 --- a/crates/rspack_binding_values/Cargo.toml +++ b/crates/rspack_binding_values/Cargo.toml @@ -13,7 +13,6 @@ rspack_identifier = { path = "../rspack_identifier" } rspack_ids = { path = "../rspack_ids" } rspack_loader_react_refresh = { path = "../rspack_loader_react_refresh" } rspack_loader_runner = { path = "../rspack_loader_runner" } -rspack_loader_sass = { path = "../rspack_loader_sass" } rspack_loader_swc = { path = "../rspack_loader_swc" } rspack_napi_shared = { path = "../rspack_napi_shared" } rspack_plugin_asset = { path = "../rspack_plugin_asset" } diff --git a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/fixtures__char-based-offset-error-span.snap b/crates/rspack_error/tests/fixtures/char-based-offset-error-span/fixtures__char-based-offset-error-span.snap deleted file mode 100644 index c0a3bbe17a7..00000000000 --- a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/fixtures__char-based-offset-error-span.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: crates/rspack_error/tests/fixtures.rs -expression: char-based-offset-error-span ---- - × Sass Error - ╭─[3:1] - 3 │ // a̐éö̲ - 4 │ .wrong { - 5 │ wrong: $wrong; - · ───┬── - · ╰── Undefined variable. - 6 │ } - ╰──── - diff --git a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.js b/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.js deleted file mode 100644 index 67aac616fc2..00000000000 --- a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.js +++ /dev/null @@ -1 +0,0 @@ -import './index.scss'; diff --git a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.scss b/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.scss deleted file mode 100644 index a6663622494..00000000000 --- a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/index.scss +++ /dev/null @@ -1,6 +0,0 @@ -// 一些中文注释 -// 一些 emoji:👏 👏 👏 -// a̐éö̲ -.wrong { - wrong: $wrong; -} diff --git a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/test.config.json b/crates/rspack_error/tests/fixtures/char-based-offset-error-span/test.config.json deleted file mode 100644 index 45a617d8b85..00000000000 --- a/crates/rspack_error/tests/fixtures/char-based-offset-error-span/test.config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "module": { - "rules": [ - { - "test": { - "type": "regexp", - "matcher": "\\.s[ac]ss$" - }, - "use": [{ "loader": "builtin:sass-loader" }], - "type": "css" - } - ] - } -} diff --git a/crates/rspack_error/tests/fixtures/sass-warnings/fixtures__sass-warnings.snap b/crates/rspack_error/tests/fixtures/sass-warnings/fixtures__sass-warnings.snap deleted file mode 100644 index d4a9492a04c..00000000000 --- a/crates/rspack_error/tests/fixtures/sass-warnings/fixtures__sass-warnings.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: crates/rspack_error/tests/fixtures.rs -expression: sass-warnings ---- - ⚠ Sass Warning - ╭─[1:1] - 1 │ .c { - 2 │ width: (12px/4px); - · ────┬─── - · ╰── Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0. - -Recommendation: math.div(12px, 4px) or calc(12px / 4px) - -More info and automated migrator: https://sass-lang.com/d/slash-div - 3 │ } - ╰──── - diff --git a/crates/rspack_error/tests/fixtures/sass-warnings/index.js b/crates/rspack_error/tests/fixtures/sass-warnings/index.js deleted file mode 100644 index b6d62f6ebe6..00000000000 --- a/crates/rspack_error/tests/fixtures/sass-warnings/index.js +++ /dev/null @@ -1 +0,0 @@ -import "./index.scss" diff --git a/crates/rspack_error/tests/fixtures/sass-warnings/index.scss b/crates/rspack_error/tests/fixtures/sass-warnings/index.scss deleted file mode 100644 index c15e450fd09..00000000000 --- a/crates/rspack_error/tests/fixtures/sass-warnings/index.scss +++ /dev/null @@ -1,3 +0,0 @@ -.c { - width: (12px/4px); -} \ No newline at end of file diff --git a/crates/rspack_error/tests/fixtures/sass-warnings/test.config.json b/crates/rspack_error/tests/fixtures/sass-warnings/test.config.json deleted file mode 100644 index 45a617d8b85..00000000000 --- a/crates/rspack_error/tests/fixtures/sass-warnings/test.config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "module": { - "rules": [ - { - "test": { - "type": "regexp", - "matcher": "\\.s[ac]ss$" - }, - "use": [{ "loader": "builtin:sass-loader" }], - "type": "css" - } - ] - } -} diff --git a/crates/rspack_loader_runner/src/loader.rs b/crates/rspack_loader_runner/src/loader.rs index 52b04203249..620a2f613c1 100644 --- a/crates/rspack_loader_runner/src/loader.rs +++ b/crates/rspack_loader_runner/src/loader.rs @@ -407,7 +407,7 @@ pub(crate) mod test { impl Identifiable for Builtin { fn identifier(&self) -> Identifier { - "builtin:sass-loader".into() + "builtin:test-loader".into() } } diff --git a/crates/rspack_loader_sass/Cargo.toml b/crates/rspack_loader_sass/Cargo.toml deleted file mode 100644 index 8c9831b42dd..00000000000 --- a/crates/rspack_loader_sass/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -edition = "2021" -license = "MIT" -name = "rspack_loader_sass" -repository = "https://github.com/web-infra-dev/rspack" -version = "0.1.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -async-trait = { workspace = true } -itertools = { workspace = true } -once_cell = { workspace = true } -regex = { workspace = true } -rspack_core = { path = "../rspack_core" } -rspack_error = { path = "../rspack_error" } -rspack_loader_runner = { path = "../rspack_loader_runner" } -sass-embedded = { version = "0.7.1", features = ["legacy", "serde"] } -serde = { workspace = true, features = ["derive"] } -str_indices = "0.4.1" -tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros", "test-util", "parking_lot"] } - -[dev-dependencies] -indexmap = { workspace = true } -rspack_testing = { path = "../rspack_testing" } diff --git a/crates/rspack_loader_sass/LICENSE b/crates/rspack_loader_sass/LICENSE deleted file mode 100644 index 46310101ad8..00000000000 --- a/crates/rspack_loader_sass/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2022-present Bytedance, Inc. and its affiliates. - - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/crates/rspack_loader_sass/src/lib.rs b/crates/rspack_loader_sass/src/lib.rs deleted file mode 100644 index 2408812d815..00000000000 --- a/crates/rspack_loader_sass/src/lib.rs +++ /dev/null @@ -1,566 +0,0 @@ -#![feature(let_chains)] - -use std::{ - env, - iter::Peekable, - path::{Path, PathBuf}, - sync::{mpsc, Arc}, -}; - -use itertools::Itertools; -use once_cell::sync::Lazy; -use regex::Regex; -use rspack_core::{ - rspack_sources::SourceMap, DependencyCategory, LoaderRunnerContext, Resolve, - ResolveOptionsWithDependencyType, ResolveResult, Resolver, ResolverFactory, -}; -use rspack_error::{ - internal_error, Diagnostic, DiagnosticKind, Error, InternalError, Result, Severity, - TraceableError, -}; -use rspack_loader_runner::{Identifiable, Identifier, Loader, LoaderContext}; -use sass_embedded::{ - legacy::{ - IndentType, LegacyImporter, LegacyImporterResult, LegacyImporterThis, LegacyOptions, - LegacyOptionsBuilder, LineFeed, OutputStyle, - }, - Exception, Logger, Sass, SourceSpan, Url, -}; -use serde::Deserialize; -use str_indices::utf16; - -static IS_SPECIAL_MODULE_IMPORT: Lazy = - Lazy::new(|| Regex::new(r"^~[^/]+$").expect("TODO:")); -static IS_NATIVE_WIN32_PATH: Lazy = - Lazy::new(|| Regex::new(r"(?i)^[a-z]:[/\\]|^\\\\").expect("TODO:")); -static MODULE_REQUEST: Lazy = Lazy::new(|| Regex::new(r"^[^?]*~").expect("TODO:")); -static IS_MODULE_IMPORT: Lazy = Lazy::new(|| { - Regex::new(r"^~([^/]+|[^/]+/|@[^/]+[/][^/]+|@[^/]+/?|@[^/]+[/][^/]+/)$").expect("TODO:") -}); - -fn get_os() -> &'static str { - match env::consts::OS { - "linux" => "linux", - "macos" => "darwin", - "windows" => "win32", - os => panic!("dart-sass-embedded is not supported for {os}"), - } -} - -fn get_arch() -> &'static str { - match env::consts::ARCH { - "x86" => "ia32", - "x86_64" => "x64", - "aarch64" => "arm64", - arch => panic!("dart-sass-embedded is not supported for {arch}"), - } -} - -fn dev_exe_path() -> PathBuf { - let os = get_os(); - let arch = get_arch(); - PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))) - .join(format!("../../node_modules/sass-embedded-{os}-{arch}")) - .join("dart-sass-embedded/dart-sass-embedded") -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", default)] -pub struct SassLoaderOptions { - sass_options: SassOptions, - // `None` means open or close source map depends on whether in production mode. - source_map: Option, - additional_data: Option, - rspack_importer: bool, - #[serde(rename = "__exePath")] - __exe_path: PathBuf, -} - -impl Default for SassLoaderOptions { - fn default() -> Self { - Self { - rspack_importer: true, - source_map: Default::default(), - additional_data: Default::default(), - sass_options: Default::default(), - __exe_path: dev_exe_path(), - } - } -} - -#[derive(Debug, Default, Deserialize)] -#[serde(rename_all = "camelCase", default)] -pub struct SassOptions { - indented_syntax: Option, - include_paths: Vec, - charset: Option, - indent_type: Option, - indent_width: Option, - linefeed: Option, - output_style: Option, - quiet_deps: Option, - verbose: Option, -} - -#[derive(Debug)] -struct RspackImporter { - include_paths: Vec, - sass_module_resolve: Arc, - sass_import_resolve: Arc, - rspack_module_resolve: Arc, - rspack_import_resolve: Arc, -} - -impl RspackImporter { - pub fn new(include_paths: Vec, factory: Arc) -> Self { - let sass_module_resolve = factory.get(ResolveOptionsWithDependencyType { - resolve_options: Some(Box::new(Resolve { - extensions: Some(vec![ - ".sass".to_owned(), - ".scss".to_owned(), - ".css".to_owned(), - ]), - alias: Some(Vec::new()), - prefer_relative: Some(true), - main_files: Some(vec!["_index".to_owned(), "index".to_owned()]), - main_fields: Some(Vec::new()), - // TODO: add restrictions field when resolver supports it. - ..Default::default() - })), - resolve_to_context: false, - dependency_category: DependencyCategory::Unknown, - }); - let sass_import_resolve = factory.get(ResolveOptionsWithDependencyType { - resolve_options: Some(Box::new(Resolve { - extensions: Some(vec![ - ".sass".to_owned(), - ".scss".to_owned(), - ".css".to_owned(), - ]), - alias: Some(Vec::new()), - prefer_relative: Some(true), - main_files: Some(vec![ - "_index.import".to_owned(), - "_index".to_owned(), - "index.import".to_owned(), - "index".to_owned(), - ]), - main_fields: Some(Vec::new()), - ..Default::default() - })), - resolve_to_context: false, - dependency_category: DependencyCategory::Unknown, - }); - let rspack_module_resolve = factory.get(ResolveOptionsWithDependencyType { - resolve_options: Some(Box::new(Resolve { - // TODO: add dependencyType. - condition_names: Some(vec!["sass".to_owned(), "style".to_owned()]), - main_fields: Some(vec![ - "sass".to_owned(), - "style".to_owned(), - "main".to_owned(), - "...".to_owned(), - ]), - main_files: Some(vec![ - "_index".to_owned(), - "index".to_owned(), - "...".to_owned(), - ]), - extensions: Some(vec![ - ".sass".to_owned(), - ".scss".to_owned(), - ".css".to_owned(), - ]), - prefer_relative: Some(true), - ..Default::default() - })), - resolve_to_context: false, - dependency_category: DependencyCategory::Unknown, - }); - let rspack_import_resolve = factory.get(ResolveOptionsWithDependencyType { - resolve_options: Some(Box::new(Resolve { - condition_names: Some(vec!["sass".to_owned(), "style".to_owned()]), - main_fields: Some(vec![ - "sass".to_owned(), - "style".to_owned(), - "main".to_owned(), - "...".to_owned(), - ]), - main_files: Some(vec![ - "_index.import".to_owned(), - "_index".to_owned(), - "index.import".to_owned(), - "index".to_owned(), - "...".to_owned(), - ]), - extensions: Some(vec![ - ".sass".to_owned(), - ".scss".to_owned(), - ".css".to_owned(), - ]), - prefer_relative: Some(true), - ..Default::default() - })), - resolve_to_context: false, - dependency_category: DependencyCategory::Unknown, - }); - Self { - include_paths, - sass_import_resolve, - sass_module_resolve, - rspack_import_resolve, - rspack_module_resolve, - } - } -} - -#[allow(clippy::result_large_err)] -fn get_possible_requests( - url: &str, - for_rspack_resolver: bool, - from_import: bool, -) -> std::result::Result, Exception> { - let mut request = url.to_string(); - if for_rspack_resolver { - if MODULE_REQUEST.is_match(url) { - request = MODULE_REQUEST.replace(&request, "").to_string(); - } - if IS_MODULE_IMPORT.is_match(url) { - if !request.ends_with('/') { - request.push('/'); - } - if request == url { - return Ok(vec![request]); - } - return Ok(vec![request, url.to_string()]); - } - } - - let request_path = Path::new(&request); - let ext = match request_path.extension() { - Some(ext) if ext.to_string_lossy() == "css" => return Ok(Vec::new()), - Some(ext) => format!(".{}", ext.to_string_lossy()), - None => "".to_owned(), - }; - - let dirname = request_path.parent(); - let dirname = if dirname.is_none() - || matches!( - dirname, - Some(p) if p == Path::new("") || p == Path::new(".") - ) { - "".to_owned() - } else { - // SAFETY: `unwrap` is ok since `None` is checked in if branch. - format!("{}/", dirname.expect("TODO:").display()) - }; - let basename = request_path - .file_name() - .ok_or_else(|| Exception::new("The path of sass's dependency should have file name"))? - .to_string_lossy(); - // SAFETY: `unwrap` is ok since `request_path` has file name is checked before. - let basename_without_ext = request_path.file_stem().expect("TODO:").to_string_lossy(); - - let mut requests = Vec::new(); - if from_import { - requests.push(format!("{dirname}_{basename_without_ext}.import{ext}")); - requests.push(format!("{dirname}{basename_without_ext}.import{ext}")); - } - requests.push(format!("{dirname}_{basename}")); - requests.push(format!("{dirname}{basename}")); - if for_rspack_resolver { - requests.push(url.to_string()); - } - Ok(requests.into_iter().unique().collect()) -} - -#[derive(Debug)] -struct Resolution<'r, 'c, I: Iterator> { - resolve: &'r Resolver, - context: &'c Path, - possible_requests: I, -} - -fn start_resolving<'r, 'c, I: Iterator>( - mut resolutions: Peekable>>, -) -> Option { - let resolution = resolutions.peek_mut()?; - if let Some(possible_request) = resolution.possible_requests.next() { - if let Ok(ResolveResult::Resource(resource)) = resolution - .resolve - .resolve(resolution.context, &possible_request) - { - Some(resource.path) - } else { - start_resolving(resolutions) - } - } else { - resolutions.next(); - start_resolving(resolutions) - } -} - -impl LegacyImporter for RspackImporter { - fn call( - &self, - options: &LegacyImporterThis, - request: &str, - context: &str, - ) -> sass_embedded::Result> { - let from_importer = options.from_import; - let need_emulate_sass_resolver = !IS_SPECIAL_MODULE_IMPORT.is_match(request) - && !request.starts_with('/') - && !IS_NATIVE_WIN32_PATH.is_match(request); - - let mut resolutions = Vec::new(); - if !self.include_paths.is_empty() && need_emulate_sass_resolver { - let sass_possible_requests = get_possible_requests(request, false, from_importer)?; - resolutions.extend(self.include_paths.iter().map(|context| Resolution { - resolve: if from_importer { - &self.sass_import_resolve - } else { - &self.sass_module_resolve - }, - context, - possible_requests: sass_possible_requests.clone().into_iter(), - })); - } - - let rspack_possible_requests = get_possible_requests(request, true, from_importer)?; - resolutions.push(Resolution { - resolve: if from_importer { - &self.rspack_import_resolve - } else { - &self.rspack_module_resolve - }, - context: Path::new(context) - .parent() - .ok_or_else(|| Exception::new(format!("dirname of {context} is `None`")))?, - possible_requests: rspack_possible_requests.into_iter(), - }); - Ok(start_resolving(resolutions.into_iter().peekable()).map(LegacyImporterResult::file)) - } -} - -#[derive(Debug)] -struct RspackLogger { - // `Sync` is required by the `Logger` trait - tx: mpsc::SyncSender>, -} - -impl Logger for RspackLogger { - fn warn(&self, message: &str, options: &sass_embedded::LoggerWarnOptions) { - self - .tx - .send(sass_log_to_diagnostics( - Severity::Warn, - message, - options.span.as_ref(), - )) - .expect("TODO:"); - } -} - -#[derive(Debug)] -pub struct SassLoader { - options: SassLoaderOptions, -} - -pub const SASS_LOADER_IDENTIFIER: &str = "builtin:sass-loader"; - -impl SassLoader { - pub fn new(options: SassLoaderOptions) -> Self { - Self { options } - } - - fn get_sass_options( - &self, - loader_context: &LoaderContext<'_, LoaderRunnerContext>, - content: String, - logger: RspackLogger, - ) -> LegacyOptions { - let mut builder = LegacyOptionsBuilder::default() - .data( - if let Some(additional_data) = &self.options.additional_data { - format!("{additional_data}\n{content}") - } else { - content - }, - ) - .logger(logger) - .file(loader_context.resource_path) - .source_map( - self - .options - .source_map - .unwrap_or_else(|| loader_context.context.options.devtool.enabled()), - ) - .source_map_contents(true) - // TODO: use OutputStyle::Compressed when loader_context.mode is production. - // .output_style( - // self - // .options - // .sass_options - // .output_style - // .unwrap_or(OutputStyle::Expanded), - // ) - .indented_syntax( - self - .options - .sass_options - .indented_syntax - .unwrap_or_else(|| { - Path::new(loader_context.resource_path) - .extension() - .map(|ext| ext == "sass") - .unwrap_or_default() - }), - ); - - let mut include_paths = vec![env::current_dir().expect("TODO:")]; - include_paths.extend(self.options.sass_options.include_paths.iter().map(|path| { - if path.is_absolute() { - path.to_owned() - } else { - env::current_dir().expect("TODO:").join(path) - } - })); - builder = builder.include_paths(&include_paths); - - if self.options.rspack_importer { - builder = builder.importer(RspackImporter::new( - include_paths, - Arc::clone(&loader_context.context.resolver_factory), - )); - } - - if let Some(charset) = &self.options.sass_options.charset { - builder = builder.charset(*charset); - } - if let Some(indent_type) = &self.options.sass_options.indent_type { - builder = builder.indent_type(indent_type.to_owned()); - } - if let Some(linefeed) = &self.options.sass_options.linefeed { - builder = builder.linefeed(linefeed.to_owned()); - } - if let Some(indent_width) = &self.options.sass_options.indent_width { - builder = builder.indent_width(*indent_width); - } - if let Some(quiet_deps) = &self.options.sass_options.quiet_deps { - builder = builder.quiet_deps(*quiet_deps); - } - if let Some(verbose) = &self.options.sass_options.verbose { - builder = builder.verbose(*verbose); - } - - builder.build() - } -} - -#[async_trait::async_trait] -impl Loader for SassLoader { - async fn run(&self, loader_context: &mut LoaderContext<'_, LoaderRunnerContext>) -> Result<()> { - let content = loader_context - .content - .to_owned() - .expect("content should available"); - let (tx, rx) = mpsc::sync_channel(8); - let logger = RspackLogger { tx }; - let sass_options = self.get_sass_options(loader_context, content.try_into_string()?, logger); - let result = Sass::new(&self.options.__exe_path) - .map_err(|e| { - InternalError::new( - format!( - "{}: The dart-sass-embedded path is {}, your OS is {}, your Arch is {}", - e.message(), - &self.options.__exe_path.display(), - get_os(), - get_arch(), - ), - Severity::Error, - ) - })? - .render(sass_options) - .map_err(sass_exception_to_error)?; - let source_map = result.map.map(|map| { - let mut map = SourceMap::from_slice(&map).expect("should be able to generate source-map"); - for source in map.sources_mut() { - if source.starts_with("file:") { - *source = Url::parse(source) - .expect("TODO:") - .to_file_path() - .expect("TODO:") - .display() - .to_string(); - } - } - map - }); - - loader_context.content = Some(result.css.into()); - loader_context.source_map = source_map; - rx.into_iter().flatten().for_each(|d| { - loader_context.emit_diagnostic(d); - }); - Ok(()) - } -} - -impl Identifiable for SassLoader { - fn identifier(&self) -> Identifier { - "builtin:sass-loader".into() - } -} - -fn sass_exception_to_error(e: Box) -> Error { - if let Some(span) = e.span() - && let Some(message) = e.sass_message() - && let Some(e) = make_traceable_error("Sass Error", message, span) - { - e.with_kind(DiagnosticKind::Scss).into() - } else { - internal_error!(e.message().to_string()) - } -} - -fn sass_log_to_diagnostics( - severity: Severity, - message: &str, - span: Option<&SourceSpan>, -) -> Vec { - let title = match severity { - Severity::Error => "Sass Error", - Severity::Warn => "Sass Warning", - }; - if let Some(span) = span - && let Some(e) = make_traceable_error(title, message, span) - { - vec![Error::from(e.with_kind(DiagnosticKind::Scss).with_severity(severity)).into()] - } else { - let f = match severity { - Severity::Error => Diagnostic::error, - Severity::Warn => Diagnostic::warn, - }; - let title = "sass-loader: ".to_string() + title; - vec![f(title, message.to_string())] - } -} - -fn make_traceable_error(title: &str, message: &str, span: &SourceSpan) -> Option { - span - .url - .as_ref() - .map(|url| { - url - .to_file_path() - .expect("TODO:") - .to_string_lossy() - .to_string() - }) - .and_then(|path| std::fs::read_to_string(path).ok()) - .map(|source| { - let start = utf16::to_byte_idx(&source, span.start.offset); - let end = utf16::to_byte_idx(&source, span.end.offset); - TraceableError::from_file(source, start, end, title.to_string(), message.to_string()) - }) -} diff --git a/crates/rspack_loader_sass/tests/expected/rspack_importer.css b/crates/rspack_loader_sass/tests/expected/rspack_importer.css deleted file mode 100644 index 5c72a7676b4..00000000000 --- a/crates/rspack_loader_sass/tests/expected/rspack_importer.css +++ /dev/null @@ -1,35 +0,0 @@ -@charset "UTF-8"; -@import "./file.css"; -body { - font: 100% Helvetica, sans-serif; - color: #333; -} - -nav ul { - margin: 0; - padding: 0; - list-style: none; -} -nav li { - display: inline-block; -} -nav a { - display: block; - padding: 6px 12px; - text-decoration: none; -} - -.box { - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - -ms-border-radius: 10px; - border-radius: 10px; -} - -.foo:before { - content: "\e0c6"; -} - -.bar:before { - content: "∑"; -} \ No newline at end of file diff --git a/crates/rspack_loader_sass/tests/fixtures.rs b/crates/rspack_loader_sass/tests/fixtures.rs deleted file mode 100644 index 495a306d260..00000000000 --- a/crates/rspack_loader_sass/tests/fixtures.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::{ - env, fs, - path::{Path, PathBuf}, - str::FromStr, - sync::Arc, -}; - -use rspack_core::{ - run_loaders, CompilerContext, CompilerOptions, Loader, LoaderRunnerContext, ResourceData, -}; -use rspack_loader_sass::{SassLoader, SassLoaderOptions}; -use rspack_testing::{fixture, test_fixture_css}; -use sass_embedded::Url; - -// UPDATE_SASS_LOADER_TEST=1 cargo test --package rspack_loader_sass test_fn_name -- --exact --nocapture -async fn loader_test(actual: impl AsRef, expected: impl AsRef) { - let tests_path = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))).join("tests"); - let expected_path = tests_path.join(expected); - let actual_path = tests_path.join(actual); - - let url = Url::from_file_path(actual_path.to_string_lossy().to_string()).expect("TODO:"); - let (result, _) = run_loaders( - &[Arc::new(SassLoader::new(SassLoaderOptions::default())) - as Arc>], - &ResourceData::new( - actual_path.to_string_lossy().to_string(), - url.to_file_path().expect("bad url file path"), - ) - .query_optional(url.query().map(|q| q.to_owned())) - .fragment_optional(url.fragment().map(|f| f.to_owned())), - &[], - CompilerContext { - options: std::sync::Arc::new(CompilerOptions { - bail: false, - context: rspack_core::Context::default(), - dev_server: rspack_core::DevServerOptions::default(), - devtool: rspack_core::Devtool::default(), - mode: rspack_core::Mode::None, - output: rspack_core::OutputOptions { - clean: false, - path: Default::default(), - public_path: Default::default(), - filename: rspack_core::Filename::from_str("").expect("TODO:"), - asset_module_filename: rspack_core::Filename::from_str("").expect("TODO:"), - wasm_loading: rspack_core::WasmLoading::Disable, - webassembly_module_filename: rspack_core::Filename::from_str("").expect("TODO:"), - chunk_filename: rspack_core::Filename::from_str("").expect("TODO:"), - cross_origin_loading: rspack_core::CrossOriginLoading::Disable, - unique_name: Default::default(), - chunk_loading: rspack_core::ChunkLoading::Enable(rspack_core::ChunkLoadingType::Jsonp), - chunk_loading_global: "webpackChunkwebpack".to_string(), - css_chunk_filename: rspack_core::Filename::from_str("").expect("TODO:"), - css_filename: rspack_core::Filename::from_str("").expect("TODO:"), - hot_update_chunk_filename: rspack_core::Filename::from_str("").expect("Should exist"), - hot_update_main_filename: rspack_core::Filename::from_str("").expect("Should exist"), - hot_update_global: "webpackHotUpdate".to_string(), - library: None, - enabled_library_types: None, - strict_module_error_handling: false, - global_object: "self".to_string(), - import_function_name: "import".to_string(), - iife: true, - module: false, - trusted_types: None, - source_map_filename: rspack_core::Filename::from_str("").expect("TODO:"), - hash_function: rspack_core::HashFunction::Xxhash64, - hash_digest: rspack_core::HashDigest::Hex, - hash_digest_length: 16, - hash_salt: rspack_core::HashSalt::None, - async_chunks: true, - worker_chunk_loading: rspack_core::ChunkLoading::Enable( - rspack_core::ChunkLoadingType::ImportScripts, - ), - worker_wasm_loading: rspack_core::WasmLoading::Disable, - worker_public_path: String::new(), - script_type: String::from("false"), - }, - target: rspack_core::Target::new(&vec![String::from("web")]).expect("TODO:"), - resolve: rspack_core::Resolve::default(), - resolve_loader: rspack_core::Resolve::default(), - builtins: Default::default(), - module: Default::default(), - stats: Default::default(), - cache: Default::default(), - snapshot: Default::default(), - experiments: Default::default(), - node: Default::default(), - optimization: rspack_core::Optimization { - remove_available_modules: false, - side_effects: Default::default(), - provided_exports: Default::default(), - used_exports: Default::default(), - inner_graph: Default::default(), - mangle_exports: Default::default(), - }, - profile: false, - }), - resolver_factory: Default::default(), - module: "".into(), - module_context: None, - }, - ) - .await - .expect("TODO:") - .split_into_parts(); - let result = result.content.try_into_string().expect("TODO:"); - - if env::var("UPDATE_SASS_LOADER_TEST").is_ok() { - fs::write(expected_path, result).expect("TODO:"); - } else { - let expected = fs::read_to_string(expected_path).expect("TODO:"); - assert_eq!(result, expected); - } -} - -#[tokio::test] -async fn rspack_importer() { - loader_test("scss/language.scss", "expected/rspack_importer.css").await; -} - -#[fixture("tests/fixtures/*")] -fn sass(fixture_path: PathBuf) { - test_fixture_css(&fixture_path); -} diff --git a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/expected/main.css b/crates/rspack_loader_sass/tests/fixtures/rspack_importer/expected/main.css deleted file mode 100644 index d8e7f7d7a08..00000000000 --- a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/expected/main.css +++ /dev/null @@ -1,38 +0,0 @@ -.color-red { - color: red; -} -@charset "UTF-8"; - -body { - font: 100% Helvetica, sans-serif; - color: #333; -} - -nav ul { - margin: 0; - padding: 0; - list-style: none; -} -nav li { - display: inline-block; -} -nav a { - display: block; - padding: 6px 12px; - text-decoration: none; -} - -.box { - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - -ms-border-radius: 10px; - border-radius: 10px; -} - -.foo:before { - content: "\e0c6"; -} - -.bar:before { - content: "∑"; -} diff --git a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/index.js b/crates/rspack_loader_sass/tests/fixtures/rspack_importer/index.js deleted file mode 100644 index 764b7eee70c..00000000000 --- a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/index.js +++ /dev/null @@ -1 +0,0 @@ -import '../../scss/language.scss'; diff --git a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/snapshot/output.snap b/crates/rspack_loader_sass/tests/fixtures/rspack_importer/snapshot/output.snap deleted file mode 100644 index 83ada6c249b..00000000000 --- a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/snapshot/output.snap +++ /dev/null @@ -1,44 +0,0 @@ ---- -source: crates/rspack_testing/src/run_fixture.rs ---- -```css title=main.css -.color-red { - color: red; -} -@charset "UTF-8"; - -body { - font: 100% Helvetica, sans-serif; - color: #333; -} - -nav ul { - margin: 0; - padding: 0; - list-style: none; -} -nav li { - display: inline-block; -} -nav a { - display: block; - padding: 6px 12px; - text-decoration: none; -} - -.box { - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - -ms-border-radius: 10px; - border-radius: 10px; -} - -.foo:before { - content: "\e0c6"; -} - -.bar:before { - content: "∑"; -} - -``` diff --git a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/test.config.json b/crates/rspack_loader_sass/tests/fixtures/rspack_importer/test.config.json deleted file mode 100644 index 45a617d8b85..00000000000 --- a/crates/rspack_loader_sass/tests/fixtures/rspack_importer/test.config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "module": { - "rules": [ - { - "test": { - "type": "regexp", - "matcher": "\\.s[ac]ss$" - }, - "use": [{ "loader": "builtin:sass-loader" }], - "type": "css" - } - ] - } -} diff --git a/crates/rspack_loader_sass/tests/scss/another/_variables.scss b/crates/rspack_loader_sass/tests/scss/another/_variables.scss deleted file mode 100644 index 83834dc5842..00000000000 --- a/crates/rspack_loader_sass/tests/scss/another/_variables.scss +++ /dev/null @@ -1 +0,0 @@ -$n-ary-summation: '\2211' diff --git a/crates/rspack_loader_sass/tests/scss/file.css b/crates/rspack_loader_sass/tests/scss/file.css deleted file mode 100644 index 1ce4f669dd7..00000000000 --- a/crates/rspack_loader_sass/tests/scss/file.css +++ /dev/null @@ -1,3 +0,0 @@ -.color-red { - color: red; -} \ No newline at end of file diff --git a/crates/rspack_loader_sass/tests/scss/language.scss b/crates/rspack_loader_sass/tests/scss/language.scss deleted file mode 100644 index cfcd68f6d94..00000000000 --- a/crates/rspack_loader_sass/tests/scss/language.scss +++ /dev/null @@ -1,48 +0,0 @@ -@import "another/variables"; -@import "./file.css"; - -$font-stack: Helvetica, sans-serif; -$primary-color: #333; -$pi: '\e0C6'; - -body { - font: 100% $font-stack; - color: $primary-color; -} - -nav { - ul { - margin: 0; - padding: 0; - list-style: none; - } - - li { display: inline-block; } - - a { - display: block; - padding: 6px 12px; - text-decoration: none; - } -} - -@mixin border-radius($radius) { - -webkit-border-radius: $radius; - -moz-border-radius: $radius; - -ms-border-radius: $radius; - border-radius: $radius; -} - -.box { @include border-radius(10px); } - -.foo { - &:before { - content: $pi; - } -} - -.bar { - &:before { - content: $n-ary-summation; - } -} diff --git a/crates/rspack_testing/Cargo.toml b/crates/rspack_testing/Cargo.toml index ebfbe47b78e..26045ca85ee 100644 --- a/crates/rspack_testing/Cargo.toml +++ b/crates/rspack_testing/Cargo.toml @@ -20,7 +20,6 @@ rspack_error = { path = "../rspack_error" } rspack_fs = { path = "../rspack_fs", features = ["async", "rspack-error"] } rspack_ids = { path = "../rspack_ids" } rspack_loader_runner = { path = "../rspack_loader_runner" } -rspack_loader_sass = { path = "../rspack_loader_sass" } rspack_loader_swc = { path = "../rspack_loader_swc" } rspack_plugin_asset = { path = "../rspack_plugin_asset" } rspack_plugin_css = { path = "../rspack_plugin_css" } diff --git a/crates/rspack_testing/src/loader.rs b/crates/rspack_testing/src/loader.rs index 8e50ab89447..e6c42b03e3a 100644 --- a/crates/rspack_testing/src/loader.rs +++ b/crates/rspack_testing/src/loader.rs @@ -4,21 +4,12 @@ use rspack_core::{ BoxLoader, CompilerOptions, NormalModule, Plugin, Resolver, BUILTIN_LOADER_PREFIX, }; use rspack_error::{internal_error, Result}; -use rspack_loader_sass::SASS_LOADER_IDENTIFIER; use rspack_loader_swc::SWC_LOADER_IDENTIFIER; #[derive(Debug)] pub struct BuiltinLoaderResolver; fn get_builtin_loader(builtin: &str, options: Option<&str>) -> BoxLoader { - if builtin.starts_with(SASS_LOADER_IDENTIFIER) { - return Arc::new(rspack_loader_sass::SassLoader::new( - serde_json::from_str(options.unwrap_or("{}")).unwrap_or_else(|e| { - panic!("Could not parse builtin:sass-loader options: {options:?}, error: {e:?}") - }), - )); - } - if builtin.starts_with(SWC_LOADER_IDENTIFIER) { return Arc::new( rspack_loader_swc::SwcLoader::new( diff --git a/package.json b/package.json index 4ec6a51f97e..e3d55ee82af 100644 --- a/package.json +++ b/package.json @@ -68,14 +68,5 @@ "webpack-cli": "4.10.0", "why-is-node-running": "2.2.1" }, - "optionalDependencies": { - "sass-embedded-darwin-arm64": "1.58.3", - "sass-embedded-darwin-x64": "1.58.3", - "sass-embedded-linux-arm64": "1.58.3", - "sass-embedded-linux-ia32": "1.58.3", - "sass-embedded-linux-x64": "1.58.3", - "sass-embedded-win32-ia32": "1.58.3", - "sass-embedded-win32-x64": "1.58.3" - }, "packageManager": "pnpm@8.10.5" } diff --git a/packages/rspack/src/config/adapterRuleUse.ts b/packages/rspack/src/config/adapterRuleUse.ts index a19c06daba3..2a509a8c504 100644 --- a/packages/rspack/src/config/adapterRuleUse.ts +++ b/packages/rspack/src/config/adapterRuleUse.ts @@ -229,17 +229,6 @@ type GetLoaderOptions = ( options: ComposeJsUseOptions ) => RuleSetLoaderWithOptions["options"]; -const getSassLoaderOptions: GetLoaderOptions = o => { - (o ??= {} as any).__exePath = require.resolve( - `sass-embedded-${process.platform}-${ - process.arch - }/dart-sass-embedded/dart-sass-embedded${ - process.platform === "win32" ? ".bat" : "" - }` - ); - return o; -}; - const getSwcLoaderOptions: GetLoaderOptions = (o, options) => { if (o && typeof o === "object" && o.rspackExperiments) { let expr = o.rspackExperiments; @@ -266,16 +255,6 @@ function getBuiltinLoaderOptions( o: RuleSetLoaderWithOptions["options"], options: ComposeJsUseOptions ): RuleSetLoaderWithOptions["options"] { - if (identifier.startsWith(`${BUILTIN_LOADER_PREFIX}sass-loader`)) { - deprecatedWarn( - `'builtin:sass-loader' has been deprecated, please migrate to ${termlink( - "sass-loader", - "https://github.com/webpack-contrib/sass-loader" - )}` - ); - return getSassLoaderOptions(o, options); - } - if (identifier.startsWith(`${BUILTIN_LOADER_PREFIX}swc-loader`)) { return getSwcLoaderOptions(o, options); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f4cbc0250b..e4d044d4605 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,28 +7,6 @@ settings: importers: .: - optionalDependencies: - sass-embedded-darwin-arm64: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-darwin-x64: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-linux-arm64: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-linux-ia32: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-linux-x64: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-win32-ia32: - specifier: 1.58.3 - version: 1.58.3 - sass-embedded-win32-x64: - specifier: 1.58.3 - version: 1.58.3 devDependencies: '@rspack/cli': specifier: workspace:* @@ -25830,69 +25808,6 @@ packages: rimraf: 2.7.1 dev: true - /sass-embedded-darwin-arm64@1.58.3: - resolution: {integrity: sha512-6CrksxvM10xKAQJX3KTJzrW6gfz21ExxUQnV6w5Ggje0adsq+QQu+BBgoPO2ziBVq+UiupcP7apcbmEHvyuZ7w==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-darwin-x64@1.58.3: - resolution: {integrity: sha512-clajXOWN0YP/WItxZJnmAvIiUBts6G28X8Oy/TPcNNzRSwRORHyHXKetbTazULWAkaSBJFFg95aP8sqJvmo+Iw==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-linux-arm64@1.58.3: - resolution: {integrity: sha512-dDaYRmV2vWxxZTiVFosfcgA6qJ+VEmHCFIO2XPO03W+uUmIGxa0G9oxdWxhLWjtUu2Z4R57sKKLj3eHI8Lj38Q==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-linux-ia32@1.58.3: - resolution: {integrity: sha512-UClCoXgaLNGHTLBRqUTQAgQXZQFkrGIaWVLIfkVN2AEyLmYJzZ31bQfq1B6mLZPBANuFQaeg3eOcdCTpNaXaOg==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-linux-x64@1.58.3: - resolution: {integrity: sha512-/waLcKwkWQp4QJrNz6EqTS44IdGYup5TGh/qmv3iz9UeL4LtgeM4lVHrFsknsF7viDPLuCOARdrHNSjqKkLRPw==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-win32-ia32@1.58.3: - resolution: {integrity: sha512-T6QYEf1NUDZY+9htvE7Zn9/Ixg0bXGQ54NcHBRSkyVY2n2KBLwQ2ZKp48AlSNxsvJiSOb9lqDE4U7VjH7WJSXg==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /sass-embedded-win32-x64@1.58.3: - resolution: {integrity: sha512-Jc6Q1Rx5+cxk/yIsI8trkpNQEHjVM9I65p7ArpCLfMU33YRQWUm35QCFH2Szaue3HnTtwXl3ZDQdgo0ZHCHLzg==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - /sass-loader@13.2.0: resolution: {integrity: sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==} engines: {node: '>= 14.15.0'}