@webjsdev/server 0.8.18 → 0.8.19
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 +1 -1
- package/src/ssr.js +25 -13
package/package.json
CHANGED
package/src/ssr.js
CHANGED
|
@@ -586,16 +586,9 @@ async function collectMetadata(route, ctx, dev) {
|
|
|
586
586
|
* @returns {{ head: string, body: string }}
|
|
587
587
|
*/
|
|
588
588
|
function hoistHeadTags(headHtml, bodyHtml) {
|
|
589
|
-
|
|
590
|
-
//
|
|
591
|
-
const
|
|
592
|
-
|
|
593
|
-
let remaining = bodyHtml;
|
|
594
|
-
let m;
|
|
595
|
-
while ((m = re.exec(remaining)) !== null) {
|
|
596
|
-
hoisted.push(m[1]);
|
|
597
|
-
remaining = remaining.slice(m[0].length);
|
|
598
|
-
}
|
|
589
|
+
// Shares the leading-run scanner (comment-skipping included) with the
|
|
590
|
+
// streaming path so both hoist identically. See collectHoistedHeadTags.
|
|
591
|
+
const { tags: hoisted, body: remaining } = collectHoistedHeadTags(bodyHtml);
|
|
599
592
|
if (!hoisted.length) return { head: headHtml, body: bodyHtml };
|
|
600
593
|
const newHead = headHtml.replace('</head>', hoisted.join('\n') + '\n</head>');
|
|
601
594
|
return { head: newHead, body: remaining };
|
|
@@ -744,14 +737,33 @@ function wrapInDocument(body, opts) {
|
|
|
744
737
|
*/
|
|
745
738
|
function collectHoistedHeadTags(bodyHtml) {
|
|
746
739
|
const tags = [];
|
|
747
|
-
|
|
740
|
+
// <script>…</script> and <style>…</style> are paired; <link …> is void.
|
|
741
|
+
// A plain HTML comment (<!-- … -->) is consumed but NOT hoisted, so a
|
|
742
|
+
// comment interleaved with head-bound tags (e.g. "<!-- Self-hosted fonts -->"
|
|
743
|
+
// between a favicon <link> and the stylesheet <link>) does not terminate
|
|
744
|
+
// the leading run and strand the stylesheet in <body>, which caused FOUC
|
|
745
|
+
// because a <link rel="stylesheet"> in <body> is not reliably
|
|
746
|
+
// render-blocking (#406). The `(?!/?wj:)` guard exempts client-router
|
|
747
|
+
// markers (<!--wj:children:…-->, <!--/wj:children-->) so a layout that
|
|
748
|
+
// renders children directly after its head tags still terminates the run
|
|
749
|
+
// there rather than swallowing the nesting marker.
|
|
750
|
+
const re =
|
|
751
|
+
/^\s*(<!--(?!\/?wj:)[\s\S]*?-->|<script[\s>][\s\S]*?<\/script>|<style[\s>][\s\S]*?<\/style>|<link\b[^>]*>)/i;
|
|
748
752
|
let remaining = bodyHtml;
|
|
753
|
+
// `body` only advances to just-past the LAST hoisted head tag. Comments
|
|
754
|
+
// are scanned through (so they don't terminate the run) but a comment that
|
|
755
|
+
// trails the final head tag stays in the body rather than being dropped.
|
|
756
|
+
let body = bodyHtml;
|
|
749
757
|
let m;
|
|
750
758
|
while ((m = re.exec(remaining)) !== null) {
|
|
751
|
-
|
|
759
|
+
const token = m[1];
|
|
752
760
|
remaining = remaining.slice(m[0].length);
|
|
761
|
+
if (!token.startsWith('<!--')) {
|
|
762
|
+
tags.push(token);
|
|
763
|
+
body = remaining;
|
|
764
|
+
}
|
|
753
765
|
}
|
|
754
|
-
return { tags, body
|
|
766
|
+
return { tags, body };
|
|
755
767
|
}
|
|
756
768
|
|
|
757
769
|
/**
|