diff --git a/codepress-swc-plugin/src/lib.rs b/codepress-swc-plugin/src/lib.rs
index e9ccdfb..d79cd1d 100644
--- a/codepress-swc-plugin/src/lib.rs
+++ b/codepress-swc-plugin/src/lib.rs
@@ -2122,12 +2122,15 @@ impl CodePressTransform {
// Build the config object: window.__CODEPRESS_CONFIG__ = { repo: "...", branch: "..." }
// Uses Object.assign to avoid overwriting if somehow multiple modules try to set it
- // Also injects and tags
- // for content script detection (content scripts run in isolated JS context)
+ // Also injects a hidden div with data attributes for content script detection
+ // (content scripts run in isolated JS context and can't access window.__CODEPRESS_CONFIG__)
let escaped_repo = repo.replace('\\', "\\\\").replace('"', "\\\"");
let escaped_branch = branch.replace('\\', "\\\\").replace('"', "\\\"");
+ // Inject into document.body (not head) to avoid conflicts with React Portal-based libraries
+ // (like @react-oauth/google) which manipulate head and cause "removeChild" errors.
+ // Using setTimeout(0) to defer DOM manipulation until after React's render cycle.
let js = format!(
- "try{{if(typeof window!=='undefined'){{window.__CODEPRESS_CONFIG__=Object.assign(window.__CODEPRESS_CONFIG__||{{}},{{repo:\"{}\",branch:\"{}\"}});}}if(typeof document!=='undefined'&&document.head&&!document.querySelector('meta[name=\"codepress-repo\"]')){{var m=document.createElement('meta');m.name='codepress-repo';m.content='{}';document.head.appendChild(m);var b=document.createElement('meta');b.name='codepress-branch';b.content='{}';document.head.appendChild(b);}}}}catch(_){{}}",
+ "try{{if(typeof window!=='undefined'){{window.__CODEPRESS_CONFIG__=Object.assign(window.__CODEPRESS_CONFIG__||{{}},{{repo:\"{}\",branch:\"{}\"}});}}setTimeout(function(){{try{{if(typeof document!=='undefined'&&document.body&&!document.getElementById('__codepress_config')){{var d=document.createElement('div');d.id='__codepress_config';d.style.display='none';d.setAttribute('data-codepress-repo','{}');d.setAttribute('data-codepress-branch','{}');document.body.appendChild(d);}}}}catch(_){{}}}},0);}}catch(_){{}}",
escaped_repo, escaped_branch, escaped_repo, escaped_branch
);
diff --git a/src/index.ts b/src/index.ts
index 61241d1..6006462 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -197,6 +197,25 @@ export default function codePressPlugin(
return t.isJSXMemberExpression(name) || t.isJSXNamespacedName(name);
}
+ function isReactFragment(name: Babel.types.JSXIdentifier | Babel.types.JSXMemberExpression | Babel.types.JSXNamespacedName): boolean {
+ // Check for
+ if (t.isJSXIdentifier(name) && name.name === "Fragment") {
+ return true;
+ }
+ // Check for
+ if (t.isJSXMemberExpression(name)) {
+ if (
+ t.isJSXIdentifier(name.object) &&
+ name.object.name === "React" &&
+ t.isJSXIdentifier(name.property) &&
+ name.property.name === "Fragment"
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
return {
name: "babel-plugin-codepress-html",
visitor: {
@@ -322,6 +341,11 @@ try {
}
const { node } = nodePath;
+
+ // Skip React.Fragment - it can only accept key and children props
+ if (isReactFragment(node.name)) {
+ return;
+ }
const startLine = node.loc?.start.line ?? 0;
const parentLoc = nodePath.parent.loc;
const endLine = parentLoc?.end.line ?? startLine;