@master/internal-site 0.2.3 → 0.2.4
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/dist/astro.mjs +26 -3
- package/package.json +1 -1
- package/src/astro/index.ts +2 -1
- package/src/astro/island-scripts.ts +31 -0
- package/src/astro/style-assets.ts +2 -2
- package/src/layouts/Document.astro +4 -2
package/dist/astro.mjs
CHANGED
|
@@ -250,7 +250,7 @@ async function inlineGeneratedStyles(file, ancestors = []) {
|
|
|
250
250
|
}
|
|
251
251
|
/** Preserve HTML link order and each reusable entry's cache identity. Originals
|
|
252
252
|
* remain available to any JS/CSS references; no client loading logic is added. */
|
|
253
|
-
async function compactStyleAssets(output) {
|
|
253
|
+
async function compactStyleAssets(output, transformPage = (html) => html) {
|
|
254
254
|
const root = resolve(output), replacements = /* @__PURE__ */ new Map();
|
|
255
255
|
const documents = /* @__PURE__ */ new Map(), users = /* @__PURE__ */ new Map();
|
|
256
256
|
const boundaries = /* @__PURE__ */ new Set();
|
|
@@ -322,9 +322,32 @@ async function compactStyleAssets(output) {
|
|
|
322
322
|
await flush();
|
|
323
323
|
html = html.replace(run[0], replacement);
|
|
324
324
|
}
|
|
325
|
-
await writeFile(file, html);
|
|
325
|
+
await writeFile(file, transformPage(html));
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
|
+
// src/astro/island-scripts.ts
|
|
329
|
+
const islandScriptSlot = "<!--master-site:island-scripts-->";
|
|
330
|
+
const islandStyles = "<style>astro-island,astro-slot,astro-static-slot{display:contents}</style>";
|
|
331
|
+
/** Move Astro's first client:load preamble ahead of the stylesheets. A classic
|
|
332
|
+
* script after a stylesheet pauses HTML parsing until that stylesheet arrives. */
|
|
333
|
+
function hoistIslandScripts(html) {
|
|
334
|
+
const slot = html.indexOf(islandScriptSlot);
|
|
335
|
+
if (slot < 0) return html;
|
|
336
|
+
const unchanged = () => html.replace(islandScriptSlot, "");
|
|
337
|
+
const headEnd = html.indexOf("</head>", slot);
|
|
338
|
+
const body = html.indexOf("<body", headEnd);
|
|
339
|
+
if (headEnd < 0 || body < 0) return unchanged();
|
|
340
|
+
const island = html.indexOf("<astro-island ", body);
|
|
341
|
+
const styles = html.indexOf(islandStyles, body);
|
|
342
|
+
if (island < 0 || styles < 0 || styles > island) return unchanged();
|
|
343
|
+
const start = styles + 74;
|
|
344
|
+
const preamble = html.slice(start, island);
|
|
345
|
+
const scripts = preamble.match(/<script>[\s\S]*?<\/script>/g);
|
|
346
|
+
if (!scripts || scripts.length !== 2 || preamble.trim() !== scripts.join("")) return unchanged();
|
|
347
|
+
const [directive, runtime] = scripts;
|
|
348
|
+
if (!directive.includes("astro:load") || !directive.includes("self.Astro") || !runtime.includes("customElements.define(") || !runtime.includes("astro-island")) return unchanged();
|
|
349
|
+
return (html.slice(0, start) + html.slice(island)).replace(islandScriptSlot, directive + runtime);
|
|
350
|
+
}
|
|
328
351
|
// src/docs-shell/remark/slug-and-toc.js
|
|
329
352
|
function remarkSlugAndTOC() {
|
|
330
353
|
return (tree) => {
|
|
@@ -688,7 +711,7 @@ function masterSite(site) {
|
|
|
688
711
|
recursive: true,
|
|
689
712
|
force: false
|
|
690
713
|
});
|
|
691
|
-
await compactStyleAssets(fileURLToPath(destination));
|
|
714
|
+
await compactStyleAssets(fileURLToPath(destination), hoistIslandScripts);
|
|
692
715
|
}
|
|
693
716
|
}
|
|
694
717
|
};
|
package/package.json
CHANGED
package/src/astro/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import serverStyles from './server-styles'
|
|
|
17
17
|
import svgMarkup from './svg-markup'
|
|
18
18
|
import localizedMdx from './localized-mdx'
|
|
19
19
|
import { compactStyleAssets } from './style-assets'
|
|
20
|
+
import { hoistIslandScripts } from './island-scripts'
|
|
20
21
|
import remarkSlugAndTOC from '../docs-shell/remark/slug-and-toc.js'
|
|
21
22
|
import remarkMarkdownComponents from '../docs-shell/remark/markdown-components.js'
|
|
22
23
|
import svgoConfig from '../docs-shell/common/svgo.config.js'
|
|
@@ -123,7 +124,7 @@ export default function masterSite(site: SiteConfig): AstroIntegration {
|
|
|
123
124
|
const destination = output
|
|
124
125
|
await mkdir(destination, { recursive: true })
|
|
125
126
|
await cp(new URL('../public/', import.meta.url), destination, { recursive: true, force: false })
|
|
126
|
-
await compactStyleAssets(fileURLToPath(destination))
|
|
127
|
+
await compactStyleAssets(fileURLToPath(destination), hoistIslandScripts)
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const islandScriptSlot = '<!--master-site:island-scripts-->'
|
|
2
|
+
|
|
3
|
+
const islandStyles = '<style>astro-island,astro-slot,astro-static-slot{display:contents}</style>'
|
|
4
|
+
|
|
5
|
+
/** Move Astro's first client:load preamble ahead of the stylesheets. A classic
|
|
6
|
+
* script after a stylesheet pauses HTML parsing until that stylesheet arrives. */
|
|
7
|
+
export function hoistIslandScripts(html: string) {
|
|
8
|
+
const slot = html.indexOf(islandScriptSlot)
|
|
9
|
+
if (slot < 0) return html
|
|
10
|
+
const unchanged = () => html.replace(islandScriptSlot, '')
|
|
11
|
+
|
|
12
|
+
const headEnd = html.indexOf('</head>', slot)
|
|
13
|
+
const body = html.indexOf('<body', headEnd)
|
|
14
|
+
if (headEnd < 0 || body < 0) return unchanged()
|
|
15
|
+
|
|
16
|
+
const island = html.indexOf('<astro-island ', body)
|
|
17
|
+
const styles = html.indexOf(islandStyles, body)
|
|
18
|
+
if (island < 0 || styles < 0 || styles > island) return unchanged()
|
|
19
|
+
|
|
20
|
+
const start = styles + islandStyles.length
|
|
21
|
+
const preamble = html.slice(start, island)
|
|
22
|
+
const scripts = preamble.match(/<script>[\s\S]*?<\/script>/g)
|
|
23
|
+
if (!scripts || scripts.length !== 2 || preamble.trim() !== scripts.join('')) return unchanged()
|
|
24
|
+
const [directive, runtime] = scripts
|
|
25
|
+
// Leave unfamiliar Astro output alone. Only the shell's known first island
|
|
26
|
+
// can supply this preamble. Author scripts and later directives stay put.
|
|
27
|
+
if (!directive.includes('astro:load') || !directive.includes('self.Astro')
|
|
28
|
+
|| !runtime.includes('customElements.define(') || !runtime.includes('astro-island')) return unchanged()
|
|
29
|
+
|
|
30
|
+
return (html.slice(0, start) + html.slice(island)).replace(islandScriptSlot, directive + runtime)
|
|
31
|
+
}
|
|
@@ -30,7 +30,7 @@ export async function inlineGeneratedStyles(file: string, ancestors: string[] =
|
|
|
30
30
|
|
|
31
31
|
/** Preserve HTML link order and each reusable entry's cache identity. Originals
|
|
32
32
|
* remain available to any JS/CSS references; no client loading logic is added. */
|
|
33
|
-
export async function compactStyleAssets(output: string) {
|
|
33
|
+
export async function compactStyleAssets(output: string, transformPage = (html: string) => html) {
|
|
34
34
|
const root = resolve(output), replacements = new Map<string, string>()
|
|
35
35
|
const documents = new Map<string, string>(), users = new Map<string, string[]>()
|
|
36
36
|
const boundaries = new Set<string>()
|
|
@@ -102,6 +102,6 @@ export async function compactStyleAssets(output: string) {
|
|
|
102
102
|
await flush()
|
|
103
103
|
html = html.replace(run[0], replacement)
|
|
104
104
|
}
|
|
105
|
-
await writeFile(file, html)
|
|
105
|
+
await writeFile(file, transformPage(html))
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -9,6 +9,7 @@ import { localizePathname } from '../astro/route-paths'
|
|
|
9
9
|
import { siteContextElementId } from '../docs-shell/site'
|
|
10
10
|
import type { Metadata } from '../docs-shell/types/Metadata'
|
|
11
11
|
import type { PageAssets } from '../astro/propagated-assets'
|
|
12
|
+
import { islandScriptSlot } from '../astro/island-scripts'
|
|
12
13
|
import NavigationTransition from './NavigationTransition.astro'
|
|
13
14
|
|
|
14
15
|
interface Props {
|
|
@@ -50,14 +51,15 @@ if (['dark', 'light'].includes(value)) document.documentElement.style.colorSchem
|
|
|
50
51
|
<link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="any" />
|
|
51
52
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
52
53
|
<script is:inline blocking="render" set:html={themeScript}></script>
|
|
54
|
+
{!bare && import.meta.env.PROD && <Fragment set:html={islandScriptSlot} />}
|
|
53
55
|
<link blocking="render" rel="preload" as="font" href="/fonts/GeistVariable.woff2" crossorigin="anonymous" />
|
|
54
56
|
<link blocking="render" rel="preload" as="font" href="/fonts/IBMPlexMono-Regular.woff2" crossorigin="anonymous" />
|
|
55
57
|
{(site.locale !== 'en' || basePathname === '/brand') && <link href={`https://fonts.googleapis.com/css2?family=Noto+Sans+${({ ja: 'JP', ko: 'KR', cn: 'SC' } as Record<string, string>)[site.locale] ?? 'TC'}:wght@100..900&display=swap`} rel="stylesheet" />}
|
|
56
58
|
<style is:inline blocking="render" set:html={fontCSS}></style>
|
|
59
|
+
{assets.links.map((href) => <link rel="stylesheet" href={href} />)}
|
|
57
60
|
{/* client:load islands can hydrate while a streamed body is still parsing.
|
|
58
|
-
|
|
61
|
+
Keep their context in the head, after stylesheet discovery. */}
|
|
59
62
|
<script is:inline type="application/json" id={siteContextElementId} set:html={siteContextJSON}></script>
|
|
60
|
-
{assets.links.map((href) => <link rel="stylesheet" href={href} />)}
|
|
61
63
|
{/* Without the dev id, Vite appends a second copy when an island imports the same CSS, reordering the cascade. */}
|
|
62
64
|
{assets.styles.map(({ id, content }) => <style is:inline data-vite-dev-id={id} set:html={content}></style>)}
|
|
63
65
|
<title>{head.title}</title>
|