Skip to content

Commit 67e4fe0

Browse files
committed
Make URL dependencies in MDX files optional
1 parent 6820335 commit 67e4fe0

File tree

3 files changed

+58
-42
lines changed

3 files changed

+58
-42
lines changed

packages/core/integration-tests/test/mdx.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe('mdx', function () {
108108
it('should support dependencies', async function () {
109109
await fsFixture(overlayFS, dir)`
110110
index.mdx:
111-
Testing [urls](another.mdx).
111+
Testing [urls](another.mdx). [optional](optional.html)
112112
113113
<audio src="some.mp3" />
114114
@@ -143,6 +143,8 @@ describe('mdx', function () {
143143
],
144144
{skipNodeModules: true},
145145
);
146+
147+
await run(b);
146148
});
147149

148150
it('should support code block props', async function () {

packages/transformers/js/core/src/dependency_collector.rs

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ impl<'a> DependencyCollector<'a> {
294294
kind: DependencyKind,
295295
source_type: SourceType,
296296
needs_stable_name: bool,
297+
optional: bool,
297298
) -> ast::Expr {
298299
// If not a library, replace with a require call pointing to a runtime that will resolve the url dynamically.
299300
if !self.config.is_library && !self.config.standalone {
@@ -302,7 +303,7 @@ impl<'a> DependencyCollector<'a> {
302303
span,
303304
kind,
304305
None,
305-
false,
306+
optional,
306307
source_type,
307308
needs_stable_name,
308309
);
@@ -329,7 +330,7 @@ impl<'a> DependencyCollector<'a> {
329330
)
330331
};
331332
let mut flags = DependencyFlags::empty();
332-
flags.set(DependencyFlags::OPTIONAL, span.is_dummy());
333+
flags.set(DependencyFlags::OPTIONAL, optional || span.is_dummy());
333334
flags.set(DependencyFlags::NEEDS_STABLE_NAME, needs_stable_name);
334335
self.items.push(DependencyDescriptor {
335336
kind,
@@ -812,41 +813,48 @@ impl<'a> Fold for DependencyCollector<'a> {
812813
};
813814
let mut node = node.clone();
814815

815-
let (specifier, span, needs_stable_name) = if let Some(s) = self.match_new_url(&arg.expr) {
816-
s
817-
} else if let Lit(ast::Lit::Str(str_)) = &*arg.expr {
818-
let (msg, docs) = if kind == DependencyKind::ServiceWorker {
819-
(
820-
"Registering service workers with a string literal is not supported.",
821-
"https://parceljs.org/languages/javascript/#service-workers",
822-
)
816+
let (specifier, span, needs_stable_name, optional) =
817+
if let Some(s) = self.match_new_url(&arg.expr) {
818+
s
819+
} else if let Lit(ast::Lit::Str(str_)) = &*arg.expr {
820+
let (msg, docs) = if kind == DependencyKind::ServiceWorker {
821+
(
822+
"Registering service workers with a string literal is not supported.",
823+
"https://parceljs.org/languages/javascript/#service-workers",
824+
)
825+
} else {
826+
(
827+
"Registering worklets with a string literal is not supported.",
828+
"https://parceljs.org/languages/javascript/#worklets",
829+
)
830+
};
831+
self.diagnostics.push(Diagnostic {
832+
message: msg.to_string(),
833+
code_highlights: Some(vec![CodeHighlight {
834+
message: None,
835+
loc: SourceLocation::from(&self.source_map, str_.span),
836+
}]),
837+
hints: Some(vec![format!(
838+
"Replace with: new URL('{}', import.meta.url)",
839+
str_.value,
840+
)]),
841+
show_environment: false,
842+
severity: DiagnosticSeverity::Error,
843+
documentation_url: Some(String::from(docs)),
844+
});
845+
return node;
823846
} else {
824-
(
825-
"Registering worklets with a string literal is not supported.",
826-
"https://parceljs.org/languages/javascript/#worklets",
827-
)
847+
return node;
828848
};
829-
self.diagnostics.push(Diagnostic {
830-
message: msg.to_string(),
831-
code_highlights: Some(vec![CodeHighlight {
832-
message: None,
833-
loc: SourceLocation::from(&self.source_map, str_.span),
834-
}]),
835-
hints: Some(vec![format!(
836-
"Replace with: new URL('{}', import.meta.url)",
837-
str_.value,
838-
)]),
839-
show_environment: false,
840-
severity: DiagnosticSeverity::Error,
841-
documentation_url: Some(String::from(docs)),
842-
});
843-
return node;
844-
} else {
845-
return node;
846-
};
847849

848-
node.args[0].expr =
849-
Box::new(self.add_url_dependency(specifier, span, kind, source_type, needs_stable_name));
850+
node.args[0].expr = Box::new(self.add_url_dependency(
851+
specifier,
852+
span,
853+
kind,
854+
source_type,
855+
needs_stable_name,
856+
optional,
857+
));
850858

851859
match opts {
852860
Some(opts) => {
@@ -980,7 +988,7 @@ impl<'a> Fold for DependencyCollector<'a> {
980988

981989
if let Some(args) = &node.args {
982990
if !args.is_empty() {
983-
let (specifier, span, needs_stable_name) =
991+
let (specifier, span, needs_stable_name, optional) =
984992
if let Some(s) = self.match_new_url(&args[0].expr) {
985993
s
986994
} else if let Lit(ast::Lit::Str(str_)) = &*args[0].expr {
@@ -1019,6 +1027,7 @@ impl<'a> Fold for DependencyCollector<'a> {
10191027
DependencyKind::WebWorker,
10201028
source_type,
10211029
needs_stable_name,
1030+
optional,
10221031
);
10231032

10241033
// Replace argument with a require call to resolve the URL at runtime.
@@ -1065,18 +1074,19 @@ impl<'a> Fold for DependencyCollector<'a> {
10651074
return expr;
10661075
}
10671076

1068-
if let Some((specifier, span, needs_stable_name)) = self.match_new_url(&node) {
1077+
if let Some((specifier, span, needs_stable_name, optional)) = self.match_new_url(&node) {
10691078
let url = self.add_url_dependency(
10701079
specifier,
10711080
span,
10721081
DependencyKind::Url,
10731082
self.config.source_type,
10741083
needs_stable_name,
1084+
optional,
10751085
);
10761086

10771087
// If this is a library, we will already have a URL object. Otherwise, we need to
10781088
// construct one from the string returned by the JSRuntime.
1079-
if !self.config.is_library && !self.config.standalone {
1089+
if !self.config.is_library && !self.config.standalone && !optional {
10801090
return Expr::New(NewExpr {
10811091
span: DUMMY_SP,
10821092
callee: Box::new(Expr::Ident(Ident::new_no_ctxt("URL".into(), DUMMY_SP))),
@@ -1387,7 +1397,10 @@ impl Fold for PromiseTransformer {
13871397
}
13881398

13891399
impl<'a> DependencyCollector<'a> {
1390-
fn match_new_url(&mut self, expr: &ast::Expr) -> Option<(JsWord, swc_core::common::Span, bool)> {
1400+
fn match_new_url(
1401+
&mut self,
1402+
expr: &ast::Expr,
1403+
) -> Option<(JsWord, swc_core::common::Span, bool, bool)> {
13911404
use ast::*;
13921405

13931406
if let Expr::New(new) = expr {
@@ -1409,7 +1422,7 @@ impl<'a> DependencyCollector<'a> {
14091422

14101423
if let Some(arg) = args.get(1) {
14111424
if self.is_import_meta_url(&arg.expr) {
1412-
return Some((specifier, span, false));
1425+
return Some((specifier, span, false, false));
14131426
}
14141427
}
14151428
}
@@ -1430,7 +1443,7 @@ impl<'a> DependencyCollector<'a> {
14301443
false
14311444
};
14321445

1433-
return Some((specifier, span, needs_stable_name));
1446+
return Some((specifier, span, needs_stable_name, true));
14341447
}
14351448
}
14361449
}
@@ -1443,7 +1456,7 @@ impl<'a> DependencyCollector<'a> {
14431456
Expr::Member(member) => member.span,
14441457
_ => unreachable!(),
14451458
};
1446-
return Some((specifier.into(), span, false));
1459+
return Some((specifier.into(), span, false, false));
14471460
}
14481461

14491462
None

packages/transformers/js/src/JSTransformer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,7 @@ export default (new Transformer({
863863
bundleBehavior: 'isolated',
864864
loc: convertLoc(dep.loc),
865865
needsStableName: Boolean(dep.flags & NEEDS_STABLE_NAME),
866+
isOptional: Boolean(dep.flags & OPTIONAL),
866867
meta: {
867868
placeholder: dep.placeholder,
868869
},

0 commit comments

Comments
 (0)