@docubook/flame 1.5.3 → 1.6.0
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/.docu/lib/build.deno.js +4 -4
- package/.docu/lib/build.impl-N2MBT3CM.js +12 -0
- package/.docu/lib/build.node.js +4 -4
- package/.docu/lib/{chunk-J5NMYSBJ.js → chunk-4IQXHHPF.js} +5 -2
- package/.docu/lib/{chunk-YI76L7LB.js → chunk-IJFMQFWW.js} +69 -25
- package/.docu/lib/{chunk-YENO4SVR.js → chunk-JTH4JBBS.js} +38 -5
- package/.docu/lib/chunk-TI6M4643.js +204 -0
- package/.docu/lib/{chunk-EIKBL7SD.js → chunk-UUS45SUC.js} +2 -2
- package/.docu/lib/{chunk-WCMRAAWH.js → chunk-Y2TAEAUQ.js} +2 -2
- package/.docu/lib/{chunk-VX4HLVHE.js → chunk-ZA5QB5UK.js} +4 -4
- package/.docu/lib/clean.js +2 -2
- package/.docu/lib/deploy.deno.js +2 -2
- package/.docu/lib/deploy.node.js +2 -2
- package/.docu/lib/preview.deno.js +3 -3
- package/.docu/lib/preview.node.js +3 -3
- package/.docu/lib/server.deno.js +4 -4
- package/.docu/lib/server.node.js +4 -4
- package/.docu/node/build.impl.ts +15 -3
- package/.docu/node/build.ts +6 -0
- package/.docu/node/client.ts +38 -13
- package/.docu/node/deploy.shared.ts +147 -12
- package/.docu/node/deploy.ts +141 -30
- package/.docu/node/html.shared.ts +19 -0
- package/.docu/node/html.ts +17 -23
- package/.docu/node/hydrate.node.ts +74 -39
- package/.docu/node/hydrate.ts +74 -48
- package/.docu/node/paths.ts +7 -5
- package/.docu/node/seo.ts +42 -0
- package/.docu/node/server-routes.ts +2 -1
- package/.docu/node/types.ts +2 -0
- package/bin/cli.js +19 -6
- package/docu.schema.json +5 -1
- package/package.json +4 -4
- package/template/docs/assets/images/og.png +0 -0
- package/template/docu.json +2 -1
- package/.docu/lib/build.impl-O3Z5XIGM.js +0 -12
- package/.docu/lib/chunk-7VXEOH7X.js +0 -79
package/.docu/lib/build.deno.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuildCli
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-JTH4JBBS.js";
|
|
4
|
+
import "./chunk-IJFMQFWW.js";
|
|
5
5
|
import "./chunk-EOK6KATZ.js";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-Y2TAEAUQ.js";
|
|
7
|
+
import "./chunk-4IQXHHPF.js";
|
|
8
8
|
|
|
9
9
|
// .docu/node/build.deno.ts
|
|
10
10
|
await runBuildCli();
|
package/.docu/lib/build.node.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runBuildCli
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-JTH4JBBS.js";
|
|
4
|
+
import "./chunk-IJFMQFWW.js";
|
|
5
5
|
import "./chunk-EOK6KATZ.js";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-Y2TAEAUQ.js";
|
|
7
|
+
import "./chunk-4IQXHHPF.js";
|
|
8
8
|
|
|
9
9
|
// .docu/node/build.node.ts
|
|
10
10
|
await runBuildCli();
|
|
@@ -16,10 +16,11 @@ var DOCS_DIR = join(PROJECT_ROOT, "docs");
|
|
|
16
16
|
var DOCS_ASSETS_DIR = join(PROJECT_ROOT, "docs/assets");
|
|
17
17
|
var DOCU_CONFIG_PATH = join(PROJECT_ROOT, "docu.json");
|
|
18
18
|
var _config = null;
|
|
19
|
-
async function cleanOldBundles() {
|
|
19
|
+
async function cleanOldBundles(preserve) {
|
|
20
20
|
try {
|
|
21
21
|
const files = await readdir(ASSETS_DIR);
|
|
22
22
|
for (const file of files) {
|
|
23
|
+
if (preserve?.has(file)) continue;
|
|
23
24
|
if (file.startsWith("client.") || file.startsWith("client-")) {
|
|
24
25
|
await unlink(join(ASSETS_DIR, file));
|
|
25
26
|
}
|
|
@@ -32,7 +33,9 @@ async function cleanOldBundles() {
|
|
|
32
33
|
try {
|
|
33
34
|
await rm(join(ASSETS_DIR, "chunks"), { recursive: true, force: true });
|
|
34
35
|
} catch (err) {
|
|
35
|
-
|
|
36
|
+
if (err.code !== "ENOENT") {
|
|
37
|
+
console.warn("[flame] Failed to clean chunks dir:", err.message);
|
|
38
|
+
}
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
function loadDocuConfig() {
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
STYLES_DIR,
|
|
16
16
|
cleanOldBundles,
|
|
17
17
|
loadDocuConfig
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4IQXHHPF.js";
|
|
19
19
|
|
|
20
20
|
// .docu/node/plugin-loader.ts
|
|
21
21
|
import { resolve } from "node:path";
|
|
@@ -706,9 +706,29 @@ function resolveTailwindBin() {
|
|
|
706
706
|
const binRel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.tailwindcss;
|
|
707
707
|
return join2(dirname(pkgPath), binRel);
|
|
708
708
|
}
|
|
709
|
-
|
|
709
|
+
function tailwindCacheKey() {
|
|
710
|
+
const globalsPath = join2(STYLES_DIR, "globals.css");
|
|
711
|
+
const globalsContent = existsSync(globalsPath) ? readFileSync(globalsPath, "utf-8") : "";
|
|
712
|
+
let themeSuffix = "";
|
|
713
|
+
try {
|
|
714
|
+
const themeColors = getThemeConfig();
|
|
715
|
+
if (themeColors) {
|
|
716
|
+
themeSuffix = JSON.stringify(themeColors);
|
|
717
|
+
}
|
|
718
|
+
} catch {
|
|
719
|
+
}
|
|
720
|
+
return createHash("md5").update(globalsContent + themeSuffix).digest("hex").slice(0, 16);
|
|
721
|
+
}
|
|
722
|
+
async function buildTailwindCss(key) {
|
|
723
|
+
const cachedFile = `client-${key}.css`;
|
|
724
|
+
const cachedPath = join2(ASSETS_DIR, cachedFile);
|
|
725
|
+
if (existsSync(cachedPath)) {
|
|
726
|
+
const content = readFileSync(cachedPath, "utf-8");
|
|
727
|
+
return { file: cachedFile, content };
|
|
728
|
+
}
|
|
729
|
+
const tmpCss = join2(ASSETS_DIR, `_tmp-${key}.css`);
|
|
710
730
|
const bin = resolveTailwindBin();
|
|
711
|
-
const twArgs = ["-i", join2(STYLES_DIR, "globals.css"), "-o",
|
|
731
|
+
const twArgs = ["-i", join2(STYLES_DIR, "globals.css"), "-o", tmpCss, "--minify"];
|
|
712
732
|
const isDeno = "Deno" in globalThis;
|
|
713
733
|
const args = isDeno ? ["run", "-A", bin, ...twArgs] : [bin, ...twArgs];
|
|
714
734
|
try {
|
|
@@ -718,6 +738,24 @@ async function runTailwind(outputCss) {
|
|
|
718
738
|
throw new Error(`Tailwind CSS build failed:
|
|
719
739
|
${stderr}`, { cause: err });
|
|
720
740
|
}
|
|
741
|
+
let cssContent = await readFile(tmpCss, "utf-8");
|
|
742
|
+
await unlink(tmpCss);
|
|
743
|
+
try {
|
|
744
|
+
const themeColors = getThemeConfig();
|
|
745
|
+
if (themeColors) {
|
|
746
|
+
cssContent = buildThemeCss(cssContent, themeColors);
|
|
747
|
+
}
|
|
748
|
+
} catch (err) {
|
|
749
|
+
console.warn(
|
|
750
|
+
`[flame] Failed to resolve theme config, falling back to globals.css only: ${err instanceof Error ? err.message : String(err)}`
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
const cssFile = `client-${key}.css`;
|
|
754
|
+
const outPath = join2(ASSETS_DIR, cssFile);
|
|
755
|
+
if (!existsSync(outPath)) {
|
|
756
|
+
await writeFile(outPath, cssContent);
|
|
757
|
+
}
|
|
758
|
+
return { file: cssFile, content: cssContent };
|
|
721
759
|
}
|
|
722
760
|
var NODE_BUILTINS_RE = new RegExp(
|
|
723
761
|
`^(node:.*|${builtinModules.map((m) => m.replace(/\//g, "\\/")).join("|")})$`
|
|
@@ -749,7 +787,10 @@ function scanDirLucideIcons(dir, set) {
|
|
|
749
787
|
}
|
|
750
788
|
}
|
|
751
789
|
}
|
|
752
|
-
} catch {
|
|
790
|
+
} catch (err) {
|
|
791
|
+
console.warn(
|
|
792
|
+
`[flame] Failed to scan lucide icons: ${err instanceof Error ? err.message : String(err)}`
|
|
793
|
+
);
|
|
753
794
|
}
|
|
754
795
|
}
|
|
755
796
|
function collectAllLucideIcons() {
|
|
@@ -768,7 +809,8 @@ function collectAllLucideIcons() {
|
|
|
768
809
|
}
|
|
769
810
|
async function buildClientBundle() {
|
|
770
811
|
await mkdir(ASSETS_DIR, { recursive: true });
|
|
771
|
-
|
|
812
|
+
const twKey = tailwindCacheKey();
|
|
813
|
+
await cleanOldBundles(/* @__PURE__ */ new Set([`client-${twKey}.css`]));
|
|
772
814
|
const nodeEnv = process.env.NODE_ENV || "development";
|
|
773
815
|
const esbuild = await import("esbuild");
|
|
774
816
|
const { build } = esbuild;
|
|
@@ -781,10 +823,8 @@ async function buildClientBundle() {
|
|
|
781
823
|
bundle: true,
|
|
782
824
|
outdir: ASSETS_DIR,
|
|
783
825
|
entryNames: "client-[hash]",
|
|
784
|
-
chunkNames: "chunks/[name]-[hash]",
|
|
785
826
|
platform: "browser",
|
|
786
827
|
format: "esm",
|
|
787
|
-
splitting: true,
|
|
788
828
|
minify: nodeEnv === "production",
|
|
789
829
|
define: { "process.env.NODE_ENV": JSON.stringify(nodeEnv) },
|
|
790
830
|
jsx: "automatic",
|
|
@@ -814,7 +854,7 @@ async function buildClientBundle() {
|
|
|
814
854
|
}
|
|
815
855
|
if (args.importer) {
|
|
816
856
|
const normalized = normalizeImporterPath(args.importer);
|
|
817
|
-
if (normalized.
|
|
857
|
+
if (normalized.includes("/mdx-content/dist/")) {
|
|
818
858
|
return { path: getLucideRealEntry(), namespace: "file" };
|
|
819
859
|
}
|
|
820
860
|
}
|
|
@@ -862,23 +902,7 @@ async function buildClientBundle() {
|
|
|
862
902
|
throw new Error("Client bundle produced no output files");
|
|
863
903
|
}
|
|
864
904
|
const jsFile = basename(jsOutput);
|
|
865
|
-
const
|
|
866
|
-
await runTailwind(tmpCss);
|
|
867
|
-
let cssContent = await readFile(tmpCss, "utf-8");
|
|
868
|
-
try {
|
|
869
|
-
const themeColors = getThemeConfig();
|
|
870
|
-
if (themeColors) {
|
|
871
|
-
cssContent = buildThemeCss(cssContent, themeColors);
|
|
872
|
-
}
|
|
873
|
-
} catch (err) {
|
|
874
|
-
console.warn(
|
|
875
|
-
`[flame] Failed to resolve theme config, falling back to globals.css only: ${err instanceof Error ? err.message : String(err)}`
|
|
876
|
-
);
|
|
877
|
-
}
|
|
878
|
-
const cssHash = createHash("md5").update(cssContent).digest("hex").slice(0, 8);
|
|
879
|
-
const cssFile = `client-${cssHash}.css`;
|
|
880
|
-
await writeFile(join2(ASSETS_DIR, cssFile), cssContent);
|
|
881
|
-
await unlink(tmpCss);
|
|
905
|
+
const { file: cssFile } = await buildTailwindCss(twKey);
|
|
882
906
|
await writeFile(join2(ASSETS_DIR, "manifest.json"), JSON.stringify({ js: jsFile, css: cssFile }));
|
|
883
907
|
return { js: jsFile, css: cssFile };
|
|
884
908
|
}
|
|
@@ -2336,6 +2360,23 @@ function htmlShell(opts) {
|
|
|
2336
2360
|
const depthPrefix = depth === 0 ? "" : "../".repeat(depth);
|
|
2337
2361
|
const assetPrefix = depthPrefix + "assets/";
|
|
2338
2362
|
const resolvePath = (path) => path.startsWith("/") ? depthPrefix + path.slice(1) : path;
|
|
2363
|
+
let seoTags = "";
|
|
2364
|
+
if (opts.seo) {
|
|
2365
|
+
const s = opts.seo;
|
|
2366
|
+
const e = escapeHtml;
|
|
2367
|
+
seoTags = `
|
|
2368
|
+
<meta property="og:title" content="${e(title)}" />
|
|
2369
|
+
<meta property="og:description" content="${e(description)}" />
|
|
2370
|
+
<meta property="og:url" content="${e(s.url)}" />
|
|
2371
|
+
<meta property="og:type" content="website" />
|
|
2372
|
+
<meta property="og:site_name" content="${e(s.siteName)}" />
|
|
2373
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
2374
|
+
<link rel="canonical" href="${e(s.url)}" />`;
|
|
2375
|
+
if (s.image) {
|
|
2376
|
+
seoTags += `
|
|
2377
|
+
<meta property="og:image" content="${e(s.image)}" />`;
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2339
2380
|
return `<!DOCTYPE html>
|
|
2340
2381
|
<html lang="en">
|
|
2341
2382
|
<head>
|
|
@@ -2344,12 +2385,15 @@ function htmlShell(opts) {
|
|
|
2344
2385
|
<title>${escapeHtml(title)}</title>
|
|
2345
2386
|
<meta name="description" content="${escapeHtml(description)}">
|
|
2346
2387
|
${favicon ? `<link rel="icon" type="image/x-icon" href="${escapeHtml(resolvePath(favicon))}">` : ""}${themeStyle}
|
|
2388
|
+
<link rel="preload" href="${escapeHtml(assetPrefix + css)}" as="style">
|
|
2347
2389
|
<link rel="stylesheet" href="${escapeHtml(assetPrefix + css)}">
|
|
2348
2390
|
${csp ? `<meta http-equiv="Content-Security-Policy" content="${escapeHtml(csp)}">` : ""}
|
|
2391
|
+
${seoTags}
|
|
2349
2392
|
<script${nonceAttr}>try{if(localStorage.getItem("theme")==="dark")document.documentElement.classList.add("dark")}catch(e){}</script>${headInjection}
|
|
2350
2393
|
</head>
|
|
2351
2394
|
<body>
|
|
2352
2395
|
<div id="root">${body}</div>
|
|
2396
|
+
<link rel="modulepreload" href="${escapeHtml(assetPrefix + js)}">
|
|
2353
2397
|
<script type="module"${nonceAttr} src="${escapeHtml(assetPrefix + js)}"></script>${extraScripts ? `
|
|
2354
2398
|
${extraScripts}` : ""}${bodyInjection}
|
|
2355
2399
|
</body>
|
|
@@ -13,14 +13,15 @@ import {
|
|
|
13
13
|
htmlShell,
|
|
14
14
|
initSentry,
|
|
15
15
|
loadPlugins
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IJFMQFWW.js";
|
|
17
17
|
import {
|
|
18
|
+
cspHeader,
|
|
18
19
|
generateNonce,
|
|
19
20
|
scanMdxFiles
|
|
20
21
|
} from "./chunk-EOK6KATZ.js";
|
|
21
22
|
import {
|
|
22
23
|
logger
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-Y2TAEAUQ.js";
|
|
24
25
|
import {
|
|
25
26
|
ASSETS_DIR,
|
|
26
27
|
CACHE_FILE,
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
DOCS_DIR,
|
|
30
31
|
PROJECT_ROOT,
|
|
31
32
|
loadDocuConfig
|
|
32
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-4IQXHHPF.js";
|
|
33
34
|
|
|
34
35
|
// .docu/node/build.impl.ts
|
|
35
36
|
import { readFile, writeFile, mkdir, readdir, copyFile } from "node:fs/promises";
|
|
@@ -38,6 +39,27 @@ import { createHash } from "node:crypto";
|
|
|
38
39
|
import { join, dirname } from "node:path";
|
|
39
40
|
import React from "react";
|
|
40
41
|
import { renderToString } from "react-dom/server";
|
|
42
|
+
|
|
43
|
+
// .docu/node/seo.ts
|
|
44
|
+
function buildSeoMeta(config, frontmatter, slug) {
|
|
45
|
+
const baseURL = config.meta?.baseURL?.replace(/\/+$/, "") || "";
|
|
46
|
+
const url = slug ? `${baseURL}/docs/${slug}` : `${baseURL}/`;
|
|
47
|
+
const result = {
|
|
48
|
+
url,
|
|
49
|
+
siteName: config.meta?.title || ""
|
|
50
|
+
};
|
|
51
|
+
const image = typeof frontmatter.image === "string" && frontmatter.image || config.meta?.ogImage;
|
|
52
|
+
if (image) {
|
|
53
|
+
try {
|
|
54
|
+
result.image = new URL(image, image.startsWith("/") ? baseURL : `${baseURL}/docs/`).href;
|
|
55
|
+
} catch {
|
|
56
|
+
result.image = image;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// .docu/node/build.impl.ts
|
|
41
63
|
function parseArgs() {
|
|
42
64
|
const args = process.argv.slice(2);
|
|
43
65
|
return {
|
|
@@ -123,11 +145,15 @@ ${msg}`, { cause: err });
|
|
|
123
145
|
const bodyExtra = builder?.collectBody(ctx);
|
|
124
146
|
const depth = slug ? slug.split("/").length : 1;
|
|
125
147
|
const favicon = docuConfig.meta?.favicon || "/docs/assets/images/favicon.ico";
|
|
148
|
+
const seo = buildSeoMeta(docuConfig, frontmatter, slug || "");
|
|
149
|
+
const csp = cspHeader(nonce, process.env.NODE_ENV !== "production");
|
|
126
150
|
let html = htmlShell({
|
|
127
151
|
title,
|
|
128
152
|
description,
|
|
129
153
|
body,
|
|
130
154
|
favicon,
|
|
155
|
+
seo,
|
|
156
|
+
csp,
|
|
131
157
|
css: assetManifest.css,
|
|
132
158
|
js: assetManifest.js,
|
|
133
159
|
nonce,
|
|
@@ -298,14 +324,18 @@ async function runBuild() {
|
|
|
298
324
|
}
|
|
299
325
|
const landingPage = React.createElement(IndexPage);
|
|
300
326
|
const landingFavicon = docuConfig.meta?.favicon || "/docs/assets/images/favicon.ico";
|
|
327
|
+
const landingSeo = buildSeoMeta(docuConfig, docuConfig.meta, "");
|
|
328
|
+
const landingNonce = generateNonce();
|
|
301
329
|
const landingHtml = htmlShell({
|
|
302
330
|
title: docuConfig.meta?.title || "DocuBook",
|
|
303
331
|
description: docuConfig.meta?.description || "",
|
|
304
332
|
body: renderToString(landingPage),
|
|
305
333
|
favicon: landingFavicon,
|
|
334
|
+
seo: landingSeo,
|
|
335
|
+
csp: cspHeader(landingNonce, process.env.NODE_ENV !== "production"),
|
|
306
336
|
css: assetManifest.css,
|
|
307
337
|
js: assetManifest.js,
|
|
308
|
-
nonce:
|
|
338
|
+
nonce: landingNonce,
|
|
309
339
|
themeCss: inlineThemeCss
|
|
310
340
|
});
|
|
311
341
|
await writeFile(join(DIST_DIR, "index.html"), landingHtml);
|
|
@@ -315,14 +345,17 @@ async function runBuild() {
|
|
|
315
345
|
React.createElement(NotFoundPage)
|
|
316
346
|
);
|
|
317
347
|
const notFoundFavicon = docuConfig.meta?.favicon || "/docs/assets/images/favicon.ico";
|
|
348
|
+
const notFoundNonce = generateNonce();
|
|
318
349
|
const notFoundHtml = htmlShell({
|
|
319
350
|
title: "404 - Not Found",
|
|
320
351
|
description: "",
|
|
321
352
|
body: renderToString(notFoundPage),
|
|
322
353
|
favicon: notFoundFavicon,
|
|
354
|
+
headExtra: ['<meta name="robots" content="noindex,follow">'],
|
|
355
|
+
csp: cspHeader(notFoundNonce, process.env.NODE_ENV !== "production"),
|
|
323
356
|
css: assetManifest.css,
|
|
324
357
|
js: assetManifest.js,
|
|
325
|
-
nonce:
|
|
358
|
+
nonce: notFoundNonce,
|
|
326
359
|
themeCss: inlineThemeCss
|
|
327
360
|
});
|
|
328
361
|
await writeFile(join(DIST_DIR, "404.html"), notFoundHtml);
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DIST_DIR,
|
|
3
|
+
PROJECT_ROOT
|
|
4
|
+
} from "./chunk-4IQXHHPF.js";
|
|
5
|
+
|
|
6
|
+
// .docu/node/deploy.shared.ts
|
|
7
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
var WORKFLOW_DIR = join(PROJECT_ROOT, ".github/workflows");
|
|
11
|
+
var WORKFLOW_FILE = join(WORKFLOW_DIR, "deploy.yml");
|
|
12
|
+
var HEADERS_FILE = `/*
|
|
13
|
+
X-Frame-Options: DENY
|
|
14
|
+
X-Content-Type-Options: nosniff
|
|
15
|
+
Referrer-Policy: strict-origin-when-cross-origin
|
|
16
|
+
|
|
17
|
+
/assets/*
|
|
18
|
+
Cache-Control: public, max-age=31536000, immutable
|
|
19
|
+
`;
|
|
20
|
+
var isDocker = !!process.env.FLAME_DEPLOY_DOCKER;
|
|
21
|
+
var isSilent = !!process.env.FLAME_DEPLOY_SILENT;
|
|
22
|
+
var log = isSilent ? { info: () => {
|
|
23
|
+
}, ok: () => {
|
|
24
|
+
}, created: () => {
|
|
25
|
+
}, out: () => {
|
|
26
|
+
} } : {
|
|
27
|
+
info: (m) => console.log(m),
|
|
28
|
+
ok: () => console.log("\n\u2705 Ready to deploy!"),
|
|
29
|
+
created: (m) => console.log(m),
|
|
30
|
+
out: (m) => console.log(m)
|
|
31
|
+
};
|
|
32
|
+
async function runBuild() {
|
|
33
|
+
process.env.NODE_ENV = "production";
|
|
34
|
+
if (isSilent) {
|
|
35
|
+
process.env.FLAME_BUILD_SILENT = "1";
|
|
36
|
+
process.env.LOG_LEVEL = "error";
|
|
37
|
+
}
|
|
38
|
+
const { runBuildCli } = await import("./build.impl-N2MBT3CM.js");
|
|
39
|
+
await runBuildCli();
|
|
40
|
+
}
|
|
41
|
+
async function writeDockerFiles() {
|
|
42
|
+
const dockerDir = PROJECT_ROOT;
|
|
43
|
+
if (!existsSync(join(dockerDir, "Dockerfile"))) {
|
|
44
|
+
await writeFile(
|
|
45
|
+
join(dockerDir, "Dockerfile"),
|
|
46
|
+
`FROM node:22-alpine AS builder
|
|
47
|
+
WORKDIR /app
|
|
48
|
+
COPY package.json package-lock.json ./
|
|
49
|
+
RUN npm ci
|
|
50
|
+
COPY . .
|
|
51
|
+
RUN npm run build
|
|
52
|
+
|
|
53
|
+
FROM nginx:alpine
|
|
54
|
+
COPY --from=builder /app/.docu/dist /usr/share/nginx/html
|
|
55
|
+
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
56
|
+
USER nginx
|
|
57
|
+
EXPOSE 80
|
|
58
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
59
|
+
`
|
|
60
|
+
);
|
|
61
|
+
log.created("\u{1F4C4} Created Dockerfile");
|
|
62
|
+
}
|
|
63
|
+
if (!existsSync(join(dockerDir, "nginx.conf"))) {
|
|
64
|
+
await writeFile(
|
|
65
|
+
join(dockerDir, "nginx.conf"),
|
|
66
|
+
`server {
|
|
67
|
+
listen 80;
|
|
68
|
+
server_name _;
|
|
69
|
+
root /usr/share/nginx/html;
|
|
70
|
+
index index.html;
|
|
71
|
+
|
|
72
|
+
gzip on;
|
|
73
|
+
gzip_types text/html text/css application/javascript image/svg+xml;
|
|
74
|
+
|
|
75
|
+
# Security headers (HSTS effective when HTTPS is terminated upstream)
|
|
76
|
+
add_header X-Frame-Options "DENY" always;
|
|
77
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
78
|
+
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
|
|
79
|
+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
80
|
+
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
|
81
|
+
|
|
82
|
+
location /assets/ {
|
|
83
|
+
expires 1y;
|
|
84
|
+
add_header Cache-Control "public, immutable";
|
|
85
|
+
add_header X-Frame-Options "DENY" always;
|
|
86
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
87
|
+
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
|
|
88
|
+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
89
|
+
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
location /docs/assets/ {
|
|
93
|
+
expires 7d;
|
|
94
|
+
add_header Cache-Control "public";
|
|
95
|
+
add_header X-Frame-Options "DENY" always;
|
|
96
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
97
|
+
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
|
|
98
|
+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
99
|
+
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
location / {
|
|
103
|
+
try_files $uri $uri.html $uri/ =404;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
`
|
|
107
|
+
);
|
|
108
|
+
log.created("\u{1F4C4} Created nginx.conf");
|
|
109
|
+
}
|
|
110
|
+
if (!existsSync(join(dockerDir, ".dockerignore"))) {
|
|
111
|
+
await writeFile(
|
|
112
|
+
join(dockerDir, ".dockerignore"),
|
|
113
|
+
`node_modules
|
|
114
|
+
.git
|
|
115
|
+
*.DS_Store
|
|
116
|
+
.docu/dist
|
|
117
|
+
.docu/lib
|
|
118
|
+
.env
|
|
119
|
+
.env.*
|
|
120
|
+
.npmrc
|
|
121
|
+
*.log
|
|
122
|
+
`
|
|
123
|
+
);
|
|
124
|
+
log.created("\u{1F4C4} Created .dockerignore");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function writeGhaWorkflow() {
|
|
128
|
+
if (!existsSync(WORKFLOW_FILE)) {
|
|
129
|
+
await mkdir(WORKFLOW_DIR, { recursive: true });
|
|
130
|
+
await writeFile(WORKFLOW_FILE, GITHUB_ACTIONS_WORKFLOW);
|
|
131
|
+
log.created("\u{1F4C4} Created .github/workflows/deploy.yml");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function runDeploy() {
|
|
135
|
+
log.info("\u{1F4E6} Building for production...\n");
|
|
136
|
+
await runBuild();
|
|
137
|
+
await writeFile(join(DIST_DIR, ".nojekyll"), "");
|
|
138
|
+
await writeFile(join(DIST_DIR, "_headers"), HEADERS_FILE);
|
|
139
|
+
if (isDocker) {
|
|
140
|
+
await writeDockerFiles();
|
|
141
|
+
} else {
|
|
142
|
+
await writeGhaWorkflow();
|
|
143
|
+
}
|
|
144
|
+
log.ok();
|
|
145
|
+
log.out(" Output: .docu/dist/");
|
|
146
|
+
if (isDocker) {
|
|
147
|
+
log.out(" Run: docker build -t my-docs . && docker run -p 80:80 my-docs");
|
|
148
|
+
} else {
|
|
149
|
+
log.out(" Push to GitHub and enable Pages (Settings \u2192 Pages \u2192 Source: GitHub Actions)");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
var GITHUB_ACTIONS_WORKFLOW = `name: Deploy to GitHub Pages
|
|
153
|
+
|
|
154
|
+
on:
|
|
155
|
+
push:
|
|
156
|
+
branches: [main]
|
|
157
|
+
workflow_dispatch:
|
|
158
|
+
|
|
159
|
+
permissions:
|
|
160
|
+
contents: read
|
|
161
|
+
pages: write
|
|
162
|
+
id-token: write
|
|
163
|
+
|
|
164
|
+
concurrency:
|
|
165
|
+
group: "pages"
|
|
166
|
+
cancel-in-progress: false
|
|
167
|
+
|
|
168
|
+
jobs:
|
|
169
|
+
build:
|
|
170
|
+
runs-on: ubuntu-latest
|
|
171
|
+
steps:
|
|
172
|
+
- uses: actions/checkout@v4
|
|
173
|
+
with:
|
|
174
|
+
fetch-depth: 0
|
|
175
|
+
|
|
176
|
+
- uses: actions/setup-node@v4
|
|
177
|
+
with:
|
|
178
|
+
node-version: 22
|
|
179
|
+
|
|
180
|
+
- run: npm install
|
|
181
|
+
|
|
182
|
+
- run: npm run build
|
|
183
|
+
|
|
184
|
+
- name: Add .nojekyll
|
|
185
|
+
run: touch .docu/dist/.nojekyll
|
|
186
|
+
|
|
187
|
+
- uses: actions/upload-pages-artifact@v3
|
|
188
|
+
with:
|
|
189
|
+
path: .docu/dist
|
|
190
|
+
|
|
191
|
+
deploy:
|
|
192
|
+
environment:
|
|
193
|
+
name: github-pages
|
|
194
|
+
url: \${{ steps.deployment.outputs.page_url }}
|
|
195
|
+
runs-on: ubuntu-latest
|
|
196
|
+
needs: build
|
|
197
|
+
steps:
|
|
198
|
+
- id: deployment
|
|
199
|
+
uses: actions/deploy-pages@v4
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
export {
|
|
203
|
+
runDeploy
|
|
204
|
+
};
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
} from "./chunk-EOK6KATZ.js";
|
|
8
8
|
import {
|
|
9
9
|
logger
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-Y2TAEAUQ.js";
|
|
11
11
|
import {
|
|
12
12
|
DIST_DIR
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-4IQXHHPF.js";
|
|
14
14
|
|
|
15
15
|
// .docu/node/preview.impl.ts
|
|
16
16
|
import { existsSync, statSync, readFileSync } from "node:fs";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadDocuConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4IQXHHPF.js";
|
|
4
4
|
|
|
5
5
|
// package.json
|
|
6
6
|
var package_default = {
|
|
7
7
|
name: "@docubook/flame",
|
|
8
|
-
version: "1.
|
|
8
|
+
version: "1.6.0",
|
|
9
9
|
description: "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
|
|
10
10
|
type: "module",
|
|
11
11
|
bin: {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
htmlShell,
|
|
15
15
|
initSentry,
|
|
16
16
|
loadPlugins
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-IJFMQFWW.js";
|
|
18
18
|
import {
|
|
19
19
|
SECURITY_HEADERS,
|
|
20
20
|
generateNonce,
|
|
@@ -27,13 +27,13 @@ import {
|
|
|
27
27
|
} from "./chunk-EOK6KATZ.js";
|
|
28
28
|
import {
|
|
29
29
|
logger
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-Y2TAEAUQ.js";
|
|
31
31
|
import {
|
|
32
32
|
DIST_DIR,
|
|
33
33
|
DOCS_DIR,
|
|
34
34
|
PROJECT_ROOT,
|
|
35
35
|
loadDocuConfig
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-4IQXHHPF.js";
|
|
37
37
|
|
|
38
38
|
// .docu/node/server.impl.ts
|
|
39
39
|
import { watch } from "node:fs";
|
|
@@ -240,7 +240,7 @@ function serveStatic(pathname) {
|
|
|
240
240
|
}
|
|
241
241
|
function serverErrorResponse(error) {
|
|
242
242
|
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
243
|
-
const st = error instanceof Error ? error.stack : void 0;
|
|
243
|
+
const st = process.env.NODE_ENV !== "production" && error instanceof Error ? error.stack : void 0;
|
|
244
244
|
return new Response(errorHtml(msg, st), {
|
|
245
245
|
status: 500,
|
|
246
246
|
headers: {
|
package/.docu/lib/clean.js
CHANGED
package/.docu/lib/deploy.deno.js
CHANGED
package/.docu/lib/deploy.node.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runPreview
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UUS45SUC.js";
|
|
4
4
|
import "./chunk-EOK6KATZ.js";
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-Y2TAEAUQ.js";
|
|
6
|
+
import "./chunk-4IQXHHPF.js";
|
|
7
7
|
|
|
8
8
|
// .docu/node/preview.deno.ts
|
|
9
9
|
import { denoAdapter } from "@docubook/runt";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runPreview
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UUS45SUC.js";
|
|
4
4
|
import "./chunk-EOK6KATZ.js";
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-Y2TAEAUQ.js";
|
|
6
|
+
import "./chunk-4IQXHHPF.js";
|
|
7
7
|
|
|
8
8
|
// .docu/node/preview.node.ts
|
|
9
9
|
import { nodeAdapter } from "@docubook/runt";
|