buner 1.0.7 → 1.0.8
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/buner.js +75 -92
- package/dist/integration.js +122 -112
- package/dist/prerender.js +144 -136
- package/dist/server.js +36 -26
- package/dist/states.js +44 -35
- package/dist/styles.js +145 -133
- package/package.json +1 -1
package/dist/buner.js
CHANGED
|
@@ -1,26 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from "path";
|
|
3
|
-
import { execSync, spawn } from "child_process";
|
|
4
3
|
import { fileURLToPath } from "url";
|
|
5
4
|
import { Command } from "commander";
|
|
6
5
|
import chalk from "chalk";
|
|
7
6
|
import fetch from "node-fetch";
|
|
8
7
|
import prompts from "prompts";
|
|
8
|
+
import { build } from "vite";
|
|
9
|
+
import { runStyles } from "./styles.js";
|
|
10
|
+
import { runStates } from "./states.js";
|
|
11
|
+
import { runServer } from "./server.js";
|
|
12
|
+
import { runPrerender } from "./prerender.js";
|
|
13
|
+
import { runIntegration } from "./integration.js";
|
|
14
|
+
import validateProjectName from "validate-npm-package-name";
|
|
9
15
|
import fs from "fs";
|
|
16
|
+
import { execSync } from "child_process";
|
|
10
17
|
import fs$1 from "fs/promises";
|
|
11
18
|
import os from "os";
|
|
12
19
|
import { globby } from "globby";
|
|
13
20
|
import { exec } from "node:child_process";
|
|
14
|
-
import
|
|
21
|
+
import "chokidar";
|
|
22
|
+
import "sass";
|
|
23
|
+
import "slash";
|
|
24
|
+
import "debounce";
|
|
25
|
+
import "glob";
|
|
26
|
+
import "postcss";
|
|
27
|
+
import "autoprefixer";
|
|
28
|
+
import "cssnano";
|
|
29
|
+
import "node:fs";
|
|
30
|
+
import "node:path";
|
|
31
|
+
import "express";
|
|
32
|
+
import "serve-static";
|
|
33
|
+
import "cheerio";
|
|
34
|
+
import "js-beautify";
|
|
35
|
+
import "node:crypto";
|
|
36
|
+
import "lodash";
|
|
15
37
|
const name = "buner";
|
|
16
|
-
const version = "1.0.
|
|
38
|
+
const version = "1.0.8";
|
|
17
39
|
const description = "Frontend build toolkit for Vite + React SSR projects — SCSS pipeline, prerender, SSR dev server, and backend integration.";
|
|
18
40
|
const type = "module";
|
|
19
41
|
const license = "MIT";
|
|
20
42
|
const repository = { "type": "git", "url": "https://github.com/precise-alloy/buner.git" };
|
|
21
43
|
const homepage = "https://www.npmjs.com/package/buner";
|
|
22
44
|
const keywords = ["vite", "react", "ssr", "scss", "prerender", "frontend", "build-tool", "cli"];
|
|
23
|
-
const bin
|
|
45
|
+
const bin = { "buner": "./dist/buner.js" };
|
|
24
46
|
const files = ["dist", "xpack", "public", "vite.config.ts", "index.html", "tsconfig.json", "eslint.config.mjs", "types.d.ts", ".env", ".env.development", ".env.eshn", "README.md"];
|
|
25
47
|
const scripts = { "start": "bun run dev", "predev": "bun upgrade", "dev": 'concurrently --kill-others "bun styles.ts --watch" "bun states.ts --watch" "cross-env scriptOnly=true vite build --mode development --watch" "bun server.ts --mode development"', "serve": "bun server.ts", "watch": "bun server.ts", "build": "bun run build:static && bun run build:server", "build:eshn": "bun run build:static:eshn && bun run build:server:eshn", "preview": "vite preview", "build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server", "build:server:eshn": "vite build --ssr src/entry-server.tsx --outDir dist/server --mode eshn", "build:static": "vite build --outDir dist/static", "build:static:eshn": "vite build --outDir dist/static --mode eshn", "generate": "bun states.ts && bun run styles && bun run build && bun prerender.ts --add-hash", "eshn": "bun states.ts && bun run styles && bun run build:eshn && bun prerender.ts --add-hash --mode eshn", "inte": "bun run styles && bun run build && bun prerender.ts && bun integration.ts", "styles": "bun styles.ts", "format": "prettier --write .", "lint": "eslint --fix", "cli:start": "vite build -c vite.cli.config.ts --watch", "cli:build": "vite build -c vite.cli.config.ts" };
|
|
26
48
|
const engines = { "node": ">=20.0.0" };
|
|
@@ -37,7 +59,7 @@ const packageJson = {
|
|
|
37
59
|
repository,
|
|
38
60
|
homepage,
|
|
39
61
|
keywords,
|
|
40
|
-
bin
|
|
62
|
+
bin,
|
|
41
63
|
files,
|
|
42
64
|
scripts,
|
|
43
65
|
engines,
|
|
@@ -46,6 +68,16 @@ const packageJson = {
|
|
|
46
68
|
devDependencies,
|
|
47
69
|
msw
|
|
48
70
|
};
|
|
71
|
+
function validateNpmName(name2) {
|
|
72
|
+
const nameValidation = validateProjectName(name2);
|
|
73
|
+
if (nameValidation.validForNewPackages && !name2.startsWith("-")) {
|
|
74
|
+
return { valid: true };
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
valid: false,
|
|
78
|
+
problems: [...nameValidation.errors || [], ...nameValidation.warnings || []]
|
|
79
|
+
};
|
|
80
|
+
}
|
|
49
81
|
const isWriteable = async (directory) => {
|
|
50
82
|
try {
|
|
51
83
|
await fs.promises.access(directory, fs.constants.W_OK);
|
|
@@ -418,55 +450,23 @@ Creating a new app in ${green$1(root)}.`);
|
|
|
418
450
|
console.log(`
|
|
419
451
|
${green$1("Success!")} Created ${appName} at ${appPath}`);
|
|
420
452
|
};
|
|
421
|
-
function validateNpmName(name2) {
|
|
422
|
-
const nameValidation = validateProjectName(name2);
|
|
423
|
-
if (nameValidation.validForNewPackages && !name2.startsWith("-")) {
|
|
424
|
-
return { valid: true };
|
|
425
|
-
}
|
|
426
|
-
return {
|
|
427
|
-
valid: false,
|
|
428
|
-
problems: [...nameValidation.errors || [], ...nameValidation.warnings || []]
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
453
|
const { green, yellow, bold, cyan, red } = chalk;
|
|
432
454
|
const packageName = "buner";
|
|
433
455
|
const packageDir = path.dirname(fileURLToPath(import.meta.url));
|
|
434
|
-
const
|
|
435
|
-
const
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
} catch {
|
|
456
|
+
const viteConfigPath = () => path.resolve(packageDir, "..", "vite.config.ts");
|
|
457
|
+
const viteBuild = async (opts) => {
|
|
458
|
+
const config = {
|
|
459
|
+
configFile: viteConfigPath(),
|
|
460
|
+
build: {
|
|
461
|
+
outDir: opts.outDir,
|
|
462
|
+
...opts.ssr ? { ssr: opts.ssr } : {},
|
|
463
|
+
...opts.watch ? { watch: {} } : {}
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
if (opts.mode) {
|
|
467
|
+
config.mode = opts.mode;
|
|
447
468
|
}
|
|
448
|
-
|
|
449
|
-
};
|
|
450
|
-
const run = (cmd, args = [], options = {}) => {
|
|
451
|
-
return new Promise((resolve, reject) => {
|
|
452
|
-
const child = spawn(cmd, args, {
|
|
453
|
-
stdio: "inherit",
|
|
454
|
-
shell: true,
|
|
455
|
-
cwd: process.cwd(),
|
|
456
|
-
...options
|
|
457
|
-
});
|
|
458
|
-
child.on("close", (code) => {
|
|
459
|
-
if (code !== 0) {
|
|
460
|
-
reject(new Error(`Command "${cmd} ${args.join(" ")}" exited with code ${code}`));
|
|
461
|
-
} else {
|
|
462
|
-
resolve();
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
child.on("error", reject);
|
|
466
|
-
});
|
|
467
|
-
};
|
|
468
|
-
const runSync = (cmd) => {
|
|
469
|
-
execSync(cmd, { stdio: "inherit", cwd: process.cwd() });
|
|
469
|
+
await build(config);
|
|
470
470
|
};
|
|
471
471
|
const onPromptState = (state) => {
|
|
472
472
|
if (state?.aborted) {
|
|
@@ -530,62 +530,45 @@ For example:
|
|
|
530
530
|
await notifyUpdate();
|
|
531
531
|
});
|
|
532
532
|
program.command("dev").description("Start development mode with all watchers").action(async () => {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
`"${bin("cross-env")} scriptOnly=true ${bin("vite")} build --config ${viteConfig} --mode development --watch"`,
|
|
539
|
-
`"node ${pkg("server.js")} --mode development"`
|
|
540
|
-
]);
|
|
533
|
+
runStyles({ watch: true });
|
|
534
|
+
runStates({ watch: true });
|
|
535
|
+
process.env.scriptOnly = "true";
|
|
536
|
+
viteBuild({ outDir: "dist/static", mode: "development", watch: true });
|
|
537
|
+
runServer({ mode: "development" });
|
|
541
538
|
});
|
|
542
539
|
program.command("serve").description("Start the SSR dev server").option("--mode <mode>", "server mode", "development").action(async (opts) => {
|
|
543
|
-
|
|
540
|
+
runServer({ mode: opts.mode });
|
|
544
541
|
});
|
|
545
542
|
program.command("build").description("Build the project (static + SSR)").action(async () => {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
runSync(`${bin("vite")} build --config ${viteConfig} --ssr src/entry-server.tsx --outDir dist/server`);
|
|
543
|
+
await viteBuild({ outDir: "dist/static" });
|
|
544
|
+
await viteBuild({ outDir: "dist/server", ssr: "src/entry-server.tsx" });
|
|
549
545
|
});
|
|
550
546
|
program.command("generate").description("Full static site generation (states + styles + build + prerender)").option("--mode <mode>", "build mode", "production").action(async (opts) => {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
runSync(`${bin("vite")} build --config ${viteConfig} --ssr src/entry-server.tsx --outDir dist/server`);
|
|
557
|
-
} else {
|
|
558
|
-
runSync(`${bin("vite")} build --config ${viteConfig} --outDir dist/static --mode ${opts.mode}`);
|
|
559
|
-
runSync(`${bin("vite")} build --config ${viteConfig} --ssr src/entry-server.tsx --outDir dist/server --mode ${opts.mode}`);
|
|
560
|
-
}
|
|
561
|
-
runSync(`node ${pkg("prerender.js")} --add-hash --mode ${opts.mode}`);
|
|
547
|
+
runStates();
|
|
548
|
+
runStyles();
|
|
549
|
+
await viteBuild({ outDir: "dist/static", mode: opts.mode !== "production" ? opts.mode : void 0 });
|
|
550
|
+
await viteBuild({ outDir: "dist/server", ssr: "src/entry-server.tsx", mode: opts.mode !== "production" ? opts.mode : void 0 });
|
|
551
|
+
await runPrerender({ addHash: true, mode: opts.mode });
|
|
562
552
|
});
|
|
563
553
|
program.command("eshn").description("Generate with --mode eshn").action(async () => {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
runSync(`node ${pkg("prerender.js")} --add-hash --mode eshn`);
|
|
554
|
+
runStates();
|
|
555
|
+
runStyles();
|
|
556
|
+
await viteBuild({ outDir: "dist/static", mode: "eshn" });
|
|
557
|
+
await viteBuild({ outDir: "dist/server", ssr: "src/entry-server.tsx", mode: "eshn" });
|
|
558
|
+
await runPrerender({ addHash: true, mode: "eshn" });
|
|
570
559
|
});
|
|
571
560
|
program.command("inte").description("Build and integrate with backend (styles + build + prerender + integration)").action(async () => {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
runSync(`node ${pkg("integration.js")}`);
|
|
561
|
+
runStyles();
|
|
562
|
+
await viteBuild({ outDir: "dist/static" });
|
|
563
|
+
await viteBuild({ outDir: "dist/server", ssr: "src/entry-server.tsx" });
|
|
564
|
+
await runPrerender();
|
|
565
|
+
runIntegration();
|
|
578
566
|
});
|
|
579
567
|
program.command("styles").description("Compile SCSS").option("--watch", "Watch for changes").action(async (opts) => {
|
|
580
|
-
|
|
581
|
-
if (opts.watch) args.push("--watch");
|
|
582
|
-
await run("node", args);
|
|
568
|
+
runStyles({ watch: opts.watch });
|
|
583
569
|
});
|
|
584
570
|
program.command("prerender").description("Pre-render HTML files").option("--add-hash", "Add content hashes to asset URLs").option("--mode <mode>", "build mode", "production").action(async (opts) => {
|
|
585
|
-
|
|
586
|
-
if (opts.addHash) args.push("--add-hash");
|
|
587
|
-
args.push("--mode", opts.mode);
|
|
588
|
-
await run("node", args);
|
|
571
|
+
await runPrerender({ addHash: opts.addHash, mode: opts.mode });
|
|
589
572
|
});
|
|
590
573
|
program.parseAsync(process.argv).catch(async (error) => {
|
|
591
574
|
console.log(red(error));
|
package/dist/integration.js
CHANGED
|
@@ -6,125 +6,135 @@ import slash from "slash";
|
|
|
6
6
|
import { glob } from "glob";
|
|
7
7
|
import { loadEnv } from "vite";
|
|
8
8
|
import chalk from "chalk";
|
|
9
|
-
const
|
|
10
|
-
const mode =
|
|
11
|
-
const projectRoot = process.cwd();
|
|
12
|
-
const xpackEnv = loadEnv(mode, projectRoot);
|
|
13
|
-
const toAbsolute = (p) => slash(path.resolve(projectRoot, p));
|
|
14
|
-
const log = console.log.bind(console);
|
|
15
|
-
const hashes = /* @__PURE__ */ new Map();
|
|
16
|
-
const staticBasePath = toAbsolute("dist/static");
|
|
17
|
-
const srcBasePath = toAbsolute("dist/static/assets");
|
|
18
|
-
const destBasePath = toAbsolute(xpackEnv.VITE_INTE_ASSET_DIR);
|
|
19
|
-
const patternPath = xpackEnv.VITE_INTE_PATTERN_DIR ? toAbsolute(xpackEnv.VITE_INTE_PATTERN_DIR) : void 0;
|
|
20
|
-
if (patternPath && fs.existsSync(patternPath)) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const copyItems = [
|
|
25
|
-
{ from: "css" },
|
|
26
|
-
{ from: "fonts" },
|
|
27
|
-
{ from: "images" },
|
|
28
|
-
{ from: "js" },
|
|
29
|
-
{ from: "vendors" },
|
|
30
|
-
{ from: "hashes.json" },
|
|
31
|
-
{ from: "pages", to: patternPath }
|
|
32
|
-
];
|
|
33
|
-
const hashItems = ["css", "images", "js"];
|
|
34
|
-
copyItems.forEach((item) => {
|
|
35
|
-
const srcPath = slash(path.join(srcBasePath, item.from));
|
|
36
|
-
const destPath = slash(item.to ?? path.join(destBasePath, item.from));
|
|
37
|
-
if (!fs.existsSync(srcPath)) {
|
|
38
|
-
return;
|
|
9
|
+
const runIntegration = (options = {}) => {
|
|
10
|
+
const mode = options.mode ?? "production";
|
|
11
|
+
const projectRoot = process.cwd();
|
|
12
|
+
const xpackEnv = loadEnv(mode, projectRoot);
|
|
13
|
+
const toAbsolute = (p) => slash(path.resolve(projectRoot, p));
|
|
14
|
+
const log = console.log.bind(console);
|
|
15
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
16
|
+
const staticBasePath = toAbsolute("dist/static");
|
|
17
|
+
const srcBasePath = toAbsolute("dist/static/assets");
|
|
18
|
+
const destBasePath = toAbsolute(xpackEnv.VITE_INTE_ASSET_DIR);
|
|
19
|
+
const patternPath = xpackEnv.VITE_INTE_PATTERN_DIR ? toAbsolute(xpackEnv.VITE_INTE_PATTERN_DIR) : void 0;
|
|
20
|
+
if (patternPath && fs.existsSync(patternPath)) {
|
|
21
|
+
fs.rmSync(patternPath, { recursive: true, force: true });
|
|
22
|
+
fs.mkdirSync(patternPath, { recursive: true });
|
|
39
23
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
const copyItems = [
|
|
25
|
+
{ from: "css" },
|
|
26
|
+
{ from: "fonts" },
|
|
27
|
+
{ from: "images" },
|
|
28
|
+
{ from: "js" },
|
|
29
|
+
{ from: "vendors" },
|
|
30
|
+
{ from: "hashes.json" },
|
|
31
|
+
{ from: "pages", to: patternPath }
|
|
32
|
+
];
|
|
33
|
+
const hashItems = ["css", "images", "js"];
|
|
34
|
+
copyItems.forEach((item) => {
|
|
35
|
+
const srcPath = slash(path.join(srcBasePath, item.from));
|
|
36
|
+
const destPath = slash(item.to ?? path.join(destBasePath, item.from));
|
|
37
|
+
if (!fs.existsSync(srcPath)) {
|
|
38
|
+
return;
|
|
51
39
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const relativePath = slash(file.substring(staticBasePath.length));
|
|
60
|
-
if (!/\.0x[a-z0-9_-]{8,12}\.\w+$/gi.test(file)) {
|
|
61
|
-
const content = fs.readFileSync(file);
|
|
62
|
-
const sha1Hash = crypto.createHash("sha1");
|
|
63
|
-
sha1Hash.update(content);
|
|
64
|
-
const hash = sha1Hash.digest("base64url").substring(0, 10);
|
|
65
|
-
hashes.set(relativePath, hash);
|
|
40
|
+
log(`Copy file ${srcPath} to ${destPath}`);
|
|
41
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
42
|
+
if (fs.existsSync(destPath)) {
|
|
43
|
+
fs.rmSync(destPath, { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
46
|
+
fs.cpSync(srcPath, destPath, { recursive: true, force: true });
|
|
66
47
|
} else {
|
|
67
|
-
|
|
48
|
+
const destDirPath = path.dirname(destPath);
|
|
49
|
+
if (!fs.existsSync(destDirPath)) {
|
|
50
|
+
fs.mkdirSync(destDirPath);
|
|
51
|
+
}
|
|
52
|
+
fs.copyFileSync(srcPath, destPath);
|
|
68
53
|
}
|
|
69
54
|
});
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
switch (segments.length) {
|
|
86
|
-
case 4:
|
|
87
|
-
basename = path.basename(slash(p).replaceAll(/(atoms|molecules|organisms|templates|pages)\/([\w._-]+)$/gi, "$1-$2"));
|
|
88
|
-
fs.copyFileSync(p, resolve(patternPath, basename));
|
|
89
|
-
break;
|
|
90
|
-
default:
|
|
91
|
-
segments.splice(0, 2);
|
|
92
|
-
fs$1.cpSync(p, resolve(patternPath, segments.join("-")), { recursive: true });
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
55
|
+
hashItems.forEach((item) => {
|
|
56
|
+
const srcPath = slash(path.join(srcBasePath, item));
|
|
57
|
+
const files = glob.sync(srcPath + "/**/*.{css,js,svg}");
|
|
58
|
+
files.forEach((file) => {
|
|
59
|
+
const relativePath = slash(file.substring(staticBasePath.length));
|
|
60
|
+
if (!/\.0x[a-z0-9_-]{8,12}\.\w+$/gi.test(file)) {
|
|
61
|
+
const content = fs.readFileSync(file);
|
|
62
|
+
const sha1Hash = crypto.createHash("sha1");
|
|
63
|
+
sha1Hash.update(content);
|
|
64
|
+
const hash = sha1Hash.digest("base64url").substring(0, 10);
|
|
65
|
+
hashes.set(relativePath, hash);
|
|
66
|
+
} else {
|
|
67
|
+
hashes.set(relativePath, "");
|
|
68
|
+
}
|
|
69
|
+
});
|
|
95
70
|
});
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
71
|
+
const sortedHashes = Array.from(hashes).sort((a, b) => a[0].localeCompare(b[0])).reduce(
|
|
72
|
+
(obj, [key, value]) => {
|
|
73
|
+
obj[key] = value;
|
|
74
|
+
return obj;
|
|
75
|
+
},
|
|
76
|
+
{}
|
|
77
|
+
);
|
|
78
|
+
fs.writeFileSync(path.join(destBasePath, "hashes.json"), JSON.stringify(sortedHashes, null, " "));
|
|
79
|
+
if (patternPath) {
|
|
80
|
+
fs.mkdirSync(patternPath, { recursive: true });
|
|
81
|
+
glob.sync("./dist/static/{atoms,molecules,organisms,templates,pages}/**/*.*").forEach((p) => {
|
|
82
|
+
let basename = "";
|
|
83
|
+
const segments = slash(p).split("/");
|
|
84
|
+
if (segments.length < 4) return;
|
|
85
|
+
switch (segments.length) {
|
|
86
|
+
case 4:
|
|
87
|
+
basename = path.basename(slash(p).replaceAll(/(atoms|molecules|organisms|templates|pages)\/([\w._-]+)$/gi, "$1-$2"));
|
|
88
|
+
fs.copyFileSync(p, resolve(patternPath, basename));
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
segments.splice(0, 2);
|
|
92
|
+
fs$1.cpSync(p, resolve(patternPath, segments.join("-")), { recursive: true });
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
glob.sync(slash(path.resolve(patternPath + "/**/*.{htm,html}"))).forEach((p) => {
|
|
97
|
+
const text = fs.readFileSync(p, "utf-8");
|
|
98
|
+
const newText = text.replaceAll(/react-loader\.0x[a-z0-9_-]{8,12}\.js/gi, "react-loader.0x00000000.js").replaceAll(/\.svg\?v=[a-z0-9_-]+/gi, ".svg");
|
|
99
|
+
if (text !== newText) {
|
|
100
|
+
fs.writeFileSync(p, newText);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const checkExistFileList = [
|
|
105
|
+
{ fileName: "hashes.json" },
|
|
106
|
+
{ fileName: /react-loader\.0x[a-z0-9_-]{8,12}\.js/gi, folder: "js" },
|
|
107
|
+
{ fileName: "main.js", folder: "js" }
|
|
108
|
+
];
|
|
109
|
+
let isAllExist = true;
|
|
110
|
+
checkExistFileList.forEach((file) => {
|
|
111
|
+
if (typeof file.fileName === "string") {
|
|
112
|
+
const destPath = slash(path.join(destBasePath, file.folder ?? "", file.fileName.toString()));
|
|
113
|
+
if (!fs.existsSync(destPath)) {
|
|
114
|
+
log(chalk.yellow(`Cannot find: ${destPath}`));
|
|
115
|
+
isAllExist = false;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
const fileName = file.fileName;
|
|
119
|
+
const folderFiles = slash(path.join(destBasePath, file.folder ?? ""));
|
|
120
|
+
const files = fs.readdirSync(folderFiles);
|
|
121
|
+
const found = files.find((f) => fileName.test(f));
|
|
122
|
+
if (!found) {
|
|
123
|
+
log(chalk.yellow(`Cannot find: ${slash(path.join(folderFiles, fileName.toString()))}`));
|
|
124
|
+
isAllExist = false;
|
|
125
|
+
}
|
|
101
126
|
}
|
|
102
127
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{ fileName: "hashes.json" },
|
|
106
|
-
{ fileName: /react-loader\.0x[a-z0-9_-]{8,12}\.js/gi, folder: "js" },
|
|
107
|
-
{ fileName: "main.js", folder: "js" }
|
|
108
|
-
];
|
|
109
|
-
let isAllExist = true;
|
|
110
|
-
checkExistFileList.forEach((file) => {
|
|
111
|
-
if (typeof file.fileName === "string") {
|
|
112
|
-
const destPath = slash(path.join(destBasePath, file.folder ?? "", file.fileName.toString()));
|
|
113
|
-
if (!fs.existsSync(destPath)) {
|
|
114
|
-
log(chalk.yellow(`Cannot find: ${destPath}`));
|
|
115
|
-
isAllExist = false;
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
const fileName = file.fileName;
|
|
119
|
-
const folderFiles = slash(path.join(destBasePath, file.folder ?? ""));
|
|
120
|
-
const files = fs.readdirSync(folderFiles);
|
|
121
|
-
const found = files.find((f) => fileName.test(f));
|
|
122
|
-
if (!found) {
|
|
123
|
-
log(chalk.yellow(`Cannot find: ${slash(path.join(folderFiles, fileName.toString()))}`));
|
|
124
|
-
isAllExist = false;
|
|
125
|
-
}
|
|
128
|
+
if (!isAllExist) {
|
|
129
|
+
process.exit(1);
|
|
126
130
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
};
|
|
132
|
+
const isDirectRun = process.argv[1]?.endsWith("integration.js") || process.argv[1]?.endsWith("integration.ts");
|
|
133
|
+
if (isDirectRun) {
|
|
134
|
+
const argvModeIndex = process.argv.indexOf("--mode");
|
|
135
|
+
const mode = argvModeIndex >= 0 && argvModeIndex < process.argv.length - 1 && !process.argv[argvModeIndex + 1].startsWith("-") ? process.argv[argvModeIndex + 1] : "production";
|
|
136
|
+
runIntegration({ mode });
|
|
130
137
|
}
|
|
138
|
+
export {
|
|
139
|
+
runIntegration
|
|
140
|
+
};
|
package/dist/prerender.js
CHANGED
|
@@ -8,151 +8,159 @@ import slash from "slash";
|
|
|
8
8
|
import _ from "lodash";
|
|
9
9
|
import { loadEnv } from "vite";
|
|
10
10
|
import chalk from "chalk";
|
|
11
|
-
const
|
|
12
|
-
const mode =
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
11
|
+
const runPrerender = async (options = {}) => {
|
|
12
|
+
const mode = options.mode ?? "production";
|
|
13
|
+
const addHash = options.addHash ?? false;
|
|
14
|
+
const projectRoot = process.cwd();
|
|
15
|
+
const xpackEnv = loadEnv(mode, projectRoot);
|
|
16
|
+
const toAbsolute = (p) => path.resolve(projectRoot, p);
|
|
17
|
+
const log = console.log.bind(console);
|
|
18
|
+
const template = fs.readFileSync(toAbsolute(process.env.VITE_TEMPLATE ?? "dist/static/index.html"), "utf-8");
|
|
19
|
+
const { render, routesToPrerender } = await import(pathToFileURL(toAbsolute("./dist/server/entry-server.js")).href);
|
|
20
|
+
const beautifyOptions = {
|
|
21
|
+
indent_size: 2,
|
|
22
|
+
indent_char: " ",
|
|
23
|
+
keep_array_indentation: false,
|
|
24
|
+
break_chained_methods: false,
|
|
25
|
+
indent_scripts: "normal",
|
|
26
|
+
brace_style: "collapse",
|
|
27
|
+
space_before_conditional: true,
|
|
28
|
+
unescape_strings: false,
|
|
29
|
+
jslint_happy: false,
|
|
30
|
+
end_with_newline: false,
|
|
31
|
+
wrap_line_length: 0,
|
|
32
|
+
indent_inner_html: false,
|
|
33
|
+
comma_first: false,
|
|
34
|
+
e4x: false,
|
|
35
|
+
indent_empty_lines: false,
|
|
36
|
+
wrap_attributes: "force",
|
|
37
|
+
max_preserve_newlines: 5,
|
|
38
|
+
preserve_newlines: true
|
|
39
|
+
};
|
|
40
|
+
const updateResourcePath = ($, tagName, attr, addHash2) => {
|
|
41
|
+
$(tagName).each((_2, el) => {
|
|
42
|
+
const href = $(el).attr(attr);
|
|
43
|
+
if (href && href.startsWith("/")) {
|
|
44
|
+
let newPath = href;
|
|
45
|
+
if (process.env.VITE_DOMAIN) {
|
|
46
|
+
newPath = process.env.VITE_DOMAIN + newPath;
|
|
47
|
+
}
|
|
48
|
+
if (href.startsWith(xpackEnv.VITE_BASE_URL) && !href.startsWith(xpackEnv.VITE_BASE_URL + "assets/vendors/") && [".css", ".ico", ".js", ".webmanifest", ".svg"].includes(path.extname(href).toLowerCase()) && !/\.0x[a-z0-9]{8}\.\w+$/gi.test(href)) {
|
|
49
|
+
const path2 = toAbsolute("dist/static/" + href.substring(xpackEnv.VITE_BASE_URL.length));
|
|
50
|
+
if (fs.existsSync(path2)) {
|
|
51
|
+
const content = fs.readFileSync(path2);
|
|
52
|
+
const sha1Hash = crypto.createHash("sha1");
|
|
53
|
+
sha1Hash.update(content);
|
|
54
|
+
const hash = sha1Hash.digest("base64url").substring(0, 10);
|
|
55
|
+
if (addHash2) {
|
|
56
|
+
newPath += "?v=" + hash;
|
|
57
|
+
}
|
|
58
|
+
} else if (path2.endsWith("mock-api.js")) ;
|
|
59
|
+
else {
|
|
60
|
+
log(chalk.yellow("Cannot find:", path2));
|
|
56
61
|
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
}
|
|
63
|
+
if (newPath != href) {
|
|
64
|
+
$(el).attr(attr, newPath);
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
const removeStyleBase = ($) => {
|
|
70
|
+
$('link[rel="stylesheet"]').each((_2, el) => {
|
|
71
|
+
const href = $(el).attr("href");
|
|
72
|
+
if (href?.includes("style-base")) {
|
|
73
|
+
$(el).remove();
|
|
64
74
|
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (href?.includes("style-base")) {
|
|
72
|
-
$(el).remove();
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
const removeDuplicateAssets = ($, selector, attr, paths) => {
|
|
77
|
-
$(selector).each((_2, el) => {
|
|
78
|
-
if ($(el).attr("data-pl-inplace") === "true") {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const path2 = $(el).attr(attr);
|
|
82
|
-
if (!path2) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const index = $(el).index();
|
|
86
|
-
const parent = $(el).parent().clone();
|
|
87
|
-
const child = parent.children()[index];
|
|
88
|
-
parent.empty();
|
|
89
|
-
parent.append(child);
|
|
90
|
-
const html = parent.html();
|
|
91
|
-
$(el).after("\n<!-- " + html + " -->");
|
|
92
|
-
if (paths.includes(path2)) {
|
|
93
|
-
$(el).remove();
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
paths.push(path2);
|
|
97
|
-
$(el).removeAttr("data-pl-require");
|
|
98
|
-
if ($(el).attr("type") === "module") {
|
|
99
|
-
const deferValue = $(el).attr("defer");
|
|
100
|
-
if ($(el).attr("defer") === "" || deferValue === "defer" || deferValue === "true") {
|
|
101
|
-
$(el).removeAttr("defer");
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
const removeDuplicateAssets = ($, selector, attr, paths) => {
|
|
78
|
+
$(selector).each((_2, el) => {
|
|
79
|
+
if ($(el).attr("data-pl-inplace") === "true") {
|
|
80
|
+
return;
|
|
102
81
|
}
|
|
82
|
+
const path2 = $(el).attr(attr);
|
|
83
|
+
if (!path2) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const index = $(el).index();
|
|
87
|
+
const parent = $(el).parent().clone();
|
|
88
|
+
const child = parent.children()[index];
|
|
89
|
+
parent.empty();
|
|
90
|
+
parent.append(child);
|
|
91
|
+
const html = parent.html();
|
|
92
|
+
$(el).after("\n<!-- " + html + " -->");
|
|
93
|
+
if (paths.includes(path2)) {
|
|
94
|
+
$(el).remove();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
paths.push(path2);
|
|
98
|
+
$(el).removeAttr("data-pl-require");
|
|
99
|
+
if ($(el).attr("type") === "module") {
|
|
100
|
+
const deferValue = $(el).attr("defer");
|
|
101
|
+
if ($(el).attr("defer") === "" || deferValue === "defer" || deferValue === "true") {
|
|
102
|
+
$(el).removeAttr("defer");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
$("head").append(el);
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
const viteAbsoluteUrl = (remain, addExtension = false) => {
|
|
109
|
+
const baseUrl = xpackEnv.VITE_BASE_URL;
|
|
110
|
+
const normalizedRemain = (remain?.startsWith("/") ? remain : "/" + remain) + (addExtension && !remain.endsWith("/") ? xpackEnv.VITE_PATH_EXTENSION ?? "" : "");
|
|
111
|
+
if (!baseUrl) {
|
|
112
|
+
return normalizedRemain;
|
|
103
113
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
};
|
|
107
|
-
const viteAbsoluteUrl = (remain, addExtension = false) => {
|
|
108
|
-
const baseUrl = xpackEnv.VITE_BASE_URL;
|
|
109
|
-
const normalizedRemain = (remain?.startsWith("/") ? remain : "/" + remain) + (addExtension && !remain.endsWith("/") ? xpackEnv.VITE_PATH_EXTENSION ?? "" : "");
|
|
110
|
-
if (!baseUrl) {
|
|
111
|
-
return normalizedRemain;
|
|
112
|
-
}
|
|
113
|
-
if (!baseUrl.endsWith("/")) {
|
|
114
|
-
return baseUrl + normalizedRemain;
|
|
115
|
-
}
|
|
116
|
-
const len = baseUrl.length;
|
|
117
|
-
return baseUrl.substring(0, len - 1) + normalizedRemain;
|
|
118
|
-
};
|
|
119
|
-
const renderPage = async (renderedPages, addHash) => {
|
|
120
|
-
for (const route of routesToPrerender) {
|
|
121
|
-
const output = await render(viteAbsoluteUrl(route.route, true));
|
|
122
|
-
const destLocalizedFolderPath = toAbsolute("dist/static");
|
|
123
|
-
let html = template.replace("<!--app-html-->", output.html ?? "").replace("@style.scss", "/assets/css/" + route.name + ".css");
|
|
124
|
-
const $ = cheerio.load(html);
|
|
125
|
-
const paths = [];
|
|
126
|
-
removeDuplicateAssets($, "link[data-pl-require][href]", "href", paths);
|
|
127
|
-
removeDuplicateAssets($, "script[data-pl-require][src]", "src", paths);
|
|
128
|
-
updateResourcePath($, "link", "href", addHash);
|
|
129
|
-
updateResourcePath($, "script", "src", addHash);
|
|
130
|
-
updateResourcePath($, "img", "src", addHash);
|
|
131
|
-
if (route.route === "/") {
|
|
132
|
-
removeStyleBase($);
|
|
114
|
+
if (!baseUrl.endsWith("/")) {
|
|
115
|
+
return baseUrl + normalizedRemain;
|
|
133
116
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
117
|
+
const len = baseUrl.length;
|
|
118
|
+
return baseUrl.substring(0, len - 1) + normalizedRemain;
|
|
119
|
+
};
|
|
120
|
+
const renderPage = async (renderedPages2, addHash2) => {
|
|
121
|
+
for (const route of routesToPrerender) {
|
|
122
|
+
const output = await render(viteAbsoluteUrl(route.route, true));
|
|
123
|
+
const destLocalizedFolderPath = toAbsolute("dist/static");
|
|
124
|
+
let html = template.replace("<!--app-html-->", output.html ?? "").replace("@style.scss", "/assets/css/" + route.name + ".css");
|
|
125
|
+
const $ = cheerio.load(html);
|
|
126
|
+
const paths = [];
|
|
127
|
+
removeDuplicateAssets($, "link[data-pl-require][href]", "href", paths);
|
|
128
|
+
removeDuplicateAssets($, "script[data-pl-require][src]", "src", paths);
|
|
129
|
+
updateResourcePath($, "link", "href", addHash2);
|
|
130
|
+
updateResourcePath($, "script", "src", addHash2);
|
|
131
|
+
updateResourcePath($, "img", "src", addHash2);
|
|
132
|
+
if (route.route === "/") {
|
|
133
|
+
removeStyleBase($);
|
|
134
|
+
}
|
|
135
|
+
$("head title").text(route.name);
|
|
136
|
+
const fileName = (route.route === "/" ? "/index" : route.route) + ".html";
|
|
137
|
+
const filePath = `${destLocalizedFolderPath}${fileName}`;
|
|
138
|
+
if (!fs.existsSync(path.dirname(filePath))) {
|
|
139
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
140
|
+
}
|
|
141
|
+
html = $.html();
|
|
142
|
+
html = jsBeautify.html_beautify(html, beautifyOptions);
|
|
143
|
+
html = html.replace("/* app-styles */", output.styles);
|
|
144
|
+
fs.writeFileSync(toAbsolute(filePath), html);
|
|
145
|
+
log("pre-rendered:", slash(filePath));
|
|
146
|
+
renderedPages2.push({
|
|
147
|
+
name: _.kebabCase(fileName.replaceAll(/\.\w+$/gi, "")),
|
|
148
|
+
url: `${process.env.VITE_DOMAIN ?? ""}${fileName}`,
|
|
149
|
+
fileName
|
|
150
|
+
});
|
|
139
151
|
}
|
|
140
|
-
|
|
141
|
-
html = jsBeautify.html_beautify(html, beautifyOptions);
|
|
142
|
-
html = html.replace("/* app-styles */", output.styles);
|
|
143
|
-
fs.writeFileSync(toAbsolute(filePath), html);
|
|
144
|
-
log("pre-rendered:", slash(filePath));
|
|
145
|
-
renderedPages.push({
|
|
146
|
-
name: _.kebabCase(fileName.replaceAll(/\.\w+$/gi, "")),
|
|
147
|
-
url: `${process.env.VITE_DOMAIN ?? ""}${fileName}`,
|
|
148
|
-
fileName
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
(async () => {
|
|
152
|
+
};
|
|
153
153
|
const renderedPages = [];
|
|
154
154
|
const pool = [];
|
|
155
|
-
const addHash = !!process.argv.includes("--add-hash");
|
|
156
155
|
pool.push(renderPage(renderedPages, addHash));
|
|
157
156
|
await Promise.all(pool);
|
|
158
|
-
}
|
|
157
|
+
};
|
|
158
|
+
const isDirectRun = process.argv[1]?.endsWith("prerender.js") || process.argv[1]?.endsWith("prerender.ts");
|
|
159
|
+
if (isDirectRun) {
|
|
160
|
+
const argvModeIndex = process.argv.indexOf("--mode");
|
|
161
|
+
const mode = argvModeIndex >= 0 && argvModeIndex < process.argv.length - 1 && !process.argv[argvModeIndex + 1].startsWith("-") ? process.argv[argvModeIndex + 1] : "production";
|
|
162
|
+
runPrerender({ addHash: process.argv.includes("--add-hash"), mode });
|
|
163
|
+
}
|
|
164
|
+
export {
|
|
165
|
+
runPrerender
|
|
166
|
+
};
|
package/dist/server.js
CHANGED
|
@@ -8,11 +8,11 @@ import fs from "fs";
|
|
|
8
8
|
import path from "path";
|
|
9
9
|
import * as cheerio from "cheerio";
|
|
10
10
|
import jsBeautify from "js-beautify";
|
|
11
|
-
const createViteDevServer = ({ root
|
|
11
|
+
const createViteDevServer = ({ root, baseUrl, hmrPort, isTest }) => {
|
|
12
12
|
const server = createServer$1({
|
|
13
|
-
root
|
|
13
|
+
root,
|
|
14
14
|
base: baseUrl,
|
|
15
|
-
logLevel:
|
|
15
|
+
logLevel: isTest ? "error" : "info",
|
|
16
16
|
server: {
|
|
17
17
|
middlewareMode: true,
|
|
18
18
|
watch: {
|
|
@@ -121,17 +121,17 @@ const _useRenderer = ({ app, indexProd, isProd: isProd2, viteDevServer, resolve
|
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
};
|
|
124
|
-
const argvModeIndex
|
|
125
|
-
const mode
|
|
124
|
+
const argvModeIndex = process.argv.indexOf("--mode");
|
|
125
|
+
const mode = argvModeIndex >= 0 && argvModeIndex < process.argv.length - 1 && !process.argv[argvModeIndex + 1].startsWith("-") ? process.argv[argvModeIndex + 1] : "production";
|
|
126
126
|
process.env.MY_CUSTOM_SECRET = "API_KEY_4c2928b5a14b475d94c3579cbea06178";
|
|
127
127
|
const isProd = process.env.NODE_ENV === "production";
|
|
128
|
-
const createServer = async ({ root
|
|
129
|
-
const resolve = (p) => path$1.join(
|
|
128
|
+
const createServer = async ({ root, hmrPort, baseUrl, isTest }) => {
|
|
129
|
+
const resolve = (p) => path$1.join(root, p);
|
|
130
130
|
const indexProd = isProd ? fs$1.readFileSync(resolve("index.html"), "utf-8") : "";
|
|
131
131
|
const app = express();
|
|
132
132
|
let viteDevServer;
|
|
133
133
|
if (!isProd) {
|
|
134
|
-
viteDevServer = await createViteDevServer({ root
|
|
134
|
+
viteDevServer = await createViteDevServer({ root, baseUrl, hmrPort, isTest });
|
|
135
135
|
app.use(viteDevServer.middlewares);
|
|
136
136
|
}
|
|
137
137
|
app.use("/assets/images", serveStatic(resolve("public/assets/images"), { index: false }));
|
|
@@ -147,25 +147,35 @@ const createServer = async ({ root: root2, hmrPort, baseUrl, isTest: isTest2 })
|
|
|
147
147
|
const startServer = (props) => {
|
|
148
148
|
createServer(props).then(({ app }) => {
|
|
149
149
|
app.listen(props.port, () => {
|
|
150
|
-
const
|
|
151
|
-
console.log("Running on " + chalk.green("http://localhost:" + props.port +
|
|
150
|
+
const xpackEnv = loadEnv(mode, props.root);
|
|
151
|
+
console.log("Running on " + chalk.green("http://localhost:" + props.port + xpackEnv.VITE_BASE_URL));
|
|
152
152
|
});
|
|
153
153
|
});
|
|
154
154
|
};
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
const root = process.cwd();
|
|
159
|
-
const xpackEnv = loadEnv(
|
|
160
|
-
const isTest = !!xpackEnv.VITE_TEST_BUILD || process.env.NODE_ENV === "test";
|
|
161
|
-
const port = xpackEnv.VITE_PORT ? parseInt(xpackEnv.VITE_PORT) : 5e3;
|
|
162
|
-
if (!isTest) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
155
|
+
const runServer = (options = {}) => {
|
|
156
|
+
const mode2 = options.mode ?? "production";
|
|
157
|
+
console.log("[INIT] server");
|
|
158
|
+
const root = process.cwd();
|
|
159
|
+
const xpackEnv = loadEnv(mode2, root);
|
|
160
|
+
const isTest = !!xpackEnv.VITE_TEST_BUILD || process.env.NODE_ENV === "test";
|
|
161
|
+
const port = xpackEnv.VITE_PORT ? parseInt(xpackEnv.VITE_PORT) : 5e3;
|
|
162
|
+
if (!isTest) {
|
|
163
|
+
console.log(root);
|
|
164
|
+
startServer({
|
|
165
|
+
root,
|
|
166
|
+
isTest,
|
|
167
|
+
port,
|
|
168
|
+
hmrPort: port + 1,
|
|
169
|
+
baseUrl: xpackEnv.VITE_BASE_URL
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const isDirectRun = process.argv[1]?.endsWith("server.js") || process.argv[1]?.endsWith("server.ts");
|
|
174
|
+
if (isDirectRun) {
|
|
175
|
+
const argvModeIndex2 = process.argv.indexOf("--mode");
|
|
176
|
+
const mode2 = argvModeIndex2 >= 0 && argvModeIndex2 < process.argv.length - 1 && !process.argv[argvModeIndex2 + 1].startsWith("-") ? process.argv[argvModeIndex2 + 1] : "production";
|
|
177
|
+
runServer({ mode: mode2 });
|
|
171
178
|
}
|
|
179
|
+
export {
|
|
180
|
+
runServer
|
|
181
|
+
};
|
package/dist/states.js
CHANGED
|
@@ -2,40 +2,49 @@ import fs from "fs";
|
|
|
2
2
|
import chokidar from "chokidar";
|
|
3
3
|
import debounce from "debounce";
|
|
4
4
|
import { glob } from "glob";
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
const runStates = (options = {}) => {
|
|
6
|
+
const isWatch = options.watch ?? false;
|
|
7
|
+
const log = console.log.bind(console);
|
|
8
|
+
const states = {};
|
|
9
|
+
const buildStates = debounce(() => {
|
|
10
|
+
const output = [];
|
|
11
|
+
const keys = Object.keys(states);
|
|
12
|
+
[].forEach.call(keys, (key) => {
|
|
13
|
+
const state = states[key];
|
|
14
|
+
if (!state) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
output.push(JSON.parse(state));
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.log(error);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const json = JSON.stringify(output, null, " ");
|
|
24
|
+
fs.writeFileSync("public/pl-states.json", json);
|
|
25
|
+
}, 500);
|
|
26
|
+
const setStates = (statePath) => {
|
|
27
|
+
const state = fs.readFileSync(statePath, "utf-8");
|
|
28
|
+
states[statePath] = state;
|
|
29
|
+
buildStates();
|
|
30
|
+
};
|
|
31
|
+
const removeStates = (statePath) => {
|
|
32
|
+
delete states[statePath];
|
|
33
|
+
buildStates();
|
|
34
|
+
};
|
|
35
|
+
if (isWatch) {
|
|
36
|
+
const watcher = chokidar.watch("src/**/*.states.json");
|
|
37
|
+
watcher.on("ready", () => {
|
|
38
|
+
log("States are ready!");
|
|
39
|
+
}).on("add", (path) => setStates(path)).on("change", (path) => setStates(path)).on("unlink", (path) => removeStates(path));
|
|
40
|
+
} else {
|
|
41
|
+
glob.sync("src/**/*.states.json").forEach((path) => setStates(path));
|
|
42
|
+
}
|
|
29
43
|
};
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
if (isWatch) {
|
|
35
|
-
const watcher = chokidar.watch("src/**/*.states.json");
|
|
36
|
-
watcher.on("ready", () => {
|
|
37
|
-
log("States are ready!");
|
|
38
|
-
}).on("add", (path) => setStates(path)).on("change", (path) => setStates(path)).on("unlink", (path) => removeStates(path));
|
|
39
|
-
} else {
|
|
40
|
-
glob.sync("src/**/*.states.json").forEach((path) => setStates(path));
|
|
44
|
+
const isDirectRun = process.argv[1]?.endsWith("states.js") || process.argv[1]?.endsWith("states.ts");
|
|
45
|
+
if (isDirectRun) {
|
|
46
|
+
runStates({ watch: process.argv.includes("--watch") });
|
|
41
47
|
}
|
|
48
|
+
export {
|
|
49
|
+
runStates
|
|
50
|
+
};
|
package/dist/styles.js
CHANGED
|
@@ -9,157 +9,169 @@ import { glob } from "glob";
|
|
|
9
9
|
import postcss from "postcss";
|
|
10
10
|
import autoprefixer from "autoprefixer";
|
|
11
11
|
import cssnano from "cssnano";
|
|
12
|
-
const
|
|
12
|
+
const runStyles = (options = {}) => {
|
|
13
|
+
const isWatch = options.watch ?? false;
|
|
14
|
+
_run(isWatch);
|
|
15
|
+
};
|
|
13
16
|
const outDir = "./public/assets/css";
|
|
14
|
-
if (!isWatch && fs.existsSync(outDir)) {
|
|
15
|
-
fs.rmSync(outDir, { force: true, recursive: true });
|
|
16
|
-
}
|
|
17
|
-
if (!fs.existsSync(outDir)) {
|
|
18
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
19
|
-
}
|
|
20
17
|
const log = console.log.bind(console);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
const _run = (isWatch) => {
|
|
19
|
+
if (!isWatch && fs.existsSync(outDir)) {
|
|
20
|
+
fs.rmSync(outDir, { force: true, recursive: true });
|
|
21
|
+
}
|
|
22
|
+
if (!fs.existsSync(outDir)) {
|
|
23
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
const prepareCssFileContent = ({
|
|
26
|
+
srcFile,
|
|
27
|
+
includeMixins = true,
|
|
28
|
+
includeAbstracts = true
|
|
29
|
+
}) => {
|
|
30
|
+
return [
|
|
31
|
+
includeAbstracts ? slash(`@use '${path.relative(path.dirname(srcFile), path.resolve("src/assets/styles/00-abstracts/abstracts"))}' as *;
|
|
28
32
|
`) : void 0,
|
|
29
|
-
|
|
33
|
+
includeMixins ? slash(`@use '${path.relative(path.dirname(srcFile), path.resolve("src/assets/styles/01-mixins/mixins"))}' as *;
|
|
30
34
|
`) : void 0,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
const stringOptions = (srcFile) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
fs.readFileSync(srcFile, "utf-8")
|
|
36
|
+
].filter(Boolean);
|
|
37
|
+
};
|
|
38
|
+
const stringOptions = (srcFile) => {
|
|
39
|
+
const options = {
|
|
40
|
+
sourceMap: true,
|
|
41
|
+
sourceMapIncludeSources: true,
|
|
42
|
+
syntax: "scss",
|
|
43
|
+
style: "compressed",
|
|
44
|
+
url: pathToFileURL(path.resolve(srcFile)),
|
|
45
|
+
importer: {
|
|
46
|
+
canonicalize(url) {
|
|
47
|
+
return new URL(url);
|
|
48
|
+
},
|
|
49
|
+
load(canonicalUrl) {
|
|
50
|
+
let filePath = fileURLToPath(canonicalUrl);
|
|
51
|
+
if (!filePath.endsWith(".scss")) {
|
|
52
|
+
const parentDir = path.dirname(filePath);
|
|
53
|
+
const fileName = path.basename(filePath);
|
|
54
|
+
filePath = path.join(parentDir, fileName + ".scss");
|
|
55
|
+
if (!fs.existsSync(filePath)) {
|
|
56
|
+
filePath = path.join(parentDir, "_" + fileName + ".scss");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!fs.existsSync(filePath)) return null;
|
|
60
|
+
if (filePath.includes("abstracts") || filePath.includes("_mixins") || filePath.includes("_base") || filePath.includes("xpack"))
|
|
61
|
+
return {
|
|
62
|
+
contents: fs.readFileSync(filePath, "utf-8"),
|
|
63
|
+
syntax: "scss"
|
|
64
|
+
};
|
|
65
|
+
let content = prepareCssFileContent({ srcFile: filePath });
|
|
66
|
+
if (filePath.includes("mixins")) {
|
|
67
|
+
content = prepareCssFileContent({ srcFile: filePath, includeMixins: false });
|
|
53
68
|
}
|
|
54
|
-
}
|
|
55
|
-
if (!fs.existsSync(filePath)) return null;
|
|
56
|
-
if (filePath.includes("abstracts") || filePath.includes("_mixins") || filePath.includes("_base") || filePath.includes("xpack"))
|
|
57
69
|
return {
|
|
58
|
-
contents:
|
|
70
|
+
contents: content.join(""),
|
|
59
71
|
syntax: "scss"
|
|
60
72
|
};
|
|
61
|
-
let content = prepareCssFileContent({ srcFile: filePath });
|
|
62
|
-
if (filePath.includes("mixins")) {
|
|
63
|
-
content = prepareCssFileContent({ srcFile: filePath, includeMixins: false });
|
|
64
73
|
}
|
|
65
|
-
return {
|
|
66
|
-
contents: content.join(""),
|
|
67
|
-
syntax: "scss"
|
|
68
|
-
};
|
|
69
74
|
}
|
|
75
|
+
};
|
|
76
|
+
return options;
|
|
77
|
+
};
|
|
78
|
+
const compile = (srcFile, options) => {
|
|
79
|
+
if (options.isReady) {
|
|
80
|
+
log("compile:", slash(srcFile));
|
|
81
|
+
}
|
|
82
|
+
if (path.basename(srcFile).startsWith("_")) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const name = path.basename(srcFile) === "index.scss" ? path.basename(path.dirname(srcFile)) + ".css" : path.basename(srcFile).replace(/\.scss$/gi, ".css");
|
|
86
|
+
const outFile = (options.prefix ?? "") + name;
|
|
87
|
+
const cssStrings = srcFile.includes("xpack") ? [fs.readFileSync(srcFile, "utf-8")] : prepareCssFileContent({ srcFile });
|
|
88
|
+
if (srcFile.includes("style-base") || srcFile.includes("style-all")) {
|
|
89
|
+
glob.sync("./src/atoms/**/*.scss").forEach((atomPath) => {
|
|
90
|
+
if (!path.basename(atomPath).startsWith("_")) {
|
|
91
|
+
cssStrings.push(sass.compileString(prepareCssFileContent({ srcFile: atomPath }).join(""), stringOptions(atomPath)).css);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
glob.sync("./src/molecules/**/*.scss").forEach((molPath) => {
|
|
95
|
+
if (!path.basename(molPath).startsWith("_")) {
|
|
96
|
+
cssStrings.push(sass.compileString(prepareCssFileContent({ srcFile: molPath }).join(""), stringOptions(molPath)).css);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
70
99
|
}
|
|
100
|
+
sass.compileStringAsync(cssStrings.join(""), stringOptions(srcFile)).then((result) => postcssProcess(result, srcFile, outFile)).catch((error) => {
|
|
101
|
+
log(error);
|
|
102
|
+
});
|
|
71
103
|
};
|
|
72
|
-
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const name = path.basename(srcFile) === "index.scss" ? path.basename(path.dirname(srcFile)) + ".css" : path.basename(srcFile).replace(/\.scss$/gi, ".css");
|
|
82
|
-
const outFile = (options.prefix ?? "") + name;
|
|
83
|
-
const cssStrings = srcFile.includes("xpack") ? [fs.readFileSync(srcFile, "utf-8")] : prepareCssFileContent({ srcFile });
|
|
84
|
-
if (srcFile.includes("style-base") || srcFile.includes("style-all")) {
|
|
85
|
-
glob.sync("./src/atoms/**/*.scss").forEach((atomPath) => {
|
|
86
|
-
if (!path.basename(atomPath).startsWith("_")) {
|
|
87
|
-
cssStrings.push(sass.compileString(prepareCssFileContent({ srcFile: atomPath }).join(""), stringOptions(atomPath)).css);
|
|
104
|
+
const postcssProcess = (result, from, to) => {
|
|
105
|
+
const postcssOptions = { from: pathToFileURL(from).href, to, map: { prev: result.sourceMap, absolute: false } };
|
|
106
|
+
postcss([autoprefixer({ grid: true }), cssnano]).process(result.css, postcssOptions).then((result2) => {
|
|
107
|
+
fs.writeFileSync(path.join(outDir, to), result2.css + (result2.map ? `
|
|
108
|
+
/*# sourceMappingURL=${to}.map */` : ""));
|
|
109
|
+
if (result2.map) {
|
|
110
|
+
fs.writeFileSync(path.join(outDir, to + ".map"), result2.map.toString());
|
|
88
111
|
}
|
|
89
112
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
113
|
+
};
|
|
114
|
+
const styleOrganisms = debounce((isReady) => {
|
|
115
|
+
const paths = glob.sync("src/organisms/**/*.scss", { nodir: true });
|
|
116
|
+
[].forEach.call(paths, (p) => styleOrganism(p, isReady));
|
|
117
|
+
}, 200);
|
|
118
|
+
const styleTemplates = debounce((isReady) => {
|
|
119
|
+
const paths = glob.sync("src/templates/**/*.scss", { nodir: true });
|
|
120
|
+
[].forEach.call(paths, (p) => styleTemplate(p, isReady));
|
|
121
|
+
}, 200);
|
|
122
|
+
const styleBase = debounce((isReady) => compile("src/assets/styles/style-base.scss", { isReady }), 200);
|
|
123
|
+
const stylePlState = debounce((isReady) => compile("xpack/styles/pl-states.scss", { isReady }), 200);
|
|
124
|
+
const styleRoot = debounce((isReady) => compile("xpack/styles/root.scss", { isReady }), 200);
|
|
125
|
+
const styleOrganism = (srcFile, isReady) => compile(srcFile, { prefix: "b-", isReady });
|
|
126
|
+
const styleTemplate = (srcFile, isReady) => compile(srcFile, { prefix: "p-", isReady });
|
|
127
|
+
const sassCompile = (inputPath, isReady) => {
|
|
128
|
+
const p = slash(inputPath);
|
|
129
|
+
if (p.startsWith("src/assets/styles/00-abstracts/") || p.startsWith("src/assets/styles/01-mixins/")) {
|
|
130
|
+
styleBase(isReady);
|
|
131
|
+
styleOrganisms(isReady);
|
|
132
|
+
styleTemplates(isReady);
|
|
133
|
+
stylePlState(isReady);
|
|
134
|
+
}
|
|
135
|
+
if (p.startsWith("src/atoms") || p.startsWith("src/molecules") || p.startsWith("src/assets/styles/02-base")) {
|
|
136
|
+
styleBase(isReady);
|
|
137
|
+
}
|
|
138
|
+
if (p.startsWith("src/organisms")) {
|
|
139
|
+
if (path.basename(p).startsWith("_")) {
|
|
140
|
+
glob.sync(path.dirname(p) + "/*.scss", { nodir: true }).filter((p2) => !path.basename(p2).startsWith("_")).forEach((p2) => styleOrganism(p2, isReady));
|
|
141
|
+
} else {
|
|
142
|
+
styleOrganism(p, isReady);
|
|
93
143
|
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
sass.compileStringAsync(cssStrings.join(""), stringOptions(srcFile)).then((result) => postcssProcess(result, srcFile, outFile)).catch((error) => {
|
|
97
|
-
log(error);
|
|
98
|
-
});
|
|
99
|
-
};
|
|
100
|
-
const postcssProcess = (result, from, to) => {
|
|
101
|
-
const postcssOptions = { from: pathToFileURL(from).href, to, map: { prev: result.sourceMap, absolute: false } };
|
|
102
|
-
postcss([autoprefixer({ grid: true }), cssnano]).process(result.css, postcssOptions).then((result2) => {
|
|
103
|
-
fs.writeFileSync(path.join(outDir, to), result2.css + (result2.map ? `
|
|
104
|
-
/*# sourceMappingURL=${to}.map */` : ""));
|
|
105
|
-
if (result2.map) {
|
|
106
|
-
fs.writeFileSync(path.join(outDir, to + ".map"), result2.map.toString());
|
|
107
144
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
const styleTemplates = debounce((isReady) => {
|
|
115
|
-
const paths = glob.sync("src/templates/**/*.scss", { nodir: true });
|
|
116
|
-
[].forEach.call(paths, (p) => styleTemplate(p, isReady));
|
|
117
|
-
}, 200);
|
|
118
|
-
const styleBase = debounce((isReady) => compile("src/assets/styles/style-base.scss", { isReady }), 200);
|
|
119
|
-
const stylePlState = debounce((isReady) => compile("xpack/styles/pl-states.scss", { isReady }), 200);
|
|
120
|
-
const styleRoot = debounce((isReady) => compile("xpack/styles/root.scss", { isReady }), 200);
|
|
121
|
-
const styleOrganism = (srcFile, isReady) => compile(srcFile, { prefix: "b-", isReady });
|
|
122
|
-
const styleTemplate = (srcFile, isReady) => compile(srcFile, { prefix: "p-", isReady });
|
|
123
|
-
const sassCompile = (inputPath, isReady) => {
|
|
124
|
-
const p = slash(inputPath);
|
|
125
|
-
if (p.startsWith("src/assets/styles/00-abstracts/") || p.startsWith("src/assets/styles/01-mixins/")) {
|
|
126
|
-
styleBase(isReady);
|
|
127
|
-
styleOrganisms(isReady);
|
|
128
|
-
styleTemplates(isReady);
|
|
129
|
-
stylePlState(isReady);
|
|
130
|
-
}
|
|
131
|
-
if (p.startsWith("src/atoms") || p.startsWith("src/molecules") || p.startsWith("src/assets/styles/02-base")) {
|
|
132
|
-
styleBase(isReady);
|
|
133
|
-
}
|
|
134
|
-
if (p.startsWith("src/organisms")) {
|
|
135
|
-
if (path.basename(p).startsWith("_")) {
|
|
136
|
-
glob.sync(path.dirname(p) + "/*.scss", { nodir: true }).filter((p2) => !path.basename(p2).startsWith("_")).forEach((p2) => styleOrganism(p2, isReady));
|
|
137
|
-
} else {
|
|
138
|
-
styleOrganism(p, isReady);
|
|
145
|
+
if (p.startsWith("src/templates")) {
|
|
146
|
+
if (path.basename(p).startsWith("_")) {
|
|
147
|
+
glob.sync(path.dirname(p) + "/*.scss", { nodir: true }).filter((p2) => !path.basename(p2).startsWith("_")).forEach((p2) => styleTemplate(p2, isReady));
|
|
148
|
+
} else {
|
|
149
|
+
styleTemplate(p, isReady);
|
|
150
|
+
}
|
|
139
151
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
} else {
|
|
145
|
-
styleTemplate(p, isReady);
|
|
152
|
+
if (p.startsWith("xpack/styles/pl-states")) {
|
|
153
|
+
stylePlState(isReady);
|
|
154
|
+
} else if (p.startsWith("xpack/styles")) {
|
|
155
|
+
styleRoot(isReady);
|
|
146
156
|
}
|
|
147
|
-
}
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
};
|
|
158
|
+
if (isWatch) {
|
|
159
|
+
const watcher = watch(["src", "xpack/styles"], { ignored: (path2, stats) => !!stats?.isFile() && !path2.endsWith(".scss") });
|
|
160
|
+
let isReady = false;
|
|
161
|
+
watcher.on("ready", () => {
|
|
162
|
+
log("SCSS ready!");
|
|
163
|
+
isReady = true;
|
|
164
|
+
}).on("add", (path2) => sassCompile(path2, isReady)).on("change", (path2) => sassCompile(path2, isReady)).on("unlink", (path2) => log(`File ${path2} has been removed`));
|
|
165
|
+
} else {
|
|
166
|
+
styleBase(true);
|
|
167
|
+
stylePlState(true);
|
|
168
|
+
glob.sync(["src/{organisms,templates}/**/*.scss", "xpack/styles/**/*.scss"]).filter((p) => !path.basename(p).startsWith("_")).forEach((path2) => sassCompile(path2, true));
|
|
152
169
|
}
|
|
153
170
|
};
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
watcher.on("ready", () => {
|
|
158
|
-
log("SCSS ready!");
|
|
159
|
-
isReady = true;
|
|
160
|
-
}).on("add", (path2) => sassCompile(path2, isReady)).on("change", (path2) => sassCompile(path2, isReady)).on("unlink", (path2) => log(`File ${path2} has been removed`));
|
|
161
|
-
} else {
|
|
162
|
-
styleBase(true);
|
|
163
|
-
stylePlState(true);
|
|
164
|
-
glob.sync(["src/{organisms,templates}/**/*.scss", "xpack/styles/**/*.scss"]).filter((p) => !path.basename(p).startsWith("_")).forEach((path2) => sassCompile(path2, true));
|
|
171
|
+
const isDirectRun = process.argv[1]?.endsWith("styles.js") || process.argv[1]?.endsWith("styles.ts");
|
|
172
|
+
if (isDirectRun) {
|
|
173
|
+
runStyles({ watch: process.argv.includes("--watch") });
|
|
165
174
|
}
|
|
175
|
+
export {
|
|
176
|
+
runStyles
|
|
177
|
+
};
|
package/package.json
CHANGED