Skip to content

Commit 54ba7c0

Browse files
committed
feat: support resolveImport for css parser
1 parent 42c39a2 commit 54ba7c0

File tree

20 files changed

+443
-15
lines changed

20 files changed

+443
-15
lines changed

crates/node_binding/napi-binding.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,7 @@ export interface RawCssAutoGeneratorOptions {
20072007
export interface RawCssAutoParserOptions {
20082008
namedExports?: boolean
20092009
url?: boolean
2010+
resolveImport?: boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)
20102011
}
20112012

20122013
export interface RawCssChunkingPluginOptions {
@@ -2043,11 +2044,13 @@ export interface RawCssModuleGeneratorOptions {
20432044
export interface RawCssModuleParserOptions {
20442045
namedExports?: boolean
20452046
url?: boolean
2047+
resolveImport?: boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)
20462048
}
20472049

20482050
export interface RawCssParserOptions {
20492051
namedExports?: boolean
20502052
url?: boolean
2053+
resolveImport?: boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)
20512054
}
20522055

20532056
export interface RawDllEntryPluginOptions {

crates/rspack_binding_api/src/raw_options/raw_module/mod.rs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ use rspack_core::{
1717
AssetGeneratorOptions, AssetInlineGeneratorOptions, AssetParserDataUrl,
1818
AssetParserDataUrlOptions, AssetParserOptions, AssetResourceGeneratorOptions,
1919
CssAutoGeneratorOptions, CssAutoParserOptions, CssGeneratorOptions, CssModuleGeneratorOptions,
20-
CssModuleParserOptions, CssParserOptions, DescriptionData, DynamicImportFetchPriority,
21-
DynamicImportMode, ExportPresenceMode, FuncUseCtx, GeneratorOptions, GeneratorOptionsMap,
22-
JavascriptParserCommonjsExportsOption, JavascriptParserCommonjsOptions, JavascriptParserOptions,
23-
JavascriptParserOrder, JavascriptParserUrl, JsonGeneratorOptions, JsonParserOptions,
24-
ModuleNoParseRule, ModuleNoParseRules, ModuleNoParseTestFn, ModuleOptions, ModuleRule,
25-
ModuleRuleEffect, ModuleRuleEnforce, ModuleRuleUse, ModuleRuleUseLoader, OverrideStrict,
26-
ParseOption, ParserOptions, ParserOptionsMap, TypeReexportPresenceMode, UnsafeCachePredicate,
20+
CssModuleParserOptions, CssParserImport, CssParserImportFnArgs, CssParserOptions,
21+
DescriptionData, DynamicImportFetchPriority, DynamicImportMode, ExportPresenceMode, FuncUseCtx,
22+
GeneratorOptions, GeneratorOptionsMap, JavascriptParserCommonjsExportsOption,
23+
JavascriptParserCommonjsOptions, JavascriptParserOptions, JavascriptParserOrder,
24+
JavascriptParserUrl, JsonGeneratorOptions, JsonParserOptions, ModuleNoParseRule,
25+
ModuleNoParseRules, ModuleNoParseTestFn, ModuleOptions, ModuleRule, ModuleRuleEffect,
26+
ModuleRuleEnforce, ModuleRuleUse, ModuleRuleUseLoader, OverrideStrict, ParseOption,
27+
ParserOptions, ParserOptionsMap, TypeReexportPresenceMode, UnsafeCachePredicate,
2728
};
2829
use rspack_error::error;
2930
use rspack_napi::threadsafe_function::ThreadsafeFunction;
@@ -461,50 +462,96 @@ impl From<RawAssetParserDataUrlOptions> for AssetParserDataUrlOptions {
461462
}
462463
}
463464

