@coraltravelcenter/b2c-landing-builder 2.1.0 → 2.2.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/README.md +9 -8
- package/package.json +1 -1
- package/src/blocks/add.mjs +3 -1
- package/src/blocks/rename.mjs +1 -1
- package/src/config/script-stack.mjs +19 -0
- package/src/config/validate-config.mjs +3 -1
- package/src/config/validate-project.mjs +10 -5
- package/src/lib/build-cms.mjs +4 -2
- package/src/lib/landingBlocksPlugin.mjs +3 -1
- package/src/vite/config.mjs +18 -3
package/README.md
CHANGED
|
@@ -76,13 +76,14 @@ export default {
|
|
|
76
76
|
|
|
77
77
|
Поддерживаются:
|
|
78
78
|
|
|
79
|
-
- JavaScript: `
|
|
79
|
+
- JavaScript: `js`, `ts`, `vue`, `vue-ts` (`vanilla` поддерживается для старых проектов);
|
|
80
80
|
- разметка: `html`, `pug`;
|
|
81
81
|
- стили: `css`, `scss`, `less`;
|
|
82
82
|
- сайты: `coral`, `sunmar`.
|
|
83
83
|
|
|
84
|
-
Зависимости выбранного стека устанавливаются локально в проект: `
|
|
85
|
-
`@vitejs/plugin-vue` для Vue, `pug` для Pug, `less` для Less и
|
|
84
|
+
Зависимости выбранного стека устанавливаются локально в проект: `typescript`
|
|
85
|
+
для TS, `vue` и `@vitejs/plugin-vue` для Vue, `pug` для Pug, `less` для Less и
|
|
86
|
+
`sass` для SCSS.
|
|
86
87
|
Builder загружает Vue-плагин из проекта, поэтому Vue-зависимости не
|
|
87
88
|
устанавливаются вместе с глобальным builder.
|
|
88
89
|
|
|
@@ -105,7 +106,7 @@ src/
|
|
|
105
106
|
styles/
|
|
106
107
|
welcome.css | welcome.scss | welcome.less
|
|
107
108
|
scripts/
|
|
108
|
-
welcome.js
|
|
109
|
+
welcome.js | welcome.ts
|
|
109
110
|
components/ # только для Vue
|
|
110
111
|
public/
|
|
111
112
|
pug.rc # только для Pug
|
|
@@ -125,13 +126,13 @@ package.json
|
|
|
125
126
|
}
|
|
126
127
|
```
|
|
127
128
|
|
|
128
|
-
Для каждого ключа builder ищет разметку, стиль и необязательный JS-файл с тем
|
|
129
|
+
Для каждого ключа builder ищет разметку, стиль и необязательный JS/TS-файл с тем
|
|
129
130
|
же именем. Форматы определяются `landing.config.mjs`.
|
|
130
131
|
|
|
131
|
-
## Контракт JavaScript
|
|
132
|
+
## Контракт JavaScript и TypeScript
|
|
132
133
|
|
|
133
|
-
Если у блока есть `src/scripts/<key>.js`, файл обязан
|
|
134
|
-
инициализации по умолчанию:
|
|
134
|
+
Если у блока есть `src/scripts/<key>.js` или `src/scripts/<key>.ts`, файл обязан
|
|
135
|
+
экспортировать функцию инициализации по умолчанию:
|
|
135
136
|
|
|
136
137
|
```js
|
|
137
138
|
export default function hero() {
|
package/package.json
CHANGED
package/src/blocks/add.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import {assertBlockKey, readOrder, writeOrder} from "./utils.mjs";
|
|
5
|
+
import {resolveScriptStack} from "../config/script-stack.mjs";
|
|
5
6
|
|
|
6
7
|
function markupTemplate(key, format) {
|
|
7
8
|
return format === "pug" ? `section.${key}\n` : `<section class="${key}">\n</section>\n`;
|
|
@@ -21,10 +22,11 @@ export function addBlock(key, config, root = process.cwd()) {
|
|
|
21
22
|
const {order, orderPath} = readOrder(root);
|
|
22
23
|
if (order.blocks.includes(key)) throw new Error(`Block already exists in src/order.json: ${key}`);
|
|
23
24
|
|
|
25
|
+
const scriptStack = resolveScriptStack(config.stack.script);
|
|
24
26
|
const files = [
|
|
25
27
|
[path.resolve(root, "src/markup", `${key}.${config.stack.markup}`), markupTemplate(key, config.stack.markup)],
|
|
26
28
|
[path.resolve(root, "src/styles", `${key}.${config.stack.styles}`), styleTemplate(key)],
|
|
27
|
-
[path.resolve(root, "src/scripts", `${key}.
|
|
29
|
+
[path.resolve(root, "src/scripts", `${key}.${scriptStack.extension}`), scriptTemplate(key)],
|
|
28
30
|
];
|
|
29
31
|
const collision = files.find(([filePath]) => fs.existsSync(filePath));
|
|
30
32
|
if (collision) throw new Error(`Cannot add block; target already exists: ${path.relative(root, collision[0])}`);
|
package/src/blocks/rename.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import {assertBlockKey, readOrder, writeOrder} from "./utils.mjs";
|
|
5
5
|
|
|
6
|
-
const FILES = {markup: ["html", "pug"], styles: ["css", "scss", "less"], scripts: ["js"]};
|
|
6
|
+
const FILES = {markup: ["html", "pug"], styles: ["css", "scss", "less"], scripts: ["js", "ts"]};
|
|
7
7
|
|
|
8
8
|
export function renameBlock(fromKey, toKey, root = process.cwd()) {
|
|
9
9
|
assertBlockKey(fromKey, "source block key");
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const SCRIPT_STACKS = {
|
|
2
|
+
vanilla: {extension: "js", vue: false, dependencies: []},
|
|
3
|
+
js: {extension: "js", vue: false, dependencies: []},
|
|
4
|
+
ts: {extension: "ts", vue: false, dependencies: ["typescript"]},
|
|
5
|
+
vue: {extension: "js", vue: true, dependencies: ["vue", "@vitejs/plugin-vue"]},
|
|
6
|
+
"vue-ts": {
|
|
7
|
+
extension: "ts",
|
|
8
|
+
vue: true,
|
|
9
|
+
dependencies: ["vue", "@vitejs/plugin-vue", "typescript"],
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const SCRIPT_STACK_VALUES = new Set(Object.keys(SCRIPT_STACKS));
|
|
14
|
+
|
|
15
|
+
export function resolveScriptStack(script) {
|
|
16
|
+
const stack = SCRIPT_STACKS[script];
|
|
17
|
+
if (!stack) throw new Error(`Unsupported stack.script: ${JSON.stringify(script)}`);
|
|
18
|
+
return stack;
|
|
19
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import {SCRIPT_STACK_VALUES} from "./script-stack.mjs";
|
|
2
|
+
|
|
1
3
|
const PROJECT_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
2
4
|
const SUPPORTED_SCHEMA_VERSIONS = new Set([1]);
|
|
3
5
|
const STACK_VALUES = {
|
|
4
|
-
script:
|
|
6
|
+
script: SCRIPT_STACK_VALUES,
|
|
5
7
|
markup: new Set(["html", "pug"]),
|
|
6
8
|
styles: new Set(["css", "scss", "less"]),
|
|
7
9
|
};
|
|
@@ -2,18 +2,22 @@ import fs from "node:fs";
|
|
|
2
2
|
import {createRequire} from "node:module";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
+
import {resolveScriptStack} from "./script-stack.mjs";
|
|
6
|
+
|
|
5
7
|
const BLOCK_KEY_RE = /^[a-z0-9][a-z0-9-_]*$/i;
|
|
6
8
|
const DEFAULT_EXPORT_RE = /\bexport\s+default\s+(?:async\s+)?(?:function\b|\([^)]*\)\s*=>|[A-Za-z_$][\w$]*\s*=>|[A-Za-z_$][\w$]*\s*;?)/;
|
|
7
9
|
const STACK_DEPENDENCIES = {
|
|
8
|
-
script: {vue: ["vue", "@vitejs/plugin-vue"]},
|
|
9
10
|
markup: {pug: ["pug"]},
|
|
10
11
|
styles: {less: ["less"], scss: ["sass"]},
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
function validateLocalDependencies(config, root) {
|
|
14
15
|
const projectRequire = createRequire(path.resolve(root, "package.json"));
|
|
15
|
-
const dependencies =
|
|
16
|
-
|
|
16
|
+
const dependencies = [
|
|
17
|
+
...resolveScriptStack(config.stack.script).dependencies,
|
|
18
|
+
...Object.entries(STACK_DEPENDENCIES)
|
|
19
|
+
.flatMap(([section, values]) => values[config.stack[section]] || []),
|
|
20
|
+
];
|
|
17
21
|
|
|
18
22
|
for (const dependency of dependencies) {
|
|
19
23
|
try {
|
|
@@ -42,6 +46,7 @@ function readJson(filePath, label) {
|
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
export function validateProject(config, root = process.cwd()) {
|
|
49
|
+
const scriptStack = resolveScriptStack(config.stack.script);
|
|
45
50
|
const orderPath = path.resolve(root, "src/order.json");
|
|
46
51
|
const order = readJson(orderPath, "src/order.json");
|
|
47
52
|
if (!Array.isArray(order.blocks)) {
|
|
@@ -61,12 +66,12 @@ export function validateProject(config, root = process.cwd()) {
|
|
|
61
66
|
throw new Error(`Missing configured markup for block ${key}: src/markup/${key}.${config.stack.markup}`);
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
const scriptPath = path.resolve(root, "src/scripts", `${key}.
|
|
69
|
+
const scriptPath = path.resolve(root, "src/scripts", `${key}.${scriptStack.extension}`);
|
|
65
70
|
if (!fs.existsSync(scriptPath)) continue;
|
|
66
71
|
const source = fs.readFileSync(scriptPath, "utf8");
|
|
67
72
|
if (!DEFAULT_EXPORT_RE.test(source)) {
|
|
68
73
|
throw new Error(
|
|
69
|
-
`src/scripts/${key}.
|
|
74
|
+
`src/scripts/${key}.${scriptStack.extension} must export its initializer as default function`
|
|
70
75
|
);
|
|
71
76
|
}
|
|
72
77
|
}
|
package/src/lib/build-cms.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {cleanDir, ensureDir, existsFile, normalizeHtml, r, readBlocks} from "./_
|
|
|
6
6
|
import {loadProjectVuePlugin} from "./loadProjectVuePlugin.mjs";
|
|
7
7
|
import {processMarkup} from "./processMarkup.mjs";
|
|
8
8
|
import {renderPugFile} from "./pugMarkup.mjs";
|
|
9
|
+
import {resolveScriptStack} from "../config/script-stack.mjs";
|
|
9
10
|
|
|
10
11
|
const ORDER_FILE = r("src/order.json");
|
|
11
12
|
|
|
@@ -83,7 +84,7 @@ try { if (typeof init === "function") init(); } catch (e) { console.warn(e); }
|
|
|
83
84
|
},
|
|
84
85
|
};
|
|
85
86
|
|
|
86
|
-
const vue = stack.script
|
|
87
|
+
const vue = resolveScriptStack(stack.script).vue
|
|
87
88
|
? await loadProjectVuePlugin(process.cwd())
|
|
88
89
|
: null;
|
|
89
90
|
const res = await build({
|
|
@@ -120,11 +121,12 @@ try { if (typeof init === "function") init(); } catch (e) { console.warn(e); }
|
|
|
120
121
|
// ---------- block build ----------
|
|
121
122
|
|
|
122
123
|
async function buildBlock(key, stack) {
|
|
124
|
+
const scriptStack = resolveScriptStack(stack.script);
|
|
123
125
|
const markupPath = path.join(MARKUP_DIR, `${key}.${stack.markup}`);
|
|
124
126
|
if (!markupPath) return null;
|
|
125
127
|
if (!existsFile(markupPath)) return null;
|
|
126
128
|
|
|
127
|
-
const jsPath = path.join(SCRIPTS_DIR, `${key}.
|
|
129
|
+
const jsPath = path.join(SCRIPTS_DIR, `${key}.${scriptStack.extension}`);
|
|
128
130
|
|
|
129
131
|
const markup = stack.markup === "pug"
|
|
130
132
|
? renderPugFile(markupPath)
|
|
@@ -4,6 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import {existsFile, normalizeHtml, readBlocks} from "./_utils.mjs";
|
|
5
5
|
import {processMarkup} from "./processMarkup.mjs";
|
|
6
6
|
import {getPugConfigFile, renderPugFile} from "./pugMarkup.mjs";
|
|
7
|
+
import {resolveScriptStack} from "../config/script-stack.mjs";
|
|
7
8
|
|
|
8
9
|
const VIRTUAL_ID = "virtual:landing-blocks";
|
|
9
10
|
const RESOLVED_VIRTUAL_ID = `\0${VIRTUAL_ID}`;
|
|
@@ -19,6 +20,7 @@ function isInside(directory, filePath) {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export function landingBlocksPlugin({root = process.cwd(), stack} = {}) {
|
|
23
|
+
const scriptStack = resolveScriptStack(stack.script);
|
|
22
24
|
const orderFile = path.resolve(root, "src/order.json");
|
|
23
25
|
const markupDir = path.resolve(root, "src/markup");
|
|
24
26
|
const stylesDir = path.resolve(root, "src/styles");
|
|
@@ -87,7 +89,7 @@ export function landingBlocksPlugin({root = process.cwd(), stack} = {}) {
|
|
|
87
89
|
imports.push(`import ${JSON.stringify(toVitePath(stylePath))};`);
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
const scriptPath = path.join(scriptsDir, `${key}.
|
|
92
|
+
const scriptPath = path.join(scriptsDir, `${key}.${scriptStack.extension}`);
|
|
91
93
|
let init = "null";
|
|
92
94
|
if (existsFile(scriptPath)) {
|
|
93
95
|
this.addWatchFile(scriptPath);
|
package/src/vite/config.mjs
CHANGED
|
@@ -2,22 +2,37 @@ import {fileURLToPath} from "node:url";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
import {createServer} from "vite";
|
|
5
|
-
import monkey from "vite-plugin-monkey";
|
|
6
5
|
|
|
7
6
|
import {loadConfig} from "../config/load-config.mjs";
|
|
8
7
|
import {resolvePreset} from "../config/resolve-preset.mjs";
|
|
9
8
|
import {landingBlocksPlugin} from "../lib/landingBlocksPlugin.mjs";
|
|
10
9
|
import {loadProjectVuePlugin} from "../lib/loadProjectVuePlugin.mjs";
|
|
10
|
+
import {resolveScriptStack} from "../config/script-stack.mjs";
|
|
11
11
|
|
|
12
12
|
const clientEntry = fileURLToPath(new URL("./client.js", import.meta.url));
|
|
13
13
|
const builderRoot = fileURLToPath(new URL("../../", import.meta.url));
|
|
14
14
|
const clientEntryUrl = `/@fs${clientEntry.replaceAll("\\", "/")}`;
|
|
15
|
+
let monkeyPlugin;
|
|
16
|
+
|
|
17
|
+
async function loadMonkeyPlugin() {
|
|
18
|
+
if (monkeyPlugin) return monkeyPlugin;
|
|
19
|
+
|
|
20
|
+
const projectRoot = process.cwd();
|
|
21
|
+
try {
|
|
22
|
+
process.chdir(builderRoot);
|
|
23
|
+
monkeyPlugin = (await import("vite-plugin-monkey")).default;
|
|
24
|
+
return monkeyPlugin;
|
|
25
|
+
} finally {
|
|
26
|
+
process.chdir(projectRoot);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
15
29
|
|
|
16
30
|
export async function createViteConfig(root = process.cwd()) {
|
|
17
31
|
const config = await loadConfig(root);
|
|
18
32
|
const preset = resolvePreset(config.site.preset);
|
|
33
|
+
const monkey = await loadMonkeyPlugin();
|
|
19
34
|
const shouldOpen = process.env.B2C_NO_OPEN !== "1";
|
|
20
|
-
const vue = config.stack.script
|
|
35
|
+
const vue = resolveScriptStack(config.stack.script).vue
|
|
21
36
|
? await loadProjectVuePlugin(root)
|
|
22
37
|
: null;
|
|
23
38
|
|
|
@@ -26,7 +41,7 @@ export async function createViteConfig(root = process.cwd()) {
|
|
|
26
41
|
configFile: false,
|
|
27
42
|
server: {
|
|
28
43
|
host: "127.0.0.1",
|
|
29
|
-
port: 5173,
|
|
44
|
+
port: Number(process.env.B2C_PORT || 5173),
|
|
30
45
|
strictPort: true,
|
|
31
46
|
cors: true,
|
|
32
47
|
open: shouldOpen ? "/__vite-plugin-monkey.install.user.js" : false,
|