@mandujs/core 0.20.5 → 0.20.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/core",
3
- "version": "0.20.5",
3
+ "version": "0.20.6",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -282,6 +282,17 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
282
282
  devtoolsScript = generateDevtoolsScript();
283
283
  }
284
284
 
285
+ // #179: body 내 <link> 태그를 <head>로 호이스팅
286
+ // React 컴포넌트(layout.tsx 등)에서 <link>를 렌더링하면 body 안에 위치하게 되는데,
287
+ // 폰트/스타일시트는 <head>에 있어야 FOUT 없이 로드됨
288
+ const linkTagPattern = /<link\s[^>]*(?:rel=["'](?:stylesheet|preconnect|preload|icon|dns-prefetch)["'][^>]*|href=["'][^"']+["'][^>]*)\/?\s*>/gi;
289
+ const hoistedLinks: string[] = [];
290
+ const bodyContent = content.replace(linkTagPattern, (match) => {
291
+ hoistedLinks.push(match);
292
+ return "";
293
+ });
294
+ const hoistedLinkTags = hoistedLinks.join("\n ");
295
+
285
296
  return `<!doctype html>
286
297
  <html lang="${escapeHtmlAttr(lang)}">
287
298
  <head>
@@ -289,11 +300,12 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
289
300
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
290
301
  <title>${escapeHtmlText(title)}</title>
291
302
  ${cssLinkTag}
303
+ ${hoistedLinkTags}
292
304
  ${headTags}
293
305
  ${collectedHeadTags}
294
306
  </head>
295
307
  <body>
296
- <div id="root">${content}</div>
308
+ <div id="root">${bodyContent}</div>
297
309
  ${dataScript}
298
310
  ${routeScript}
299
311
  ${hydrationScripts}
@@ -540,12 +540,15 @@ function generateHTMLTailContent(options: StreamingSSROptions): string {
540
540
  }
541
541
  }
542
542
 
543
- // 9. HMR 스크립트 (개발 모드 Zero-JS 페이지에서도 CSS 핫리로드 지원)
543
+ // 9. #179: body <link> 태그를 <head>로 호이스팅 (외부 폰트/스타일시트 지원)
544
+ scripts.push(`<script>document.querySelectorAll('#root link[rel="stylesheet"],#root link[rel="preconnect"],#root link[rel="preload"],#root link[rel="icon"],#root link[rel="dns-prefetch"]').forEach(function(l){document.head.appendChild(l)})</script>`);
545
+
546
+ // 10. HMR 스크립트 (개발 모드 — Zero-JS 페이지에서도 CSS 핫리로드 지원)
544
547
  if (isDev && hmrPort) {
545
548
  scripts.push(generateHMRScript(hmrPort));
546
549
  }
547
550
 
548
- // 10. DevTools 번들 로드 (개발 모드)
551
+ // 11. DevTools 번들 로드 (개발 모드)
549
552
  if (isDev) {
550
553
  scripts.push(`<script type="module" src="/.mandu/client/_devtools.js"></script>`);
551
554
  }