465+
// Use tuple to pass arguments separately to JS function
466+
type RawCssImportFn = ThreadsafeFunction<
467+
(
468+
String,
469+
Option<String>,
470+
String,
471+
Option<String>,
472+
Option<String>,
473+
),
474+
bool,
475+
>;
476+
477+
fn convert_import_option(import: Option<Either<bool, RawCssImportFn>>) -> Option<CssParserImport> {
478+
import.map(|i| match i {
479+
Either::A(b) => CssParserImport::Bool(b),
480+
Either::B(f) => CssParserImport::Func(Arc::new(move |args: CssParserImportFnArgs| {
481+
let f = f.clone();
482+
Box::pin(async move {
483+
f.call_with_sync((
484+
args.url,
485+
args.media,
486+
args.resource_path,
487+
args.supports,
488+
args.layer,
489+
))
490+
.await
491+
})
492+
})),
493+
})
494+
}
495+
464496
#[derive(Debug, Default)]
465-
#[napi(object)]
497+
#[napi(object, object_to_js = false)]
466498
pub struct RawCssParserOptions {
467499
pub named_exports: Option<bool>,
468500
pub url: Option<bool>,
501+
#[napi(
502+
ts_type = "boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)"
503+
)]
504+
pub resolve_import: Option<Either<bool, RawCssImportFn>>,
469505
}
470506

471507
impl From<RawCssParserOptions> for CssParserOptions {
472508
fn from(value: RawCssParserOptions) -> Self {
473509
Self {
474510
named_exports: value.named_exports,
475511
url: value.url,
512+
resolve_import: convert_import_option(value.resolve_import),
476513
}
477514
}
478515
}
479516

480517
#[derive(Debug, Default)]
481-
#[napi(object)]
518+
#[napi(object, object_to_js = false)]
482519
pub struct RawCssAutoParserOptions {
483520
pub named_exports: Option<bool>,
484521
pub url: Option<bool>,
522+
#[napi(
523+
ts_type = "boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)"
524+
)]
525+
pub resolve_import: Option<Either<bool, RawCssImportFn>>,
485526
}
486527

487528
impl From<RawCssAutoParserOptions> for CssAutoParserOptions {
488529
fn from(value: RawCssAutoParserOptions) -> Self {
489530
Self {
490531
named_exports: value.named_exports,
491532
url: value.url,
533+
resolve_import: convert_import_option(value.resolve_import),
492534
}
493535
}
494536
}
495537

496538
#[derive(Debug, Default)]
497-
#[napi(object)]
539+
#[napi(object, object_to_js = false)]
498540
pub struct RawCssModuleParserOptions {
499541
pub named_exports: Option<bool>,
500542
pub url: Option<bool>,
543+
#[napi(
544+
ts_type = "boolean | ((args: [string, string | undefined, string, string | undefined, string | undefined]) => boolean)"
545+
)]
546+
pub resolve_import: Option<Either<bool, RawCssImportFn>>,
501547
}
502548

503549
impl From<RawCssModuleParserOptions> for CssModuleParserOptions {
504550
fn from(value: RawCssModuleParserOptions) -> Self {
505551
Self {
506552
named_exports: value.named_exports,
507553
url: value.url,
554+
resolve_import: convert_import_option(value.resolve_import),
508555
}
509556
}
510557
}

crates/rspack_core/src/options/module.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,25 +330,76 @@ pub struct AssetParserDataUrlOptions {
330330
pub max_size: Option<f64>,
331331
}
332332

333+
/// Arguments passed to the CSS parser import filter function
334+
pub struct CssParserImportFnArgs {
335+
pub url: String,
336+
pub media: Option<String>,
337+
pub resource_path: String,
338+
pub supports: Option<String>,
339+
pub layer: Option<String>,
340+
}
341+
342+
pub type CssParserImportFn =
343+
Arc<dyn Fn(CssParserImportFnArgs) -> BoxFuture<'static, Result<bool>> + Sync + Send>;
344+
345+
#[cacheable]
346+
pub enum CssParserImport {
347+
Bool(bool),
348+
Func(#[cacheable(with=Unsupported)] CssParserImportFn),
349+
}
350+
351+
impl Default for CssParserImport {
352+
fn default() -> Self {
353+
Self::Bool(true)
354+
}
355+
}
356+
357+
impl fmt::Debug for CssParserImport {
358+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359+
match self {
360+
Self::Bool(b) => write!(f, "CssParserImport::Bool({b})"),
361+
Self::Func(_) => write!(f, "CssParserImport::Func(...)"),
362+
}
363+
}
364+
}
365+
366+
impl Clone for CssParserImport {
367+
fn clone(&self) -> Self {
368+
match self {
369+
Self::Bool(b) => Self::Bool(*b),
370+
Self::Func(f) => Self::Func(f.clone()),
371+
}
372+
}
373+
}
374+
375+
impl MergeFrom for CssParserImport {
376+
fn merge_from(self, other: &Self) -> Self {
377+
other.clone()
378+
}
379+
}
380+
333381
#[cacheable]
334382
#[derive(Debug, Clone, MergeFrom)]
335383
pub struct CssParserOptions {
336384
pub named_exports: Option<bool>,
337385
pub url: Option<bool>,
386+
pub resolve_import: Option<CssParserImport>,
338387
}
339388

