defuss-ssg 0.6.0 → 0.6.2
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/README.md +2 -1
- package/dist/cli.mjs +5 -4
- package/dist/index.cjs +4 -3
- package/dist/index.mjs +5 -4
- package/dist/runtime.cjs +26 -4
- package/dist/runtime.mjs +26 -4
- package/dist/{serve-Cd4Pw98E.mjs → serve-CTYzPwKQ.mjs} +1 -1
- package/dist/{vite-CBAZNNYA.cjs → vite-CkpguLfK.cjs} +173 -47
- package/dist/{vite-CaqPNORI.mjs → vite-DdJcWQGP.mjs} +174 -48
- package/dist/vite.cjs +4 -3
- package/dist/vite.mjs +4 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ Use Bun for package management. The published package targets Node `^20.19.0 ||
|
|
|
19
19
|
- defuss components imported into MDX and HTML-like pages
|
|
20
20
|
- Automatic hydration boundaries for components rendered from `components/`, `src/components/`, `csr/`, or `src/csr/`
|
|
21
21
|
- Static assets copied from `assets/` or `src/assets/`
|
|
22
|
+
- Vite-style `public/` assets copied to the output root and served at `/<file>`
|
|
22
23
|
- File-based API routes from `pages/**/*.ts` and `pages/**/*.js`
|
|
23
24
|
- Root `index.mdx`, `index.md`, or `index.html` fallback when no pages directory exists
|
|
24
25
|
- Pre-rendered endpoints via `prerender = true` and `getStaticPaths()`
|
|
@@ -282,7 +283,7 @@ Single command -> <command> .
|
|
|
282
283
|
Command + folder -> <command> <folder>
|
|
283
284
|
```
|
|
284
285
|
|
|
285
|
-
When `pages`, `components`, or `assets` are not configured explicitly, `defuss-ssg` prefers `src/pages`, `src/components`, `src/csr`, and `src/assets` before falling back to their project-root equivalents. If no pages directory exists, it falls back to root `index.mdx`, then `index.md`, then `index.html`.
|
|
286
|
+
When `pages`, `components`, or `assets` are not configured explicitly, `defuss-ssg` prefers `src/pages`, `src/components`, `src/csr`, and `src/assets` before falling back to their project-root equivalents. If no pages directory exists, it falls back to root `index.mdx`, then `index.md`, then `index.html`. A project-root `public/` directory is treated like Vite/Astro `public`: its files are available at the site root.
|
|
286
287
|
|
|
287
288
|
Commands:
|
|
288
289
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { v as validateProjectDir, b as build } from './vite-
|
|
3
|
-
import { d as dev, s as serve } from './serve-
|
|
2
|
+
import { v as validateProjectDir, b as build } from './vite-DdJcWQGP.mjs';
|
|
3
|
+
import { d as dev, s as serve } from './serve-CTYzPwKQ.mjs';
|
|
4
4
|
import { join, dirname, resolve } from 'node:path';
|
|
5
5
|
import { existsSync, readFileSync } from 'node:fs';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
|
+
import 'fast-glob';
|
|
7
8
|
import 'node:fs/promises';
|
|
8
|
-
import 'node:url';
|
|
9
9
|
import 'defuss/server';
|
|
10
10
|
import 'node:crypto';
|
|
11
11
|
import '@mdx-js/rollup';
|
|
12
|
-
import 'fast-glob';
|
|
13
12
|
import 'vite';
|
|
14
13
|
import 'defuss-vite';
|
|
14
|
+
import 'node:module';
|
|
15
|
+
import 'node:url';
|
|
15
16
|
import 'node:os';
|
|
16
17
|
import 'esbuild';
|
|
17
18
|
import 'rehype-katex';
|
package/dist/index.cjs
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var vite = require('./vite-
|
|
3
|
+
var vite = require('./vite-CkpguLfK.cjs');
|
|
4
4
|
var mdx = require('@mdx-js/rollup');
|
|
5
5
|
var vite$1 = require('vite');
|
|
6
6
|
var defuss = require('defuss-vite');
|
|
7
7
|
var node_fs = require('node:fs');
|
|
8
8
|
var node_path = require('node:path');
|
|
9
9
|
var defussExpress = require('defuss-express');
|
|
10
|
+
require('fast-glob');
|
|
10
11
|
require('node:fs/promises');
|
|
11
|
-
require('node:url');
|
|
12
12
|
require('defuss/server');
|
|
13
13
|
require('node:crypto');
|
|
14
|
-
require('
|
|
14
|
+
require('node:module');
|
|
15
|
+
require('node:url');
|
|
15
16
|
require('node:os');
|
|
16
17
|
require('esbuild');
|
|
17
18
|
require('rehype-katex');
|
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
export { H as HTTP_METHODS, b as build, a as buildEndpoints, c as compileEndpoints, d as compileRpcModule, e as configDefaults, f as defussSsg, g as discoverEndpointSourceFiles, h as discoverRpcFile, i as endpointFileToRoute, j as handleEndpointRoute, k as handleRpcRequest, l as initializeRpc, m as loadEndpointModule, n as matchRoutePattern, r as readConfig, o as registerEndpoints, p as resolveEndpoints, q as routeToExpressPattern } from './vite-
|
|
2
|
-
export { d as dev, s as serve } from './serve-
|
|
1
|
+
export { H as HTTP_METHODS, b as build, a as buildEndpoints, c as compileEndpoints, d as compileRpcModule, e as configDefaults, f as defussSsg, g as discoverEndpointSourceFiles, h as discoverRpcFile, i as endpointFileToRoute, j as handleEndpointRoute, k as handleRpcRequest, l as initializeRpc, m as loadEndpointModule, n as matchRoutePattern, r as readConfig, o as registerEndpoints, p as resolveEndpoints, q as routeToExpressPattern } from './vite-DdJcWQGP.mjs';
|
|
2
|
+
export { d as dev, s as serve } from './serve-CTYzPwKQ.mjs';
|
|
3
|
+
import 'fast-glob';
|
|
3
4
|
import 'node:fs';
|
|
4
5
|
import 'node:fs/promises';
|
|
5
6
|
import 'node:path';
|
|
6
|
-
import 'node:url';
|
|
7
7
|
import 'defuss/server';
|
|
8
8
|
import 'node:crypto';
|
|
9
9
|
import '@mdx-js/rollup';
|
|
10
|
-
import 'fast-glob';
|
|
11
10
|
import 'vite';
|
|
12
11
|
import 'defuss-vite';
|
|
12
|
+
import 'node:module';
|
|
13
|
+
import 'node:url';
|
|
13
14
|
import 'node:os';
|
|
14
15
|
import 'esbuild';
|
|
15
16
|
import 'rehype-katex';
|
package/dist/runtime.cjs
CHANGED
|
@@ -7,6 +7,22 @@ const setupLiveReload = () => {
|
|
|
7
7
|
};
|
|
8
8
|
const runtimeWindow = window;
|
|
9
9
|
const pageCache = runtimeWindow.__defuss_pageCache ?? /* @__PURE__ */ new Map();
|
|
10
|
+
const isHydratableComponent = (value) => typeof value === "function";
|
|
11
|
+
const pickHydrationComponent = (moduleExports, preferredExportName) => {
|
|
12
|
+
if (isHydratableComponent(moduleExports.default)) {
|
|
13
|
+
return moduleExports.default;
|
|
14
|
+
}
|
|
15
|
+
if (preferredExportName && isHydratableComponent(moduleExports[preferredExportName])) {
|
|
16
|
+
return moduleExports[preferredExportName];
|
|
17
|
+
}
|
|
18
|
+
const functionExports = Object.entries(moduleExports).filter(
|
|
19
|
+
([key, value]) => key !== "default" && isHydratableComponent(value)
|
|
20
|
+
);
|
|
21
|
+
if (functionExports.length === 1) {
|
|
22
|
+
return functionExports[0][1];
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
10
26
|
const HYDRATION_ATTRIBUTE_NAMES = [
|
|
11
27
|
"data-hydrate-id",
|
|
12
28
|
"data-hydrate",
|
|
@@ -514,6 +530,7 @@ const hydrateBoundary = async (boundary, options = {}) => {
|
|
|
514
530
|
return;
|
|
515
531
|
}
|
|
516
532
|
const id = boundary.getAttribute("data-hydrate-id");
|
|
533
|
+
const exportName = boundary.getAttribute("data-hydrate-export");
|
|
517
534
|
const src = boundary.getAttribute("data-hydrate-src");
|
|
518
535
|
const propsStr = boundary.getAttribute("data-hydrate-props");
|
|
519
536
|
const runtimeUrl = boundary.getAttribute("data-hydrate-runtime");
|
|
@@ -530,15 +547,20 @@ const hydrateBoundary = async (boundary, options = {}) => {
|
|
|
530
547
|
/* @vite-ignore */
|
|
531
548
|
`${runtimeUrl}${cacheBust}`
|
|
532
549
|
);
|
|
533
|
-
const
|
|
550
|
+
const moduleExports = await import(
|
|
534
551
|
/* @vite-ignore */
|
|
535
552
|
`${src}${cacheBust}`
|
|
536
553
|
);
|
|
537
|
-
|
|
538
|
-
|
|
554
|
+
const Component = pickHydrationComponent(
|
|
555
|
+
moduleExports,
|
|
556
|
+
exportName
|
|
557
|
+
);
|
|
558
|
+
if (!Component) {
|
|
559
|
+
console.error(
|
|
560
|
+
`[hydrate:${id}] No hydratable export in ${src}${exportName ? ` (expected ${exportName})` : ""}`
|
|
561
|
+
);
|
|
539
562
|
return;
|
|
540
563
|
}
|
|
541
|
-
const Component = exports$1.default;
|
|
542
564
|
const props = JSON.parse(propsStr);
|
|
543
565
|
console.log(
|
|
544
566
|
`[hydrate:${id}] Rendering component ${Component.name || "(anon)"} with props:`,
|
package/dist/runtime.mjs
CHANGED
|
@@ -5,6 +5,22 @@ const setupLiveReload = () => {
|
|
|
5
5
|
};
|
|
6
6
|
const runtimeWindow = window;
|
|
7
7
|
const pageCache = runtimeWindow.__defuss_pageCache ?? /* @__PURE__ */ new Map();
|
|
8
|
+
const isHydratableComponent = (value) => typeof value === "function";
|
|
9
|
+
const pickHydrationComponent = (moduleExports, preferredExportName) => {
|
|
10
|
+
if (isHydratableComponent(moduleExports.default)) {
|
|
11
|
+
return moduleExports.default;
|
|
12
|
+
}
|
|
13
|
+
if (preferredExportName && isHydratableComponent(moduleExports[preferredExportName])) {
|
|
14
|
+
return moduleExports[preferredExportName];
|
|
15
|
+
}
|
|
16
|
+
const functionExports = Object.entries(moduleExports).filter(
|
|
17
|
+
([key, value]) => key !== "default" && isHydratableComponent(value)
|
|
18
|
+
);
|
|
19
|
+
if (functionExports.length === 1) {
|
|
20
|
+
return functionExports[0][1];
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
};
|
|
8
24
|
const HYDRATION_ATTRIBUTE_NAMES = [
|
|
9
25
|
"data-hydrate-id",
|
|
10
26
|
"data-hydrate",
|
|
@@ -512,6 +528,7 @@ const hydrateBoundary = async (boundary, options = {}) => {
|
|
|
512
528
|
return;
|
|
513
529
|
}
|
|
514
530
|
const id = boundary.getAttribute("data-hydrate-id");
|
|
531
|
+
const exportName = boundary.getAttribute("data-hydrate-export");
|
|
515
532
|
const src = boundary.getAttribute("data-hydrate-src");
|
|
516
533
|
const propsStr = boundary.getAttribute("data-hydrate-props");
|
|
517
534
|
const runtimeUrl = boundary.getAttribute("data-hydrate-runtime");
|
|
@@ -528,15 +545,20 @@ const hydrateBoundary = async (boundary, options = {}) => {
|
|
|
528
545
|
/* @vite-ignore */
|
|
529
546
|
`${runtimeUrl}${cacheBust}`
|
|
530
547
|
);
|
|
531
|
-
const
|
|
548
|
+
const moduleExports = await import(
|
|
532
549
|
/* @vite-ignore */
|
|
533
550
|
`${src}${cacheBust}`
|
|
534
551
|
);
|
|
535
|
-
|
|
536
|
-
|
|
552
|
+
const Component = pickHydrationComponent(
|
|
553
|
+
moduleExports,
|
|
554
|
+
exportName
|
|
555
|
+
);
|
|
556
|
+
if (!Component) {
|
|
557
|
+
console.error(
|
|
558
|
+
`[hydrate:${id}] No hydratable export in ${src}${exportName ? ` (expected ${exportName})` : ""}`
|
|
559
|
+
);
|
|
537
560
|
return;
|
|
538
561
|
}
|
|
539
|
-
const Component = exports$1.default;
|
|
540
562
|
const props = JSON.parse(propsStr);
|
|
541
563
|
console.log(
|
|
542
564
|
`[hydrate:${id}] Rendering component ${Component.name || "(anon)"} with props:`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import mdx from '@mdx-js/rollup';
|
|
2
2
|
import { createServer } from 'vite';
|
|
3
3
|
import defuss from 'defuss-vite';
|
|
4
|
-
import { v as validateProjectDir, r as readConfig, f as defussSsg, o as registerEndpoints, l as initializeRpc, s as readIncomingBody, t as createWebRequest, k as handleRpcRequest, u as sendWebResponse } from './vite-
|
|
4
|
+
import { v as validateProjectDir, r as readConfig, f as defussSsg, o as registerEndpoints, l as initializeRpc, s as readIncomingBody, t as createWebRequest, k as handleRpcRequest, u as sendWebResponse } from './vite-DdJcWQGP.mjs';
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { express, startServer } from 'defuss-express';
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var glob = require('fast-glob');
|
|
3
4
|
var node_fs = require('node:fs');
|
|
4
5
|
var promises = require('node:fs/promises');
|
|
5
6
|
var node_path = require('node:path');
|
|
6
|
-
var node_url = require('node:url');
|
|
7
7
|
var server = require('defuss/server');
|
|
8
8
|
var node_crypto = require('node:crypto');
|
|
9
9
|
var mdx = require('@mdx-js/rollup');
|
|
10
|
-
var glob = require('fast-glob');
|
|
11
10
|
var vite = require('vite');
|
|
12
11
|
var defuss = require('defuss-vite');
|
|
12
|
+
var node_module = require('node:module');
|
|
13
|
+
var node_url = require('node:url');
|
|
13
14
|
var node_os = require('node:os');
|
|
14
15
|
var esbuild = require('esbuild');
|
|
15
16
|
var rehypeKatex = require('rehype-katex');
|
|
@@ -78,6 +79,13 @@ const toStableHydrateId = (seed) => {
|
|
|
78
79
|
const digest = node_crypto.createHash("sha1").update(seed).digest("hex").slice(0, 12);
|
|
79
80
|
return `dh_${digest}`;
|
|
80
81
|
};
|
|
82
|
+
const toPascalCase = (value) => value.split(/[^A-Za-z0-9]+/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
|
|
83
|
+
const toComponentExportName = (componentFilePath) => {
|
|
84
|
+
const extension = node_path.extname(componentFilePath);
|
|
85
|
+
const fileStem = node_path.basename(componentFilePath, extension);
|
|
86
|
+
const exportBaseName = fileStem.toLowerCase() === "index" ? node_path.basename(node_path.dirname(componentFilePath)) : fileStem;
|
|
87
|
+
return toPascalCase(exportBaseName);
|
|
88
|
+
};
|
|
81
89
|
function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeOutputHtmlFilePath) {
|
|
82
90
|
const componentsRoot = node_path.resolve(componentsDir);
|
|
83
91
|
let hydrateIndex = 0;
|
|
@@ -93,6 +101,9 @@ function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeO
|
|
|
93
101
|
if (vnode.sourceInfo && typeof vnode.sourceInfo === "object" && typeof vnode.sourceInfo.fileName === "string" && vnode.sourceInfo.fileName.includes(componentsDir) && vnode.type !== "script" && vnode.type !== "head" && vnode.type !== "link" && vnode.type !== "meta" && vnode.type !== "title") {
|
|
94
102
|
const sourceFile = node_path.resolve(vnode.sourceInfo.fileName);
|
|
95
103
|
const relativeComponentPath = node_path.relative(componentsRoot, sourceFile);
|
|
104
|
+
const componentExportName = toComponentExportName(
|
|
105
|
+
relativeComponentPath
|
|
106
|
+
);
|
|
96
107
|
if (relativeComponentPath.startsWith("..") || relativeComponentPath.length === 0) {
|
|
97
108
|
throw new Error(
|
|
98
109
|
`[auto-hydrate] Component source file is outside the components directory: ${sourceFile}`
|
|
@@ -126,6 +137,7 @@ function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeO
|
|
|
126
137
|
attributes: {
|
|
127
138
|
"data-hydrate-id": id,
|
|
128
139
|
"data-hydrate": "true",
|
|
140
|
+
"data-hydrate-export": componentExportName,
|
|
129
141
|
"data-hydrate-src": clientSrcFile,
|
|
130
142
|
"data-hydrate-props": JSON.stringify(componentProps),
|
|
131
143
|
"data-hydrate-runtime": `/${componentsPublicPrefix}/runtime.js`
|
|
@@ -643,8 +655,8 @@ const registerEndpoints = async (registrar, projectDir, _config, debug = false)
|
|
|
643
655
|
}
|
|
644
656
|
};
|
|
645
657
|
|
|
646
|
-
const __filename$
|
|
647
|
-
const __dirname$
|
|
658
|
+
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite-CkpguLfK.cjs', document.baseURI).href)));
|
|
659
|
+
const __dirname$1 = node_path.dirname(__filename$1);
|
|
648
660
|
const isHtmlLikePageSource = (filePath) => {
|
|
649
661
|
const extension = node_path.extname(filePath).toLowerCase();
|
|
650
662
|
return extension === "" || extension === ".md" || extension === ".mdx" || extension === ".html";
|
|
@@ -658,16 +670,103 @@ const isPathInOrUnder$1 = (filePath, dirPath) => {
|
|
|
658
670
|
const isRootIndexPageSource$1 = (filePath) => /^index(?:\.mdx?|\.html)?$/i.test(normalizePath$1(filePath));
|
|
659
671
|
const resolveLocalHelperFile = (sourceRelativePath, builtRelativePath) => {
|
|
660
672
|
const candidates = [
|
|
661
|
-
node_path.resolve(__dirname$
|
|
662
|
-
node_path.resolve(__dirname$
|
|
663
|
-
node_path.resolve(__dirname$
|
|
673
|
+
node_path.resolve(__dirname$1, sourceRelativePath),
|
|
674
|
+
node_path.resolve(__dirname$1, "..", "src", sourceRelativePath),
|
|
675
|
+
node_path.resolve(__dirname$1, builtRelativePath)
|
|
664
676
|
];
|
|
665
677
|
for (const candidate of candidates) {
|
|
666
678
|
if (node_fs.existsSync(candidate)) {
|
|
667
679
|
return candidate;
|
|
668
680
|
}
|
|
669
681
|
}
|
|
670
|
-
return node_path.resolve(__dirname$
|
|
682
|
+
return node_path.resolve(__dirname$1, builtRelativePath);
|
|
683
|
+
};
|
|
684
|
+
const loadProjectTailwindVitePlugins = async (projectDir, debug) => {
|
|
685
|
+
const requireFromBuild = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite-CkpguLfK.cjs', document.baseURI).href)));
|
|
686
|
+
try {
|
|
687
|
+
const resolvedPluginPath = requireFromBuild.resolve("@tailwindcss/vite", {
|
|
688
|
+
paths: [projectDir]
|
|
689
|
+
});
|
|
690
|
+
const tailwindModule = await import(node_url.pathToFileURL(resolvedPluginPath).href);
|
|
691
|
+
if (typeof tailwindModule.default !== "function") {
|
|
692
|
+
return [];
|
|
693
|
+
}
|
|
694
|
+
const plugin = tailwindModule.default();
|
|
695
|
+
if (!plugin) {
|
|
696
|
+
return [];
|
|
697
|
+
}
|
|
698
|
+
return Array.isArray(plugin) ? plugin : [plugin];
|
|
699
|
+
} catch (error) {
|
|
700
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
701
|
+
const isMissingPlugin = message.includes("@tailwindcss/vite");
|
|
702
|
+
if (!isMissingPlugin && debug) {
|
|
703
|
+
console.warn("[build] Failed to load @tailwindcss/vite from project:", error);
|
|
704
|
+
}
|
|
705
|
+
return [];
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
const injectStylesheetLinks$1 = (html, hrefs) => {
|
|
709
|
+
const missingHrefs = hrefs.filter((href) => !html.includes(`href="${href}"`));
|
|
710
|
+
if (missingHrefs.length === 0) {
|
|
711
|
+
return html;
|
|
712
|
+
}
|
|
713
|
+
const linkTags = missingHrefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
714
|
+
if (html.includes("</head>")) {
|
|
715
|
+
return html.replace("</head>", `${linkTags}</head>`);
|
|
716
|
+
}
|
|
717
|
+
return `${linkTags}${html}`;
|
|
718
|
+
};
|
|
719
|
+
const normalizeComponentStylesheet = (css) => {
|
|
720
|
+
const compiledTailwindBanner = "/*! tailwindcss";
|
|
721
|
+
const compiledTailwindIndex = css.indexOf(compiledTailwindBanner);
|
|
722
|
+
if (compiledTailwindIndex <= 0) {
|
|
723
|
+
return css;
|
|
724
|
+
}
|
|
725
|
+
const prefix = css.slice(0, compiledTailwindIndex).trimStart();
|
|
726
|
+
const hasRawTailwindPrelude = prefix.startsWith("@layer theme, base, components, utilities;") && prefix.includes("@theme default");
|
|
727
|
+
if (!hasRawTailwindPrelude) {
|
|
728
|
+
return css;
|
|
729
|
+
}
|
|
730
|
+
return css.slice(compiledTailwindIndex);
|
|
731
|
+
};
|
|
732
|
+
const normalizeComponentStylesheets = async (componentsOutputDir) => {
|
|
733
|
+
const cssFiles = await glob.async(node_path.join(componentsOutputDir, "**/*.css"));
|
|
734
|
+
for (const cssFile of cssFiles) {
|
|
735
|
+
const currentCss = await promises.readFile(cssFile, "utf-8");
|
|
736
|
+
const normalizedCss = normalizeComponentStylesheet(currentCss);
|
|
737
|
+
if (normalizedCss !== currentCss) {
|
|
738
|
+
await promises.writeFile(cssFile, normalizedCss);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
const getComponentStylesheetHrefs$1 = async (componentsOutputDir, componentsPublicDir) => {
|
|
743
|
+
if (!node_fs.existsSync(componentsOutputDir)) {
|
|
744
|
+
return [];
|
|
745
|
+
}
|
|
746
|
+
const cssFiles = await glob.async(node_path.join(componentsOutputDir, "**/*.css"));
|
|
747
|
+
return cssFiles.sort((left, right) => left.localeCompare(right)).map(
|
|
748
|
+
(cssFile) => `/${normalizePath$1(node_path.join(componentsPublicDir, node_path.relative(componentsOutputDir, cssFile)))}`
|
|
749
|
+
);
|
|
750
|
+
};
|
|
751
|
+
const injectComponentStylesheetsIntoOutputHtml = async (outputProjectDir, componentsOutputDir, componentsPublicDir) => {
|
|
752
|
+
if (!node_fs.existsSync(outputProjectDir)) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const stylesheetHrefs = await getComponentStylesheetHrefs$1(
|
|
756
|
+
componentsOutputDir,
|
|
757
|
+
componentsPublicDir
|
|
758
|
+
);
|
|
759
|
+
if (stylesheetHrefs.length === 0) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
const htmlFiles = await glob.async(node_path.join(outputProjectDir, "**/*.html"));
|
|
763
|
+
for (const htmlFile of htmlFiles) {
|
|
764
|
+
const currentHtml = await promises.readFile(htmlFile, "utf8");
|
|
765
|
+
const nextHtml = injectStylesheetLinks$1(currentHtml, stylesheetHrefs);
|
|
766
|
+
if (nextHtml !== currentHtml) {
|
|
767
|
+
await promises.writeFile(htmlFile, nextHtml);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
671
770
|
};
|
|
672
771
|
const build = async ({
|
|
673
772
|
projectDir,
|
|
@@ -703,6 +802,7 @@ const build = async ({
|
|
|
703
802
|
const inputPagesDir = projectPaths.pagesSourceDirAbsolute;
|
|
704
803
|
const inputComponentsDir = projectPaths.componentsSourceDirAbsolute;
|
|
705
804
|
const inputAssetsDir = projectPaths.assetsSourceDirAbsolute;
|
|
805
|
+
const inputPublicDir = node_path.join(projectDir, "public");
|
|
706
806
|
const hasInputPagesDir = projectPaths.hasPagesSourceDir;
|
|
707
807
|
const tmpPagesDir = node_path.join(config.tmp, projectPaths.pagesSourceDir);
|
|
708
808
|
const tmpComponentsDir = node_path.join(config.tmp, projectPaths.componentsSourceDir);
|
|
@@ -723,6 +823,7 @@ const build = async ({
|
|
|
723
823
|
console.log("Input pages dir:", inputPagesDir);
|
|
724
824
|
console.log("Input components dir:", inputComponentsDir);
|
|
725
825
|
console.log("Input assets dir:", inputAssetsDir);
|
|
826
|
+
console.log("Input public dir:", inputPublicDir);
|
|
726
827
|
console.log("Temp pages dir:", tmpPagesDir);
|
|
727
828
|
console.log("Temp components dir:", tmpComponentsDir);
|
|
728
829
|
console.log("Output pages dir:", outputPagesDir);
|
|
@@ -741,6 +842,8 @@ const build = async ({
|
|
|
741
842
|
changeKind = "component";
|
|
742
843
|
} else if (isPathInOrUnder$1(changedRelative, projectPaths.assetsSourceDir)) {
|
|
743
844
|
changeKind = "asset";
|
|
845
|
+
} else if (isPathInOrUnder$1(changedRelative, "public")) {
|
|
846
|
+
changeKind = "asset";
|
|
744
847
|
} else if (changedRelative === "config.ts" || changedRelative === "config.js") {
|
|
745
848
|
changeKind = "config";
|
|
746
849
|
}
|
|
@@ -758,7 +861,7 @@ const build = async ({
|
|
|
758
861
|
const shouldCopyToTemp = (src) => {
|
|
759
862
|
const relative2 = src.startsWith(projectDir) ? normalizePath$1(src.slice(projectDir.length).replace(/^[\\/]+/, "")) : src;
|
|
760
863
|
const firstSegment = relative2.split(/[\\/]/)[0];
|
|
761
|
-
return !(firstSegment === "node_modules" || firstSegment === config.output || firstSegment === ".endpoints" || firstSegment === ".ssg-temp" || firstSegment === ".git" || projectPaths.assetsSourceDirCandidates.some(
|
|
864
|
+
return !(firstSegment === "node_modules" || firstSegment === config.output || firstSegment === ".endpoints" || firstSegment === ".ssg-temp" || firstSegment === ".git" || firstSegment === "public" || projectPaths.assetsSourceDirCandidates.some(
|
|
762
865
|
(candidateDir) => isPathInOrUnder$1(relative2, candidateDir)
|
|
763
866
|
));
|
|
764
867
|
};
|
|
@@ -1015,11 +1118,15 @@ const build = async ({
|
|
|
1015
1118
|
node_path.resolve(entryFile)
|
|
1016
1119
|
])
|
|
1017
1120
|
);
|
|
1121
|
+
const componentBuildPlugins = [
|
|
1122
|
+
defuss(),
|
|
1123
|
+
...await loadProjectTailwindVitePlugins(projectDir, debug)
|
|
1124
|
+
];
|
|
1018
1125
|
await vite.build({
|
|
1019
1126
|
root: node_path.resolve(tmpComponentsDir),
|
|
1020
1127
|
configFile: false,
|
|
1021
1128
|
publicDir: false,
|
|
1022
|
-
plugins:
|
|
1129
|
+
plugins: componentBuildPlugins,
|
|
1023
1130
|
build: {
|
|
1024
1131
|
lib: {
|
|
1025
1132
|
entry: componentEntries,
|
|
@@ -1037,6 +1144,7 @@ const build = async ({
|
|
|
1037
1144
|
}
|
|
1038
1145
|
}
|
|
1039
1146
|
});
|
|
1147
|
+
await normalizeComponentStylesheets(tmpComponentOutDir);
|
|
1040
1148
|
timeEndDebug("[build] vite-components");
|
|
1041
1149
|
}
|
|
1042
1150
|
if (isFullBuild || changeKind === "page" || changeKind === "endpoint") {
|
|
@@ -1052,6 +1160,16 @@ const build = async ({
|
|
|
1052
1160
|
if (node_fs.existsSync(inputAssetsDir)) {
|
|
1053
1161
|
await promises.cp(inputAssetsDir, outputAssetsDir, { recursive: true });
|
|
1054
1162
|
}
|
|
1163
|
+
if (node_fs.existsSync(inputPublicDir)) {
|
|
1164
|
+
await promises.cp(inputPublicDir, outputProjectDir, { recursive: true });
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (isFullBuild || changeKind === "page" || changeKind === "component") {
|
|
1168
|
+
await injectComponentStylesheetsIntoOutputHtml(
|
|
1169
|
+
outputProjectDir,
|
|
1170
|
+
outputComponentsDir,
|
|
1171
|
+
projectPaths.componentsPublicDir
|
|
1172
|
+
);
|
|
1055
1173
|
}
|
|
1056
1174
|
timeEndDebug("[build] copy-outputs");
|
|
1057
1175
|
if (isFullBuild || changeKind === "component") {
|
|
@@ -1280,8 +1398,6 @@ const handleRpcRequest = async (ctx) => {
|
|
|
1280
1398
|
}
|
|
1281
1399
|
};
|
|
1282
1400
|
|
|
1283
|
-
const __filename$1 = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite-CBAZNNYA.cjs', document.baseURI).href)));
|
|
1284
|
-
const __dirname$1 = node_path.dirname(__filename$1);
|
|
1285
1401
|
const MIME_TYPES = {
|
|
1286
1402
|
".css": "text/css; charset=utf-8",
|
|
1287
1403
|
".gif": "image/gif",
|
|
@@ -1680,18 +1796,25 @@ const injectHmrClientModule = (html) => {
|
|
|
1680
1796
|
}
|
|
1681
1797
|
return `${importTag}${html}`;
|
|
1682
1798
|
};
|
|
1683
|
-
const
|
|
1684
|
-
const
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
node_path.join(__dirname$1, "runtime.mjs")
|
|
1688
|
-
];
|
|
1689
|
-
for (const candidate of candidates) {
|
|
1690
|
-
if (node_fs.existsSync(candidate)) {
|
|
1691
|
-
return candidate;
|
|
1692
|
-
}
|
|
1799
|
+
const injectStylesheetLinks = (html, hrefs) => {
|
|
1800
|
+
const missingHrefs = hrefs.filter((href) => !html.includes(`href="${href}"`));
|
|
1801
|
+
if (missingHrefs.length === 0) {
|
|
1802
|
+
return html;
|
|
1693
1803
|
}
|
|
1694
|
-
|
|
1804
|
+
const linkTags = missingHrefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
1805
|
+
if (html.includes("</head>")) {
|
|
1806
|
+
return html.replace("</head>", `${linkTags}</head>`);
|
|
1807
|
+
}
|
|
1808
|
+
return `${linkTags}${html}`;
|
|
1809
|
+
};
|
|
1810
|
+
const getComponentStylesheetHrefs = async (componentsOutputDir, componentsPublicDir) => {
|
|
1811
|
+
if (!node_fs.existsSync(componentsOutputDir)) {
|
|
1812
|
+
return [];
|
|
1813
|
+
}
|
|
1814
|
+
const cssFiles = await glob.async(node_path.join(componentsOutputDir, "**/*.css"));
|
|
1815
|
+
return cssFiles.sort((left, right) => left.localeCompare(right)).map(
|
|
1816
|
+
(cssFile) => `/${normalizePath(node_path.join(componentsPublicDir, node_path.relative(componentsOutputDir, cssFile)))}`
|
|
1817
|
+
);
|
|
1695
1818
|
};
|
|
1696
1819
|
const isHtmlLikeFile = (filePath) => {
|
|
1697
1820
|
const extension = node_path.extname(filePath);
|
|
@@ -1741,6 +1864,9 @@ const classifyChangedFile = (file, projectDir, config, rpcFile) => {
|
|
|
1741
1864
|
if (isPathInOrUnder(relativeFile, paths.assetsSourceDir)) {
|
|
1742
1865
|
return "asset";
|
|
1743
1866
|
}
|
|
1867
|
+
if (isPathInOrUnder(relativeFile, "public")) {
|
|
1868
|
+
return "asset";
|
|
1869
|
+
}
|
|
1744
1870
|
return "dependency";
|
|
1745
1871
|
};
|
|
1746
1872
|
const filePathToComponentPublicPath = (file, componentsSourceDir, componentsPublicDir) => {
|
|
@@ -2129,6 +2255,13 @@ function defussSsg(options = {}) {
|
|
|
2129
2255
|
);
|
|
2130
2256
|
const el = server.renderSync(vdom, document.documentElement, { browserGlobals });
|
|
2131
2257
|
let html = server.renderToString(el);
|
|
2258
|
+
html = injectStylesheetLinks(
|
|
2259
|
+
html,
|
|
2260
|
+
await getComponentStylesheetHrefs(
|
|
2261
|
+
node_path.join(projectDir, config.output, currentPaths.componentsPublicDir),
|
|
2262
|
+
currentPaths.componentsPublicDir
|
|
2263
|
+
)
|
|
2264
|
+
);
|
|
2132
2265
|
html = injectHmrClientModule(html);
|
|
2133
2266
|
html = await server$1.transformIndexHtml(requestUrl.pathname, html);
|
|
2134
2267
|
res.setHeader("Cache-Control", "no-store");
|
|
@@ -2143,27 +2276,14 @@ function defussSsg(options = {}) {
|
|
|
2143
2276
|
const maybeServeComponent = async (server, req, res) => {
|
|
2144
2277
|
const requestUrl = new URL(req.url || "/", "http://localhost");
|
|
2145
2278
|
const pathname = requestUrl.pathname;
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
const componentRoutePrefix = `/${config.components}/`;
|
|
2150
|
-
if (pathname === `/${config.components}/runtime.js`) {
|
|
2151
|
-
const runtimePath = resolveRuntimeHelperFile();
|
|
2152
|
-
if (!runtimePath) {
|
|
2153
|
-
return false;
|
|
2154
|
-
}
|
|
2155
|
-
const transformed2 = await server.transformRequest(runtimePath);
|
|
2156
|
-
if (transformed2) {
|
|
2157
|
-
res.setHeader("Cache-Control", "no-store");
|
|
2158
|
-
res.setHeader("Content-Type", "text/javascript; charset=utf-8");
|
|
2159
|
-
res.statusCode = 200;
|
|
2160
|
-
res.end(transformed2.code);
|
|
2161
|
-
return true;
|
|
2162
|
-
}
|
|
2279
|
+
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2280
|
+
const componentRoutePrefix = `/${currentPaths.componentsPublicDir}/`;
|
|
2281
|
+
if (!pathname.startsWith(componentRoutePrefix)) {
|
|
2163
2282
|
return false;
|
|
2164
2283
|
}
|
|
2165
2284
|
const relativeComponentPath = pathname.slice(componentRoutePrefix.length);
|
|
2166
|
-
const
|
|
2285
|
+
const componentExtension = node_path.extname(relativeComponentPath).toLowerCase();
|
|
2286
|
+
const isBuiltComponentAsset = relativeComponentPath === "runtime.js" || relativeComponentPath.startsWith("chunks/") || /^chunk-|^client-/.test(relativeComponentPath) || componentExtension !== ".js";
|
|
2167
2287
|
if (isBuiltComponentAsset) {
|
|
2168
2288
|
return false;
|
|
2169
2289
|
}
|
|
@@ -2171,7 +2291,6 @@ function defussSsg(options = {}) {
|
|
|
2171
2291
|
node_path.extname(relativeComponentPath),
|
|
2172
2292
|
""
|
|
2173
2293
|
);
|
|
2174
|
-
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2175
2294
|
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
2176
2295
|
let sourceFile = null;
|
|
2177
2296
|
for (const ext of extensions) {
|
|
@@ -2185,10 +2304,7 @@ function defussSsg(options = {}) {
|
|
|
2185
2304
|
}
|
|
2186
2305
|
}
|
|
2187
2306
|
if (!sourceFile) {
|
|
2188
|
-
|
|
2189
|
-
res.statusCode = 404;
|
|
2190
|
-
res.end();
|
|
2191
|
-
return true;
|
|
2307
|
+
return false;
|
|
2192
2308
|
}
|
|
2193
2309
|
const transformed = await server.transformRequest(sourceFile);
|
|
2194
2310
|
if (transformed) {
|
|
@@ -2226,9 +2342,18 @@ function defussSsg(options = {}) {
|
|
|
2226
2342
|
MIME_TYPES[node_path.extname(outputFile)] ?? "application/octet-stream"
|
|
2227
2343
|
);
|
|
2228
2344
|
if (outputFile.endsWith(".html")) {
|
|
2345
|
+
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2229
2346
|
const html = await server.transformIndexHtml(
|
|
2230
2347
|
requestUrl.pathname,
|
|
2231
|
-
injectHmrClientModule(
|
|
2348
|
+
injectHmrClientModule(
|
|
2349
|
+
injectStylesheetLinks(
|
|
2350
|
+
body.toString("utf8"),
|
|
2351
|
+
await getComponentStylesheetHrefs(
|
|
2352
|
+
node_path.join(projectDir, config.output, currentPaths.componentsPublicDir),
|
|
2353
|
+
currentPaths.componentsPublicDir
|
|
2354
|
+
)
|
|
2355
|
+
)
|
|
2356
|
+
)
|
|
2232
2357
|
);
|
|
2233
2358
|
res.statusCode = 200;
|
|
2234
2359
|
res.end(method === "HEAD" ? void 0 : html);
|
|
@@ -2283,6 +2408,7 @@ function defussSsg(options = {}) {
|
|
|
2283
2408
|
...paths.assetsSourceDirCandidates.map(
|
|
2284
2409
|
(candidateDir) => node_path.join(projectDir, candidateDir)
|
|
2285
2410
|
),
|
|
2411
|
+
node_path.join(projectDir, "public"),
|
|
2286
2412
|
node_path.join(projectDir, "config.ts"),
|
|
2287
2413
|
node_path.join(projectDir, "config.js")
|
|
2288
2414
|
];
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import glob from 'fast-glob';
|
|
1
2
|
import { existsSync, statSync, mkdirSync, rmSync, readdirSync, symlinkSync } from 'node:fs';
|
|
2
3
|
import { writeFile, readFile, cp, stat } from 'node:fs/promises';
|
|
3
|
-
import { join, resolve, relative, sep, extname, dirname } from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { join, resolve, relative, sep, extname, basename, dirname } from 'node:path';
|
|
5
5
|
import { getBrowserGlobals, getDocument, renderSync, renderToString } from 'defuss/server';
|
|
6
6
|
import { createHash } from 'node:crypto';
|
|
7
7
|
import mdx from '@mdx-js/rollup';
|
|
8
|
-
import glob from 'fast-glob';
|
|
9
8
|
import { createServer, build as build$1 } from 'vite';
|
|
10
9
|
import defuss from 'defuss-vite';
|
|
10
|
+
import { createRequire } from 'node:module';
|
|
11
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
11
12
|
import { tmpdir } from 'node:os';
|
|
12
13
|
import esbuild from 'esbuild';
|
|
13
14
|
import rehypeKatex from 'rehype-katex';
|
|
@@ -75,6 +76,13 @@ const toStableHydrateId = (seed) => {
|
|
|
75
76
|
const digest = createHash("sha1").update(seed).digest("hex").slice(0, 12);
|
|
76
77
|
return `dh_${digest}`;
|
|
77
78
|
};
|
|
79
|
+
const toPascalCase = (value) => value.split(/[^A-Za-z0-9]+/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
|
|
80
|
+
const toComponentExportName = (componentFilePath) => {
|
|
81
|
+
const extension = extname(componentFilePath);
|
|
82
|
+
const fileStem = basename(componentFilePath, extension);
|
|
83
|
+
const exportBaseName = fileStem.toLowerCase() === "index" ? basename(dirname(componentFilePath)) : fileStem;
|
|
84
|
+
return toPascalCase(exportBaseName);
|
|
85
|
+
};
|
|
78
86
|
function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeOutputHtmlFilePath) {
|
|
79
87
|
const componentsRoot = resolve(componentsDir);
|
|
80
88
|
let hydrateIndex = 0;
|
|
@@ -90,6 +98,9 @@ function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeO
|
|
|
90
98
|
if (vnode.sourceInfo && typeof vnode.sourceInfo === "object" && typeof vnode.sourceInfo.fileName === "string" && vnode.sourceInfo.fileName.includes(componentsDir) && vnode.type !== "script" && vnode.type !== "head" && vnode.type !== "link" && vnode.type !== "meta" && vnode.type !== "title") {
|
|
91
99
|
const sourceFile = resolve(vnode.sourceInfo.fileName);
|
|
92
100
|
const relativeComponentPath = relative(componentsRoot, sourceFile);
|
|
101
|
+
const componentExportName = toComponentExportName(
|
|
102
|
+
relativeComponentPath
|
|
103
|
+
);
|
|
93
104
|
if (relativeComponentPath.startsWith("..") || relativeComponentPath.length === 0) {
|
|
94
105
|
throw new Error(
|
|
95
106
|
`[auto-hydrate] Component source file is outside the components directory: ${sourceFile}`
|
|
@@ -123,6 +134,7 @@ function applyAutoHydrate(vdom, componentsDir, componentsPublicPrefix, relativeO
|
|
|
123
134
|
attributes: {
|
|
124
135
|
"data-hydrate-id": id,
|
|
125
136
|
"data-hydrate": "true",
|
|
137
|
+
"data-hydrate-export": componentExportName,
|
|
126
138
|
"data-hydrate-src": clientSrcFile,
|
|
127
139
|
"data-hydrate-props": JSON.stringify(componentProps),
|
|
128
140
|
"data-hydrate-runtime": `/${componentsPublicPrefix}/runtime.js`
|
|
@@ -640,8 +652,8 @@ const registerEndpoints = async (registrar, projectDir, _config, debug = false)
|
|
|
640
652
|
}
|
|
641
653
|
};
|
|
642
654
|
|
|
643
|
-
const __filename$
|
|
644
|
-
const __dirname$
|
|
655
|
+
const __filename$1 = fileURLToPath(import.meta.url);
|
|
656
|
+
const __dirname$1 = dirname(__filename$1);
|
|
645
657
|
const isHtmlLikePageSource = (filePath) => {
|
|
646
658
|
const extension = extname(filePath).toLowerCase();
|
|
647
659
|
return extension === "" || extension === ".md" || extension === ".mdx" || extension === ".html";
|
|
@@ -655,16 +667,103 @@ const isPathInOrUnder$1 = (filePath, dirPath) => {
|
|
|
655
667
|
const isRootIndexPageSource$1 = (filePath) => /^index(?:\.mdx?|\.html)?$/i.test(normalizePath$1(filePath));
|
|
656
668
|
const resolveLocalHelperFile = (sourceRelativePath, builtRelativePath) => {
|
|
657
669
|
const candidates = [
|
|
658
|
-
resolve(__dirname$
|
|
659
|
-
resolve(__dirname$
|
|
660
|
-
resolve(__dirname$
|
|
670
|
+
resolve(__dirname$1, sourceRelativePath),
|
|
671
|
+
resolve(__dirname$1, "..", "src", sourceRelativePath),
|
|
672
|
+
resolve(__dirname$1, builtRelativePath)
|
|
661
673
|
];
|
|
662
674
|
for (const candidate of candidates) {
|
|
663
675
|
if (existsSync(candidate)) {
|
|
664
676
|
return candidate;
|
|
665
677
|
}
|
|
666
678
|
}
|
|
667
|
-
return resolve(__dirname$
|
|
679
|
+
return resolve(__dirname$1, builtRelativePath);
|
|
680
|
+
};
|
|
681
|
+
const loadProjectTailwindVitePlugins = async (projectDir, debug) => {
|
|
682
|
+
const requireFromBuild = createRequire(import.meta.url);
|
|
683
|
+
try {
|
|
684
|
+
const resolvedPluginPath = requireFromBuild.resolve("@tailwindcss/vite", {
|
|
685
|
+
paths: [projectDir]
|
|
686
|
+
});
|
|
687
|
+
const tailwindModule = await import(pathToFileURL(resolvedPluginPath).href);
|
|
688
|
+
if (typeof tailwindModule.default !== "function") {
|
|
689
|
+
return [];
|
|
690
|
+
}
|
|
691
|
+
const plugin = tailwindModule.default();
|
|
692
|
+
if (!plugin) {
|
|
693
|
+
return [];
|
|
694
|
+
}
|
|
695
|
+
return Array.isArray(plugin) ? plugin : [plugin];
|
|
696
|
+
} catch (error) {
|
|
697
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
698
|
+
const isMissingPlugin = message.includes("@tailwindcss/vite");
|
|
699
|
+
if (!isMissingPlugin && debug) {
|
|
700
|
+
console.warn("[build] Failed to load @tailwindcss/vite from project:", error);
|
|
701
|
+
}
|
|
702
|
+
return [];
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
const injectStylesheetLinks$1 = (html, hrefs) => {
|
|
706
|
+
const missingHrefs = hrefs.filter((href) => !html.includes(`href="${href}"`));
|
|
707
|
+
if (missingHrefs.length === 0) {
|
|
708
|
+
return html;
|
|
709
|
+
}
|
|
710
|
+
const linkTags = missingHrefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
711
|
+
if (html.includes("</head>")) {
|
|
712
|
+
return html.replace("</head>", `${linkTags}</head>`);
|
|
713
|
+
}
|
|
714
|
+
return `${linkTags}${html}`;
|
|
715
|
+
};
|
|
716
|
+
const normalizeComponentStylesheet = (css) => {
|
|
717
|
+
const compiledTailwindBanner = "/*! tailwindcss";
|
|
718
|
+
const compiledTailwindIndex = css.indexOf(compiledTailwindBanner);
|
|
719
|
+
if (compiledTailwindIndex <= 0) {
|
|
720
|
+
return css;
|
|
721
|
+
}
|
|
722
|
+
const prefix = css.slice(0, compiledTailwindIndex).trimStart();
|
|
723
|
+
const hasRawTailwindPrelude = prefix.startsWith("@layer theme, base, components, utilities;") && prefix.includes("@theme default");
|
|
724
|
+
if (!hasRawTailwindPrelude) {
|
|
725
|
+
return css;
|
|
726
|
+
}
|
|
727
|
+
return css.slice(compiledTailwindIndex);
|
|
728
|
+
};
|
|
729
|
+
const normalizeComponentStylesheets = async (componentsOutputDir) => {
|
|
730
|
+
const cssFiles = await glob.async(join(componentsOutputDir, "**/*.css"));
|
|
731
|
+
for (const cssFile of cssFiles) {
|
|
732
|
+
const currentCss = await readFile(cssFile, "utf-8");
|
|
733
|
+
const normalizedCss = normalizeComponentStylesheet(currentCss);
|
|
734
|
+
if (normalizedCss !== currentCss) {
|
|
735
|
+
await writeFile(cssFile, normalizedCss);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
const getComponentStylesheetHrefs$1 = async (componentsOutputDir, componentsPublicDir) => {
|
|
740
|
+
if (!existsSync(componentsOutputDir)) {
|
|
741
|
+
return [];
|
|
742
|
+
}
|
|
743
|
+
const cssFiles = await glob.async(join(componentsOutputDir, "**/*.css"));
|
|
744
|
+
return cssFiles.sort((left, right) => left.localeCompare(right)).map(
|
|
745
|
+
(cssFile) => `/${normalizePath$1(join(componentsPublicDir, relative(componentsOutputDir, cssFile)))}`
|
|
746
|
+
);
|
|
747
|
+
};
|
|
748
|
+
const injectComponentStylesheetsIntoOutputHtml = async (outputProjectDir, componentsOutputDir, componentsPublicDir) => {
|
|
749
|
+
if (!existsSync(outputProjectDir)) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const stylesheetHrefs = await getComponentStylesheetHrefs$1(
|
|
753
|
+
componentsOutputDir,
|
|
754
|
+
componentsPublicDir
|
|
755
|
+
);
|
|
756
|
+
if (stylesheetHrefs.length === 0) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const htmlFiles = await glob.async(join(outputProjectDir, "**/*.html"));
|
|
760
|
+
for (const htmlFile of htmlFiles) {
|
|
761
|
+
const currentHtml = await readFile(htmlFile, "utf8");
|
|
762
|
+
const nextHtml = injectStylesheetLinks$1(currentHtml, stylesheetHrefs);
|
|
763
|
+
if (nextHtml !== currentHtml) {
|
|
764
|
+
await writeFile(htmlFile, nextHtml);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
668
767
|
};
|
|
669
768
|
const build = async ({
|
|
670
769
|
projectDir,
|
|
@@ -700,6 +799,7 @@ const build = async ({
|
|
|
700
799
|
const inputPagesDir = projectPaths.pagesSourceDirAbsolute;
|
|
701
800
|
const inputComponentsDir = projectPaths.componentsSourceDirAbsolute;
|
|
702
801
|
const inputAssetsDir = projectPaths.assetsSourceDirAbsolute;
|
|
802
|
+
const inputPublicDir = join(projectDir, "public");
|
|
703
803
|
const hasInputPagesDir = projectPaths.hasPagesSourceDir;
|
|
704
804
|
const tmpPagesDir = join(config.tmp, projectPaths.pagesSourceDir);
|
|
705
805
|
const tmpComponentsDir = join(config.tmp, projectPaths.componentsSourceDir);
|
|
@@ -720,6 +820,7 @@ const build = async ({
|
|
|
720
820
|
console.log("Input pages dir:", inputPagesDir);
|
|
721
821
|
console.log("Input components dir:", inputComponentsDir);
|
|
722
822
|
console.log("Input assets dir:", inputAssetsDir);
|
|
823
|
+
console.log("Input public dir:", inputPublicDir);
|
|
723
824
|
console.log("Temp pages dir:", tmpPagesDir);
|
|
724
825
|
console.log("Temp components dir:", tmpComponentsDir);
|
|
725
826
|
console.log("Output pages dir:", outputPagesDir);
|
|
@@ -738,6 +839,8 @@ const build = async ({
|
|
|
738
839
|
changeKind = "component";
|
|
739
840
|
} else if (isPathInOrUnder$1(changedRelative, projectPaths.assetsSourceDir)) {
|
|
740
841
|
changeKind = "asset";
|
|
842
|
+
} else if (isPathInOrUnder$1(changedRelative, "public")) {
|
|
843
|
+
changeKind = "asset";
|
|
741
844
|
} else if (changedRelative === "config.ts" || changedRelative === "config.js") {
|
|
742
845
|
changeKind = "config";
|
|
743
846
|
}
|
|
@@ -755,7 +858,7 @@ const build = async ({
|
|
|
755
858
|
const shouldCopyToTemp = (src) => {
|
|
756
859
|
const relative2 = src.startsWith(projectDir) ? normalizePath$1(src.slice(projectDir.length).replace(/^[\\/]+/, "")) : src;
|
|
757
860
|
const firstSegment = relative2.split(/[\\/]/)[0];
|
|
758
|
-
return !(firstSegment === "node_modules" || firstSegment === config.output || firstSegment === ".endpoints" || firstSegment === ".ssg-temp" || firstSegment === ".git" || projectPaths.assetsSourceDirCandidates.some(
|
|
861
|
+
return !(firstSegment === "node_modules" || firstSegment === config.output || firstSegment === ".endpoints" || firstSegment === ".ssg-temp" || firstSegment === ".git" || firstSegment === "public" || projectPaths.assetsSourceDirCandidates.some(
|
|
759
862
|
(candidateDir) => isPathInOrUnder$1(relative2, candidateDir)
|
|
760
863
|
));
|
|
761
864
|
};
|
|
@@ -1012,11 +1115,15 @@ const build = async ({
|
|
|
1012
1115
|
resolve(entryFile)
|
|
1013
1116
|
])
|
|
1014
1117
|
);
|
|
1118
|
+
const componentBuildPlugins = [
|
|
1119
|
+
defuss(),
|
|
1120
|
+
...await loadProjectTailwindVitePlugins(projectDir, debug)
|
|
1121
|
+
];
|
|
1015
1122
|
await build$1({
|
|
1016
1123
|
root: resolve(tmpComponentsDir),
|
|
1017
1124
|
configFile: false,
|
|
1018
1125
|
publicDir: false,
|
|
1019
|
-
plugins:
|
|
1126
|
+
plugins: componentBuildPlugins,
|
|
1020
1127
|
build: {
|
|
1021
1128
|
lib: {
|
|
1022
1129
|
entry: componentEntries,
|
|
@@ -1034,6 +1141,7 @@ const build = async ({
|
|
|
1034
1141
|
}
|
|
1035
1142
|
}
|
|
1036
1143
|
});
|
|
1144
|
+
await normalizeComponentStylesheets(tmpComponentOutDir);
|
|
1037
1145
|
timeEndDebug("[build] vite-components");
|
|
1038
1146
|
}
|
|
1039
1147
|
if (isFullBuild || changeKind === "page" || changeKind === "endpoint") {
|
|
@@ -1049,6 +1157,16 @@ const build = async ({
|
|
|
1049
1157
|
if (existsSync(inputAssetsDir)) {
|
|
1050
1158
|
await cp(inputAssetsDir, outputAssetsDir, { recursive: true });
|
|
1051
1159
|
}
|
|
1160
|
+
if (existsSync(inputPublicDir)) {
|
|
1161
|
+
await cp(inputPublicDir, outputProjectDir, { recursive: true });
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
if (isFullBuild || changeKind === "page" || changeKind === "component") {
|
|
1165
|
+
await injectComponentStylesheetsIntoOutputHtml(
|
|
1166
|
+
outputProjectDir,
|
|
1167
|
+
outputComponentsDir,
|
|
1168
|
+
projectPaths.componentsPublicDir
|
|
1169
|
+
);
|
|
1052
1170
|
}
|
|
1053
1171
|
timeEndDebug("[build] copy-outputs");
|
|
1054
1172
|
if (isFullBuild || changeKind === "component") {
|
|
@@ -1277,8 +1395,6 @@ const handleRpcRequest = async (ctx) => {
|
|
|
1277
1395
|
}
|
|
1278
1396
|
};
|
|
1279
1397
|
|
|
1280
|
-
const __filename$1 = fileURLToPath(import.meta.url);
|
|
1281
|
-
const __dirname$1 = dirname(__filename$1);
|
|
1282
1398
|
const MIME_TYPES = {
|
|
1283
1399
|
".css": "text/css; charset=utf-8",
|
|
1284
1400
|
".gif": "image/gif",
|
|
@@ -1677,18 +1793,25 @@ const injectHmrClientModule = (html) => {
|
|
|
1677
1793
|
}
|
|
1678
1794
|
return `${importTag}${html}`;
|
|
1679
1795
|
};
|
|
1680
|
-
const
|
|
1681
|
-
const
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
join(__dirname$1, "runtime.mjs")
|
|
1685
|
-
];
|
|
1686
|
-
for (const candidate of candidates) {
|
|
1687
|
-
if (existsSync(candidate)) {
|
|
1688
|
-
return candidate;
|
|
1689
|
-
}
|
|
1796
|
+
const injectStylesheetLinks = (html, hrefs) => {
|
|
1797
|
+
const missingHrefs = hrefs.filter((href) => !html.includes(`href="${href}"`));
|
|
1798
|
+
if (missingHrefs.length === 0) {
|
|
1799
|
+
return html;
|
|
1690
1800
|
}
|
|
1691
|
-
|
|
1801
|
+
const linkTags = missingHrefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("");
|
|
1802
|
+
if (html.includes("</head>")) {
|
|
1803
|
+
return html.replace("</head>", `${linkTags}</head>`);
|
|
1804
|
+
}
|
|
1805
|
+
return `${linkTags}${html}`;
|
|
1806
|
+
};
|
|
1807
|
+
const getComponentStylesheetHrefs = async (componentsOutputDir, componentsPublicDir) => {
|
|
1808
|
+
if (!existsSync(componentsOutputDir)) {
|
|
1809
|
+
return [];
|
|
1810
|
+
}
|
|
1811
|
+
const cssFiles = await glob.async(join(componentsOutputDir, "**/*.css"));
|
|
1812
|
+
return cssFiles.sort((left, right) => left.localeCompare(right)).map(
|
|
1813
|
+
(cssFile) => `/${normalizePath(join(componentsPublicDir, relative(componentsOutputDir, cssFile)))}`
|
|
1814
|
+
);
|
|
1692
1815
|
};
|
|
1693
1816
|
const isHtmlLikeFile = (filePath) => {
|
|
1694
1817
|
const extension = extname(filePath);
|
|
@@ -1738,6 +1861,9 @@ const classifyChangedFile = (file, projectDir, config, rpcFile) => {
|
|
|
1738
1861
|
if (isPathInOrUnder(relativeFile, paths.assetsSourceDir)) {
|
|
1739
1862
|
return "asset";
|
|
1740
1863
|
}
|
|
1864
|
+
if (isPathInOrUnder(relativeFile, "public")) {
|
|
1865
|
+
return "asset";
|
|
1866
|
+
}
|
|
1741
1867
|
return "dependency";
|
|
1742
1868
|
};
|
|
1743
1869
|
const filePathToComponentPublicPath = (file, componentsSourceDir, componentsPublicDir) => {
|
|
@@ -2126,6 +2252,13 @@ function defussSsg(options = {}) {
|
|
|
2126
2252
|
);
|
|
2127
2253
|
const el = renderSync(vdom, document.documentElement, { browserGlobals });
|
|
2128
2254
|
let html = renderToString(el);
|
|
2255
|
+
html = injectStylesheetLinks(
|
|
2256
|
+
html,
|
|
2257
|
+
await getComponentStylesheetHrefs(
|
|
2258
|
+
join(projectDir, config.output, currentPaths.componentsPublicDir),
|
|
2259
|
+
currentPaths.componentsPublicDir
|
|
2260
|
+
)
|
|
2261
|
+
);
|
|
2129
2262
|
html = injectHmrClientModule(html);
|
|
2130
2263
|
html = await server.transformIndexHtml(requestUrl.pathname, html);
|
|
2131
2264
|
res.setHeader("Cache-Control", "no-store");
|
|
@@ -2140,27 +2273,14 @@ function defussSsg(options = {}) {
|
|
|
2140
2273
|
const maybeServeComponent = async (server, req, res) => {
|
|
2141
2274
|
const requestUrl = new URL(req.url || "/", "http://localhost");
|
|
2142
2275
|
const pathname = requestUrl.pathname;
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
const componentRoutePrefix = `/${config.components}/`;
|
|
2147
|
-
if (pathname === `/${config.components}/runtime.js`) {
|
|
2148
|
-
const runtimePath = resolveRuntimeHelperFile();
|
|
2149
|
-
if (!runtimePath) {
|
|
2150
|
-
return false;
|
|
2151
|
-
}
|
|
2152
|
-
const transformed2 = await server.transformRequest(runtimePath);
|
|
2153
|
-
if (transformed2) {
|
|
2154
|
-
res.setHeader("Cache-Control", "no-store");
|
|
2155
|
-
res.setHeader("Content-Type", "text/javascript; charset=utf-8");
|
|
2156
|
-
res.statusCode = 200;
|
|
2157
|
-
res.end(transformed2.code);
|
|
2158
|
-
return true;
|
|
2159
|
-
}
|
|
2276
|
+
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2277
|
+
const componentRoutePrefix = `/${currentPaths.componentsPublicDir}/`;
|
|
2278
|
+
if (!pathname.startsWith(componentRoutePrefix)) {
|
|
2160
2279
|
return false;
|
|
2161
2280
|
}
|
|
2162
2281
|
const relativeComponentPath = pathname.slice(componentRoutePrefix.length);
|
|
2163
|
-
const
|
|
2282
|
+
const componentExtension = extname(relativeComponentPath).toLowerCase();
|
|
2283
|
+
const isBuiltComponentAsset = relativeComponentPath === "runtime.js" || relativeComponentPath.startsWith("chunks/") || /^chunk-|^client-/.test(relativeComponentPath) || componentExtension !== ".js";
|
|
2164
2284
|
if (isBuiltComponentAsset) {
|
|
2165
2285
|
return false;
|
|
2166
2286
|
}
|
|
@@ -2168,7 +2288,6 @@ function defussSsg(options = {}) {
|
|
|
2168
2288
|
extname(relativeComponentPath),
|
|
2169
2289
|
""
|
|
2170
2290
|
);
|
|
2171
|
-
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2172
2291
|
const extensions = [".tsx", ".ts", ".jsx", ".js"];
|
|
2173
2292
|
let sourceFile = null;
|
|
2174
2293
|
for (const ext of extensions) {
|
|
@@ -2182,10 +2301,7 @@ function defussSsg(options = {}) {
|
|
|
2182
2301
|
}
|
|
2183
2302
|
}
|
|
2184
2303
|
if (!sourceFile) {
|
|
2185
|
-
|
|
2186
|
-
res.statusCode = 404;
|
|
2187
|
-
res.end();
|
|
2188
|
-
return true;
|
|
2304
|
+
return false;
|
|
2189
2305
|
}
|
|
2190
2306
|
const transformed = await server.transformRequest(sourceFile);
|
|
2191
2307
|
if (transformed) {
|
|
@@ -2223,9 +2339,18 @@ function defussSsg(options = {}) {
|
|
|
2223
2339
|
MIME_TYPES[extname(outputFile)] ?? "application/octet-stream"
|
|
2224
2340
|
);
|
|
2225
2341
|
if (outputFile.endsWith(".html")) {
|
|
2342
|
+
const currentPaths = resolveSsgPaths(projectDir, config);
|
|
2226
2343
|
const html = await server.transformIndexHtml(
|
|
2227
2344
|
requestUrl.pathname,
|
|
2228
|
-
injectHmrClientModule(
|
|
2345
|
+
injectHmrClientModule(
|
|
2346
|
+
injectStylesheetLinks(
|
|
2347
|
+
body.toString("utf8"),
|
|
2348
|
+
await getComponentStylesheetHrefs(
|
|
2349
|
+
join(projectDir, config.output, currentPaths.componentsPublicDir),
|
|
2350
|
+
currentPaths.componentsPublicDir
|
|
2351
|
+
)
|
|
2352
|
+
)
|
|
2353
|
+
)
|
|
2229
2354
|
);
|
|
2230
2355
|
res.statusCode = 200;
|
|
2231
2356
|
res.end(method === "HEAD" ? void 0 : html);
|
|
@@ -2280,6 +2405,7 @@ function defussSsg(options = {}) {
|
|
|
2280
2405
|
...paths.assetsSourceDirCandidates.map(
|
|
2281
2406
|
(candidateDir) => join(projectDir, candidateDir)
|
|
2282
2407
|
),
|
|
2408
|
+
join(projectDir, "public"),
|
|
2283
2409
|
join(projectDir, "config.ts"),
|
|
2284
2410
|
join(projectDir, "config.js")
|
|
2285
2411
|
];
|
package/dist/vite.cjs
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
require('fast-glob');
|
|
3
4
|
require('node:fs');
|
|
4
5
|
require('node:fs/promises');
|
|
5
6
|
require('node:path');
|
|
6
|
-
require('node:url');
|
|
7
7
|
require('defuss/server');
|
|
8
|
-
var vite = require('./vite-
|
|
8
|
+
var vite = require('./vite-CkpguLfK.cjs');
|
|
9
9
|
require('node:crypto');
|
|
10
10
|
require('@mdx-js/rollup');
|
|
11
|
-
require('fast-glob');
|
|
12
11
|
require('vite');
|
|
13
12
|
require('defuss-vite');
|
|
13
|
+
require('node:module');
|
|
14
|
+
require('node:url');
|
|
14
15
|
require('node:os');
|
|
15
16
|
require('esbuild');
|
|
16
17
|
require('rehype-katex');
|
package/dist/vite.mjs
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import 'fast-glob';
|
|
1
2
|
import 'node:fs';
|
|
2
3
|
import 'node:fs/promises';
|
|
3
4
|
import 'node:path';
|
|
4
|
-
import 'node:url';
|
|
5
5
|
import 'defuss/server';
|
|
6
|
-
export { f as defussSsg } from './vite-
|
|
6
|
+
export { f as defussSsg } from './vite-DdJcWQGP.mjs';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import '@mdx-js/rollup';
|
|
9
|
-
import 'fast-glob';
|
|
10
9
|
import 'vite';
|
|
11
10
|
import 'defuss-vite';
|
|
11
|
+
import 'node:module';
|
|
12
|
+
import 'node:url';
|
|
12
13
|
import 'node:os';
|
|
13
14
|
import 'esbuild';
|
|
14
15
|
import 'rehype-katex';
|