Skip to content

Commit cac69b1

Browse files
committed
adding element with key as child of cpProvider
1 parent 33ec909 commit cac69b1

File tree

1 file changed

+68
-14
lines changed
  • codepress-swc-plugin/src

1 file changed

+68
-14
lines changed

codepress-swc-plugin/src/lib.rs

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,22 +2161,18 @@ impl CodePressTransform {
21612161
return;
21622162
}
21632163

2164-
// Skip if file uses Next.js font loaders (same check as ensure_provider_inline)
2165-
for item in &m.body {
2166-
if let ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) = item {
2167-
let src = atom_to_string(&import_decl.src.value);
2168-
if src.starts_with("next/font/") || src.starts_with("@next/font/") {
2169-
return;
2170-
}
2171-
}
2172-
}
2164+
// NOTE: We intentionally do NOT skip files with Next.js fonts here.
2165+
// Unlike the legacy per-component __CPProvider wrapping which could
2166+
// interfere with font optimization, __CPRefreshProvider only uses
2167+
// useSyncExternalStore and simply returns children - no context wrapping.
2168+
// This allows HMR to work even in files that use next/font.
21732169

21742170
// Check if file is TSX/JSX (has JSX content)
21752171
if !file.ends_with(".tsx") && !file.ends_with(".jsx") {
21762172
return;
21772173
}
21782174

2179-
// import { useSyncExternalStore } from "react";
2175+
// import { useSyncExternalStore, createElement } from "react";
21802176
let import_decl = ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl {
21812177
span: DUMMY_SP,
21822178
specifiers: vec![
@@ -2186,6 +2182,12 @@ impl CodePressTransform {
21862182
imported: None,
21872183
is_type_only: false,
21882184
}),
2185+
ImportSpecifier::Named(ImportNamedSpecifier {
2186+
span: DUMMY_SP,
2187+
local: cp_ident("createElement".into()),
2188+
imported: None,
2189+
is_type_only: false,
2190+
}),
21892191
],
21902192
src: Box::new(Str {
21912193
span: DUMMY_SP,
@@ -2403,14 +2405,14 @@ impl CodePressTransform {
24032405
ctxt: SyntaxContext::empty(),
24042406
});
24052407

2406-
// const _ = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2408+
// const __cpV = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
24072409
let use_sync_stmt = Stmt::Decl(Decl::Var(Box::new(VarDecl {
24082410
span: DUMMY_SP,
24092411
kind: VarDeclKind::Const,
24102412
declare: false,
24112413
decls: vec![VarDeclarator {
24122414
span: DUMMY_SP,
2413-
name: Pat::Ident(BindingIdent { id: cp_ident("_".into()), type_ann: None }),
2415+
name: Pat::Ident(BindingIdent { id: cp_ident("__cpV".into()), type_ann: None }),
24142416
init: Some(Box::new(Expr::Call(CallExpr {
24152417
span: DUMMY_SP,
24162418
callee: Callee::Expr(Box::new(Expr::Ident(cp_ident("useSyncExternalStore".into())))),
@@ -2429,10 +2431,62 @@ impl CodePressTransform {
24292431
ctxt: SyntaxContext::empty(),
24302432
})));
24312433

2432-
// return children;
2434+
// return createElement("div", { key: __cpV, style: { display: "contents" } }, children);
2435+
// Using a div with display:contents so it's layout-neutral but has a key to force remount
24332436
let return_children = Stmt::Return(ReturnStmt {
24342437
span: DUMMY_SP,
2435-
arg: Some(Box::new(Expr::Ident(cp_ident("children".into())))),
2438+
arg: Some(Box::new(Expr::Call(CallExpr {
2439+
span: DUMMY_SP,
2440+
callee: Callee::Expr(Box::new(Expr::Ident(cp_ident("createElement".into())))),
2441+
args: vec![
2442+
// "div"
2443+
ExprOrSpread {
2444+
spread: None,
2445+
expr: Box::new(Expr::Lit(Lit::Str(Str {
2446+
span: DUMMY_SP,
2447+
value: "div".into(),
2448+
raw: None,
2449+
}))),
2450+
},
2451+
// { key: __cpV, style: { display: "contents" } }
2452+
ExprOrSpread {
2453+
spread: None,
2454+
expr: Box::new(Expr::Object(ObjectLit {
2455+
span: DUMMY_SP,
2456+
props: vec![
2457+
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
2458+
key: PropName::Ident(cp_ident_name("key".into())),
2459+
value: Box::new(Expr::Ident(cp_ident("__cpV".into()))),
2460+
}))),
2461+
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
2462+
key: PropName::Ident(cp_ident_name("style".into())),
2463+
value: Box::new(Expr::Object(ObjectLit {
2464+
span: DUMMY_SP,
2465+
props: vec![
2466+
PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
2467+
key: PropName::Ident(cp_ident_name("display".into())),
2468+
value: Box::new(Expr::Lit(Lit::Str(Str {
2469+
span: DUMMY_SP,
2470+
value: "contents".into(),
2471+
raw: None,
2472+
}))),
2473+
}))),
2474+
],
2475+
})),
2476+
}))),
2477+
],
2478+
})),
2479+
},
2480+
// children
2481+
ExprOrSpread {
2482+
spread: None,
2483+
expr: Box::new(Expr::Ident(cp_ident("children".into()))),
2484+
},
2485+
],
2486+
type_args: None,
2487+
#[cfg(not(feature = "compat_0_87"))]
2488+
ctxt: SyntaxContext::empty(),
2489+
}))),
24362490
});
24372491

24382492
// function __CPRefreshProvider({ children }) { ... }

0 commit comments

Comments
 (0)