340389
#[cacheable]
341390
#[derive(Debug, Clone, MergeFrom)]
342391
pub struct CssAutoParserOptions {
343392
pub named_exports: Option<bool>,
344393
pub url: Option<bool>,
394+
pub resolve_import: Option<CssParserImport>,
345395
}
346396

347397
impl From<CssParserOptions> for CssAutoParserOptions {
348398
fn from(value: CssParserOptions) -> Self {
349399
Self {
350400
named_exports: value.named_exports,
351401
url: value.url,
402+
resolve_import: value.resolve_import,
352403
}
353404
}
354405
}
@@ -358,13 +409,15 @@ impl From<CssParserOptions> for CssAutoParserOptions {
358409
pub struct CssModuleParserOptions {
359410
pub named_exports: Option<bool>,
360411
pub url: Option<bool>,
412+
pub resolve_import: Option<CssParserImport>,
361413
}
362414

363415
impl From<CssParserOptions> for CssModuleParserOptions {
364416
fn from(value: CssParserOptions) -> Self {
365417
Self {
366418
named_exports: value.named_exports,
367419
url: value.url,
420+
resolve_import: value.resolve_import,
368421
}
369422
}
370423
}

crates/rspack_plugin_css/src/parser_and_generator/mod.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ use rspack_cacheable::{
1212
};
1313
use rspack_core::{
1414
BoxDependencyTemplate, BoxModuleDependency, BuildMetaDefaultObject, BuildMetaExportsType,
15-
ChunkGraph, Compilation, ConstDependency, CssExportsConvention, Dependency, DependencyId,
16-
DependencyRange, DependencyType, GenerateContext, LocalIdentName, Module, ModuleGraph,
17-
ModuleIdentifier, ModuleInitFragments, ModuleType, NormalModule, ParseContext, ParseResult,
18-
ParserAndGenerator, PrefetchExportsInfoMode, RuntimeGlobals, RuntimeSpec, SourceType,
19-
TemplateContext, UsageState,
15+
ChunkGraph, Compilation, ConstDependency, CssExportsConvention, CssParserImport,
16+
CssParserImportFnArgs, Dependency, DependencyId, DependencyRange, DependencyType,
17+
GenerateContext, LocalIdentName, Module, ModuleGraph, ModuleIdentifier, ModuleInitFragments,
18+
ModuleType, NormalModule, ParseContext, ParseResult, ParserAndGenerator, PrefetchExportsInfoMode,
19+
RuntimeGlobals, RuntimeSpec, SourceType, TemplateContext, UsageState,
2020
diagnostics::map_box_diagnostics_to_module_parse_diagnostics,
2121
remove_bom,
2222
rspack_sources::{BoxSource, ConcatSource, RawStringSource, ReplaceSource, Source, SourceExt},
@@ -83,6 +83,7 @@ pub struct CssParserAndGenerator {
8383
pub named_exports: bool,
8484
pub es_module: bool,
8585
pub url: bool,
86+
pub resolve_import: CssParserImport,
8687
#[cacheable(with=AsOption<AsMap<AsCacheable, AsVec>>)]
8788
pub exports: Option<CssExports>,
8889
pub local_names: Option<FxHashMap<String, String>>,
@@ -227,6 +228,29 @@ impl ParserAndGenerator for CssParserAndGenerator {
227228
)));
228229
continue;
229230
}
231+
// Check the import option
232+
let should_import = match &self.resolve_import {
233+
CssParserImport::Bool(b) => *b,
234+
CssParserImport::Func(f) => {
235+
// Call the filter function with the import arguments
236+
let args = CssParserImportFnArgs {
237+
url: request.to_string(),
238+
media: media.map(|s| s.to_string()),
239+
resource_path: resource_path
240+
.map(|p| p.as_str().to_string())
241+
.unwrap_or_default(),
242+
supports: supports.map(|s| s.to_string()),
243+
layer: layer.map(|s| s.to_string()),
244+
};
245+
match f(args).await {
246+
Ok(result) => result,
247+
Err(_) => true, // Default to include if function call fails
248+
}
249+
}
250+
};
251+
if !should_import {
252+
continue;
253+
}
230254
let request = replace_module_request_prefix(
231255
request,
232256
&mut diagnostics,

crates/rspack_plugin_css/src/plugin/impl_plugin_for_css_plugin.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ impl Plugin for CssPlugin {
519519
es_module: g.es_module.expect("should have es_module"),
520520
hot: false,
521521
url: p.url.expect("should have url"),
522+
resolve_import: p.resolve_import.clone().unwrap_or_default(),
522523
}) as Box<dyn ParserAndGenerator>
523524
}),
524525
);
@@ -548,6 +549,7 @@ impl Plugin for CssPlugin {
548549
es_module: g.es_module.expect("should have es_module"),
549550
hot: false,
550551
url: p.url.expect("should have url"),
552+
resolve_import: p.resolve_import.clone().unwrap_or_default(),
551553
}) as Box<dyn ParserAndGenerator>
552554
}),
553555
);
@@ -577,6 +579,7 @@ impl Plugin for CssPlugin {
577579
es_module: g.es_module.expect("should have es_module"),
578580
hot: false,
579581
url: p.url.expect("should have url"),
582+
resolve_import: p.resolve_import.clone().unwrap_or_default(),
580583
}) as Box<dyn ParserAndGenerator>
581584
}),
582585
);

packages/rspack/etc/core.api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,7 @@ export type CssAutoGeneratorOptions = {
16121612
export type CssAutoParserOptions = {
16131613
namedExports?: CssParserNamedExports;
16141614
url?: CssParserUrl;
1615+
resolveImport?: CssParserResolveImport;
16151616
};
16161617

16171618
// @public
@@ -1718,6 +1719,7 @@ export type CssModuleGeneratorOptions = CssAutoGeneratorOptions;
17181719
export type CssModuleParserOptions = {
17191720
namedExports?: CssParserNamedExports;
17201721
url?: CssParserUrl;
1722+
resolveImport?: CssParserResolveImport;
17211723
};
17221724

17231725
// @public (undocumented)
@@ -1727,8 +1729,12 @@ export type CssParserNamedExports = boolean;
17271729
export type CssParserOptions = {
17281730
namedExports?: CssParserNamedExports;
17291731
url?: CssParserUrl;
1732+
resolveImport?: CssParserResolveImport;
17301733
};
17311734

1735+
// @public (undocumented)
1736+
export type CssParserResolveImport = boolean | ((url: string, media: string | undefined, resourcePath: string, supports: string | undefined, layer: string | undefined) => boolean);
1737+
17321738
// @public (undocumented)
17331739
export type CssParserUrl = boolean;
17341740

@@ -6835,6 +6841,7 @@ declare namespace rspackExports {
68356841
AssetParserOptions,
68366842
CssParserNamedExports,
68376843
CssParserUrl,
6844+
CssParserResolveImport,
68386845
CssParserOptions,
68396846
CssAutoParserOptions,
68406847
CssModuleParserOptions,

packages/rspack/src/config/adapter.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,21 @@ function getRawCssParserOptions(
628628
return {
629629
namedExports: parser.namedExports,
630630
url: parser.url,
631+
resolveImport:
632+
parser.resolveImport === undefined
633+
? undefined
634+
: typeof parser.resolveImport === 'function'
635+
? (args) =>
636+
(
637+
parser.resolveImport as (
638+
url: string,
639+
media: string | undefined,
640+
resourcePath: string,
641+
supports: string | undefined,
642+
layer: string | undefined,
643+
) => boolean
644+
)(...args)
645+
: parser.resolveImport,
631646
};
632647
}
633648

0 commit comments

Comments
 (0)