elcrm 1.1.13 → 1.1.15
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 +1 -1
- package/dist/index.js +1982 -1443
- package/package.json +3 -3
- package/templates/elcrm-cursor/rules/elcrm-jsdoc.mdc +1 -1
- package/templates/elcrm-cursor/rules/elcrm-packages.mdc +1 -1
- package/templates/elcrm-cursor/rules/elcrm-ui.mdc +3 -1
- package/templates/elcrm-docs/BUTTON.elCRM.md +3 -3
- package/templates/elcrm-docs/CLI.elCRM.md +26 -12
- package/templates/elcrm-docs/COMPONENTS.elCRM.md +18 -10
- package/templates/elcrm-docs/FORM.elCRM.md +11 -3
- package/templates/elcrm-docs/ICONS.elCRM.md +2 -0
- package/templates/elcrm-docs/NOTIFICATIONS.elCRM.md +1 -1
- package/templates/elcrm-docs/SERVER.elCRM.md +3 -1
- package/templates/orbit/README.md +12 -0
- package/templates/orbit/index.html +28 -0
- package/templates/orbit/package.json +39 -0
- package/templates/orbit/src/App.tsx +34 -0
- package/templates/orbit/src/component/Nav.tsx +139 -0
- package/templates/orbit/src/lazyRoute.ts +4 -0
- package/templates/orbit/src/lib/icon.tsx +48 -0
- package/templates/orbit/src/lib/theme.ts +39 -0
- package/templates/orbit/src/main.tsx +54 -0
- package/templates/orbit/src/modules/Analytics/index.tsx +5 -0
- package/templates/orbit/src/modules/Catalog/index.tsx +7 -0
- package/templates/orbit/src/modules/Customers/index.tsx +5 -0
- package/templates/orbit/src/modules/Finances/index.tsx +5 -0
- package/templates/orbit/src/modules/Home/index.tsx +317 -0
- package/templates/orbit/src/modules/Integrations/index.tsx +7 -0
- package/templates/orbit/src/modules/Link/index.tsx +7 -0
- package/templates/orbit/src/modules/Marketing/index.tsx +5 -0
- package/templates/orbit/src/modules/Placeholder.tsx +13 -0
- package/templates/orbit/src/modules/Settings/index.tsx +22 -0
- package/templates/orbit/src/modules/Store/index.tsx +7 -0
- package/templates/orbit/src/pages/Auth.tsx +45 -0
- package/templates/orbit/src/pages/Main.tsx +29 -0
- package/templates/orbit/src/router-data.d.ts +10 -0
- package/templates/orbit/src/state.ts +28 -0
- package/templates/orbit/src/style/elcrm.css +27 -0
- package/templates/orbit/src/style/theme-dark.css +148 -0
- package/templates/orbit/src/style/theme-light.css +148 -0
- package/templates/orbit/src/style/theme.css +177 -0
- package/templates/orbit/src/vite-env.d.ts +1 -0
- package/templates/orbit/tsconfig.json +19 -0
- package/templates/orbit/vite.config.ts +14 -0
- package/templates/panel/README.md +1 -1
- package/templates/panel/web/package.json +9 -9
- package/templates/panel/web/src/pages/Auth.tsx +1 -1
- package/templates/panel/web/src/style/theme-dark.css +9 -32
- package/templates/panel/web/src/style/theme-light.css +9 -32
- package/templates/panel/web/src/style/theme.css +20 -39
- package/templates/panel/web/vite.config.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -1,22 +1,197 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
6
|
+
import { dirname as dirname4, join as join18 } from "path";
|
|
7
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8
|
+
|
|
9
|
+
// src/parseArgs.ts
|
|
10
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
11
|
+
const options = {};
|
|
12
|
+
const flags = [];
|
|
13
|
+
const positionals = [];
|
|
14
|
+
for (let i = 0;i < argv.length; i++) {
|
|
15
|
+
const arg = argv[i];
|
|
16
|
+
if (arg === "--") {
|
|
17
|
+
positionals.push(...argv.slice(i + 1));
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
if (arg.startsWith("--")) {
|
|
21
|
+
const body = arg.slice(2);
|
|
22
|
+
if (body.includes("=")) {
|
|
23
|
+
const eq = body.indexOf("=");
|
|
24
|
+
const key = body.slice(0, eq);
|
|
25
|
+
const value = body.slice(eq + 1);
|
|
26
|
+
if (key)
|
|
27
|
+
options[key] = value;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const next = argv[i + 1];
|
|
31
|
+
if (next && !next.startsWith("-")) {
|
|
32
|
+
const valueOpts = new Set([
|
|
33
|
+
"template",
|
|
34
|
+
"url",
|
|
35
|
+
"name",
|
|
36
|
+
"dir",
|
|
37
|
+
"folder",
|
|
38
|
+
"out"
|
|
39
|
+
]);
|
|
40
|
+
if (valueOpts.has(body)) {
|
|
41
|
+
options[body] = next;
|
|
42
|
+
i++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (body && !flags.includes(body))
|
|
47
|
+
flags.push(body);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (arg.startsWith("-") && arg.length > 1) {
|
|
51
|
+
const short = arg.slice(1);
|
|
52
|
+
if (short === "t" && argv[i + 1] && !argv[i + 1].startsWith("-")) {
|
|
53
|
+
options.template = argv[i + 1];
|
|
54
|
+
i++;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (short && !flags.includes(short))
|
|
58
|
+
flags.push(short);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
positionals.push(arg);
|
|
62
|
+
}
|
|
63
|
+
const [command = "", ...rest] = positionals;
|
|
64
|
+
return {
|
|
65
|
+
command,
|
|
66
|
+
positionals: rest,
|
|
67
|
+
options,
|
|
68
|
+
flags
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function hasFlag(parsed, ...names) {
|
|
72
|
+
return names.some((n) => parsed.flags.includes(n));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/lib/test/detect.ts
|
|
76
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
77
|
+
import { join } from "path";
|
|
78
|
+
function hasElcrmServer(pkg) {
|
|
79
|
+
for (const section of [
|
|
80
|
+
"dependencies",
|
|
81
|
+
"devDependencies",
|
|
82
|
+
"peerDependencies"
|
|
83
|
+
]) {
|
|
84
|
+
const map = pkg[section];
|
|
85
|
+
if (map && typeof map === "object" && "@elcrm/server" in map)
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
function detectTestMode(pkg, force) {
|
|
91
|
+
if (force === "server" || force === "front")
|
|
92
|
+
return force;
|
|
93
|
+
return hasElcrmServer(pkg) ? "server" : "front";
|
|
94
|
+
}
|
|
95
|
+
function listWorkspaceDirs(cwd, pkg) {
|
|
96
|
+
const raw = pkg.workspaces;
|
|
97
|
+
let patterns = [];
|
|
98
|
+
if (Array.isArray(raw)) {
|
|
99
|
+
patterns = raw.filter((p) => typeof p === "string");
|
|
100
|
+
} else if (raw && typeof raw === "object" && Array.isArray(raw.packages)) {
|
|
101
|
+
patterns = raw.packages.filter((p) => typeof p === "string");
|
|
102
|
+
}
|
|
103
|
+
if (!patterns.length)
|
|
104
|
+
return [];
|
|
105
|
+
const out = [];
|
|
106
|
+
for (const pat of patterns) {
|
|
107
|
+
if (!pat.includes("*")) {
|
|
108
|
+
const dir = join(cwd, pat);
|
|
109
|
+
if (existsSync(join(dir, "package.json")))
|
|
110
|
+
out.push(dir);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const base = pat.replace(/\/\*$/, "").replace(/\*$/, "");
|
|
114
|
+
const parent = join(cwd, base);
|
|
115
|
+
if (!existsSync(parent) || !statSync(parent).isDirectory())
|
|
116
|
+
continue;
|
|
117
|
+
for (const name of readdirSync(parent)) {
|
|
118
|
+
const dir = join(parent, name);
|
|
119
|
+
if (statSync(dir).isDirectory() && existsSync(join(dir, "package.json"))) {
|
|
120
|
+
out.push(dir);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
function readPkgAt(dir) {
|
|
127
|
+
const path = join(dir, "package.json");
|
|
128
|
+
if (!existsSync(path))
|
|
129
|
+
return null;
|
|
130
|
+
try {
|
|
131
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
132
|
+
} catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/lib/pkg.ts
|
|
138
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
139
|
+
import { join as join2 } from "path";
|
|
140
|
+
function packageJsonPath(cwd = process.cwd()) {
|
|
141
|
+
return join2(cwd, "package.json");
|
|
142
|
+
}
|
|
143
|
+
function readPackageJson(cwd = process.cwd()) {
|
|
144
|
+
const path = packageJsonPath(cwd);
|
|
145
|
+
if (!existsSync2(path))
|
|
146
|
+
return null;
|
|
147
|
+
try {
|
|
148
|
+
return JSON.parse(readFileSync2(path, "utf8"));
|
|
149
|
+
} catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function writePackageJson(pkg, cwd = process.cwd()) {
|
|
154
|
+
writeFileSync(packageJsonPath(cwd), JSON.stringify(pkg, null, 2) + `
|
|
155
|
+
`, "utf8");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/lib/elcrmDeps.ts
|
|
159
|
+
var SECTIONS = [
|
|
160
|
+
"dependencies",
|
|
161
|
+
"devDependencies",
|
|
162
|
+
"peerDependencies"
|
|
163
|
+
];
|
|
164
|
+
function listElcrmDeps(pkg) {
|
|
165
|
+
const out = [];
|
|
166
|
+
for (const section of SECTIONS) {
|
|
167
|
+
const map = pkg[section];
|
|
168
|
+
if (!map || typeof map !== "object")
|
|
169
|
+
continue;
|
|
170
|
+
for (const [name, version] of Object.entries(map)) {
|
|
171
|
+
if (name.startsWith("@elcrm/") && typeof version === "string") {
|
|
172
|
+
out.push({ name, version, section });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
function uniqueElcrmNames(deps) {
|
|
179
|
+
return [...new Set(deps.map((d) => d.name))].sort();
|
|
180
|
+
}
|
|
181
|
+
function uniqueElcrmNamesInTree(cwd, pkg) {
|
|
182
|
+
const set = new Set(uniqueElcrmNames(listElcrmDeps(pkg)));
|
|
183
|
+
for (const dir of listWorkspaceDirs(cwd, pkg)) {
|
|
184
|
+
const child = readPackageJson(dir);
|
|
185
|
+
if (!child)
|
|
186
|
+
continue;
|
|
187
|
+
for (const name of uniqueElcrmNames(listElcrmDeps(child)))
|
|
188
|
+
set.add(name);
|
|
189
|
+
}
|
|
190
|
+
return [...set].sort();
|
|
191
|
+
}
|
|
18
192
|
|
|
19
193
|
// src/lib/latest.ts
|
|
194
|
+
var CACHE = new Map;
|
|
20
195
|
async function fetchLatestVersion(name) {
|
|
21
196
|
if (CACHE.has(name))
|
|
22
197
|
return CACHE.get(name);
|
|
@@ -68,184 +243,96 @@ async function fetchCorePinnedVersions() {
|
|
|
68
243
|
} catch {}
|
|
69
244
|
return map;
|
|
70
245
|
}
|
|
71
|
-
var CACHE;
|
|
72
|
-
var init_latest = __esm(() => {
|
|
73
|
-
CACHE = new Map;
|
|
74
|
-
});
|
|
75
246
|
|
|
76
|
-
// src/lib/
|
|
77
|
-
import { existsSync as
|
|
78
|
-
import { join as
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const path = packageJsonPath(cwd);
|
|
84
|
-
if (!existsSync2(path))
|
|
85
|
-
return null;
|
|
86
|
-
try {
|
|
87
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
88
|
-
} catch {
|
|
89
|
-
return null;
|
|
247
|
+
// src/lib/install.ts
|
|
248
|
+
import { existsSync as existsSync3 } from "fs";
|
|
249
|
+
import { join as join3 } from "path";
|
|
250
|
+
import { spawnSync } from "child_process";
|
|
251
|
+
function detectPackageManager(cwd = process.cwd()) {
|
|
252
|
+
if (existsSync3(join3(cwd, "bun.lockb")) || existsSync3(join3(cwd, "bun.lock"))) {
|
|
253
|
+
return "bun";
|
|
90
254
|
}
|
|
255
|
+
const bun = spawnSync("bun", ["--version"], { encoding: "utf8" });
|
|
256
|
+
if (bun.status === 0)
|
|
257
|
+
return "bun";
|
|
258
|
+
return "npm";
|
|
91
259
|
}
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
|
|
260
|
+
function installDeps(cwd = process.cwd()) {
|
|
261
|
+
const pm = detectPackageManager(cwd);
|
|
262
|
+
console.log(`\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439 (${pm} install)\u2026`);
|
|
263
|
+
const r = spawnSync(pm, ["install"], {
|
|
264
|
+
cwd,
|
|
265
|
+
stdio: "inherit",
|
|
266
|
+
env: process.env
|
|
267
|
+
});
|
|
268
|
+
return r.status === 0;
|
|
269
|
+
}
|
|
270
|
+
function installGlobalElcrm() {
|
|
271
|
+
const bun = spawnSync("bun", ["--version"], { encoding: "utf8" });
|
|
272
|
+
const cmd = bun.status === 0 ? "bun" : "npm";
|
|
273
|
+
const args = ["i", "-g", "elcrm@latest"];
|
|
274
|
+
console.log(`CLI: ${cmd} ${args.join(" ")}`);
|
|
275
|
+
const r = spawnSync(cmd, args, {
|
|
276
|
+
stdio: "inherit",
|
|
277
|
+
env: process.env
|
|
278
|
+
});
|
|
279
|
+
return r.status === 0;
|
|
95
280
|
}
|
|
96
|
-
var init_pkg = () => {};
|
|
97
281
|
|
|
98
|
-
// src/lib/
|
|
282
|
+
// src/lib/ansi.ts
|
|
283
|
+
var enabled = process.env.NO_COLOR == null && process.env.FORCE_COLOR !== "0" && Boolean(process.stdout.isTTY);
|
|
284
|
+
function wrap(code, text) {
|
|
285
|
+
if (!enabled)
|
|
286
|
+
return text;
|
|
287
|
+
return `\x1B[${code}m${text}\x1B[0m`;
|
|
288
|
+
}
|
|
289
|
+
var c = {
|
|
290
|
+
gray: (t) => wrap("90", t),
|
|
291
|
+
green: (t) => wrap("32", t),
|
|
292
|
+
blue: (t) => wrap("34", t),
|
|
293
|
+
yellow: (t) => wrap("33", t),
|
|
294
|
+
red: (t) => wrap("31", t),
|
|
295
|
+
cyan: (t) => wrap("36", t),
|
|
296
|
+
dim: (t) => wrap("2", t)
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// src/lib/cssSync.ts
|
|
300
|
+
import {
|
|
301
|
+
existsSync as existsSync5,
|
|
302
|
+
readdirSync as readdirSync3,
|
|
303
|
+
readFileSync as readFileSync7,
|
|
304
|
+
statSync as statSync3,
|
|
305
|
+
writeFileSync as writeFileSync3
|
|
306
|
+
} from "fs";
|
|
307
|
+
import { createRequire } from "module";
|
|
308
|
+
import { dirname, join as join5 } from "path";
|
|
309
|
+
|
|
310
|
+
// src/lib/migrate/form-tokens.ts
|
|
311
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
312
|
+
|
|
313
|
+
// src/lib/migrate/walk.ts
|
|
99
314
|
import {
|
|
100
|
-
existsSync as
|
|
101
|
-
readdirSync,
|
|
102
|
-
readFileSync as
|
|
103
|
-
statSync,
|
|
315
|
+
existsSync as existsSync4,
|
|
316
|
+
readdirSync as readdirSync2,
|
|
317
|
+
readFileSync as readFileSync3,
|
|
318
|
+
statSync as statSync2,
|
|
104
319
|
writeFileSync as writeFileSync2
|
|
105
320
|
} from "fs";
|
|
106
|
-
import { join as join3 } from "path";
|
|
107
|
-
function walkFiles(dir, out = []) {
|
|
108
|
-
if (!existsSync3(dir))
|
|
109
|
-
return out;
|
|
110
|
-
for (const name of readdirSync(dir)) {
|
|
111
|
-
if (SKIP_DIRS.has(name))
|
|
112
|
-
continue;
|
|
113
|
-
const full = join3(dir, name);
|
|
114
|
-
const st = statSync(full);
|
|
115
|
-
if (st.isDirectory())
|
|
116
|
-
walkFiles(full, out);
|
|
117
|
-
else {
|
|
118
|
-
const ext = name.includes(".") ? `.${name.split(".").pop()}` : "";
|
|
119
|
-
if (TEXT_EXT.has(ext))
|
|
120
|
-
out.push(full);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return out;
|
|
124
|
-
}
|
|
125
|
-
function rewriteImports(source) {
|
|
126
|
-
let hits = 0;
|
|
127
|
-
let next = source;
|
|
128
|
-
const patterns = [
|
|
129
|
-
[
|
|
130
|
-
/from\s+["']@elcrm\/socket\/server["']/g,
|
|
131
|
-
'from "@elcrm/server"'
|
|
132
|
-
],
|
|
133
|
-
[
|
|
134
|
-
/from\s+["']@elcrm\/socket-server["']/g,
|
|
135
|
-
'from "@elcrm/server"'
|
|
136
|
-
],
|
|
137
|
-
[
|
|
138
|
-
/require\s*\(\s*["']@elcrm\/socket\/server["']\s*\)/g,
|
|
139
|
-
'require("@elcrm/server")'
|
|
140
|
-
],
|
|
141
|
-
[
|
|
142
|
-
/require\s*\(\s*["']@elcrm\/socket-server["']\s*\)/g,
|
|
143
|
-
'require("@elcrm/server")'
|
|
144
|
-
]
|
|
145
|
-
];
|
|
146
|
-
for (const [re, repl] of patterns) {
|
|
147
|
-
const before = next;
|
|
148
|
-
next = next.replace(re, () => {
|
|
149
|
-
hits++;
|
|
150
|
-
return repl;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
return { next, hits };
|
|
154
|
-
}
|
|
155
|
-
async function migrateSocketServer(cwd, dry) {
|
|
156
|
-
const changes = [];
|
|
157
|
-
const pkg = readPackageJson(cwd);
|
|
158
|
-
let removedSocketServer = false;
|
|
159
|
-
if (pkg) {
|
|
160
|
-
for (const section of [
|
|
161
|
-
"dependencies",
|
|
162
|
-
"devDependencies",
|
|
163
|
-
"peerDependencies"
|
|
164
|
-
]) {
|
|
165
|
-
const map = pkg[section];
|
|
166
|
-
if (!map)
|
|
167
|
-
continue;
|
|
168
|
-
if (map["@elcrm/socket-server"]) {
|
|
169
|
-
removedSocketServer = true;
|
|
170
|
-
changes.push({
|
|
171
|
-
file: "package.json",
|
|
172
|
-
detail: `\u0443\u0434\u0430\u043B\u0438\u0442\u044C ${section}["@elcrm/socket-server"]`
|
|
173
|
-
});
|
|
174
|
-
if (!dry)
|
|
175
|
-
delete map["@elcrm/socket-server"];
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
const hasServer = Boolean(pkg.dependencies?.["@elcrm/server"]) || Boolean(pkg.devDependencies?.["@elcrm/server"]);
|
|
179
|
-
if (removedSocketServer && !hasServer) {
|
|
180
|
-
const latest = dry ? null : await fetchLatestVersion("@elcrm/server");
|
|
181
|
-
const ver = latest ? `^${latest}` : "^0.5.3";
|
|
182
|
-
changes.push({
|
|
183
|
-
file: "package.json",
|
|
184
|
-
detail: `\u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C dependencies["@elcrm/server"] = ${ver}`
|
|
185
|
-
});
|
|
186
|
-
if (!dry) {
|
|
187
|
-
if (!pkg.dependencies)
|
|
188
|
-
pkg.dependencies = {};
|
|
189
|
-
pkg.dependencies["@elcrm/server"] = ver;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (!dry && changes.some((c2) => c2.file === "package.json")) {
|
|
193
|
-
writePackageJson(pkg, cwd);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
const roots = ["src", "app", "server", "lib"].map((d) => join3(cwd, d));
|
|
197
|
-
const files = roots.flatMap((r) => walkFiles(r));
|
|
198
|
-
for (const file of files) {
|
|
199
|
-
const raw = readFileSync2(file, "utf8");
|
|
200
|
-
const { next, hits } = rewriteImports(raw);
|
|
201
|
-
if (hits > 0) {
|
|
202
|
-
changes.push({
|
|
203
|
-
file: file.replace(cwd + "/", ""),
|
|
204
|
-
detail: `${hits} \u0437\u0430\u043C\u0435\u043D(\u044B) \u0438\u043C\u043F\u043E\u0440\u0442\u043E\u0432 \u2192 @elcrm/server`
|
|
205
|
-
});
|
|
206
|
-
if (!dry)
|
|
207
|
-
writeFileSync2(file, next, "utf8");
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return changes;
|
|
211
|
-
}
|
|
212
|
-
var SKIP_DIRS, TEXT_EXT;
|
|
213
|
-
var init_socket_server = __esm(() => {
|
|
214
|
-
init_latest();
|
|
215
|
-
init_pkg();
|
|
216
|
-
SKIP_DIRS = new Set([
|
|
217
|
-
"node_modules",
|
|
218
|
-
"dist",
|
|
219
|
-
".git",
|
|
220
|
-
"coverage",
|
|
221
|
-
".turbo"
|
|
222
|
-
]);
|
|
223
|
-
TEXT_EXT = new Set([
|
|
224
|
-
".ts",
|
|
225
|
-
".tsx",
|
|
226
|
-
".js",
|
|
227
|
-
".jsx",
|
|
228
|
-
".mjs",
|
|
229
|
-
".cjs",
|
|
230
|
-
".mts",
|
|
231
|
-
".cts"
|
|
232
|
-
]);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
// src/lib/migrate/walk.ts
|
|
236
|
-
import {
|
|
237
|
-
existsSync as existsSync4,
|
|
238
|
-
readdirSync as readdirSync2,
|
|
239
|
-
readFileSync as readFileSync3,
|
|
240
|
-
statSync as statSync2,
|
|
241
|
-
writeFileSync as writeFileSync3
|
|
242
|
-
} from "fs";
|
|
243
321
|
import { join as join4, relative } from "path";
|
|
322
|
+
var SKIP_DIRS = new Set([
|
|
323
|
+
"node_modules",
|
|
324
|
+
"dist",
|
|
325
|
+
".git",
|
|
326
|
+
"coverage",
|
|
327
|
+
".turbo",
|
|
328
|
+
".next",
|
|
329
|
+
"build"
|
|
330
|
+
]);
|
|
244
331
|
function walkCodeFiles(dir, out = []) {
|
|
245
332
|
if (!existsSync4(dir))
|
|
246
333
|
return out;
|
|
247
334
|
for (const name of readdirSync2(dir)) {
|
|
248
|
-
if (
|
|
335
|
+
if (SKIP_DIRS.has(name))
|
|
249
336
|
continue;
|
|
250
337
|
const full = join4(dir, name);
|
|
251
338
|
let st;
|
|
@@ -272,373 +359,197 @@ function writeIfChanged(file, next, dry) {
|
|
|
272
359
|
if (prev === next)
|
|
273
360
|
return false;
|
|
274
361
|
if (!dry)
|
|
275
|
-
|
|
362
|
+
writeFileSync2(file, next, "utf8");
|
|
276
363
|
return true;
|
|
277
364
|
}
|
|
278
|
-
var SKIP_DIRS2;
|
|
279
|
-
var init_walk = __esm(() => {
|
|
280
|
-
SKIP_DIRS2 = new Set([
|
|
281
|
-
"node_modules",
|
|
282
|
-
"dist",
|
|
283
|
-
".git",
|
|
284
|
-
"coverage",
|
|
285
|
-
".turbo",
|
|
286
|
-
".next",
|
|
287
|
-
"build"
|
|
288
|
-
]);
|
|
289
|
-
});
|
|
290
365
|
|
|
291
|
-
// src/lib/migrate/
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
let
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
continue;
|
|
314
|
-
if (writeIfChanged(file, next, dry) || dry) {
|
|
315
|
-
changes.push({
|
|
316
|
-
file: rel(cwd, file),
|
|
317
|
-
detail: `${hits}\xD7 size sm/md \u2192 s/m`
|
|
318
|
-
});
|
|
366
|
+
// src/lib/migrate/css-decl.ts
|
|
367
|
+
function removeCssDecl(css, name) {
|
|
368
|
+
const re = new RegExp(`\\n?[ \\t]*${name.replace(/-/g, "\\-")}(?![\\w-])\\s*:`, "g");
|
|
369
|
+
let n = 0;
|
|
370
|
+
const ranges = [];
|
|
371
|
+
let m;
|
|
372
|
+
while ((m = re.exec(css)) !== null) {
|
|
373
|
+
const start = m.index;
|
|
374
|
+
let i = m.index + m[0].length;
|
|
375
|
+
let depth = 0;
|
|
376
|
+
while (i < css.length) {
|
|
377
|
+
const ch = css[i];
|
|
378
|
+
if (ch === "(")
|
|
379
|
+
depth++;
|
|
380
|
+
else if (ch === ")")
|
|
381
|
+
depth = Math.max(0, depth - 1);
|
|
382
|
+
else if ((ch === ";" || ch === "}") && depth === 0) {
|
|
383
|
+
if (ch === ";")
|
|
384
|
+
i++;
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
i++;
|
|
319
388
|
}
|
|
389
|
+
let s = start;
|
|
390
|
+
if (s > 0 && css[s - 1] === `
|
|
391
|
+
`)
|
|
392
|
+
s--;
|
|
393
|
+
ranges.push({ start: s, end: i });
|
|
394
|
+
n++;
|
|
320
395
|
}
|
|
321
|
-
|
|
396
|
+
if (!ranges.length)
|
|
397
|
+
return { next: css, n: 0 };
|
|
398
|
+
let next = css;
|
|
399
|
+
for (let r = ranges.length - 1;r >= 0; r--) {
|
|
400
|
+
const { start, end } = ranges[r];
|
|
401
|
+
next = next.slice(0, start) + next.slice(end);
|
|
402
|
+
}
|
|
403
|
+
return { next: next.replace(/\n{3,}/g, `
|
|
404
|
+
|
|
405
|
+
`), n };
|
|
322
406
|
}
|
|
323
|
-
var PATTERNS;
|
|
324
|
-
var init_size_sml = __esm(() => {
|
|
325
|
-
init_walk();
|
|
326
|
-
PATTERNS = [
|
|
327
|
-
[/size\s*=\s*"sm"/g, 'size="s"'],
|
|
328
|
-
[/size\s*=\s*'sm'/g, "size='s'"],
|
|
329
|
-
[/size\s*=\s*\{\s*"sm"\s*\}/g, 'size={"s"}'],
|
|
330
|
-
[/size\s*=\s*\{\s*'sm'\s*\}/g, "size={'s'}"],
|
|
331
|
-
[/size\s*=\s*"md"/g, 'size="m"'],
|
|
332
|
-
[/size\s*=\s*'md'/g, "size='m'"],
|
|
333
|
-
[/size\s*=\s*\{\s*"md"\s*\}/g, 'size={"m"}'],
|
|
334
|
-
[/size\s*=\s*\{\s*'md'\s*\}/g, "size={'m'}"]
|
|
335
|
-
];
|
|
336
|
-
});
|
|
337
407
|
|
|
338
|
-
// src/lib/migrate/
|
|
339
|
-
import { readFileSync as
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
408
|
+
// src/lib/migrate/css-sanitize.ts
|
|
409
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
410
|
+
var MIX_SPACE_RE = /(?:in\s+srgb|in\s+hsl|in\s+hwb|in\s+lab|in\s+lch)/i;
|
|
411
|
+
var ORPHAN_MIX_BLOCK_RE = /(?:^|\n)([ \t]*(?:in\s+srgb|in\s+hsl|in\s+hwb|in\s+lab|in\s+lch)[\s\S]*?\n[ \t]*\);?[ \t]*)(?=\n|$)/gi;
|
|
412
|
+
function prevNonEmptyLine(source, index) {
|
|
413
|
+
const before = source.slice(0, index);
|
|
414
|
+
const lines = before.split(/\r?\n/);
|
|
415
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
416
|
+
const t = (lines[i] ?? "").trimEnd();
|
|
417
|
+
if (t.length > 0)
|
|
418
|
+
return t;
|
|
347
419
|
}
|
|
348
|
-
return
|
|
420
|
+
return "";
|
|
349
421
|
}
|
|
350
|
-
function
|
|
422
|
+
function isInsideColorMix(prevLine) {
|
|
423
|
+
return /color-mix\s*\(\s*$/i.test(prevLine);
|
|
424
|
+
}
|
|
425
|
+
function stripOrphanColorMix(source) {
|
|
351
426
|
let hits = 0;
|
|
352
|
-
let next = source
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
427
|
+
let next = source.replace(ORPHAN_MIX_BLOCK_RE, (match, _block, offset) => {
|
|
428
|
+
const contentStart = offset + (match.startsWith(`
|
|
429
|
+
`) ? 1 : 0);
|
|
430
|
+
const prev = prevNonEmptyLine(source, contentStart);
|
|
431
|
+
if (isInsideColorMix(prev)) {
|
|
432
|
+
return match;
|
|
433
|
+
}
|
|
434
|
+
hits++;
|
|
435
|
+
return match.startsWith(`
|
|
436
|
+
`) ? `
|
|
437
|
+
` : "";
|
|
438
|
+
});
|
|
439
|
+
const lines = next.split(/\r?\n/);
|
|
440
|
+
const kept = [];
|
|
441
|
+
let mixOpen = 0;
|
|
442
|
+
for (const line of lines) {
|
|
443
|
+
const opens = (line.match(/color-mix\s*\(/gi) ?? []).length;
|
|
444
|
+
if (opens)
|
|
445
|
+
mixOpen += opens;
|
|
446
|
+
const trimmed = line.trim();
|
|
447
|
+
const orphanAlone = mixOpen === 0 && (/^in\s+(?:srgb|hsl|hwb|lab|lch)\s*,?\s*$/i.test(trimmed) || /^transparent\s*\)\s*;?\s*$/i.test(trimmed));
|
|
448
|
+
if (orphanAlone) {
|
|
359
449
|
hits++;
|
|
360
|
-
|
|
361
|
-
}
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
kept.push(line);
|
|
453
|
+
if (mixOpen > 0) {
|
|
454
|
+
if (/\)\s*;?\s*$/.test(trimmed) && !/^var\(/.test(trimmed)) {
|
|
455
|
+
const closes = (trimmed.match(/\)/g) ?? []).length;
|
|
456
|
+
const vars = (trimmed.match(/var\s*\(/g) ?? []).length;
|
|
457
|
+
mixOpen = Math.max(0, mixOpen - Math.max(0, closes - vars));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
362
460
|
}
|
|
461
|
+
next = kept.join(`
|
|
462
|
+
`);
|
|
463
|
+
next = next.replace(/[ \t]*[-\w]+\s*:\s*color-mix\(\s*\n(?:[ \t]*\n)+(?=[ \t]*(?:[-\w]+\s*:|\}))/g, () => {
|
|
464
|
+
hits++;
|
|
465
|
+
return "";
|
|
466
|
+
});
|
|
467
|
+
next = next.replace(/[ \t]*[-\w]+\s*:\s*color-mix\(\s*\n[ \t]*\}/g, () => {
|
|
468
|
+
hits++;
|
|
469
|
+
return "}";
|
|
470
|
+
});
|
|
471
|
+
next = next.replace(/\n{3,}/g, `
|
|
472
|
+
|
|
473
|
+
`);
|
|
363
474
|
return { next, hits };
|
|
364
475
|
}
|
|
365
|
-
|
|
476
|
+
function lineHasOrphanColorMix(line, prevNonEmpty) {
|
|
477
|
+
const t = line.trim();
|
|
478
|
+
if (!t || t.startsWith("/*") || t.startsWith("*"))
|
|
479
|
+
return false;
|
|
480
|
+
if (MIX_SPACE_RE.test(t) && /color-mix\s*\(/i.test(t))
|
|
481
|
+
return false;
|
|
482
|
+
if (/^in\s+(?:srgb|hsl|hwb|lab|lch)\b/i.test(t) && !/color-mix\s*\(/i.test(t)) {
|
|
483
|
+
if (prevNonEmpty != null && isInsideColorMix(prevNonEmpty))
|
|
484
|
+
return false;
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
if (/^transparent\s*\)\s*;?\s*$/i.test(t)) {
|
|
488
|
+
if (prevNonEmpty != null && /color-mix\s*\(/i.test(prevNonEmpty)) {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
if (prevNonEmpty != null && MIX_SPACE_RE.test(prevNonEmpty))
|
|
492
|
+
return false;
|
|
493
|
+
if (prevNonEmpty != null && /%\s*,?\s*$/.test(prevNonEmpty.trim())) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
async function migrateCssSanitize(cwd, dry) {
|
|
366
501
|
const changes = [];
|
|
367
502
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => f.endsWith(".css"));
|
|
368
503
|
for (const file of files) {
|
|
369
|
-
const raw =
|
|
370
|
-
const { next, hits } =
|
|
371
|
-
if (hits === 0)
|
|
504
|
+
const raw = readFileSync4(file, "utf8");
|
|
505
|
+
const { next, hits } = stripOrphanColorMix(raw);
|
|
506
|
+
if (hits === 0 || next === raw)
|
|
372
507
|
continue;
|
|
373
508
|
if (writeIfChanged(file, next, dry) || dry) {
|
|
374
509
|
changes.push({
|
|
375
510
|
file: rel(cwd, file),
|
|
376
|
-
detail: `${hits}\xD7
|
|
511
|
+
detail: `${hits}\xD7 \u0443\u0434\u0430\u043B\u0435\u043D\u044B \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0435 color-mix/\u0444\u0440\u0430\u0433\u043C\u0435\u043D\u0442\u044B`
|
|
377
512
|
});
|
|
378
513
|
}
|
|
379
514
|
}
|
|
380
515
|
return changes;
|
|
381
516
|
}
|
|
382
|
-
var VARS;
|
|
383
|
-
var init_field_border = __esm(() => {
|
|
384
|
-
init_walk();
|
|
385
|
-
VARS = [
|
|
386
|
-
"--field-border-focus",
|
|
387
|
-
"--field-border-hover",
|
|
388
|
-
"--field-border-error",
|
|
389
|
-
"--field-border-disabled"
|
|
390
|
-
];
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// src/lib/migrate/modal-create.ts
|
|
394
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
395
|
-
async function migrateModalCreate(cwd, dry) {
|
|
396
|
-
const changes = [];
|
|
397
|
-
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /\.(tsx|jsx)$/.test(f));
|
|
398
|
-
const addRe = /Modal\.Add\s*\(\s*<([A-Za-z_][\w.]*)\s+key=\{Date\.now\(\)\}/;
|
|
399
|
-
for (const file of files) {
|
|
400
|
-
const raw = readFileSync6(file, "utf8");
|
|
401
|
-
if (!addRe.test(raw) && !/Modal\.Add\s*\(/.test(raw))
|
|
402
|
-
continue;
|
|
403
|
-
if (/export\s+default\s+Modal\.Create\s*\(/.test(raw)) {
|
|
404
|
-
if (/Modal\.Add\s*\(/.test(raw)) {
|
|
405
|
-
changes.push({
|
|
406
|
-
file: rel(cwd, file),
|
|
407
|
-
detail: "\u043E\u0441\u0442\u0430\u043B\u0441\u044F Modal.Add \u0440\u044F\u0434\u043E\u043C \u0441 Create \u2014 \u0443\u0431\u0435\u0440\u0438\u0442\u0435 Add \u0432\u0440\u0443\u0447\u043D\u0443\u044E"
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
const simple = /function\s+Screen\b/.test(raw) || /const\s+Screen\s*=/.test(raw) || /function\s+\w+\s*\([^)]*\)\s*\{[\s\S]*Modal\.Main/.test(raw);
|
|
413
|
-
const openWrapper = /(?:const|function)\s+Open\s*=\s*(?:\([^)]*\)|[A-Za-z_]\w*)\s*=>\s*\{?\s*Modal\.Add/;
|
|
414
|
-
if (simple && openWrapper.test(raw) && /export\s+default/.test(raw)) {
|
|
415
|
-
let next = raw;
|
|
416
|
-
next = next.replace(/\n(?:const|function)\s+Open\s*=\s*[\s\S]*?(?=\n(?:const|function|export)\s)/, `
|
|
417
|
-
`);
|
|
418
|
-
next = next.replace(/\n(?:const|function)\s+Icon\s*=\s*[\s\S]*?(?=\n(?:const|function|export)\s)/, `
|
|
419
|
-
`);
|
|
420
|
-
next = next.replace(/\nconst\s+Add\s*=\s*\{[\s\S]*?\};\s*\nexport\s+default\s+Add\s*;?/, `
|
|
421
|
-
export default Modal.Create(Screen);
|
|
422
|
-
`);
|
|
423
|
-
next = next.replace(/export\s+default\s+\{\s*Open\s*,?\s*Icon?\s*,?\s*\}\s*;?/, "export default Modal.Create(Screen);");
|
|
424
|
-
next = next.replace(/export\s+function\s+open\w+\s*\([^)]*\)\s*\{[\s\S]*?Modal\.Add\([\s\S]*?\);\s*\}/, (block) => {
|
|
425
|
-
return `/* TODO: \u0437\u0430\u043C\u0435\u043D\u0438\u0442\u0435 \u0432\u044B\u0437\u043E\u0432\u044B \u043D\u0430 Modal.Open("Module","Name", props) \u0438\u043B\u0438 Create.Open */
|
|
426
|
-
${block}`;
|
|
427
|
-
});
|
|
428
|
-
if (next !== raw && !/Modal\.Add/.test(next)) {
|
|
429
|
-
if (writeIfChanged(file, next, dry) || dry) {
|
|
430
|
-
changes.push({
|
|
431
|
-
file: rel(cwd, file),
|
|
432
|
-
detail: "Modal.Add \u2192 Modal.Create(Screen)"
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
continue;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
const count = (raw.match(/Modal\.Add\s*\(/g) || []).length;
|
|
439
|
-
changes.push({
|
|
440
|
-
file: rel(cwd, file),
|
|
441
|
-
detail: `${count}\xD7 Modal.Add \u2014 \u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430 Modal.Create + Open (\u0441\u043C. Projects/modal/Create)`
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
return changes;
|
|
445
|
-
}
|
|
446
|
-
var init_modal_create = __esm(() => {
|
|
447
|
-
init_walk();
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
// src/lib/migrate/legacy-hacks.ts
|
|
451
|
-
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
452
|
-
import { join as join5 } from "path";
|
|
453
|
-
async function migrateLegacyReactHack(cwd, dry) {
|
|
454
|
-
const changes = [];
|
|
455
|
-
const files = new Set(projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /(^|\/)(main|bootstrap)\.(tsx?|jsx?)$/.test(f)));
|
|
456
|
-
for (const name of ["main.tsx", "main.ts", "src/main.tsx", "src/main.ts"]) {
|
|
457
|
-
const full = join5(cwd, name);
|
|
458
|
-
if (existsSync5(full))
|
|
459
|
-
files.add(full);
|
|
460
|
-
}
|
|
461
|
-
for (const file of files) {
|
|
462
|
-
const raw = readFileSync7(file, "utf8");
|
|
463
|
-
if (!HACK_RE.test(raw))
|
|
464
|
-
continue;
|
|
465
|
-
const next = raw.replace(/\/\*\s*@elcrm\/modal[\s\S]*?\*\/\s*/m, "").replace(/\(globalThis\s+as\s+typeof\s+globalThis\s+&\s+\{\s*React:\s*typeof\s+React\s*\}\)\.React\s*=\s*React\s*;\s*/g, "").replace(/globalThis\.React\s*=\s*React\s*;\s*/g, "");
|
|
466
|
-
if (next === raw) {
|
|
467
|
-
changes.push({
|
|
468
|
-
file: rel(cwd, file),
|
|
469
|
-
detail: "globalThis.React \u2014 \u0443\u0434\u0430\u043B\u0438\u0442\u0435 \u0432\u0440\u0443\u0447\u043D\u0443\u044E \u043F\u043E\u0441\u043B\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F @elcrm/modal"
|
|
470
|
-
});
|
|
471
|
-
continue;
|
|
472
|
-
}
|
|
473
|
-
if (writeIfChanged(file, next, dry) || dry) {
|
|
474
|
-
changes.push({
|
|
475
|
-
file: rel(cwd, file),
|
|
476
|
-
detail: "\u0443\u0434\u0430\u043B\u0451\u043D globalThis.React \u0445\u0430\u043A"
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
return changes;
|
|
481
|
-
}
|
|
482
|
-
var HACK_RE;
|
|
483
|
-
var init_legacy_hacks = __esm(() => {
|
|
484
|
-
init_walk();
|
|
485
|
-
HACK_RE = /\(globalThis\s+as\s+[^)]+\)\.React\s*=\s*React\s*;?|globalThis\.React\s*=\s*React\s*;?/;
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
// src/lib/migrate/form-aliases.ts
|
|
489
|
-
import { readFileSync as readFileSync8 } from "fs";
|
|
490
|
-
function rewrite2(source) {
|
|
491
|
-
let next = source;
|
|
492
|
-
const labels = [];
|
|
493
|
-
for (const [re, repl, label] of REPLACEMENTS) {
|
|
494
|
-
let n = 0;
|
|
495
|
-
next = next.replace(re, () => {
|
|
496
|
-
n++;
|
|
497
|
-
return repl;
|
|
498
|
-
});
|
|
499
|
-
if (n > 0)
|
|
500
|
-
labels.push(`${n}\xD7 ${label}`);
|
|
501
|
-
}
|
|
502
|
-
return { next, labels };
|
|
503
|
-
}
|
|
504
|
-
async function migrateFormAliases(cwd, dry) {
|
|
505
|
-
const changes = [];
|
|
506
|
-
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
507
|
-
for (const file of files) {
|
|
508
|
-
if (file.endsWith(".css"))
|
|
509
|
-
continue;
|
|
510
|
-
const raw = readFileSync8(file, "utf8");
|
|
511
|
-
const { next, labels } = rewrite2(raw);
|
|
512
|
-
if (labels.length === 0)
|
|
513
|
-
continue;
|
|
514
|
-
if (writeIfChanged(file, next, dry) || dry) {
|
|
515
|
-
changes.push({
|
|
516
|
-
file: rel(cwd, file),
|
|
517
|
-
detail: labels.join(", ")
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
return changes;
|
|
522
|
-
}
|
|
523
|
-
var REPLACEMENTS;
|
|
524
|
-
var init_form_aliases = __esm(() => {
|
|
525
|
-
init_walk();
|
|
526
|
-
REPLACEMENTS = [
|
|
527
|
-
[/\bProgressField\b/g, "RangeField", "ProgressField\u2192RangeField"],
|
|
528
|
-
[/\bReadonlyField\b/g, "DisplayField", "ReadonlyField\u2192DisplayField"],
|
|
529
|
-
[/\bOtpField\b/g, "CodeField", "OtpField\u2192CodeField"],
|
|
530
|
-
[/\bSegmentField\b/g, "TabsField", "SegmentField\u2192TabsField"],
|
|
531
|
-
[/\bDragonDropField\b/g, "DragDropField", "DragonDropField\u2192DragDropField"],
|
|
532
|
-
[/\bTProgress\b/g, "TRange", "TProgress\u2192TRange"]
|
|
533
|
-
];
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
// src/lib/migrate/css-decl.ts
|
|
537
|
-
function removeCssDecl(css, name) {
|
|
538
|
-
const re = new RegExp(`\\n?[ \\t]*${name.replace(/-/g, "\\-")}(?![\\w-])\\s*:`, "g");
|
|
539
|
-
let n = 0;
|
|
540
|
-
const ranges = [];
|
|
541
|
-
let m;
|
|
542
|
-
while ((m = re.exec(css)) !== null) {
|
|
543
|
-
const start = m.index;
|
|
544
|
-
let i = m.index + m[0].length;
|
|
545
|
-
let depth = 0;
|
|
546
|
-
while (i < css.length) {
|
|
547
|
-
const ch = css[i];
|
|
548
|
-
if (ch === "(")
|
|
549
|
-
depth++;
|
|
550
|
-
else if (ch === ")")
|
|
551
|
-
depth = Math.max(0, depth - 1);
|
|
552
|
-
else if ((ch === ";" || ch === "}") && depth === 0) {
|
|
553
|
-
if (ch === ";")
|
|
554
|
-
i++;
|
|
555
|
-
break;
|
|
556
|
-
}
|
|
557
|
-
i++;
|
|
558
|
-
}
|
|
559
|
-
let s = start;
|
|
560
|
-
if (s > 0 && css[s - 1] === `
|
|
561
|
-
`)
|
|
562
|
-
s--;
|
|
563
|
-
ranges.push({ start: s, end: i });
|
|
564
|
-
n++;
|
|
565
|
-
}
|
|
566
|
-
if (!ranges.length)
|
|
567
|
-
return { next: css, n: 0 };
|
|
568
|
-
let next = css;
|
|
569
|
-
for (let r = ranges.length - 1;r >= 0; r--) {
|
|
570
|
-
const { start, end } = ranges[r];
|
|
571
|
-
next = next.slice(0, start) + next.slice(end);
|
|
572
|
-
}
|
|
573
|
-
return { next: next.replace(/\n{3,}/g, `
|
|
574
|
-
|
|
575
|
-
`), n };
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// src/lib/migrate/css-sanitize.ts
|
|
579
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
580
|
-
function stripOrphanColorMix(source) {
|
|
581
|
-
let next = source;
|
|
582
|
-
let hits = 0;
|
|
583
|
-
next = next.replace(ORPHAN_MIX_BLOCK_RE, () => {
|
|
584
|
-
hits++;
|
|
585
|
-
return `
|
|
586
|
-
`;
|
|
587
|
-
});
|
|
588
|
-
const lines = next.split(/\r?\n/);
|
|
589
|
-
const kept = [];
|
|
590
|
-
for (const line of lines) {
|
|
591
|
-
if (/^[ \t]*in\s+(?:srgb|hsl|hwb|lab|lch)\s*,?\s*$/i.test(line) || /^[ \t]*transparent\s*\)\s*;?\s*$/i.test(line) || /^[ \t]*var\([^)]+\)\s*\d+%\s*,?\s*$/i.test(line)) {
|
|
592
|
-
const prev = kept[kept.length - 1] ?? "";
|
|
593
|
-
if (!/color-mix\s*\(\s*$/i.test(prev) && !/color-mix\s*\(/i.test(prev)) {
|
|
594
|
-
hits++;
|
|
595
|
-
continue;
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
kept.push(line);
|
|
599
|
-
}
|
|
600
|
-
next = kept.join(`
|
|
601
|
-
`).replace(/\n{3,}/g, `
|
|
602
|
-
|
|
603
|
-
`);
|
|
604
|
-
return { next, hits };
|
|
605
|
-
}
|
|
606
|
-
function lineHasOrphanColorMix(line) {
|
|
607
|
-
const t = line.trim();
|
|
608
|
-
if (!t || t.startsWith("/*") || t.startsWith("*"))
|
|
609
|
-
return false;
|
|
610
|
-
if (/^in\s+(?:srgb|hsl|hwb|lab|lch)\b/i.test(t) && !/color-mix\s*\(/i.test(t)) {
|
|
611
|
-
return true;
|
|
612
|
-
}
|
|
613
|
-
if (/^transparent\s*\)\s*;?\s*$/i.test(t))
|
|
614
|
-
return true;
|
|
615
|
-
return false;
|
|
616
|
-
}
|
|
617
|
-
async function migrateCssSanitize(cwd, dry) {
|
|
618
|
-
const changes = [];
|
|
619
|
-
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => f.endsWith(".css"));
|
|
620
|
-
for (const file of files) {
|
|
621
|
-
const raw = readFileSync9(file, "utf8");
|
|
622
|
-
const { next, hits } = stripOrphanColorMix(raw);
|
|
623
|
-
if (hits === 0 || next === raw)
|
|
624
|
-
continue;
|
|
625
|
-
if (writeIfChanged(file, next, dry) || dry) {
|
|
626
|
-
changes.push({
|
|
627
|
-
file: rel(cwd, file),
|
|
628
|
-
detail: `${hits}\xD7 \u0443\u0434\u0430\u043B\u0435\u043D\u044B \u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0435 color-mix/\u0444\u0440\u0430\u0433\u043C\u0435\u043D\u0442\u044B`
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
return changes;
|
|
633
|
-
}
|
|
634
|
-
var ORPHAN_MIX_BLOCK_RE;
|
|
635
|
-
var init_css_sanitize = __esm(() => {
|
|
636
|
-
init_walk();
|
|
637
|
-
ORPHAN_MIX_BLOCK_RE = /(?:^|\n)[ \t]*(?:in\s+srgb|in\s+hsl|in\s+hwb|in\s+lab|in\s+lch)[\s\S]*?\n[ \t]*\);?[ \t]*(?=\n|$)/gi;
|
|
638
|
-
});
|
|
639
517
|
|
|
640
518
|
// src/lib/migrate/form-tokens.ts
|
|
641
|
-
|
|
519
|
+
var VAR_REPLACEMENTS = [
|
|
520
|
+
[
|
|
521
|
+
/var\(\s*--field-note-padding-top\s*(?:,[^)]+)?\)/gi,
|
|
522
|
+
"var(--field-padding-block)"
|
|
523
|
+
],
|
|
524
|
+
[
|
|
525
|
+
/var\(\s*--field-note-padding\s*(?:,[^)]+)?\)/gi,
|
|
526
|
+
"var(--field-padding-block)"
|
|
527
|
+
],
|
|
528
|
+
[
|
|
529
|
+
/var\(\s*--field-side-padding\s*(?:,[^)]+)?\)/gi,
|
|
530
|
+
"var(--field-padding-inline)"
|
|
531
|
+
],
|
|
532
|
+
[
|
|
533
|
+
/var\(\s*--control-side-padding\s*(?:,[^)]+)?\)/gi,
|
|
534
|
+
"var(--field-padding-inline)"
|
|
535
|
+
],
|
|
536
|
+
[
|
|
537
|
+
/var\(\s*--control-inner-padding\s*(?:,[^)]+)?\)/gi,
|
|
538
|
+
"var(--field-padding)"
|
|
539
|
+
],
|
|
540
|
+
[
|
|
541
|
+
/var\(\s*--date-popup-shadow\s*(?:,[^)]+)?\)/gi,
|
|
542
|
+
"var(--popup-shadow)"
|
|
543
|
+
]
|
|
544
|
+
];
|
|
545
|
+
var DECL_REMOVE = [
|
|
546
|
+
"--field-note-padding-top",
|
|
547
|
+
"--field-note-padding",
|
|
548
|
+
"--control-inner-padding",
|
|
549
|
+
"--control-side-padding",
|
|
550
|
+
"--field-side-padding",
|
|
551
|
+
"--date-popup-shadow"
|
|
552
|
+
];
|
|
642
553
|
function migrateDatePopupShadowDecl(css) {
|
|
643
554
|
let n = 0;
|
|
644
555
|
let next = css;
|
|
@@ -697,6 +608,18 @@ function rewriteFormTokens(source) {
|
|
|
697
608
|
next = rem.next;
|
|
698
609
|
hits += rem.n;
|
|
699
610
|
}
|
|
611
|
+
{
|
|
612
|
+
const names = new Set;
|
|
613
|
+
const re = /--search-[a-z0-9-]+(?=\s*:)/gi;
|
|
614
|
+
let m;
|
|
615
|
+
while (m = re.exec(next))
|
|
616
|
+
names.add(m[0]);
|
|
617
|
+
for (const name of names) {
|
|
618
|
+
const rem = removeCssDecl(next, name);
|
|
619
|
+
next = rem.next;
|
|
620
|
+
hits += rem.n;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
700
623
|
const clean = stripOrphanColorMix(next);
|
|
701
624
|
next = clean.next;
|
|
702
625
|
hits += clean.hits;
|
|
@@ -704,12 +627,12 @@ function rewriteFormTokens(source) {
|
|
|
704
627
|
}
|
|
705
628
|
async function migrateFormTokens(cwd, dry) {
|
|
706
629
|
const pkg = readPackageJson(cwd);
|
|
707
|
-
if (pkg?.name === "@elcrm/form")
|
|
630
|
+
if (pkg?.name === "@elcrm/form" || pkg?.name === "@elcrm/search")
|
|
708
631
|
return [];
|
|
709
632
|
const changes = [];
|
|
710
633
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => f.endsWith(".css"));
|
|
711
634
|
for (const file of files) {
|
|
712
|
-
const raw =
|
|
635
|
+
const raw = readFileSync5(file, "utf8");
|
|
713
636
|
const { next, hits } = rewriteFormTokens(raw);
|
|
714
637
|
if (hits === 0 || next === raw)
|
|
715
638
|
continue;
|
|
@@ -722,10 +645,22 @@ async function migrateFormTokens(cwd, dry) {
|
|
|
722
645
|
}
|
|
723
646
|
return changes;
|
|
724
647
|
}
|
|
648
|
+
var FORM_TOKEN_DEPRECATED = [
|
|
649
|
+
"--field-note-padding",
|
|
650
|
+
"--field-note-padding-top",
|
|
651
|
+
"--control-inner-padding",
|
|
652
|
+
"--control-side-padding",
|
|
653
|
+
"--field-side-padding",
|
|
654
|
+
"--date-popup-shadow"
|
|
655
|
+
];
|
|
656
|
+
var DEPRECATED_VAR_RE = new RegExp(`var\\(\\s*(?:${FORM_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})\\s*`, "i");
|
|
657
|
+
var DEPRECATED_DECL_RE = new RegExp(`(?:${FORM_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})\\s*:`);
|
|
725
658
|
function lineHasDeprecatedFormToken(line) {
|
|
726
659
|
const t = line.trim();
|
|
727
660
|
if (!t || t.startsWith("/*") || t.startsWith("*"))
|
|
728
661
|
return false;
|
|
662
|
+
if (/(?:var\(\s*)?--search-[a-z0-9-]+/.test(t))
|
|
663
|
+
return true;
|
|
729
664
|
if (DEPRECATED_VAR_RE.test(t))
|
|
730
665
|
return true;
|
|
731
666
|
if (!DEPRECATED_DECL_RE.test(t))
|
|
@@ -734,59 +669,186 @@ function lineHasDeprecatedFormToken(line) {
|
|
|
734
669
|
return false;
|
|
735
670
|
return true;
|
|
736
671
|
}
|
|
737
|
-
var VAR_REPLACEMENTS, DECL_REMOVE, FORM_TOKEN_DEPRECATED, DEPRECATED_VAR_RE, DEPRECATED_DECL_RE;
|
|
738
|
-
var init_form_tokens = __esm(() => {
|
|
739
|
-
init_pkg();
|
|
740
|
-
init_walk();
|
|
741
|
-
init_css_sanitize();
|
|
742
|
-
VAR_REPLACEMENTS = [
|
|
743
|
-
[
|
|
744
|
-
/var\(\s*--field-note-padding-top\s*(?:,[^)]+)?\)/gi,
|
|
745
|
-
"var(--field-padding-block)"
|
|
746
|
-
],
|
|
747
|
-
[
|
|
748
|
-
/var\(\s*--field-note-padding\s*(?:,[^)]+)?\)/gi,
|
|
749
|
-
"var(--field-padding-block)"
|
|
750
|
-
],
|
|
751
|
-
[
|
|
752
|
-
/var\(\s*--field-side-padding\s*(?:,[^)]+)?\)/gi,
|
|
753
|
-
"var(--field-padding-inline)"
|
|
754
|
-
],
|
|
755
|
-
[
|
|
756
|
-
/var\(\s*--control-side-padding\s*(?:,[^)]+)?\)/gi,
|
|
757
|
-
"var(--field-padding-inline)"
|
|
758
|
-
],
|
|
759
|
-
[
|
|
760
|
-
/var\(\s*--control-inner-padding\s*(?:,[^)]+)?\)/gi,
|
|
761
|
-
"var(--field-padding)"
|
|
762
|
-
],
|
|
763
|
-
[
|
|
764
|
-
/var\(\s*--date-popup-shadow\s*(?:,[^)]+)?\)/gi,
|
|
765
|
-
"var(--popup-shadow)"
|
|
766
|
-
]
|
|
767
|
-
];
|
|
768
|
-
DECL_REMOVE = [
|
|
769
|
-
"--field-note-padding-top",
|
|
770
|
-
"--field-note-padding",
|
|
771
|
-
"--control-inner-padding",
|
|
772
|
-
"--control-side-padding",
|
|
773
|
-
"--field-side-padding",
|
|
774
|
-
"--date-popup-shadow"
|
|
775
|
-
];
|
|
776
|
-
FORM_TOKEN_DEPRECATED = [
|
|
777
|
-
"--field-note-padding",
|
|
778
|
-
"--field-note-padding-top",
|
|
779
|
-
"--control-inner-padding",
|
|
780
|
-
"--control-side-padding",
|
|
781
|
-
"--field-side-padding",
|
|
782
|
-
"--date-popup-shadow"
|
|
783
|
-
];
|
|
784
|
-
DEPRECATED_VAR_RE = new RegExp(`var\\(\\s*(?:${FORM_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})\\s*`, "i");
|
|
785
|
-
DEPRECATED_DECL_RE = new RegExp(`(?:${FORM_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})\\s*:`);
|
|
786
|
-
});
|
|
787
672
|
|
|
788
673
|
// src/lib/migrate/components.ts
|
|
789
|
-
import { readFileSync as
|
|
674
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
675
|
+
var VAR_REPLACEMENTS2 = [
|
|
676
|
+
[/var\(\s*--layout-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background-muted)"],
|
|
677
|
+
[/var\(\s*--header-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
678
|
+
[/var\(\s*--header-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
679
|
+
[/var\(\s*--header-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
680
|
+
[/var\(\s*--footer-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
681
|
+
[/var\(\s*--footer-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
682
|
+
[/var\(\s*--item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
683
|
+
[/var\(\s*--item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
684
|
+
[/var\(\s*--item-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
685
|
+
[/var\(\s*--item-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
686
|
+
[/var\(\s*--item-color-muted\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
687
|
+
[/var\(\s*--item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
688
|
+
[/var\(\s*--item-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
689
|
+
[/var\(\s*--card-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
690
|
+
[/var\(\s*--card-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
691
|
+
[/var\(\s*--card-shadow\s*(?:,[^)]+)?\)/gi, "var(--shell-shadow)"],
|
|
692
|
+
[/var\(\s*--card-padding\s*(?:,[^)]+)?\)/gi, "var(--shell-padding)"],
|
|
693
|
+
[/var\(\s*--menu-item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
694
|
+
[/var\(\s*--menu-item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
695
|
+
[/var\(\s*--menu-item-color-active\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
696
|
+
[/var\(\s*--menu-item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
697
|
+
[/var\(\s*--loading-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
698
|
+
[/var\(\s*--section-title-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
699
|
+
[/var\(\s*--section-description-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
700
|
+
[/var\(\s*--section-auth-card-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
701
|
+
[/var\(\s*--section-auth-card-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
702
|
+
[/var\(\s*--section-auth-card-shadow\s*(?:,[^)]+)?\)/gi, "var(--shell-shadow)"],
|
|
703
|
+
[/var\(\s*--section-block-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
704
|
+
[/var\(\s*--nav-sections-label-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
705
|
+
[/var\(\s*--nav-sections-item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
706
|
+
[/var\(\s*--nav-sections-item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
707
|
+
[/var\(\s*--nav-sections-item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
708
|
+
[/var\(\s*--nav-sections-accent\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
709
|
+
[/var\(\s*--nav-sections-icon-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
710
|
+
[/var\(\s*--nav-sections-group-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
711
|
+
[/var\(\s*--nav-sections-footer-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
712
|
+
[/var\(\s*--tab-sections-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
713
|
+
[/var\(\s*--tab-sections-color-active\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
714
|
+
[/var\(\s*--tab-sections-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
715
|
+
[/var\(\s*--tab-sections-accent\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
716
|
+
[/var\(\s*--tab-sections-badge-background\s*(?:,[^)]+)?\)/gi, "var(--shell-color-danger)"],
|
|
717
|
+
[/var\(\s*--brand-color-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
718
|
+
[/var\(\s*--brand-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
719
|
+
[/var\(\s*--badge-neutral-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
720
|
+
[/var\(\s*--badge-accent-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
721
|
+
[/var\(\s*--badge-success-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-success)"],
|
|
722
|
+
[/var\(\s*--badge-danger-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-danger)"],
|
|
723
|
+
[/var\(\s*--list-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap-sm)"],
|
|
724
|
+
[/var\(\s*--item-padding\s*(?:,[^)]+)?\)/gi, "var(--shell-padding)"],
|
|
725
|
+
[/var\(\s*--item-radius\s*(?:,[^)]+)?\)/gi, "var(--shell-radius)"],
|
|
726
|
+
[/var\(\s*--block-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
727
|
+
[/var\(\s*--row-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
728
|
+
[/var\(\s*--column-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
729
|
+
[/var\(\s*--page-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
730
|
+
[/var\(\s*--page-pad\s*(?:,[^)]+)?\)/gi, "var(--shell-padding)"],
|
|
731
|
+
[/var\(\s*--page-pad-x\s*(?:,[^)]+)?\)/gi, "var(--shell-padding-inline)"],
|
|
732
|
+
[/var\(\s*--page-pad-y\s*(?:,[^)]+)?\)/gi, "var(--shell-padding-block)"],
|
|
733
|
+
[/var\(\s*--card-radius\s*(?:,[^)]+)?\)/gi, "var(--shell-radius)"],
|
|
734
|
+
[/var\(\s*--section-description-size\s*(?:,[^)]+)?\)/gi, "0.95rem"],
|
|
735
|
+
[/var\(\s*--section-title-size\s*(?:,[^)]+)?\)/gi, "1.5rem"]
|
|
736
|
+
];
|
|
737
|
+
var COMPONENTS_TOKEN_DEPRECATED = [
|
|
738
|
+
"--layout-background",
|
|
739
|
+
"--layout-min-height",
|
|
740
|
+
"--layout-gap",
|
|
741
|
+
"--header-background",
|
|
742
|
+
"--header-color",
|
|
743
|
+
"--header-border",
|
|
744
|
+
"--header-padding",
|
|
745
|
+
"--header-gap",
|
|
746
|
+
"--footer-background",
|
|
747
|
+
"--footer-color",
|
|
748
|
+
"--footer-border",
|
|
749
|
+
"--footer-padding",
|
|
750
|
+
"--footer-font-size",
|
|
751
|
+
"--list-gap",
|
|
752
|
+
"--list-padding",
|
|
753
|
+
"--item-background",
|
|
754
|
+
"--item-background-hover",
|
|
755
|
+
"--item-background-active",
|
|
756
|
+
"--item-color",
|
|
757
|
+
"--item-color-muted",
|
|
758
|
+
"--item-border",
|
|
759
|
+
"--item-radius",
|
|
760
|
+
"--item-padding",
|
|
761
|
+
"--item-gap",
|
|
762
|
+
"--card-background",
|
|
763
|
+
"--card-border",
|
|
764
|
+
"--card-shadow",
|
|
765
|
+
"--card-radius",
|
|
766
|
+
"--card-padding",
|
|
767
|
+
"--block-gap",
|
|
768
|
+
"--block-padding",
|
|
769
|
+
"--row-gap",
|
|
770
|
+
"--column-gap",
|
|
771
|
+
"--menu-gap",
|
|
772
|
+
"--menu-item-radius",
|
|
773
|
+
"--menu-item-padding",
|
|
774
|
+
"--menu-item-background",
|
|
775
|
+
"--menu-item-background-hover",
|
|
776
|
+
"--menu-item-background-active",
|
|
777
|
+
"--menu-item-color",
|
|
778
|
+
"--menu-item-color-active",
|
|
779
|
+
"--loading-padding",
|
|
780
|
+
"--loading-color",
|
|
781
|
+
"--section-gap",
|
|
782
|
+
"--section-description-size",
|
|
783
|
+
"--section-icon-gap",
|
|
784
|
+
"--section-body-gap",
|
|
785
|
+
"--section-actions-gap",
|
|
786
|
+
"--section-auth-padding",
|
|
787
|
+
"--section-auth-card-padding",
|
|
788
|
+
"--section-auth-card-radius",
|
|
789
|
+
"--section-block-padding-bottom",
|
|
790
|
+
"--section-block-margin-bottom",
|
|
791
|
+
"--section-title-color",
|
|
792
|
+
"--section-description-color",
|
|
793
|
+
"--section-auth-card-background",
|
|
794
|
+
"--section-auth-card-border",
|
|
795
|
+
"--section-auth-card-shadow",
|
|
796
|
+
"--section-block-border",
|
|
797
|
+
"--nav-sections-gap",
|
|
798
|
+
"--nav-sections-item-radius",
|
|
799
|
+
"--nav-sections-item-padding",
|
|
800
|
+
"--nav-sections-label-color",
|
|
801
|
+
"--nav-sections-item-color",
|
|
802
|
+
"--nav-sections-item-background-hover",
|
|
803
|
+
"--nav-sections-item-background-active",
|
|
804
|
+
"--nav-sections-accent",
|
|
805
|
+
"--nav-sections-icon-color",
|
|
806
|
+
"--nav-sections-group-border",
|
|
807
|
+
"--nav-sections-footer-border",
|
|
808
|
+
"--tab-sections-gap",
|
|
809
|
+
"--tab-sections-tab-padding",
|
|
810
|
+
"--tab-sections-tab-gap",
|
|
811
|
+
"--tab-sections-badge-size",
|
|
812
|
+
"--tab-sections-border",
|
|
813
|
+
"--tab-sections-color",
|
|
814
|
+
"--tab-sections-color-active",
|
|
815
|
+
"--tab-sections-accent",
|
|
816
|
+
"--tab-sections-badge-background",
|
|
817
|
+
"--tab-sections-badge-color",
|
|
818
|
+
"--badge-padding",
|
|
819
|
+
"--badge-radius",
|
|
820
|
+
"--badge-font-size",
|
|
821
|
+
"--badge-font-weight",
|
|
822
|
+
"--badge-border",
|
|
823
|
+
"--badge-neutral-background",
|
|
824
|
+
"--badge-neutral-color",
|
|
825
|
+
"--badge-accent-background",
|
|
826
|
+
"--badge-accent-color",
|
|
827
|
+
"--badge-success-background",
|
|
828
|
+
"--badge-success-color",
|
|
829
|
+
"--badge-warning-background",
|
|
830
|
+
"--badge-warning-color",
|
|
831
|
+
"--badge-danger-background",
|
|
832
|
+
"--badge-danger-color",
|
|
833
|
+
"--brand-font-weight",
|
|
834
|
+
"--brand-letter-spacing",
|
|
835
|
+
"--brand-color",
|
|
836
|
+
"--brand-color-hover",
|
|
837
|
+
"--empty-state-gap",
|
|
838
|
+
"--empty-state-padding",
|
|
839
|
+
"--empty-state-icon-gap",
|
|
840
|
+
"--empty-state-title-size",
|
|
841
|
+
"--empty-state-description-size",
|
|
842
|
+
"--empty-state-max-width",
|
|
843
|
+
"--empty-state-actions-gap",
|
|
844
|
+
"--empty-state-actions-margin-top",
|
|
845
|
+
"--radio-group-gap",
|
|
846
|
+
"--page-pad",
|
|
847
|
+
"--page-pad-x",
|
|
848
|
+
"--page-pad-y",
|
|
849
|
+
"--page-gap",
|
|
850
|
+
"--card-radius"
|
|
851
|
+
];
|
|
790
852
|
function rewriteComponentsCss(source) {
|
|
791
853
|
let next = source;
|
|
792
854
|
let hits = 0;
|
|
@@ -806,7 +868,7 @@ function rewriteComponentsCss(source) {
|
|
|
806
868
|
}
|
|
807
869
|
return { next, hits };
|
|
808
870
|
}
|
|
809
|
-
function
|
|
871
|
+
function rewriteImports(source) {
|
|
810
872
|
let hits = 0;
|
|
811
873
|
let next = source;
|
|
812
874
|
const replaceImportList = (list) => {
|
|
@@ -928,7 +990,7 @@ function rewriteItemKeys(source) {
|
|
|
928
990
|
function rewriteComponentsTsx(source) {
|
|
929
991
|
let hits = 0;
|
|
930
992
|
let next = source;
|
|
931
|
-
const imp =
|
|
993
|
+
const imp = rewriteImports(next);
|
|
932
994
|
next = imp.next;
|
|
933
995
|
hits += imp.hits;
|
|
934
996
|
const jsx = rewriteJsx(next);
|
|
@@ -952,7 +1014,7 @@ async function migrateComponents(cwd, dry) {
|
|
|
952
1014
|
const changes = [];
|
|
953
1015
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
954
1016
|
for (const file of files) {
|
|
955
|
-
const raw =
|
|
1017
|
+
const raw = readFileSync6(file, "utf8");
|
|
956
1018
|
let next = raw;
|
|
957
1019
|
let hits = 0;
|
|
958
1020
|
if (file.endsWith(".css")) {
|
|
@@ -978,6 +1040,8 @@ async function migrateComponents(cwd, dry) {
|
|
|
978
1040
|
}
|
|
979
1041
|
return changes;
|
|
980
1042
|
}
|
|
1043
|
+
var DEPRECATED_VAR_RE2 = new RegExp(`var\\(\\s*(?:${COMPONENTS_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})(?![\\w-])`, "i");
|
|
1044
|
+
var DEPRECATED_DECL_RE2 = new RegExp(`(?:${COMPONENTS_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})(?![\\w-])\\s*:`);
|
|
981
1045
|
function lineHasDeprecatedComponentsToken(line) {
|
|
982
1046
|
const t = line.trim();
|
|
983
1047
|
if (!t || t.startsWith("/*") || t.startsWith("*"))
|
|
@@ -990,407 +1054,8 @@ function lineHasDeprecatedComponentsToken(line) {
|
|
|
990
1054
|
return false;
|
|
991
1055
|
return true;
|
|
992
1056
|
}
|
|
993
|
-
var VAR_REPLACEMENTS2, COMPONENTS_TOKEN_DEPRECATED, DEPRECATED_VAR_RE2, DEPRECATED_DECL_RE2;
|
|
994
|
-
var init_components = __esm(() => {
|
|
995
|
-
init_pkg();
|
|
996
|
-
init_walk();
|
|
997
|
-
init_css_sanitize();
|
|
998
|
-
VAR_REPLACEMENTS2 = [
|
|
999
|
-
[/var\(\s*--layout-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background-muted)"],
|
|
1000
|
-
[/var\(\s*--header-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
1001
|
-
[/var\(\s*--header-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1002
|
-
[/var\(\s*--header-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1003
|
-
[/var\(\s*--footer-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1004
|
-
[/var\(\s*--footer-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1005
|
-
[/var\(\s*--item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
1006
|
-
[/var\(\s*--item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
1007
|
-
[/var\(\s*--item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1008
|
-
[/var\(\s*--card-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
1009
|
-
[/var\(\s*--card-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1010
|
-
[/var\(\s*--card-shadow\s*(?:,[^)]+)?\)/gi, "var(--shell-shadow)"],
|
|
1011
|
-
[/var\(\s*--menu-item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
1012
|
-
[/var\(\s*--menu-item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
1013
|
-
[/var\(\s*--menu-item-color-active\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1014
|
-
[/var\(\s*--menu-item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1015
|
-
[/var\(\s*--loading-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1016
|
-
[/var\(\s*--section-title-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1017
|
-
[/var\(\s*--section-description-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1018
|
-
[/var\(\s*--section-auth-card-background\s*(?:,[^)]+)?\)/gi, "var(--shell-background)"],
|
|
1019
|
-
[/var\(\s*--section-auth-card-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1020
|
-
[/var\(\s*--section-auth-card-shadow\s*(?:,[^)]+)?\)/gi, "var(--shell-shadow)"],
|
|
1021
|
-
[/var\(\s*--section-block-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1022
|
-
[/var\(\s*--nav-sections-label-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1023
|
-
[/var\(\s*--nav-sections-item-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1024
|
-
[/var\(\s*--nav-sections-item-background-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-background-hover)"],
|
|
1025
|
-
[/var\(\s*--nav-sections-item-background-active\s*(?:,[^)]+)?\)/gi, "var(--shell-background-selected)"],
|
|
1026
|
-
[/var\(\s*--nav-sections-accent\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
1027
|
-
[/var\(\s*--nav-sections-icon-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1028
|
-
[/var\(\s*--nav-sections-group-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1029
|
-
[/var\(\s*--nav-sections-footer-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1030
|
-
[/var\(\s*--tab-sections-border\s*(?:,[^)]+)?\)/gi, "var(--shell-border)"],
|
|
1031
|
-
[/var\(\s*--tab-sections-color-active\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1032
|
-
[/var\(\s*--tab-sections-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-muted)"],
|
|
1033
|
-
[/var\(\s*--tab-sections-accent\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1034
|
-
[/var\(\s*--tab-sections-badge-background\s*(?:,[^)]+)?\)/gi, "var(--shell-color-danger)"],
|
|
1035
|
-
[/var\(\s*--brand-color-hover\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
1036
|
-
[/var\(\s*--brand-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1037
|
-
[/var\(\s*--badge-neutral-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color)"],
|
|
1038
|
-
[/var\(\s*--badge-accent-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-accent)"],
|
|
1039
|
-
[/var\(\s*--badge-success-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-success)"],
|
|
1040
|
-
[/var\(\s*--badge-danger-color\s*(?:,[^)]+)?\)/gi, "var(--shell-color-danger)"],
|
|
1041
|
-
[/var\(\s*--list-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap-sm)"],
|
|
1042
|
-
[/var\(\s*--item-padding\s*(?:,[^)]+)?\)/gi, "var(--shell-padding)"],
|
|
1043
|
-
[/var\(\s*--item-radius\s*(?:,[^)]+)?\)/gi, "var(--shell-radius)"],
|
|
1044
|
-
[/var\(\s*--block-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
1045
|
-
[/var\(\s*--row-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
1046
|
-
[/var\(\s*--column-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
1047
|
-
[/var\(\s*--page-gap\s*(?:,[^)]+)?\)/gi, "var(--shell-gap)"],
|
|
1048
|
-
[/var\(\s*--page-pad\s*(?:,[^)]+)?\)/gi, "var(--shell-padding)"],
|
|
1049
|
-
[/var\(\s*--page-pad-x\s*(?:,[^)]+)?\)/gi, "var(--shell-padding-inline)"],
|
|
1050
|
-
[/var\(\s*--page-pad-y\s*(?:,[^)]+)?\)/gi, "var(--shell-padding-block)"],
|
|
1051
|
-
[/var\(\s*--card-radius\s*(?:,[^)]+)?\)/gi, "var(--shell-radius)"],
|
|
1052
|
-
[/var\(\s*--section-description-size\s*(?:,[^)]+)?\)/gi, "0.95rem"],
|
|
1053
|
-
[/var\(\s*--section-title-size\s*(?:,[^)]+)?\)/gi, "1.5rem"]
|
|
1054
|
-
];
|
|
1055
|
-
COMPONENTS_TOKEN_DEPRECATED = [
|
|
1056
|
-
"--layout-background",
|
|
1057
|
-
"--layout-min-height",
|
|
1058
|
-
"--layout-gap",
|
|
1059
|
-
"--header-background",
|
|
1060
|
-
"--header-color",
|
|
1061
|
-
"--header-border",
|
|
1062
|
-
"--header-padding",
|
|
1063
|
-
"--header-gap",
|
|
1064
|
-
"--footer-background",
|
|
1065
|
-
"--footer-color",
|
|
1066
|
-
"--footer-border",
|
|
1067
|
-
"--footer-padding",
|
|
1068
|
-
"--footer-font-size",
|
|
1069
|
-
"--list-gap",
|
|
1070
|
-
"--list-padding",
|
|
1071
|
-
"--item-background",
|
|
1072
|
-
"--item-background-hover",
|
|
1073
|
-
"--item-background-active",
|
|
1074
|
-
"--item-color",
|
|
1075
|
-
"--item-color-muted",
|
|
1076
|
-
"--item-border",
|
|
1077
|
-
"--item-radius",
|
|
1078
|
-
"--item-padding",
|
|
1079
|
-
"--item-gap",
|
|
1080
|
-
"--card-background",
|
|
1081
|
-
"--card-border",
|
|
1082
|
-
"--card-shadow",
|
|
1083
|
-
"--card-radius",
|
|
1084
|
-
"--card-padding",
|
|
1085
|
-
"--block-gap",
|
|
1086
|
-
"--block-padding",
|
|
1087
|
-
"--row-gap",
|
|
1088
|
-
"--column-gap",
|
|
1089
|
-
"--menu-gap",
|
|
1090
|
-
"--menu-item-radius",
|
|
1091
|
-
"--menu-item-padding",
|
|
1092
|
-
"--menu-item-background",
|
|
1093
|
-
"--menu-item-background-hover",
|
|
1094
|
-
"--menu-item-background-active",
|
|
1095
|
-
"--menu-item-color",
|
|
1096
|
-
"--menu-item-color-active",
|
|
1097
|
-
"--loading-padding",
|
|
1098
|
-
"--loading-color",
|
|
1099
|
-
"--section-gap",
|
|
1100
|
-
"--section-description-size",
|
|
1101
|
-
"--section-icon-gap",
|
|
1102
|
-
"--section-body-gap",
|
|
1103
|
-
"--section-actions-gap",
|
|
1104
|
-
"--section-auth-padding",
|
|
1105
|
-
"--section-auth-card-padding",
|
|
1106
|
-
"--section-auth-card-radius",
|
|
1107
|
-
"--section-block-padding-bottom",
|
|
1108
|
-
"--section-block-margin-bottom",
|
|
1109
|
-
"--section-title-color",
|
|
1110
|
-
"--section-description-color",
|
|
1111
|
-
"--section-auth-card-background",
|
|
1112
|
-
"--section-auth-card-border",
|
|
1113
|
-
"--section-auth-card-shadow",
|
|
1114
|
-
"--section-block-border",
|
|
1115
|
-
"--nav-sections-gap",
|
|
1116
|
-
"--nav-sections-item-radius",
|
|
1117
|
-
"--nav-sections-item-padding",
|
|
1118
|
-
"--nav-sections-label-color",
|
|
1119
|
-
"--nav-sections-item-color",
|
|
1120
|
-
"--nav-sections-item-background-hover",
|
|
1121
|
-
"--nav-sections-item-background-active",
|
|
1122
|
-
"--nav-sections-accent",
|
|
1123
|
-
"--nav-sections-icon-color",
|
|
1124
|
-
"--nav-sections-group-border",
|
|
1125
|
-
"--nav-sections-footer-border",
|
|
1126
|
-
"--tab-sections-gap",
|
|
1127
|
-
"--tab-sections-tab-padding",
|
|
1128
|
-
"--tab-sections-tab-gap",
|
|
1129
|
-
"--tab-sections-badge-size",
|
|
1130
|
-
"--tab-sections-border",
|
|
1131
|
-
"--tab-sections-color",
|
|
1132
|
-
"--tab-sections-color-active",
|
|
1133
|
-
"--tab-sections-accent",
|
|
1134
|
-
"--tab-sections-badge-background",
|
|
1135
|
-
"--tab-sections-badge-color",
|
|
1136
|
-
"--badge-padding",
|
|
1137
|
-
"--badge-radius",
|
|
1138
|
-
"--badge-font-size",
|
|
1139
|
-
"--badge-font-weight",
|
|
1140
|
-
"--badge-border",
|
|
1141
|
-
"--badge-neutral-background",
|
|
1142
|
-
"--badge-neutral-color",
|
|
1143
|
-
"--badge-accent-background",
|
|
1144
|
-
"--badge-accent-color",
|
|
1145
|
-
"--badge-success-background",
|
|
1146
|
-
"--badge-success-color",
|
|
1147
|
-
"--badge-warning-background",
|
|
1148
|
-
"--badge-warning-color",
|
|
1149
|
-
"--badge-danger-background",
|
|
1150
|
-
"--badge-danger-color",
|
|
1151
|
-
"--brand-font-weight",
|
|
1152
|
-
"--brand-letter-spacing",
|
|
1153
|
-
"--brand-color",
|
|
1154
|
-
"--brand-color-hover",
|
|
1155
|
-
"--empty-state-gap",
|
|
1156
|
-
"--empty-state-padding",
|
|
1157
|
-
"--empty-state-icon-gap",
|
|
1158
|
-
"--empty-state-title-size",
|
|
1159
|
-
"--empty-state-description-size",
|
|
1160
|
-
"--empty-state-max-width",
|
|
1161
|
-
"--empty-state-actions-gap",
|
|
1162
|
-
"--empty-state-actions-margin-top",
|
|
1163
|
-
"--radio-group-gap",
|
|
1164
|
-
"--page-pad",
|
|
1165
|
-
"--page-pad-x",
|
|
1166
|
-
"--page-pad-y",
|
|
1167
|
-
"--page-gap",
|
|
1168
|
-
"--card-radius"
|
|
1169
|
-
];
|
|
1170
|
-
DEPRECATED_VAR_RE2 = new RegExp(`var\\(\\s*(?:${COMPONENTS_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})(?![\\w-])`, "i");
|
|
1171
|
-
DEPRECATED_DECL_RE2 = new RegExp(`(?:${COMPONENTS_TOKEN_DEPRECATED.map((n) => n.replace(/-/g, "\\-")).join("|")})(?![\\w-])\\s*:`);
|
|
1172
|
-
});
|
|
1173
|
-
|
|
1174
|
-
// src/lib/migrate/front.ts
|
|
1175
|
-
var exports_front = {};
|
|
1176
|
-
__export(exports_front, {
|
|
1177
|
-
migrateFrontAll: () => migrateFrontAll,
|
|
1178
|
-
FRONT_MIGRATIONS: () => FRONT_MIGRATIONS,
|
|
1179
|
-
FRONT_MIGRATE_ORDER: () => FRONT_MIGRATE_ORDER
|
|
1180
|
-
});
|
|
1181
|
-
async function migrateFrontAll(cwd, dry) {
|
|
1182
|
-
const all = [];
|
|
1183
|
-
for (const name of FRONT_MIGRATE_ORDER) {
|
|
1184
|
-
const part = await FRONT_MIGRATIONS[name](cwd, dry);
|
|
1185
|
-
for (const c2 of part) {
|
|
1186
|
-
all.push({ file: c2.file, detail: `[${name}] ${c2.detail}` });
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
return all;
|
|
1190
|
-
}
|
|
1191
|
-
var FRONT_MIGRATIONS, FRONT_MIGRATE_ORDER;
|
|
1192
|
-
var init_front = __esm(() => {
|
|
1193
|
-
init_socket_server();
|
|
1194
|
-
init_size_sml();
|
|
1195
|
-
init_field_border();
|
|
1196
|
-
init_modal_create();
|
|
1197
|
-
init_legacy_hacks();
|
|
1198
|
-
init_form_aliases();
|
|
1199
|
-
init_form_tokens();
|
|
1200
|
-
init_components();
|
|
1201
|
-
init_css_sanitize();
|
|
1202
|
-
FRONT_MIGRATIONS = {
|
|
1203
|
-
"size-sml": migrateSizeSml,
|
|
1204
|
-
"field-border": migrateFieldBorder,
|
|
1205
|
-
"modal-create": migrateModalCreate,
|
|
1206
|
-
"form-aliases": migrateFormAliases,
|
|
1207
|
-
"form-tokens": migrateFormTokens,
|
|
1208
|
-
components: migrateComponents,
|
|
1209
|
-
"css-sanitize": migrateCssSanitize,
|
|
1210
|
-
"legacy-hacks": migrateLegacyReactHack,
|
|
1211
|
-
"socket-server": migrateSocketServer
|
|
1212
|
-
};
|
|
1213
|
-
FRONT_MIGRATE_ORDER = [
|
|
1214
|
-
"form-aliases",
|
|
1215
|
-
"form-tokens",
|
|
1216
|
-
"components",
|
|
1217
|
-
"css-sanitize",
|
|
1218
|
-
"size-sml",
|
|
1219
|
-
"field-border",
|
|
1220
|
-
"modal-create",
|
|
1221
|
-
"socket-server"
|
|
1222
|
-
];
|
|
1223
|
-
});
|
|
1224
|
-
|
|
1225
|
-
// src/index.ts
|
|
1226
|
-
import { readFileSync as readFileSync21 } from "fs";
|
|
1227
|
-
import { dirname as dirname4, join as join18 } from "path";
|
|
1228
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1229
|
-
|
|
1230
|
-
// src/parseArgs.ts
|
|
1231
|
-
function parseArgs(argv = process.argv.slice(2)) {
|
|
1232
|
-
const options = {};
|
|
1233
|
-
const flags = [];
|
|
1234
|
-
const positionals = [];
|
|
1235
|
-
for (let i = 0;i < argv.length; i++) {
|
|
1236
|
-
const arg = argv[i];
|
|
1237
|
-
if (arg === "--") {
|
|
1238
|
-
positionals.push(...argv.slice(i + 1));
|
|
1239
|
-
break;
|
|
1240
|
-
}
|
|
1241
|
-
if (arg.startsWith("--")) {
|
|
1242
|
-
const body = arg.slice(2);
|
|
1243
|
-
if (body.includes("=")) {
|
|
1244
|
-
const eq = body.indexOf("=");
|
|
1245
|
-
const key = body.slice(0, eq);
|
|
1246
|
-
const value = body.slice(eq + 1);
|
|
1247
|
-
if (key)
|
|
1248
|
-
options[key] = value;
|
|
1249
|
-
continue;
|
|
1250
|
-
}
|
|
1251
|
-
const next = argv[i + 1];
|
|
1252
|
-
if (next && !next.startsWith("-")) {
|
|
1253
|
-
const valueOpts = new Set([
|
|
1254
|
-
"template",
|
|
1255
|
-
"url",
|
|
1256
|
-
"name",
|
|
1257
|
-
"dir",
|
|
1258
|
-
"folder",
|
|
1259
|
-
"out"
|
|
1260
|
-
]);
|
|
1261
|
-
if (valueOpts.has(body)) {
|
|
1262
|
-
options[body] = next;
|
|
1263
|
-
i++;
|
|
1264
|
-
continue;
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
if (body && !flags.includes(body))
|
|
1268
|
-
flags.push(body);
|
|
1269
|
-
continue;
|
|
1270
|
-
}
|
|
1271
|
-
if (arg.startsWith("-") && arg.length > 1) {
|
|
1272
|
-
const short = arg.slice(1);
|
|
1273
|
-
if (short === "t" && argv[i + 1] && !argv[i + 1].startsWith("-")) {
|
|
1274
|
-
options.template = argv[i + 1];
|
|
1275
|
-
i++;
|
|
1276
|
-
continue;
|
|
1277
|
-
}
|
|
1278
|
-
if (short && !flags.includes(short))
|
|
1279
|
-
flags.push(short);
|
|
1280
|
-
continue;
|
|
1281
|
-
}
|
|
1282
|
-
positionals.push(arg);
|
|
1283
|
-
}
|
|
1284
|
-
const [command = "", ...rest] = positionals;
|
|
1285
|
-
return {
|
|
1286
|
-
command,
|
|
1287
|
-
positionals: rest,
|
|
1288
|
-
options,
|
|
1289
|
-
flags
|
|
1290
|
-
};
|
|
1291
|
-
}
|
|
1292
|
-
function hasFlag(parsed, ...names) {
|
|
1293
|
-
return names.some((n) => parsed.flags.includes(n));
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
// src/lib/elcrmDeps.ts
|
|
1297
|
-
var SECTIONS = [
|
|
1298
|
-
"dependencies",
|
|
1299
|
-
"devDependencies",
|
|
1300
|
-
"peerDependencies"
|
|
1301
|
-
];
|
|
1302
|
-
function listElcrmDeps(pkg) {
|
|
1303
|
-
const out = [];
|
|
1304
|
-
for (const section of SECTIONS) {
|
|
1305
|
-
const map = pkg[section];
|
|
1306
|
-
if (!map || typeof map !== "object")
|
|
1307
|
-
continue;
|
|
1308
|
-
for (const [name, version] of Object.entries(map)) {
|
|
1309
|
-
if (name.startsWith("@elcrm/") && typeof version === "string") {
|
|
1310
|
-
out.push({ name, version, section });
|
|
1311
|
-
}
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
return out;
|
|
1315
|
-
}
|
|
1316
|
-
function uniqueElcrmNames(deps) {
|
|
1317
|
-
return [...new Set(deps.map((d) => d.name))].sort();
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
// src/commands/update.ts
|
|
1321
|
-
init_latest();
|
|
1322
|
-
|
|
1323
|
-
// src/lib/install.ts
|
|
1324
|
-
import { existsSync } from "fs";
|
|
1325
|
-
import { join } from "path";
|
|
1326
|
-
import { spawnSync } from "child_process";
|
|
1327
|
-
function detectPackageManager(cwd = process.cwd()) {
|
|
1328
|
-
if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock"))) {
|
|
1329
|
-
return "bun";
|
|
1330
|
-
}
|
|
1331
|
-
const bun = spawnSync("bun", ["--version"], { encoding: "utf8" });
|
|
1332
|
-
if (bun.status === 0)
|
|
1333
|
-
return "bun";
|
|
1334
|
-
return "npm";
|
|
1335
|
-
}
|
|
1336
|
-
function installDeps(cwd = process.cwd()) {
|
|
1337
|
-
const pm = detectPackageManager(cwd);
|
|
1338
|
-
console.log(`\u0423\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043C\u043E\u0441\u0442\u0435\u0439 (${pm} install)\u2026`);
|
|
1339
|
-
const r = spawnSync(pm, ["install"], {
|
|
1340
|
-
cwd,
|
|
1341
|
-
stdio: "inherit",
|
|
1342
|
-
env: process.env
|
|
1343
|
-
});
|
|
1344
|
-
return r.status === 0;
|
|
1345
|
-
}
|
|
1346
|
-
function installGlobalElcrm() {
|
|
1347
|
-
const bun = spawnSync("bun", ["--version"], { encoding: "utf8" });
|
|
1348
|
-
const cmd = bun.status === 0 ? "bun" : "npm";
|
|
1349
|
-
const args = ["i", "-g", "elcrm@latest"];
|
|
1350
|
-
console.log(`CLI: ${cmd} ${args.join(" ")}`);
|
|
1351
|
-
const r = spawnSync(cmd, args, {
|
|
1352
|
-
stdio: "inherit",
|
|
1353
|
-
env: process.env
|
|
1354
|
-
});
|
|
1355
|
-
return r.status === 0;
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
// src/commands/update.ts
|
|
1359
|
-
init_pkg();
|
|
1360
|
-
|
|
1361
|
-
// src/lib/ansi.ts
|
|
1362
|
-
var enabled = process.env.NO_COLOR == null && process.env.FORCE_COLOR !== "0" && Boolean(process.stdout.isTTY);
|
|
1363
|
-
function wrap(code, text) {
|
|
1364
|
-
if (!enabled)
|
|
1365
|
-
return text;
|
|
1366
|
-
return `\x1B[${code}m${text}\x1B[0m`;
|
|
1367
|
-
}
|
|
1368
|
-
var c = {
|
|
1369
|
-
gray: (t) => wrap("90", t),
|
|
1370
|
-
green: (t) => wrap("32", t),
|
|
1371
|
-
blue: (t) => wrap("34", t),
|
|
1372
|
-
yellow: (t) => wrap("33", t),
|
|
1373
|
-
red: (t) => wrap("31", t),
|
|
1374
|
-
cyan: (t) => wrap("36", t),
|
|
1375
|
-
dim: (t) => wrap("2", t)
|
|
1376
|
-
};
|
|
1377
|
-
|
|
1378
|
-
// src/commands/update.ts
|
|
1379
|
-
init_front();
|
|
1380
|
-
init_css_sanitize();
|
|
1381
1057
|
|
|
1382
1058
|
// src/lib/cssSync.ts
|
|
1383
|
-
init_form_tokens();
|
|
1384
|
-
init_components();
|
|
1385
|
-
import {
|
|
1386
|
-
existsSync as existsSync6,
|
|
1387
|
-
readdirSync as readdirSync3,
|
|
1388
|
-
readFileSync as readFileSync12,
|
|
1389
|
-
statSync as statSync3,
|
|
1390
|
-
writeFileSync as writeFileSync4
|
|
1391
|
-
} from "fs";
|
|
1392
|
-
import { createRequire } from "module";
|
|
1393
|
-
import { dirname, join as join6 } from "path";
|
|
1394
1059
|
var TOKEN_DEPRECATED = new Set([
|
|
1395
1060
|
...FORM_TOKEN_DEPRECATED,
|
|
1396
1061
|
...COMPONENTS_TOKEN_DEPRECATED
|
|
@@ -1483,12 +1148,12 @@ function isColorToken(name, value) {
|
|
|
1483
1148
|
return false;
|
|
1484
1149
|
}
|
|
1485
1150
|
function listCssFiles(dir, acc = []) {
|
|
1486
|
-
if (!
|
|
1151
|
+
if (!existsSync5(dir))
|
|
1487
1152
|
return acc;
|
|
1488
1153
|
for (const name of readdirSync3(dir)) {
|
|
1489
1154
|
if (name === "node_modules")
|
|
1490
1155
|
continue;
|
|
1491
|
-
const full =
|
|
1156
|
+
const full = join5(dir, name);
|
|
1492
1157
|
let st;
|
|
1493
1158
|
try {
|
|
1494
1159
|
st = statSync3(full);
|
|
@@ -1504,17 +1169,17 @@ function listCssFiles(dir, acc = []) {
|
|
|
1504
1169
|
}
|
|
1505
1170
|
function resolvePkgRoot(pkgName, cwd) {
|
|
1506
1171
|
try {
|
|
1507
|
-
const req = createRequire(
|
|
1172
|
+
const req = createRequire(join5(cwd, "package.json"));
|
|
1508
1173
|
const pkgJson = req.resolve(`${pkgName}/package.json`);
|
|
1509
1174
|
return dirname(pkgJson);
|
|
1510
1175
|
} catch {
|
|
1511
|
-
const fallback =
|
|
1512
|
-
return
|
|
1176
|
+
const fallback = join5(cwd, "node_modules", ...pkgName.split("/"));
|
|
1177
|
+
return existsSync5(join5(fallback, "package.json")) ? fallback : null;
|
|
1513
1178
|
}
|
|
1514
1179
|
}
|
|
1515
1180
|
function readPkgJson(dir) {
|
|
1516
1181
|
try {
|
|
1517
|
-
return JSON.parse(
|
|
1182
|
+
return JSON.parse(readFileSync7(join5(dir, "package.json"), "utf8"));
|
|
1518
1183
|
} catch {
|
|
1519
1184
|
return null;
|
|
1520
1185
|
}
|
|
@@ -1538,11 +1203,11 @@ function inspectPkgCss(pkgName, cwd) {
|
|
|
1538
1203
|
return null;
|
|
1539
1204
|
const pkg = readPkgJson(root);
|
|
1540
1205
|
const exp = pkg?.exports;
|
|
1541
|
-
const abs = (rel2) => rel2 ?
|
|
1206
|
+
const abs = (rel2) => rel2 ? join5(root, rel2.replace(/^\.\//, "")) : undefined;
|
|
1542
1207
|
const fileIfExists = (key) => {
|
|
1543
1208
|
const rel2 = exportPath(exp, key);
|
|
1544
1209
|
const a = abs(rel2);
|
|
1545
|
-
return a &&
|
|
1210
|
+
return a && existsSync5(a) ? a : undefined;
|
|
1546
1211
|
};
|
|
1547
1212
|
return {
|
|
1548
1213
|
name: pkgName,
|
|
@@ -1567,8 +1232,8 @@ function resolveElcrmCssImport(spec, cwd) {
|
|
|
1567
1232
|
const rel2 = exportPath(pkg?.exports, `./${sub}`);
|
|
1568
1233
|
if (!rel2)
|
|
1569
1234
|
return null;
|
|
1570
|
-
const abs =
|
|
1571
|
-
return
|
|
1235
|
+
const abs = join5(root, rel2.replace(/^\.\//, ""));
|
|
1236
|
+
return existsSync5(abs) ? abs : null;
|
|
1572
1237
|
}
|
|
1573
1238
|
function pruneBrokenElcrmImports(css, cwd) {
|
|
1574
1239
|
const removed = [];
|
|
@@ -1594,15 +1259,15 @@ function collectPkgTokens(pkgName, cwd) {
|
|
|
1594
1259
|
if (!root)
|
|
1595
1260
|
return [];
|
|
1596
1261
|
const files = [
|
|
1597
|
-
...listCssFiles(
|
|
1598
|
-
...listCssFiles(
|
|
1599
|
-
...listCssFiles(
|
|
1600
|
-
|
|
1601
|
-
].filter((f) =>
|
|
1262
|
+
...listCssFiles(join5(root, "dist")),
|
|
1263
|
+
...listCssFiles(join5(root, "src/lib/styles")),
|
|
1264
|
+
...listCssFiles(join5(root, "src/style")),
|
|
1265
|
+
join5(root, "test/main.css")
|
|
1266
|
+
].filter((f) => existsSync5(f));
|
|
1602
1267
|
const acc = [];
|
|
1603
1268
|
const seen = new Set;
|
|
1604
1269
|
for (const file of files) {
|
|
1605
|
-
const css =
|
|
1270
|
+
const css = readFileSync7(file, "utf8");
|
|
1606
1271
|
const kind = fileKind(file);
|
|
1607
1272
|
if (kind !== "mixed") {
|
|
1608
1273
|
for (const [name, value] of parseCustomProps(css)) {
|
|
@@ -1705,8 +1370,8 @@ ${snippet}${after}`;
|
|
|
1705
1370
|
return null;
|
|
1706
1371
|
}
|
|
1707
1372
|
function findStyleDir(cwd) {
|
|
1708
|
-
for (const d of [
|
|
1709
|
-
if (
|
|
1373
|
+
for (const d of [join5(cwd, "src/style"), join5(cwd, "web/src/style")]) {
|
|
1374
|
+
if (existsSync5(join5(d, "theme-light.css")) || existsSync5(join5(d, "elcrm.css")) || existsSync5(join5(d, "theme.css"))) {
|
|
1710
1375
|
return d;
|
|
1711
1376
|
}
|
|
1712
1377
|
}
|
|
@@ -1741,10 +1406,10 @@ function syncElcrmCss(options) {
|
|
|
1741
1406
|
throw new Error("\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D src/style (theme.css / theme-light.css / elcrm.css).");
|
|
1742
1407
|
}
|
|
1743
1408
|
const paths = {
|
|
1744
|
-
geometry:
|
|
1745
|
-
light:
|
|
1746
|
-
dark:
|
|
1747
|
-
elcrm:
|
|
1409
|
+
geometry: join5(styleDir, "theme.css"),
|
|
1410
|
+
light: join5(styleDir, "theme-light.css"),
|
|
1411
|
+
dark: join5(styleDir, "theme-dark.css"),
|
|
1412
|
+
elcrm: join5(styleDir, "elcrm.css")
|
|
1748
1413
|
};
|
|
1749
1414
|
const allDefs = [];
|
|
1750
1415
|
const skippedPkgs = [];
|
|
@@ -1769,11 +1434,11 @@ function syncElcrmCss(options) {
|
|
|
1769
1434
|
const labelFor = (bucket) => bucket === "geometry" ? "theme.css" : bucket === "light" ? "theme-light.css" : "theme-dark.css";
|
|
1770
1435
|
for (const bucket of ["geometry", "light", "dark"]) {
|
|
1771
1436
|
const file = fileFor(bucket);
|
|
1772
|
-
if (!
|
|
1437
|
+
if (!existsSync5(file))
|
|
1773
1438
|
continue;
|
|
1774
|
-
let css =
|
|
1439
|
+
let css = readFileSync7(file, "utf8");
|
|
1775
1440
|
const have = existingTokenNames(css);
|
|
1776
|
-
const missing = allDefs.filter((d) => d.bucket === bucket && !have.has(d.name) && !TOKEN_DEPRECATED.has(d.name));
|
|
1441
|
+
const missing = allDefs.filter((d) => d.bucket === bucket && !have.has(d.name) && !d.name.startsWith("--search-") && !TOKEN_DEPRECATED.has(d.name));
|
|
1777
1442
|
const uniq = [];
|
|
1778
1443
|
const seen = new Set;
|
|
1779
1444
|
for (const d of missing) {
|
|
@@ -1793,10 +1458,10 @@ function syncElcrmCss(options) {
|
|
|
1793
1458
|
}
|
|
1794
1459
|
added[labelFor(bucket)] = uniq.map((d) => d.name);
|
|
1795
1460
|
if (!options.dry)
|
|
1796
|
-
|
|
1461
|
+
writeFileSync3(file, next, "utf8");
|
|
1797
1462
|
}
|
|
1798
|
-
if (
|
|
1799
|
-
let css =
|
|
1463
|
+
if (existsSync5(paths.elcrm)) {
|
|
1464
|
+
let css = readFileSync7(paths.elcrm, "utf8");
|
|
1800
1465
|
const pruned = pruneBrokenElcrmImports(css, options.cwd);
|
|
1801
1466
|
css = pruned.css;
|
|
1802
1467
|
removedImports = pruned.removed;
|
|
@@ -1816,83 +1481,953 @@ function syncElcrmCss(options) {
|
|
|
1816
1481
|
}
|
|
1817
1482
|
}
|
|
1818
1483
|
if ((imports.length || removedImports.length) && !options.dry) {
|
|
1819
|
-
|
|
1484
|
+
writeFileSync3(paths.elcrm, css, "utf8");
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return { styleDir, added, imports, removedImports, skippedPkgs };
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/lib/migrate/socket-server.ts
|
|
1491
|
+
import {
|
|
1492
|
+
existsSync as existsSync6,
|
|
1493
|
+
readdirSync as readdirSync4,
|
|
1494
|
+
readFileSync as readFileSync8,
|
|
1495
|
+
statSync as statSync4,
|
|
1496
|
+
writeFileSync as writeFileSync4
|
|
1497
|
+
} from "fs";
|
|
1498
|
+
import { join as join6 } from "path";
|
|
1499
|
+
var SKIP_DIRS2 = new Set([
|
|
1500
|
+
"node_modules",
|
|
1501
|
+
"dist",
|
|
1502
|
+
".git",
|
|
1503
|
+
"coverage",
|
|
1504
|
+
".turbo"
|
|
1505
|
+
]);
|
|
1506
|
+
var TEXT_EXT = new Set([
|
|
1507
|
+
".ts",
|
|
1508
|
+
".tsx",
|
|
1509
|
+
".js",
|
|
1510
|
+
".jsx",
|
|
1511
|
+
".mjs",
|
|
1512
|
+
".cjs",
|
|
1513
|
+
".mts",
|
|
1514
|
+
".cts"
|
|
1515
|
+
]);
|
|
1516
|
+
function walkFiles(dir, out = []) {
|
|
1517
|
+
if (!existsSync6(dir))
|
|
1518
|
+
return out;
|
|
1519
|
+
for (const name of readdirSync4(dir)) {
|
|
1520
|
+
if (SKIP_DIRS2.has(name))
|
|
1521
|
+
continue;
|
|
1522
|
+
const full = join6(dir, name);
|
|
1523
|
+
const st = statSync4(full);
|
|
1524
|
+
if (st.isDirectory())
|
|
1525
|
+
walkFiles(full, out);
|
|
1526
|
+
else {
|
|
1527
|
+
const ext = name.includes(".") ? `.${name.split(".").pop()}` : "";
|
|
1528
|
+
if (TEXT_EXT.has(ext))
|
|
1529
|
+
out.push(full);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
return out;
|
|
1533
|
+
}
|
|
1534
|
+
function rewriteImports2(source) {
|
|
1535
|
+
let hits = 0;
|
|
1536
|
+
let next = source;
|
|
1537
|
+
const patterns = [
|
|
1538
|
+
[
|
|
1539
|
+
/from\s+["']@elcrm\/socket\/server["']/g,
|
|
1540
|
+
'from "@elcrm/server"'
|
|
1541
|
+
],
|
|
1542
|
+
[
|
|
1543
|
+
/from\s+["']@elcrm\/socket-server["']/g,
|
|
1544
|
+
'from "@elcrm/server"'
|
|
1545
|
+
],
|
|
1546
|
+
[
|
|
1547
|
+
/require\s*\(\s*["']@elcrm\/socket\/server["']\s*\)/g,
|
|
1548
|
+
'require("@elcrm/server")'
|
|
1549
|
+
],
|
|
1550
|
+
[
|
|
1551
|
+
/require\s*\(\s*["']@elcrm\/socket-server["']\s*\)/g,
|
|
1552
|
+
'require("@elcrm/server")'
|
|
1553
|
+
]
|
|
1554
|
+
];
|
|
1555
|
+
for (const [re, repl] of patterns) {
|
|
1556
|
+
const before = next;
|
|
1557
|
+
next = next.replace(re, () => {
|
|
1558
|
+
hits++;
|
|
1559
|
+
return repl;
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1562
|
+
return { next, hits };
|
|
1563
|
+
}
|
|
1564
|
+
async function migrateSocketServer(cwd, dry) {
|
|
1565
|
+
const changes = [];
|
|
1566
|
+
const pkg = readPackageJson(cwd);
|
|
1567
|
+
let removedSocketServer = false;
|
|
1568
|
+
if (pkg) {
|
|
1569
|
+
for (const section of [
|
|
1570
|
+
"dependencies",
|
|
1571
|
+
"devDependencies",
|
|
1572
|
+
"peerDependencies"
|
|
1573
|
+
]) {
|
|
1574
|
+
const map = pkg[section];
|
|
1575
|
+
if (!map)
|
|
1576
|
+
continue;
|
|
1577
|
+
if (map["@elcrm/socket-server"]) {
|
|
1578
|
+
removedSocketServer = true;
|
|
1579
|
+
changes.push({
|
|
1580
|
+
file: "package.json",
|
|
1581
|
+
detail: `\u0443\u0434\u0430\u043B\u0438\u0442\u044C ${section}["@elcrm/socket-server"]`
|
|
1582
|
+
});
|
|
1583
|
+
if (!dry)
|
|
1584
|
+
delete map["@elcrm/socket-server"];
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
const hasServer = Boolean(pkg.dependencies?.["@elcrm/server"]) || Boolean(pkg.devDependencies?.["@elcrm/server"]);
|
|
1588
|
+
if (removedSocketServer && !hasServer) {
|
|
1589
|
+
const latest = dry ? null : await fetchLatestVersion("@elcrm/server");
|
|
1590
|
+
const ver = latest ? `^${latest}` : "^0.5.3";
|
|
1591
|
+
changes.push({
|
|
1592
|
+
file: "package.json",
|
|
1593
|
+
detail: `\u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C dependencies["@elcrm/server"] = ${ver}`
|
|
1594
|
+
});
|
|
1595
|
+
if (!dry) {
|
|
1596
|
+
if (!pkg.dependencies)
|
|
1597
|
+
pkg.dependencies = {};
|
|
1598
|
+
pkg.dependencies["@elcrm/server"] = ver;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
if (!dry && changes.some((c2) => c2.file === "package.json")) {
|
|
1602
|
+
writePackageJson(pkg, cwd);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
const roots = ["src", "app", "server", "lib"].map((d) => join6(cwd, d));
|
|
1606
|
+
const files = roots.flatMap((r) => walkFiles(r));
|
|
1607
|
+
for (const file of files) {
|
|
1608
|
+
const raw = readFileSync8(file, "utf8");
|
|
1609
|
+
const { next, hits } = rewriteImports2(raw);
|
|
1610
|
+
if (hits > 0) {
|
|
1611
|
+
changes.push({
|
|
1612
|
+
file: file.replace(cwd + "/", ""),
|
|
1613
|
+
detail: `${hits} \u0437\u0430\u043C\u0435\u043D(\u044B) \u0438\u043C\u043F\u043E\u0440\u0442\u043E\u0432 \u2192 @elcrm/server`
|
|
1614
|
+
});
|
|
1615
|
+
if (!dry)
|
|
1616
|
+
writeFileSync4(file, next, "utf8");
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
return changes;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// src/lib/migrate/size-sml.ts
|
|
1623
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
1624
|
+
var PATTERNS = [
|
|
1625
|
+
[/size\s*=\s*"sm"/g, 'size="s"'],
|
|
1626
|
+
[/size\s*=\s*'sm'/g, "size='s'"],
|
|
1627
|
+
[/size\s*=\s*\{\s*"sm"\s*\}/g, 'size={"s"}'],
|
|
1628
|
+
[/size\s*=\s*\{\s*'sm'\s*\}/g, "size={'s'}"],
|
|
1629
|
+
[/size\s*=\s*"md"/g, 'size="m"'],
|
|
1630
|
+
[/size\s*=\s*'md'/g, "size='m'"],
|
|
1631
|
+
[/size\s*=\s*\{\s*"md"\s*\}/g, 'size={"m"}'],
|
|
1632
|
+
[/size\s*=\s*\{\s*'md'\s*\}/g, "size={'m'}"]
|
|
1633
|
+
];
|
|
1634
|
+
function rewrite(source) {
|
|
1635
|
+
let next = source;
|
|
1636
|
+
let hits = 0;
|
|
1637
|
+
for (const [re, repl] of PATTERNS) {
|
|
1638
|
+
next = next.replace(re, () => {
|
|
1639
|
+
hits++;
|
|
1640
|
+
return repl;
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
return { next, hits };
|
|
1644
|
+
}
|
|
1645
|
+
async function migrateSizeSml(cwd, dry) {
|
|
1646
|
+
const changes = [];
|
|
1647
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
1648
|
+
for (const file of files) {
|
|
1649
|
+
if (file.endsWith(".css"))
|
|
1650
|
+
continue;
|
|
1651
|
+
const raw = readFileSync9(file, "utf8");
|
|
1652
|
+
const { next, hits } = rewrite(raw);
|
|
1653
|
+
if (hits === 0)
|
|
1654
|
+
continue;
|
|
1655
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1656
|
+
changes.push({
|
|
1657
|
+
file: rel(cwd, file),
|
|
1658
|
+
detail: `${hits}\xD7 size sm/md \u2192 s/m`
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return changes;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// src/lib/migrate/field-border.ts
|
|
1666
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
1667
|
+
var VARS = [
|
|
1668
|
+
"--field-border-focus",
|
|
1669
|
+
"--field-border-hover",
|
|
1670
|
+
"--field-border-error",
|
|
1671
|
+
"--field-border-disabled"
|
|
1672
|
+
];
|
|
1673
|
+
function extractColor(value) {
|
|
1674
|
+
const v = value.trim().replace(/;$/, "");
|
|
1675
|
+
const m = v.match(/^(?:\d+(?:\.\d+)?(?:px|em|rem)?\s+)?(?:solid|dashed|dotted|double)\s+(.+)$/i);
|
|
1676
|
+
if (m)
|
|
1677
|
+
return m[1].trim();
|
|
1678
|
+
if (/^(#|rgb|hsl|var\(|color-mix|transparent|currentColor)/i.test(v)) {
|
|
1679
|
+
return null;
|
|
1680
|
+
}
|
|
1681
|
+
return null;
|
|
1682
|
+
}
|
|
1683
|
+
function rewriteCss(source) {
|
|
1684
|
+
let hits = 0;
|
|
1685
|
+
let next = source;
|
|
1686
|
+
for (const name of VARS) {
|
|
1687
|
+
const re = new RegExp(`(${name.replace(/-/g, "\\-")}\\s*:\\s*)([^;\\n}]+)`, "g");
|
|
1688
|
+
next = next.replace(re, (full, prefix, rawVal) => {
|
|
1689
|
+
const color = extractColor(rawVal);
|
|
1690
|
+
if (!color)
|
|
1691
|
+
return full;
|
|
1692
|
+
hits++;
|
|
1693
|
+
return `${prefix}${color}`;
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
return { next, hits };
|
|
1697
|
+
}
|
|
1698
|
+
async function migrateFieldBorder(cwd, dry) {
|
|
1699
|
+
const changes = [];
|
|
1700
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => f.endsWith(".css"));
|
|
1701
|
+
for (const file of files) {
|
|
1702
|
+
const raw = readFileSync10(file, "utf8");
|
|
1703
|
+
const { next, hits } = rewriteCss(raw);
|
|
1704
|
+
if (hits === 0)
|
|
1705
|
+
continue;
|
|
1706
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1707
|
+
changes.push({
|
|
1708
|
+
file: rel(cwd, file),
|
|
1709
|
+
detail: `${hits}\xD7 border hover/focus \u2192 \u0442\u043E\u043B\u044C\u043A\u043E \u0446\u0432\u0435\u0442`
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
return changes;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/lib/migrate/modal-create.ts
|
|
1717
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
1718
|
+
async function migrateModalCreate(cwd, dry) {
|
|
1719
|
+
const changes = [];
|
|
1720
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /\.(tsx|jsx)$/.test(f));
|
|
1721
|
+
const addRe = /Modal\.Add\s*\(\s*<([A-Za-z_][\w.]*)\s+key=\{Date\.now\(\)\}/;
|
|
1722
|
+
for (const file of files) {
|
|
1723
|
+
const raw = readFileSync11(file, "utf8");
|
|
1724
|
+
if (!addRe.test(raw) && !/Modal\.Add\s*\(/.test(raw))
|
|
1725
|
+
continue;
|
|
1726
|
+
if (/export\s+default\s+Modal\.Create\s*\(/.test(raw)) {
|
|
1727
|
+
if (/Modal\.Add\s*\(/.test(raw)) {
|
|
1728
|
+
changes.push({
|
|
1729
|
+
file: rel(cwd, file),
|
|
1730
|
+
detail: "\u043E\u0441\u0442\u0430\u043B\u0441\u044F Modal.Add \u0440\u044F\u0434\u043E\u043C \u0441 Create \u2014 \u0443\u0431\u0435\u0440\u0438\u0442\u0435 Add \u0432\u0440\u0443\u0447\u043D\u0443\u044E"
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
const simple = /function\s+Screen\b/.test(raw) || /const\s+Screen\s*=/.test(raw) || /function\s+\w+\s*\([^)]*\)\s*\{[\s\S]*Modal\.Main/.test(raw);
|
|
1736
|
+
const openWrapper = /(?:const|function)\s+Open\s*=\s*(?:\([^)]*\)|[A-Za-z_]\w*)\s*=>\s*\{?\s*Modal\.Add/;
|
|
1737
|
+
if (simple && openWrapper.test(raw) && /export\s+default/.test(raw)) {
|
|
1738
|
+
let next = raw;
|
|
1739
|
+
next = next.replace(/\n(?:const|function)\s+Open\s*=\s*[\s\S]*?(?=\n(?:const|function|export)\s)/, `
|
|
1740
|
+
`);
|
|
1741
|
+
next = next.replace(/\n(?:const|function)\s+Icon\s*=\s*[\s\S]*?(?=\n(?:const|function|export)\s)/, `
|
|
1742
|
+
`);
|
|
1743
|
+
next = next.replace(/\nconst\s+Add\s*=\s*\{[\s\S]*?\};\s*\nexport\s+default\s+Add\s*;?/, `
|
|
1744
|
+
export default Modal.Create(Screen);
|
|
1745
|
+
`);
|
|
1746
|
+
next = next.replace(/export\s+default\s+\{\s*Open\s*,?\s*Icon?\s*,?\s*\}\s*;?/, "export default Modal.Create(Screen);");
|
|
1747
|
+
next = next.replace(/export\s+function\s+open\w+\s*\([^)]*\)\s*\{[\s\S]*?Modal\.Add\([\s\S]*?\);\s*\}/, (block) => {
|
|
1748
|
+
return `/* TODO: \u0437\u0430\u043C\u0435\u043D\u0438\u0442\u0435 \u0432\u044B\u0437\u043E\u0432\u044B \u043D\u0430 Modal.Open("Module","Name", props) \u0438\u043B\u0438 Create.Open */
|
|
1749
|
+
${block}`;
|
|
1750
|
+
});
|
|
1751
|
+
if (next !== raw && !/Modal\.Add/.test(next)) {
|
|
1752
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1753
|
+
changes.push({
|
|
1754
|
+
file: rel(cwd, file),
|
|
1755
|
+
detail: "Modal.Add \u2192 Modal.Create(Screen)"
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
continue;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
const count = (raw.match(/Modal\.Add\s*\(/g) || []).length;
|
|
1762
|
+
changes.push({
|
|
1763
|
+
file: rel(cwd, file),
|
|
1764
|
+
detail: `${count}\xD7 Modal.Add \u2014 \u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0438\u0442\u0435 \u043D\u0430 Modal.Create + Open (\u0441\u043C. Projects/modal/Create)`
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
return changes;
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
// src/lib/migrate/legacy-hacks.ts
|
|
1771
|
+
import { existsSync as existsSync7, readFileSync as readFileSync12 } from "fs";
|
|
1772
|
+
import { join as join7 } from "path";
|
|
1773
|
+
var HACK_RE = /\(globalThis\s+as\s+[^)]+\)\.React\s*=\s*React\s*;?|globalThis\.React\s*=\s*React\s*;?/;
|
|
1774
|
+
async function migrateLegacyReactHack(cwd, dry) {
|
|
1775
|
+
const changes = [];
|
|
1776
|
+
const files = new Set(projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /(^|\/)(main|bootstrap)\.(tsx?|jsx?)$/.test(f)));
|
|
1777
|
+
for (const name of ["main.tsx", "main.ts", "src/main.tsx", "src/main.ts"]) {
|
|
1778
|
+
const full = join7(cwd, name);
|
|
1779
|
+
if (existsSync7(full))
|
|
1780
|
+
files.add(full);
|
|
1781
|
+
}
|
|
1782
|
+
for (const file of files) {
|
|
1783
|
+
const raw = readFileSync12(file, "utf8");
|
|
1784
|
+
if (!HACK_RE.test(raw))
|
|
1785
|
+
continue;
|
|
1786
|
+
const next = raw.replace(/\/\*\s*@elcrm\/modal[\s\S]*?\*\/\s*/m, "").replace(/\(globalThis\s+as\s+typeof\s+globalThis\s+&\s+\{\s*React:\s*typeof\s+React\s*\}\)\.React\s*=\s*React\s*;\s*/g, "").replace(/globalThis\.React\s*=\s*React\s*;\s*/g, "");
|
|
1787
|
+
if (next === raw) {
|
|
1788
|
+
changes.push({
|
|
1789
|
+
file: rel(cwd, file),
|
|
1790
|
+
detail: "globalThis.React \u2014 \u0443\u0434\u0430\u043B\u0438\u0442\u0435 \u0432\u0440\u0443\u0447\u043D\u0443\u044E \u043F\u043E\u0441\u043B\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F @elcrm/modal"
|
|
1791
|
+
});
|
|
1792
|
+
continue;
|
|
1793
|
+
}
|
|
1794
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1795
|
+
changes.push({
|
|
1796
|
+
file: rel(cwd, file),
|
|
1797
|
+
detail: "\u0443\u0434\u0430\u043B\u0451\u043D globalThis.React \u0445\u0430\u043A"
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
return changes;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
// src/lib/migrate/form-aliases.ts
|
|
1805
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
1806
|
+
var REPLACEMENTS = [
|
|
1807
|
+
[/\bProgressField\b/g, "RangeField", "ProgressField\u2192RangeField"],
|
|
1808
|
+
[/\bReadonlyField\b/g, "DisplayField", "ReadonlyField\u2192DisplayField"],
|
|
1809
|
+
[/\bOtpField\b/g, "CodeField", "OtpField\u2192CodeField"],
|
|
1810
|
+
[/\bSegmentField\b/g, "TabsField", "SegmentField\u2192TabsField"],
|
|
1811
|
+
[/\bDragonDropField\b/g, "DragDropField", "DragonDropField\u2192DragDropField"],
|
|
1812
|
+
[/\bTProgress\b/g, "TRange", "TProgress\u2192TRange"]
|
|
1813
|
+
];
|
|
1814
|
+
function rewrite2(source) {
|
|
1815
|
+
let next = source;
|
|
1816
|
+
const labels = [];
|
|
1817
|
+
for (const [re, repl, label] of REPLACEMENTS) {
|
|
1818
|
+
let n = 0;
|
|
1819
|
+
next = next.replace(re, () => {
|
|
1820
|
+
n++;
|
|
1821
|
+
return repl;
|
|
1822
|
+
});
|
|
1823
|
+
if (n > 0)
|
|
1824
|
+
labels.push(`${n}\xD7 ${label}`);
|
|
1825
|
+
}
|
|
1826
|
+
return { next, labels };
|
|
1827
|
+
}
|
|
1828
|
+
async function migrateFormAliases(cwd, dry) {
|
|
1829
|
+
const changes = [];
|
|
1830
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
1831
|
+
for (const file of files) {
|
|
1832
|
+
if (file.endsWith(".css"))
|
|
1833
|
+
continue;
|
|
1834
|
+
const raw = readFileSync13(file, "utf8");
|
|
1835
|
+
const { next, labels } = rewrite2(raw);
|
|
1836
|
+
if (labels.length === 0)
|
|
1837
|
+
continue;
|
|
1838
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1839
|
+
changes.push({
|
|
1840
|
+
file: rel(cwd, file),
|
|
1841
|
+
detail: labels.join(", ")
|
|
1842
|
+
});
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return changes;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
// src/lib/migrate/form-native.ts
|
|
1849
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
1850
|
+
function lineLooksLikeFormNativeProp(line) {
|
|
1851
|
+
const t = line.trim();
|
|
1852
|
+
if (!t || t.startsWith("//") || t.startsWith("*") || t.startsWith("/*")) {
|
|
1853
|
+
return false;
|
|
1854
|
+
}
|
|
1855
|
+
if (/\bnavigator\b|\bnativeEvent\b|\bcreateNative\b/.test(line)) {
|
|
1856
|
+
return false;
|
|
1857
|
+
}
|
|
1858
|
+
if (/['"`]native['"`]/.test(line))
|
|
1859
|
+
return false;
|
|
1860
|
+
if (/\binstallMode\b/.test(line) && /\bnative\b/.test(line))
|
|
1861
|
+
return false;
|
|
1862
|
+
return /(?:^|\s)native(?:\s*$|\s*=\s*\{?\s*true\s*\}?|(?=\s+[A-Za-z_./{])|(?=\s*\/?>))/.test(line);
|
|
1863
|
+
}
|
|
1864
|
+
function stripFormNativePropLine(line) {
|
|
1865
|
+
if (!lineLooksLikeFormNativeProp(line))
|
|
1866
|
+
return line;
|
|
1867
|
+
const trimmed = line.trim();
|
|
1868
|
+
if (trimmed === "native" || trimmed === "native={true}") {
|
|
1869
|
+
return "";
|
|
1870
|
+
}
|
|
1871
|
+
let next = line.replace(/\s+native=\{true\}/g, "");
|
|
1872
|
+
next = next.replace(/(?<=[\s{(])native(?=\s*\/?>)/g, "");
|
|
1873
|
+
next = next.replace(/(?<=\s)native(?=\s+[A-Za-z_./{])/g, "");
|
|
1874
|
+
if (/^\s*$/.test(next))
|
|
1875
|
+
return "";
|
|
1876
|
+
return next;
|
|
1877
|
+
}
|
|
1878
|
+
function rewriteFormNative(source) {
|
|
1879
|
+
const lines = source.split(/\r?\n/);
|
|
1880
|
+
let hits = 0;
|
|
1881
|
+
const out = [];
|
|
1882
|
+
for (const line of lines) {
|
|
1883
|
+
if (!lineLooksLikeFormNativeProp(line)) {
|
|
1884
|
+
out.push(line);
|
|
1885
|
+
continue;
|
|
1886
|
+
}
|
|
1887
|
+
const next = stripFormNativePropLine(line);
|
|
1888
|
+
if (next !== line)
|
|
1889
|
+
hits++;
|
|
1890
|
+
if (next === "" && line.trim() !== "") {
|
|
1891
|
+
continue;
|
|
1892
|
+
}
|
|
1893
|
+
out.push(next);
|
|
1894
|
+
}
|
|
1895
|
+
return { next: out.join(`
|
|
1896
|
+
`), hits };
|
|
1897
|
+
}
|
|
1898
|
+
async function migrateFormNative(cwd, dry) {
|
|
1899
|
+
const changes = [];
|
|
1900
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /\.(tsx|jsx)$/.test(f));
|
|
1901
|
+
for (const file of files) {
|
|
1902
|
+
const raw = readFileSync14(file, "utf8");
|
|
1903
|
+
const { next, hits } = rewriteFormNative(raw);
|
|
1904
|
+
if (hits === 0)
|
|
1905
|
+
continue;
|
|
1906
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
1907
|
+
changes.push({
|
|
1908
|
+
file: rel(cwd, file),
|
|
1909
|
+
detail: `${hits}\xD7 \u0441\u043D\u044F\u0442 prop native`
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
return changes;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// src/lib/migrate/native-html.ts
|
|
1917
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
1918
|
+
function findNativeHtmlTags(source) {
|
|
1919
|
+
const out = [];
|
|
1920
|
+
const re = /<(input|textarea|select)\b/gi;
|
|
1921
|
+
let m;
|
|
1922
|
+
while (m = re.exec(source)) {
|
|
1923
|
+
const name = m[1].toLowerCase();
|
|
1924
|
+
const start = m.index;
|
|
1925
|
+
let i = m.index + m[0].length;
|
|
1926
|
+
let quote = null;
|
|
1927
|
+
let brace = 0;
|
|
1928
|
+
let attrsEnd = -1;
|
|
1929
|
+
let selfClosing = false;
|
|
1930
|
+
while (i < source.length) {
|
|
1931
|
+
const ch = source[i];
|
|
1932
|
+
if (quote) {
|
|
1933
|
+
if (ch === "\\" && quote === '"') {
|
|
1934
|
+
i += 2;
|
|
1935
|
+
continue;
|
|
1936
|
+
}
|
|
1937
|
+
if (ch === quote)
|
|
1938
|
+
quote = null;
|
|
1939
|
+
i++;
|
|
1940
|
+
continue;
|
|
1941
|
+
}
|
|
1942
|
+
if (ch === '"' || ch === "'") {
|
|
1943
|
+
quote = ch;
|
|
1944
|
+
i++;
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
if (ch === "{") {
|
|
1948
|
+
brace++;
|
|
1949
|
+
i++;
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
if (ch === "}" && brace > 0) {
|
|
1953
|
+
brace--;
|
|
1954
|
+
i++;
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
if (brace > 0) {
|
|
1958
|
+
i++;
|
|
1959
|
+
continue;
|
|
1960
|
+
}
|
|
1961
|
+
if (ch === "/" && source[i + 1] === ">") {
|
|
1962
|
+
attrsEnd = i;
|
|
1963
|
+
selfClosing = true;
|
|
1964
|
+
i += 2;
|
|
1965
|
+
out.push({
|
|
1966
|
+
start,
|
|
1967
|
+
end: i,
|
|
1968
|
+
name,
|
|
1969
|
+
attrs: source.slice(m.index + m[0].length, attrsEnd),
|
|
1970
|
+
inner: "",
|
|
1971
|
+
selfClosing: true
|
|
1972
|
+
});
|
|
1973
|
+
break;
|
|
1974
|
+
}
|
|
1975
|
+
if (ch === ">") {
|
|
1976
|
+
attrsEnd = i;
|
|
1977
|
+
i++;
|
|
1978
|
+
if (name === "input" || selfClosing) {
|
|
1979
|
+
out.push({
|
|
1980
|
+
start,
|
|
1981
|
+
end: i,
|
|
1982
|
+
name,
|
|
1983
|
+
attrs: source.slice(m.index + m[0].length, attrsEnd),
|
|
1984
|
+
inner: "",
|
|
1985
|
+
selfClosing: false
|
|
1986
|
+
});
|
|
1987
|
+
break;
|
|
1988
|
+
}
|
|
1989
|
+
const close = new RegExp(`</${name}\\s*>`, "i");
|
|
1990
|
+
close.lastIndex = i;
|
|
1991
|
+
const cm = close.exec(source);
|
|
1992
|
+
if (!cm)
|
|
1993
|
+
break;
|
|
1994
|
+
out.push({
|
|
1995
|
+
start,
|
|
1996
|
+
end: cm.index + cm[0].length,
|
|
1997
|
+
name,
|
|
1998
|
+
attrs: source.slice(m.index + m[0].length, attrsEnd),
|
|
1999
|
+
inner: source.slice(i, cm.index),
|
|
2000
|
+
selfClosing: false
|
|
2001
|
+
});
|
|
2002
|
+
i = cm.index + cm[0].length;
|
|
2003
|
+
break;
|
|
2004
|
+
}
|
|
2005
|
+
i++;
|
|
2006
|
+
}
|
|
2007
|
+
re.lastIndex = Math.max(re.lastIndex, i);
|
|
2008
|
+
}
|
|
2009
|
+
return out;
|
|
2010
|
+
}
|
|
2011
|
+
function attrType(attrs) {
|
|
2012
|
+
const m = /\btype\s*=\s*(?:\{["'](\w+)["']\}|["'](\w+)["'])/i.exec(attrs);
|
|
2013
|
+
return (m?.[1] || m?.[2] || "text").toLowerCase();
|
|
2014
|
+
}
|
|
2015
|
+
function hasAttr(attrs, name) {
|
|
2016
|
+
return new RegExp(`\\b${name}\\s*=`).test(attrs) || new RegExp(`(?:^|\\s)${name}(?:\\s|$)`).test(attrs);
|
|
2017
|
+
}
|
|
2018
|
+
function sliceAttrValue(attrs, eqIndex) {
|
|
2019
|
+
let i = eqIndex + 1;
|
|
2020
|
+
while (i < attrs.length && /\s/.test(attrs[i]))
|
|
2021
|
+
i++;
|
|
2022
|
+
if (i >= attrs.length)
|
|
2023
|
+
return null;
|
|
2024
|
+
const start = i;
|
|
2025
|
+
const ch = attrs[i];
|
|
2026
|
+
if (ch === '"' || ch === "'") {
|
|
2027
|
+
const q = ch;
|
|
2028
|
+
i++;
|
|
2029
|
+
while (i < attrs.length && attrs[i] !== q) {
|
|
2030
|
+
if (attrs[i] === "\\" && q === '"')
|
|
2031
|
+
i++;
|
|
2032
|
+
i++;
|
|
2033
|
+
}
|
|
2034
|
+
return { value: attrs.slice(start, i + 1), end: i + 1 };
|
|
2035
|
+
}
|
|
2036
|
+
if (ch === "{") {
|
|
2037
|
+
let brace = 0;
|
|
2038
|
+
let quote = null;
|
|
2039
|
+
while (i < attrs.length) {
|
|
2040
|
+
const c2 = attrs[i];
|
|
2041
|
+
if (quote) {
|
|
2042
|
+
if (c2 === "\\" && quote === '"') {
|
|
2043
|
+
i += 2;
|
|
2044
|
+
continue;
|
|
2045
|
+
}
|
|
2046
|
+
if (c2 === quote)
|
|
2047
|
+
quote = null;
|
|
2048
|
+
i++;
|
|
2049
|
+
continue;
|
|
2050
|
+
}
|
|
2051
|
+
if (c2 === '"' || c2 === "'") {
|
|
2052
|
+
quote = c2;
|
|
2053
|
+
i++;
|
|
2054
|
+
continue;
|
|
2055
|
+
}
|
|
2056
|
+
if (c2 === "{")
|
|
2057
|
+
brace++;
|
|
2058
|
+
else if (c2 === "}") {
|
|
2059
|
+
brace--;
|
|
2060
|
+
if (brace === 0) {
|
|
2061
|
+
i++;
|
|
2062
|
+
return { value: attrs.slice(start, i), end: i };
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
i++;
|
|
2066
|
+
}
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2069
|
+
while (i < attrs.length && /[^\s/>]/.test(attrs[i]))
|
|
2070
|
+
i++;
|
|
2071
|
+
return { value: attrs.slice(start, i), end: i };
|
|
2072
|
+
}
|
|
2073
|
+
function findAttrSpan(attrs, name) {
|
|
2074
|
+
const re = new RegExp(`(?:^|\\s)(${name})(?=\\s|=|$)`, "i");
|
|
2075
|
+
const m = re.exec(attrs);
|
|
2076
|
+
if (!m)
|
|
2077
|
+
return null;
|
|
2078
|
+
const nameStart = m.index + (m[0].startsWith(" ") || m[0].startsWith(`
|
|
2079
|
+
`) || m[0].startsWith("\t") ? 1 : 0);
|
|
2080
|
+
const nameIdx = attrs.indexOf(m[1], m.index);
|
|
2081
|
+
let i = nameIdx + m[1].length;
|
|
2082
|
+
while (i < attrs.length && /\s/.test(attrs[i]))
|
|
2083
|
+
i++;
|
|
2084
|
+
if (attrs[i] === "=") {
|
|
2085
|
+
const sliced = sliceAttrValue(attrs, i);
|
|
2086
|
+
if (!sliced)
|
|
2087
|
+
return null;
|
|
2088
|
+
return { start: m.index, end: sliced.end, value: sliced.value };
|
|
2089
|
+
}
|
|
2090
|
+
return { start: m.index, end: nameIdx + m[1].length, value: null };
|
|
2091
|
+
}
|
|
2092
|
+
function getAttrExpr(attrs, name) {
|
|
2093
|
+
const span = findAttrSpan(attrs, name);
|
|
2094
|
+
return span?.value ?? null;
|
|
2095
|
+
}
|
|
2096
|
+
function dropAttrs(attrs, names) {
|
|
2097
|
+
let next = attrs;
|
|
2098
|
+
for (const name of names) {
|
|
2099
|
+
for (;; ) {
|
|
2100
|
+
const span = findAttrSpan(next, name);
|
|
2101
|
+
if (!span)
|
|
2102
|
+
break;
|
|
2103
|
+
next = next.slice(0, span.start) + next.slice(span.end);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
return next;
|
|
2107
|
+
}
|
|
2108
|
+
function compactAttrs(attrs) {
|
|
2109
|
+
const t = attrs.replace(/\s+/g, " ").trim();
|
|
2110
|
+
return t ? ` ${t}` : "";
|
|
2111
|
+
}
|
|
2112
|
+
function rewriteOnChangeToOnValue(attrs, mode) {
|
|
2113
|
+
const onChange = getAttrExpr(attrs, "onChange");
|
|
2114
|
+
if (!onChange)
|
|
2115
|
+
return dropAttrs(attrs, ["onChange", "checked", "type"]);
|
|
2116
|
+
let body = onChange;
|
|
2117
|
+
if (mode === "value") {
|
|
2118
|
+
body = onChange.replace(/\(e\)\s*=>\s*/g, "({ value }) => ").replace(/\be\s*=>\s*/g, "({ value }) => ").replace(/e\.target\.value/g, "String(value ?? '')");
|
|
2119
|
+
} else if (mode === "checked") {
|
|
2120
|
+
body = onChange.replace(/\(e\)\s*=>\s*/g, "({ value }) => ").replace(/\be\s*=>\s*/g, "({ value }) => ").replace(/e\.target\.checked/g, "Boolean(value)");
|
|
2121
|
+
} else {
|
|
2122
|
+
body = onChange.replace(/\(e\)\s*=>\s*/g, "({ value }) => ").replace(/\be\s*=>\s*/g, "({ value }) => ").replace(/e\.target\.files/g, "(value as FileList | null)").replace(/e\.target\.files\??\.\[0\]/g, "(Array.isArray(value) ? value[0] : value)");
|
|
2123
|
+
}
|
|
2124
|
+
let next = dropAttrs(attrs, ["onChange", "type"]);
|
|
2125
|
+
if (mode === "checked") {
|
|
2126
|
+
const checked = getAttrExpr(attrs, "checked");
|
|
2127
|
+
next = dropAttrs(next, ["checked"]);
|
|
2128
|
+
if (checked)
|
|
2129
|
+
next += ` value=${checked}`;
|
|
2130
|
+
}
|
|
2131
|
+
next += ` onValue=${body}`;
|
|
2132
|
+
return next;
|
|
2133
|
+
}
|
|
2134
|
+
function convertInput(attrs) {
|
|
2135
|
+
const type = attrType(attrs);
|
|
2136
|
+
if (type === "hidden")
|
|
2137
|
+
return null;
|
|
2138
|
+
if (hasAttr(attrs, "ref"))
|
|
2139
|
+
return null;
|
|
2140
|
+
if (type === "checkbox") {
|
|
2141
|
+
if (!hasAttr(attrs, "checked") && !hasAttr(attrs, "onChange"))
|
|
2142
|
+
return null;
|
|
2143
|
+
const next = compactAttrs(dropAttrs(rewriteOnChangeToOnValue(attrs, "checked"), ["defaultChecked"]));
|
|
2144
|
+
return {
|
|
2145
|
+
jsx: `<CheckField variant="plain"${next} />`,
|
|
2146
|
+
imports: ["CheckField"]
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
if (type === "file") {
|
|
2150
|
+
const next = compactAttrs(dropAttrs(rewriteOnChangeToOnValue(attrs, "files"), ["multiple"]));
|
|
2151
|
+
const multiple = hasAttr(attrs, "multiple") ? " multiple" : "";
|
|
2152
|
+
return {
|
|
2153
|
+
jsx: `<FileField keepFile${multiple}${next} />`,
|
|
2154
|
+
imports: ["FileField"]
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
if (type === "text" || type === "search" || type === "tel" || type === "url" || type === "number" || type === "email" || type === "password") {
|
|
2158
|
+
const field = type === "password" ? "PasswordField" : type === "email" ? "EmailField" : type === "number" ? "NumberField" : "StringField";
|
|
2159
|
+
let next = rewriteOnChangeToOnValue(attrs, "value");
|
|
2160
|
+
next = dropAttrs(next, [
|
|
2161
|
+
"autoFocus",
|
|
2162
|
+
"autofocus",
|
|
2163
|
+
"inputMode",
|
|
2164
|
+
"inputmode",
|
|
2165
|
+
"onKeyDown",
|
|
2166
|
+
"onKeyUp",
|
|
2167
|
+
"onKeyPress"
|
|
2168
|
+
]);
|
|
2169
|
+
const maxLength = getAttrExpr(attrs, "maxLength");
|
|
2170
|
+
if (maxLength && !getAttrExpr(next, "maxLength")) {
|
|
2171
|
+
next += ` maxLength=${maxLength}`;
|
|
2172
|
+
}
|
|
2173
|
+
return {
|
|
2174
|
+
jsx: `<${field}${compactAttrs(next)} />`,
|
|
2175
|
+
imports: [field]
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
return null;
|
|
2179
|
+
}
|
|
2180
|
+
function convertTextarea(attrs) {
|
|
2181
|
+
if (hasAttr(attrs, "ref") || hasAttr(attrs, "onKeyDown"))
|
|
2182
|
+
return null;
|
|
2183
|
+
const next = compactAttrs(rewriteOnChangeToOnValue(attrs, "value"));
|
|
2184
|
+
return {
|
|
2185
|
+
jsx: `<TextareaField${next} />`,
|
|
2186
|
+
imports: ["TextareaField"]
|
|
2187
|
+
};
|
|
2188
|
+
}
|
|
2189
|
+
function ensureFormImports(source, names) {
|
|
2190
|
+
const uniq = [...new Set(names)];
|
|
2191
|
+
if (uniq.length === 0)
|
|
2192
|
+
return source;
|
|
2193
|
+
const importRe = /import\s*\{([^}]*)\}\s*from\s*["']@elcrm\/form["']\s*;?/;
|
|
2194
|
+
const m = importRe.exec(source);
|
|
2195
|
+
if (m) {
|
|
2196
|
+
const existing = m[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
2197
|
+
const set = new Set(existing);
|
|
2198
|
+
for (const n of uniq)
|
|
2199
|
+
set.add(n);
|
|
2200
|
+
const list = [...set].sort().join(", ");
|
|
2201
|
+
const after = source.slice(m.index + m[0].length);
|
|
2202
|
+
const needsNl = after.length > 0 && !/^\r?\n/.test(after);
|
|
2203
|
+
const stmt = `import { ${list} } from "@elcrm/form";${needsNl ? `
|
|
2204
|
+
` : ""}`;
|
|
2205
|
+
return source.slice(0, m.index) + stmt + after;
|
|
2206
|
+
}
|
|
2207
|
+
const insert = `import { ${uniq.sort().join(", ")} } from "@elcrm/form";
|
|
2208
|
+
`;
|
|
2209
|
+
const reactImport = /import\s+.+\s+from\s+["']react["']\s*;?\n/;
|
|
2210
|
+
if (reactImport.test(source)) {
|
|
2211
|
+
return source.replace(reactImport, (block) => block + insert);
|
|
2212
|
+
}
|
|
2213
|
+
return insert + source;
|
|
2214
|
+
}
|
|
2215
|
+
function rewriteNativeHtml(source) {
|
|
2216
|
+
const tags = findNativeHtmlTags(source);
|
|
2217
|
+
if (tags.length === 0) {
|
|
2218
|
+
return { next: source, hits: 0, skipped: [] };
|
|
2219
|
+
}
|
|
2220
|
+
let hits = 0;
|
|
2221
|
+
const imports = [];
|
|
2222
|
+
const skipped = [];
|
|
2223
|
+
let next = source;
|
|
2224
|
+
for (let ti = tags.length - 1;ti >= 0; ti--) {
|
|
2225
|
+
const tag = tags[ti];
|
|
2226
|
+
let conv = null;
|
|
2227
|
+
if (tag.name === "input")
|
|
2228
|
+
conv = convertInput(tag.attrs);
|
|
2229
|
+
else if (tag.name === "textarea") {
|
|
2230
|
+
if (tag.inner.trim()) {
|
|
2231
|
+
skipped.push("textarea with children");
|
|
2232
|
+
continue;
|
|
2233
|
+
}
|
|
2234
|
+
conv = convertTextarea(tag.attrs);
|
|
2235
|
+
} else {
|
|
2236
|
+
skipped.push("select \u2192 SelectField \u0432\u0440\u0443\u0447\u043D\u0443\u044E (options id:number)");
|
|
2237
|
+
continue;
|
|
2238
|
+
}
|
|
2239
|
+
if (!conv) {
|
|
2240
|
+
skipped.push(`${tag.name} type=${attrType(tag.attrs)}`);
|
|
2241
|
+
continue;
|
|
2242
|
+
}
|
|
2243
|
+
next = next.slice(0, tag.start) + conv.jsx + next.slice(tag.end);
|
|
2244
|
+
imports.push(...conv.imports);
|
|
2245
|
+
hits++;
|
|
2246
|
+
}
|
|
2247
|
+
if (hits > 0)
|
|
2248
|
+
next = ensureFormImports(next, imports);
|
|
2249
|
+
return { next, hits, skipped };
|
|
2250
|
+
}
|
|
2251
|
+
async function migrateNativeHtml(cwd, dry) {
|
|
2252
|
+
const changes = [];
|
|
2253
|
+
const pkg = readPackageJson(cwd);
|
|
2254
|
+
if (pkg?.name === "@elcrm/form")
|
|
2255
|
+
return changes;
|
|
2256
|
+
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r)).filter((f) => /\.(tsx|jsx)$/.test(f));
|
|
2257
|
+
for (const file of files) {
|
|
2258
|
+
const raw = readFileSync15(file, "utf8");
|
|
2259
|
+
if (!/<(?:input|textarea|select)\b/.test(raw))
|
|
2260
|
+
continue;
|
|
2261
|
+
const { next, hits, skipped } = rewriteNativeHtml(raw);
|
|
2262
|
+
const detailParts = [];
|
|
2263
|
+
if (hits > 0)
|
|
2264
|
+
detailParts.push(`${hits}\xD7 \u2192 @elcrm/form`);
|
|
2265
|
+
if (skipped.length > 0) {
|
|
2266
|
+
detailParts.push(`\u043F\u0440\u043E\u043F\u0443\u0441\u043A: ${[...new Set(skipped)].slice(0, 3).join("; ")}`);
|
|
2267
|
+
}
|
|
2268
|
+
if (detailParts.length === 0)
|
|
2269
|
+
continue;
|
|
2270
|
+
if (hits > 0) {
|
|
2271
|
+
if (writeIfChanged(file, next, dry) || dry) {
|
|
2272
|
+
changes.push({
|
|
2273
|
+
file: rel(cwd, file),
|
|
2274
|
+
detail: detailParts.join("; ")
|
|
2275
|
+
});
|
|
2276
|
+
}
|
|
2277
|
+
} else {
|
|
2278
|
+
changes.push({
|
|
2279
|
+
file: rel(cwd, file),
|
|
2280
|
+
detail: detailParts.join("; ")
|
|
2281
|
+
});
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return changes;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
// src/lib/migrate/front.ts
|
|
2288
|
+
var FRONT_MIGRATIONS = {
|
|
2289
|
+
"size-sml": migrateSizeSml,
|
|
2290
|
+
"field-border": migrateFieldBorder,
|
|
2291
|
+
"modal-create": migrateModalCreate,
|
|
2292
|
+
"form-aliases": migrateFormAliases,
|
|
2293
|
+
"form-tokens": migrateFormTokens,
|
|
2294
|
+
"form-native": migrateFormNative,
|
|
2295
|
+
"native-html": migrateNativeHtml,
|
|
2296
|
+
components: migrateComponents,
|
|
2297
|
+
"css-sanitize": migrateCssSanitize,
|
|
2298
|
+
"legacy-hacks": migrateLegacyReactHack,
|
|
2299
|
+
"socket-server": migrateSocketServer
|
|
2300
|
+
};
|
|
2301
|
+
var FRONT_MIGRATE_ORDER = [
|
|
2302
|
+
"form-aliases",
|
|
2303
|
+
"form-native",
|
|
2304
|
+
"native-html",
|
|
2305
|
+
"form-tokens",
|
|
2306
|
+
"components",
|
|
2307
|
+
"css-sanitize",
|
|
2308
|
+
"size-sml",
|
|
2309
|
+
"field-border",
|
|
2310
|
+
"modal-create",
|
|
2311
|
+
"socket-server"
|
|
2312
|
+
];
|
|
2313
|
+
async function migrateFrontAll(cwd, dry) {
|
|
2314
|
+
const all = [];
|
|
2315
|
+
for (const name of FRONT_MIGRATE_ORDER) {
|
|
2316
|
+
const part = await FRONT_MIGRATIONS[name](cwd, dry);
|
|
2317
|
+
for (const c2 of part) {
|
|
2318
|
+
all.push({ file: c2.file, detail: `[${name}] ${c2.detail}` });
|
|
1820
2319
|
}
|
|
1821
2320
|
}
|
|
1822
|
-
return
|
|
2321
|
+
return all;
|
|
1823
2322
|
}
|
|
1824
2323
|
|
|
1825
|
-
// src/
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
function hasElcrmServer(pkg) {
|
|
1832
|
-
for (const section of [
|
|
1833
|
-
"dependencies",
|
|
1834
|
-
"devDependencies",
|
|
1835
|
-
"peerDependencies"
|
|
1836
|
-
]) {
|
|
1837
|
-
const map = pkg[section];
|
|
1838
|
-
if (map && typeof map === "object" && "@elcrm/server" in map)
|
|
1839
|
-
return true;
|
|
2324
|
+
// src/lib/tidy.ts
|
|
2325
|
+
function applyPackageHygiene(pkg) {
|
|
2326
|
+
const done = [];
|
|
2327
|
+
if (pkg.type !== "module") {
|
|
2328
|
+
pkg.type = "module";
|
|
2329
|
+
done.push('type: "module"');
|
|
1840
2330
|
}
|
|
1841
|
-
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
return hasElcrmServer(pkg) ? "server" : "front";
|
|
1847
|
-
}
|
|
1848
|
-
function listWorkspaceDirs(cwd, pkg) {
|
|
1849
|
-
const raw = pkg.workspaces;
|
|
1850
|
-
let patterns = [];
|
|
1851
|
-
if (Array.isArray(raw)) {
|
|
1852
|
-
patterns = raw.filter((p) => typeof p === "string");
|
|
1853
|
-
} else if (raw && typeof raw === "object" && Array.isArray(raw.packages)) {
|
|
1854
|
-
patterns = raw.packages.filter((p) => typeof p === "string");
|
|
2331
|
+
if (!pkg.engines)
|
|
2332
|
+
pkg.engines = {};
|
|
2333
|
+
if (!pkg.engines.node && !pkg.engines.bun) {
|
|
2334
|
+
pkg.engines.node = ">=18";
|
|
2335
|
+
done.push("engines.node >=18");
|
|
1855
2336
|
}
|
|
1856
|
-
if (
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
if (existsSync7(join7(dir, "package.json")))
|
|
1863
|
-
out.push(dir);
|
|
1864
|
-
continue;
|
|
2337
|
+
if (pkg.name?.startsWith("@elcrm/")) {
|
|
2338
|
+
if (!pkg.scripts)
|
|
2339
|
+
pkg.scripts = {};
|
|
2340
|
+
if (!pkg.scripts["pack:check"]) {
|
|
2341
|
+
pkg.scripts["pack:check"] = "npm pack --dry-run";
|
|
2342
|
+
done.push("scripts.pack:check");
|
|
1865
2343
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
2344
|
+
}
|
|
2345
|
+
return done;
|
|
2346
|
+
}
|
|
2347
|
+
function printCssSync(css) {
|
|
2348
|
+
let added = 0;
|
|
2349
|
+
for (const [file, tokens] of Object.entries(css.added)) {
|
|
2350
|
+
if (!tokens.length)
|
|
1869
2351
|
continue;
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2352
|
+
added += tokens.length;
|
|
2353
|
+
console.log(` ${c.green("+")} ${file}: ${tokens.join(", ")}`);
|
|
2354
|
+
}
|
|
2355
|
+
if (css.imports.length) {
|
|
2356
|
+
console.log(` ${c.green("+")} elcrm.css @import: ${css.imports.join(", ")}`);
|
|
2357
|
+
}
|
|
2358
|
+
if (css.removedImports.length) {
|
|
2359
|
+
console.log(` ${c.red("\u2212")} elcrm.css \u0431\u0438\u0442\u044B\u0435 @import: ${css.removedImports.join(", ")}`);
|
|
2360
|
+
}
|
|
2361
|
+
if (added === 0 && css.imports.length === 0 && css.removedImports.length === 0) {
|
|
2362
|
+
console.log(" \u0422\u043E\u043A\u0435\u043D\u044B \u0438 @import \u0443\u0436\u0435 \u043D\u0430 \u043C\u0435\u0441\u0442\u0435.");
|
|
1876
2363
|
}
|
|
1877
|
-
return out;
|
|
1878
2364
|
}
|
|
1879
|
-
function
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
return
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
}
|
|
1886
|
-
|
|
2365
|
+
function printChanges(changes, empty) {
|
|
2366
|
+
if (!changes.length) {
|
|
2367
|
+
console.log(` ${empty}`);
|
|
2368
|
+
return;
|
|
2369
|
+
}
|
|
2370
|
+
for (const ch of changes)
|
|
2371
|
+
console.log(` ${ch.file}: ${ch.detail}`);
|
|
2372
|
+
console.log(` \u0418\u0442\u043E\u0433\u043E: ${changes.length}.`);
|
|
2373
|
+
}
|
|
2374
|
+
async function tidyFrontProject(opts) {
|
|
2375
|
+
const { cwd, pkg, dry } = opts;
|
|
2376
|
+
const prefix = dry ? "[dry] " : "";
|
|
2377
|
+
console.log(`
|
|
2378
|
+
${prefix}1) package.json`);
|
|
2379
|
+
const hygiene = applyPackageHygiene(pkg);
|
|
2380
|
+
if (hygiene.length) {
|
|
2381
|
+
if (!dry)
|
|
2382
|
+
writePackageJson(pkg, cwd);
|
|
2383
|
+
console.log(` ${hygiene.join(", ")}`);
|
|
2384
|
+
} else {
|
|
2385
|
+
console.log(" \u0431\u0435\u0437 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439.");
|
|
2386
|
+
}
|
|
2387
|
+
console.log(`
|
|
2388
|
+
${prefix}2) migrate front (\u0430\u043B\u0438\u0430\u0441\u044B, native, \u0442\u043E\u043A\u0435\u043D\u044B, size, Modal.Create, \u2026)`);
|
|
2389
|
+
const migrate = await migrateFrontAll(cwd, dry);
|
|
2390
|
+
printChanges(migrate, "\u043A\u043E\u0434\u0430 \u043C\u0435\u043D\u044F\u0442\u044C \u043D\u0435 \u043D\u0443\u0436\u043D\u043E.");
|
|
2391
|
+
let hacks = [];
|
|
2392
|
+
if (opts.hacks) {
|
|
2393
|
+
console.log(`
|
|
2394
|
+
${prefix}2b) migrate legacy-hacks`);
|
|
2395
|
+
hacks = await migrateLegacyReactHack(cwd, dry);
|
|
2396
|
+
printChanges(hacks, "\u0445\u0430\u043A\u043E\u0432 \u043D\u0435\u0442.");
|
|
2397
|
+
}
|
|
2398
|
+
console.log(`
|
|
2399
|
+
${prefix}3) CSS: \u043D\u0435\u0434\u043E\u0441\u0442\u0430\u044E\u0449\u0438\u0435 --field-* / \u0442\u043E\u043A\u0435\u043D\u044B \u043F\u0430\u043A\u0435\u0442\u043E\u0432, \u2212\u0431\u0438\u0442\u044B\u0435 @import`);
|
|
2400
|
+
let css = null;
|
|
2401
|
+
let cssError = null;
|
|
2402
|
+
const names = uniqueElcrmNamesInTree(cwd, pkg);
|
|
2403
|
+
if (!names.length) {
|
|
2404
|
+
console.log(" \u043D\u0435\u0442 @elcrm/* \u2014 sync CSS \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D.");
|
|
2405
|
+
} else {
|
|
2406
|
+
try {
|
|
2407
|
+
css = syncElcrmCss({
|
|
2408
|
+
cwd,
|
|
2409
|
+
pkgNames: names,
|
|
2410
|
+
dry
|
|
2411
|
+
});
|
|
2412
|
+
printCssSync(css);
|
|
2413
|
+
} catch (e) {
|
|
2414
|
+
cssError = e instanceof Error ? e.message : String(e);
|
|
2415
|
+
console.log(` ${c.gray(cssError)}`);
|
|
2416
|
+
}
|
|
1887
2417
|
}
|
|
2418
|
+
console.log(`
|
|
2419
|
+
${prefix}4) css-sanitize (\u043E\u0441\u0438\u0440\u043E\u0442\u0435\u0432\u0448\u0438\u0439 color-mix)`);
|
|
2420
|
+
const sanitize = await migrateCssSanitize(cwd, dry);
|
|
2421
|
+
printChanges(sanitize, "\u0431\u0435\u0437 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439.");
|
|
2422
|
+
return { hygiene, migrate, css, cssError, sanitize, hacks };
|
|
1888
2423
|
}
|
|
1889
2424
|
|
|
2425
|
+
// src/commands/test.ts
|
|
2426
|
+
import { resolve } from "path";
|
|
2427
|
+
|
|
1890
2428
|
// src/lib/test/front.ts
|
|
1891
|
-
import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as
|
|
2429
|
+
import { existsSync as existsSync8, readdirSync as readdirSync5, readFileSync as readFileSync16, statSync as statSync5 } from "fs";
|
|
1892
2430
|
import { join as join8, relative as relative2 } from "path";
|
|
1893
|
-
init_form_tokens();
|
|
1894
|
-
init_components();
|
|
1895
|
-
init_css_sanitize();
|
|
1896
2431
|
var SKIP = new Set(["node_modules", "dist", ".git", "coverage", ".bun"]);
|
|
1897
2432
|
function isThemeTokenFile(rel2) {
|
|
1898
2433
|
const n = rel2.replace(/\\/g, "/");
|
|
@@ -1909,6 +2444,9 @@ function lineForColorScan(line) {
|
|
|
1909
2444
|
return line.replace(/var\([^)]*\)/g, "").replace(/url\s*\([^)]*\)/gi, "");
|
|
1910
2445
|
}
|
|
1911
2446
|
function hardcodedColorReason(line) {
|
|
2447
|
+
const trimmed = line.trim();
|
|
2448
|
+
if (/^--[\w-]+\s*:/.test(trimmed))
|
|
2449
|
+
return null;
|
|
1912
2450
|
const s = lineForColorScan(line);
|
|
1913
2451
|
if (HARD_HEX_RE.test(s) || HARD_RGB_RE.test(s) || JSX_COLOR_PROP_RE.test(line)) {
|
|
1914
2452
|
return "\u043B\u0438\u0442\u0435\u0440\u0430\u043B \u0446\u0432\u0435\u0442\u0430 \u2014 var(--button-*|--field-*|--item-*|--layout-*) \u0438\u0437 theme";
|
|
@@ -2027,6 +2565,7 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2027
2565
|
}
|
|
2028
2566
|
const files = [];
|
|
2029
2567
|
walkCode(join8(cwd, "src"), files);
|
|
2568
|
+
walkCode(join8(cwd, "web", "src"), files);
|
|
2030
2569
|
walkCode(join8(cwd, "style"), files);
|
|
2031
2570
|
for (const name of ["bootstrap.tsx", "bootstrap.ts", "main.tsx", "main.ts", "index.tsx", "index.ts", "App.tsx"]) {
|
|
2032
2571
|
const full = join8(cwd, name);
|
|
@@ -2037,7 +2576,7 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2037
2576
|
files.push(inSrc);
|
|
2038
2577
|
}
|
|
2039
2578
|
for (const file of files) {
|
|
2040
|
-
const text =
|
|
2579
|
+
const text = readFileSync16(file, "utf8");
|
|
2041
2580
|
const rel2 = relative2(cwd, file);
|
|
2042
2581
|
const skipHardColor = isLib || isThemeTokenFile(rel2) || isGeneratedIcons(rel2);
|
|
2043
2582
|
if (DEPRECATED_SOCKET_IMPORT_RE.test(text)) {
|
|
@@ -2078,32 +2617,35 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2078
2617
|
});
|
|
2079
2618
|
}
|
|
2080
2619
|
const lines = text.split(/\r?\n/);
|
|
2620
|
+
let prevNonEmpty = "";
|
|
2081
2621
|
lines.forEach((line, i) => {
|
|
2082
2622
|
const trimmed = line.trim();
|
|
2083
2623
|
if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*")) {
|
|
2084
2624
|
return;
|
|
2085
2625
|
}
|
|
2086
2626
|
if (/<(?:input|textarea|select)\b/.test(line)) {
|
|
2087
|
-
if (pkg.name
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2627
|
+
if (pkg.name !== "@elcrm/form") {
|
|
2628
|
+
issues.push({
|
|
2629
|
+
level: "error",
|
|
2630
|
+
code: "native-html-input",
|
|
2631
|
+
message: "\u043D\u0430\u0442\u0438\u0432\u043D\u044B\u0439 <input|textarea|select> \u2014 @elcrm/form (elcrm migrate native-html)",
|
|
2632
|
+
file: rel2,
|
|
2633
|
+
line: i + 1,
|
|
2634
|
+
fixable: true
|
|
2635
|
+
});
|
|
2636
|
+
}
|
|
2096
2637
|
}
|
|
2097
|
-
if (/(?:^|\s)native(?:\s|$|=|\/|>)/.test(line) && !/\bnavigator\b|\bnativeEvent\b|\bcreateNative/.test(line)) {
|
|
2098
|
-
if (pkg.name
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2638
|
+
if (/(?:^|\s)native(?:\s|$|=|\/|>)/.test(line) && !/\bnavigator\b|\bnativeEvent\b|\bcreateNative/.test(line) && !/['"`]native['"`]/.test(line) && !(/\binstallMode\b/.test(line) && /\bnative\b/.test(line))) {
|
|
2639
|
+
if (pkg.name !== "@elcrm/form") {
|
|
2640
|
+
issues.push({
|
|
2641
|
+
level: "warn",
|
|
2642
|
+
code: "form-native-prop",
|
|
2643
|
+
message: "prop native \u0443 \u043F\u043E\u043B\u044F \u0444\u043E\u0440\u043C\u044B \u2014 \u0443\u0431\u0435\u0440\u0438\u0442\u0435 (elcrm migrate form-native)",
|
|
2644
|
+
file: rel2,
|
|
2645
|
+
line: i + 1,
|
|
2646
|
+
fixable: true
|
|
2647
|
+
});
|
|
2648
|
+
}
|
|
2107
2649
|
}
|
|
2108
2650
|
if (/size\s*=\s*["'](?:sm|md)["']/.test(line) && !/titleSize/.test(line)) {
|
|
2109
2651
|
issues.push({
|
|
@@ -2155,7 +2697,7 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2155
2697
|
fixable: true
|
|
2156
2698
|
});
|
|
2157
2699
|
}
|
|
2158
|
-
if (lineHasOrphanColorMix(line)) {
|
|
2700
|
+
if (lineHasOrphanColorMix(line, prevNonEmpty)) {
|
|
2159
2701
|
issues.push({
|
|
2160
2702
|
level: "error",
|
|
2161
2703
|
code: "css-orphan-mix",
|
|
@@ -2165,6 +2707,8 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2165
2707
|
fixable: true
|
|
2166
2708
|
});
|
|
2167
2709
|
}
|
|
2710
|
+
if (trimmed.length > 0)
|
|
2711
|
+
prevNonEmpty = line;
|
|
2168
2712
|
if (/\b(Block|Row|Column)\b/.test(line) && /@elcrm\/components/.test(text) && /from\s+["']@elcrm\/components/.test(text)) {
|
|
2169
2713
|
if (/import\s*\{[^}]*\b(Block|Row|Column)\b/.test(line) || /<\/?(?:Block|Row|Column)\b/.test(line)) {
|
|
2170
2714
|
issues.push({
|
|
@@ -2204,7 +2748,7 @@ function collectFrontIssues(cwd, pkg) {
|
|
|
2204
2748
|
return issues;
|
|
2205
2749
|
}
|
|
2206
2750
|
async function runPkgScript(cwd, script) {
|
|
2207
|
-
const pkg = JSON.parse(
|
|
2751
|
+
const pkg = JSON.parse(readFileSync16(join8(cwd, "package.json"), "utf8"));
|
|
2208
2752
|
if (!pkg.scripts?.[script])
|
|
2209
2753
|
return { ran: false, ok: true };
|
|
2210
2754
|
console.log(`\u2192 bun run ${script}`);
|
|
@@ -2247,7 +2791,7 @@ function printIssues(issues, title) {
|
|
|
2247
2791
|
}
|
|
2248
2792
|
|
|
2249
2793
|
// src/lib/test/serverScan.ts
|
|
2250
|
-
import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as
|
|
2794
|
+
import { existsSync as existsSync9, readdirSync as readdirSync6, readFileSync as readFileSync17, statSync as statSync6 } from "fs";
|
|
2251
2795
|
import { join as join9, relative as relative3 } from "path";
|
|
2252
2796
|
|
|
2253
2797
|
// src/lib/test/serverRules.ts
|
|
@@ -2649,7 +3193,7 @@ function scanServerProject(root) {
|
|
|
2649
3193
|
walkFiles2(root, root, files);
|
|
2650
3194
|
const findings = [];
|
|
2651
3195
|
for (const file of files) {
|
|
2652
|
-
const text =
|
|
3196
|
+
const text = readFileSync17(file, "utf8");
|
|
2653
3197
|
if (file.endsWith("package.json")) {
|
|
2654
3198
|
findings.push(...scanPackageJson(root, file, text));
|
|
2655
3199
|
} else {
|
|
@@ -2697,7 +3241,7 @@ elcrm test (server) \u2014 ${root}`);
|
|
|
2697
3241
|
}
|
|
2698
3242
|
|
|
2699
3243
|
// src/commands/test.ts
|
|
2700
|
-
async function testOneDir(cwd, force, runScripts) {
|
|
3244
|
+
async function testOneDir(cwd, force, runScripts, fix, dry) {
|
|
2701
3245
|
const pkg = readPkgAt(cwd);
|
|
2702
3246
|
if (!pkg) {
|
|
2703
3247
|
console.error(`package.json \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${cwd}`);
|
|
@@ -2711,14 +3255,32 @@ elcrm test \u2014 ${cwd}
|
|
|
2711
3255
|
const result = scanServerProject(cwd);
|
|
2712
3256
|
return printServerFindings(result);
|
|
2713
3257
|
}
|
|
3258
|
+
if (fix) {
|
|
3259
|
+
console.log(`
|
|
3260
|
+
${c.cyan("\u2192")} migrate front${dry ? " (--dry)" : ""}\u2026`);
|
|
3261
|
+
const changes = await migrateFrontAll(cwd, dry);
|
|
3262
|
+
if (!changes.length) {
|
|
3263
|
+
console.log("\u0410\u0432\u0442\u043E\u043C\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043D\u0435 \u043F\u043E\u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043B\u043E\u0441\u044C.");
|
|
3264
|
+
} else {
|
|
3265
|
+
for (const ch of changes) {
|
|
3266
|
+
console.log(` ${ch.file}: ${ch.detail}`);
|
|
3267
|
+
}
|
|
3268
|
+
console.log(dry ? `
|
|
3269
|
+
--dry: ${changes.length} \u043F\u043E\u0442\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439.` : `
|
|
3270
|
+
\u041F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E: ${changes.length}.`);
|
|
3271
|
+
}
|
|
3272
|
+
if (dry) {
|
|
3273
|
+
console.log(c.gray("(--dry: \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0430\u043D\u0430\u043B\u0438\u0437 \u043F\u043E \u0438\u0441\u0445\u043E\u0434\u043D\u043E\u043C\u0443 \u043A\u043E\u0434\u0443)"));
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
2714
3276
|
const issues = collectFrontIssues(cwd, pkg);
|
|
2715
3277
|
let errors = printIssues(issues, `
|
|
2716
3278
|
\u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0430\u043D\u0430\u043B\u0438\u0437:`);
|
|
2717
|
-
if (runScripts) {
|
|
3279
|
+
if (runScripts && !dry) {
|
|
2718
3280
|
console.log("");
|
|
2719
3281
|
const scriptFails = await runFrontScripts(cwd);
|
|
2720
3282
|
errors += scriptFails;
|
|
2721
|
-
} else {
|
|
3283
|
+
} else if (!runScripts) {
|
|
2722
3284
|
console.log(c.gray(`
|
|
2723
3285
|
(--no-scripts: check:css / check:tokens / test \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D\u044B)`));
|
|
2724
3286
|
}
|
|
@@ -2728,6 +3290,8 @@ async function cmdTest(parsed) {
|
|
|
2728
3290
|
const target = resolve(parsed.positionals[0] ?? process.cwd());
|
|
2729
3291
|
const force = hasFlag(parsed, "server") ? "server" : hasFlag(parsed, "front") ? "front" : null;
|
|
2730
3292
|
const runScripts = !hasFlag(parsed, "no-scripts");
|
|
3293
|
+
const fix = hasFlag(parsed, "fix");
|
|
3294
|
+
const dry = hasFlag(parsed, "dry");
|
|
2731
3295
|
const rootPkg = readPkgAt(target);
|
|
2732
3296
|
if (!rootPkg) {
|
|
2733
3297
|
console.error("package.json \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.");
|
|
@@ -2739,17 +3303,20 @@ async function cmdTest(parsed) {
|
|
|
2739
3303
|
console.log(c.dim(`workspaces: ${workspaces.map((d) => d.replace(target + "/", "")).join(", ")}`));
|
|
2740
3304
|
const rootHasElcrm = Boolean(rootPkg.dependencies && Object.keys(rootPkg.dependencies).some((k) => k.startsWith("@elcrm/"))) || Boolean(rootPkg.devDependencies && Object.keys(rootPkg.devDependencies).some((k) => k.startsWith("@elcrm/")));
|
|
2741
3305
|
if (rootHasElcrm || hasFlag(parsed, "root")) {
|
|
2742
|
-
totalErrors += await testOneDir(target, force, runScripts);
|
|
3306
|
+
totalErrors += await testOneDir(target, force, runScripts, fix, dry);
|
|
2743
3307
|
}
|
|
2744
3308
|
for (const dir of workspaces) {
|
|
2745
|
-
totalErrors += await testOneDir(dir, force, runScripts);
|
|
3309
|
+
totalErrors += await testOneDir(dir, force, runScripts, fix, dry);
|
|
2746
3310
|
}
|
|
2747
3311
|
} else {
|
|
2748
|
-
totalErrors += await testOneDir(target, force, runScripts);
|
|
3312
|
+
totalErrors += await testOneDir(target, force, runScripts, fix, dry);
|
|
2749
3313
|
}
|
|
2750
3314
|
if (totalErrors > 0) {
|
|
2751
3315
|
console.log(c.yellow(`
|
|
2752
3316
|
elcrm test: ${totalErrors} error(s)`));
|
|
3317
|
+
if (!fix) {
|
|
3318
|
+
console.log(c.dim("\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435: elcrm test --fix / elcrm migrate front"));
|
|
3319
|
+
}
|
|
2753
3320
|
process.exit(1);
|
|
2754
3321
|
}
|
|
2755
3322
|
console.log(c.green(`
|
|
@@ -2827,29 +3394,8 @@ async function cmdUpdate(parsed) {
|
|
|
2827
3394
|
--dry: \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u043D\u0435 \u0437\u0430\u043F\u0438\u0441\u0430\u043D\u043E (\u043A \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044E: ${changed}).`);
|
|
2828
3395
|
if (doFix) {
|
|
2829
3396
|
console.log(`
|
|
2830
|
-
--fix + --dry: \u043F\u0440\u0435\u0432\u044C\u044E
|
|
2831
|
-
|
|
2832
|
-
if (front.length === 0)
|
|
2833
|
-
console.log(" \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u0439 \u043A\u043E\u0434\u0430 \u043D\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F.");
|
|
2834
|
-
else
|
|
2835
|
-
for (const c2 of front)
|
|
2836
|
-
console.log(` ${c2.file}: ${c2.detail}`);
|
|
2837
|
-
console.log(`
|
|
2838
|
-
--fix + --dry: \u043F\u0440\u0435\u0432\u044C\u044E CSS-\u0442\u043E\u043A\u0435\u043D\u043E\u0432\u2026`);
|
|
2839
|
-
try {
|
|
2840
|
-
const css = syncElcrmCss({ cwd, pkgNames: names, dry: true });
|
|
2841
|
-
let n = 0;
|
|
2842
|
-
for (const [file, tokens] of Object.entries(css.added)) {
|
|
2843
|
-
if (!tokens.length)
|
|
2844
|
-
continue;
|
|
2845
|
-
n += tokens.length;
|
|
2846
|
-
console.log(` ${file}: ${tokens.join(", ")}`);
|
|
2847
|
-
}
|
|
2848
|
-
if (n === 0)
|
|
2849
|
-
console.log(" \u041D\u043E\u0432\u044B\u0445 \u0442\u043E\u043A\u0435\u043D\u043E\u0432 \u043D\u0435\u0442.");
|
|
2850
|
-
} catch (e) {
|
|
2851
|
-
console.log(` ${c.gray("css:")} ${e instanceof Error ? e.message : e}`);
|
|
2852
|
-
}
|
|
3397
|
+
--fix + --dry: \u043F\u0440\u0435\u0432\u044C\u044E \u043D\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u044F \u043F\u043E\u0440\u044F\u0434\u043A\u0430 (\u043A\u0430\u043A elcrm doctor)\u2026`);
|
|
3398
|
+
await tidyFrontProject({ cwd, pkg, dry: true });
|
|
2853
3399
|
}
|
|
2854
3400
|
return;
|
|
2855
3401
|
}
|
|
@@ -2872,46 +3418,9 @@ package.json \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D (${changed}).`);
|
|
|
2872
3418
|
}
|
|
2873
3419
|
if (doFix) {
|
|
2874
3420
|
console.log(`
|
|
2875
|
-
--fix:
|
|
2876
|
-
const
|
|
2877
|
-
|
|
2878
|
-
console.log(" \u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u043A\u043E\u0434\u0430 \u043D\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F.");
|
|
2879
|
-
} else {
|
|
2880
|
-
for (const ch of front)
|
|
2881
|
-
console.log(` ${ch.file}: ${ch.detail}`);
|
|
2882
|
-
console.log(` \u041F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E: ${front.length}.`);
|
|
2883
|
-
}
|
|
2884
|
-
console.log(`
|
|
2885
|
-
--fix: sync CSS-\u0442\u043E\u043A\u0435\u043D\u043E\u0432 (elcrm css)\u2026`);
|
|
2886
|
-
try {
|
|
2887
|
-
const pkgAfter = readPackageJson(cwd) ?? pkg;
|
|
2888
|
-
const cssNames = uniqueElcrmNames(listElcrmDeps(pkgAfter));
|
|
2889
|
-
const css = syncElcrmCss({ cwd, pkgNames: cssNames, dry: false });
|
|
2890
|
-
let added = 0;
|
|
2891
|
-
for (const [file, tokens] of Object.entries(css.added)) {
|
|
2892
|
-
if (!tokens.length)
|
|
2893
|
-
continue;
|
|
2894
|
-
added += tokens.length;
|
|
2895
|
-
console.log(` ${c.green("+")} ${file}: ${tokens.join(", ")}`);
|
|
2896
|
-
}
|
|
2897
|
-
if (css.imports.length) {
|
|
2898
|
-
console.log(` ${c.green("+")} elcrm.css @import: ${css.imports.join(", ")}`);
|
|
2899
|
-
}
|
|
2900
|
-
if (css.removedImports.length) {
|
|
2901
|
-
console.log(` ${c.red("\u2212")} elcrm.css \u0431\u0438\u0442\u044B\u0435 @import: ${css.removedImports.join(", ")}`);
|
|
2902
|
-
}
|
|
2903
|
-
if (added === 0 && css.imports.length === 0 && css.removedImports.length === 0) {
|
|
2904
|
-
console.log(" \u0422\u043E\u043A\u0435\u043D\u044B \u0443\u0436\u0435 \u043D\u0430 \u043C\u0435\u0441\u0442\u0435.");
|
|
2905
|
-
}
|
|
2906
|
-
const cleaned = await migrateCssSanitize(cwd, false);
|
|
2907
|
-
if (cleaned.length) {
|
|
2908
|
-
console.log(" css-sanitize:");
|
|
2909
|
-
for (const ch of cleaned)
|
|
2910
|
-
console.log(` ${ch.file}: ${ch.detail}`);
|
|
2911
|
-
}
|
|
2912
|
-
} catch (e) {
|
|
2913
|
-
console.log(` ${c.gray("css sync \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D:")} ${e instanceof Error ? e.message : e}`);
|
|
2914
|
-
}
|
|
3421
|
+
--fix: \u043D\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u043F\u043E\u0440\u044F\u0434\u043A\u0430 (elcrm doctor)\u2026`);
|
|
3422
|
+
const pkgAfter = readPackageJson(cwd) ?? pkg;
|
|
3423
|
+
await tidyFrontProject({ cwd, pkg: pkgAfter, dry: false });
|
|
2915
3424
|
}
|
|
2916
3425
|
if (doTest) {
|
|
2917
3426
|
console.log(`
|
|
@@ -2933,7 +3442,7 @@ import {
|
|
|
2933
3442
|
existsSync as existsSync11,
|
|
2934
3443
|
mkdirSync,
|
|
2935
3444
|
readdirSync as readdirSync7,
|
|
2936
|
-
readFileSync as
|
|
3445
|
+
readFileSync as readFileSync18,
|
|
2937
3446
|
statSync as statSync7,
|
|
2938
3447
|
writeFileSync as writeFileSync5
|
|
2939
3448
|
} from "fs";
|
|
@@ -2977,7 +3486,7 @@ function isEmptyDir(dir) {
|
|
|
2977
3486
|
function writePkgName(pkgPath, name) {
|
|
2978
3487
|
if (!existsSync11(pkgPath))
|
|
2979
3488
|
return;
|
|
2980
|
-
const pkg = JSON.parse(
|
|
3489
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
2981
3490
|
pkg.name = name;
|
|
2982
3491
|
pkg.version = pkg.version ?? "0.0.0";
|
|
2983
3492
|
writeFileSync5(pkgPath, JSON.stringify(pkg, null, 2) + `
|
|
@@ -3031,6 +3540,16 @@ function libPackageName(pathOrName) {
|
|
|
3031
3540
|
function doneHint(template, cdPath) {
|
|
3032
3541
|
const prefix = cdPath ? ` cd ${cdPath}
|
|
3033
3542
|
` : "";
|
|
3543
|
+
if (template === "orbit") {
|
|
3544
|
+
console.log(`
|
|
3545
|
+
\u0413\u043E\u0442\u043E\u0432\u043E (orbit: \u0432\u0438\u0442\u0440\u0438\u043D\u0430 \u043D\u0430 @elcrm/components).
|
|
3546
|
+
|
|
3547
|
+
${prefix} bun run dev
|
|
3548
|
+
|
|
3549
|
+
Web \u2192 http://localhost:5173
|
|
3550
|
+
`);
|
|
3551
|
+
return;
|
|
3552
|
+
}
|
|
3034
3553
|
if (template === "panel") {
|
|
3035
3554
|
console.log(`
|
|
3036
3555
|
\u0413\u043E\u0442\u043E\u0432\u043E (panel: web + api).
|
|
@@ -3099,8 +3618,6 @@ async function cmdInit(parsed) {
|
|
|
3099
3618
|
}
|
|
3100
3619
|
|
|
3101
3620
|
// src/commands/migrate.ts
|
|
3102
|
-
init_socket_server();
|
|
3103
|
-
init_front();
|
|
3104
3621
|
var MIGRATIONS = {
|
|
3105
3622
|
"socket-server": migrateSocketServer,
|
|
3106
3623
|
...FRONT_MIGRATIONS,
|
|
@@ -3138,101 +3655,255 @@ async function cmdMigrate(parsed) {
|
|
|
3138
3655
|
console.log("\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u043D\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F.");
|
|
3139
3656
|
return;
|
|
3140
3657
|
}
|
|
3141
|
-
for (const c2 of changes) {
|
|
3142
|
-
console.log(` ${c2.file}: ${c2.detail}`);
|
|
3658
|
+
for (const c2 of changes) {
|
|
3659
|
+
console.log(` ${c2.file}: ${c2.detail}`);
|
|
3660
|
+
}
|
|
3661
|
+
console.log(dry ? `
|
|
3662
|
+
--dry: ${changes.length} \u043F\u043E\u0442\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439.` : `
|
|
3663
|
+
\u041F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u043E: ${changes.length}.`);
|
|
3664
|
+
if (name === "front" || name === "ui" || name === "size-sml" || name === "form-tokens" || name === "form-native" || name === "native-html" || name === "components" || name === "css-sanitize") {
|
|
3665
|
+
console.log("\u0414\u0430\u043B\u044C\u0448\u0435: elcrm css && elcrm audit");
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
// src/commands/doctor.ts
|
|
3670
|
+
import { resolve as resolve5 } from "path";
|
|
3671
|
+
|
|
3672
|
+
// src/commands/docs.ts
|
|
3673
|
+
import { join as join13, resolve as resolve3 } from "path";
|
|
3674
|
+
|
|
3675
|
+
// src/lib/projectKind.ts
|
|
3676
|
+
function detectProjectKind(cwd) {
|
|
3677
|
+
const pkg = readPkgAt(cwd);
|
|
3678
|
+
if (!pkg)
|
|
3679
|
+
return "front";
|
|
3680
|
+
const workspaces = listWorkspaceDirs(cwd, pkg);
|
|
3681
|
+
if (workspaces.length) {
|
|
3682
|
+
const modes = new Set;
|
|
3683
|
+
for (const dir of workspaces) {
|
|
3684
|
+
const w = readPkgAt(dir);
|
|
3685
|
+
if (w)
|
|
3686
|
+
modes.add(detectTestMode(w));
|
|
3687
|
+
}
|
|
3688
|
+
if (modes.has("front") && modes.has("server"))
|
|
3689
|
+
return "mixed";
|
|
3690
|
+
if (modes.has("server") && !modes.has("front"))
|
|
3691
|
+
return "server";
|
|
3692
|
+
if (modes.has("front"))
|
|
3693
|
+
return "front";
|
|
3694
|
+
}
|
|
3695
|
+
return hasElcrmServer(pkg) ? "server" : "front";
|
|
3696
|
+
}
|
|
3697
|
+
function isElcrmLibPackage(cwd) {
|
|
3698
|
+
const pkg = readPkgAt(cwd);
|
|
3699
|
+
const name = pkg?.name;
|
|
3700
|
+
return typeof name === "string" && name.startsWith("@elcrm/");
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
// src/lib/elcrmDocsCatalog.ts
|
|
3704
|
+
var ALL_ELCRM_DOCS = [
|
|
3705
|
+
"CLI.elCRM.md",
|
|
3706
|
+
"API.elCRM.md",
|
|
3707
|
+
"ALERT.elCRM.md",
|
|
3708
|
+
"BUTTON.elCRM.md",
|
|
3709
|
+
"MODAL.elCRM.md",
|
|
3710
|
+
"NOTICE.elCRM.md",
|
|
3711
|
+
"NOTIFICATIONS.elCRM.md",
|
|
3712
|
+
"PASSKEY.elCRM.md",
|
|
3713
|
+
"ROUTER.elCRM.md",
|
|
3714
|
+
"SOCKET.elCRM.md",
|
|
3715
|
+
"TOOLTIP.elCRM.md",
|
|
3716
|
+
"ICONS.elCRM.md",
|
|
3717
|
+
"FORM.elCRM.md",
|
|
3718
|
+
"COMPONENTS.elCRM.md",
|
|
3719
|
+
"SERVER.elCRM.md"
|
|
3720
|
+
];
|
|
3721
|
+
var SERVER_DOCS = [
|
|
3722
|
+
"SERVER.elCRM.md",
|
|
3723
|
+
"CLI.elCRM.md",
|
|
3724
|
+
"API.elCRM.md",
|
|
3725
|
+
"SOCKET.elCRM.md"
|
|
3726
|
+
];
|
|
3727
|
+
function docsForProject(kind, lib) {
|
|
3728
|
+
if (lib || kind === "front" || kind === "mixed")
|
|
3729
|
+
return ALL_ELCRM_DOCS;
|
|
3730
|
+
return SERVER_DOCS;
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
// src/lib/scaffoldFiles.ts
|
|
3734
|
+
import {
|
|
3735
|
+
existsSync as existsSync12,
|
|
3736
|
+
mkdirSync as mkdirSync2,
|
|
3737
|
+
readdirSync as readdirSync8,
|
|
3738
|
+
readFileSync as readFileSync19,
|
|
3739
|
+
writeFileSync as writeFileSync6
|
|
3740
|
+
} from "fs";
|
|
3741
|
+
import { dirname as dirname3, join as join12 } from "path";
|
|
3742
|
+
function writeScaffoldFile(dest, body, opts) {
|
|
3743
|
+
if (opts.dry)
|
|
3744
|
+
return "dry";
|
|
3745
|
+
if (!opts.force && existsSync12(dest))
|
|
3746
|
+
return "skip";
|
|
3747
|
+
mkdirSync2(dirname3(dest), { recursive: true });
|
|
3748
|
+
writeFileSync6(dest, body, "utf8");
|
|
3749
|
+
return "write";
|
|
3750
|
+
}
|
|
3751
|
+
function readBundled(relPath) {
|
|
3752
|
+
const full = join12(packageRoot(), "templates", relPath);
|
|
3753
|
+
if (!existsSync12(full)) {
|
|
3754
|
+
throw new Error(`\u0428\u0430\u0431\u043B\u043E\u043D \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${relPath}`);
|
|
3755
|
+
}
|
|
3756
|
+
return readFileSync19(full, "utf8");
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
// src/commands/docs.ts
|
|
3760
|
+
async function cmdDocs(parsed) {
|
|
3761
|
+
const cwd = resolve3(parsed.options.dir || process.cwd());
|
|
3762
|
+
const dry = hasFlag(parsed, "dry");
|
|
3763
|
+
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3764
|
+
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
3765
|
+
const kind = detectProjectKind(cwd);
|
|
3766
|
+
const names = docsForProject(kind, lib);
|
|
3767
|
+
console.log(`${dry ? "[dry] " : ""}elcrm docs \u2192 ${cwd}/docs (${kind}${lib ? ", lib" : ""})`);
|
|
3768
|
+
for (const name of names) {
|
|
3769
|
+
const body = readBundled(join13("elcrm-docs", name));
|
|
3770
|
+
const dest = join13(cwd, "docs", name);
|
|
3771
|
+
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
3772
|
+
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
3773
|
+
console.log(` ${mark} docs/${name}`);
|
|
3774
|
+
}
|
|
3775
|
+
if (kind === "server" && !lib) {
|
|
3776
|
+
console.log(c.gray("\u0441\u0435\u0440\u0432\u0435\u0440: SERVER, CLI, API, SOCKET"));
|
|
3143
3777
|
}
|
|
3144
|
-
console.log(
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3778
|
+
console.log("\u0414\u0430\u043B\u044C\u0448\u0435: elcrm cursor \u2014 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0432 .cursor/rules (+ .cursor/docs)");
|
|
3779
|
+
}
|
|
3780
|
+
|
|
3781
|
+
// src/commands/cursor.ts
|
|
3782
|
+
import { join as join14, resolve as resolve4 } from "path";
|
|
3783
|
+
var ALWAYS = ["elcrm.mdc", "elcrm-packages.mdc", "elcrm-jsdoc.mdc"];
|
|
3784
|
+
var UI = [
|
|
3785
|
+
"elcrm-ui.mdc",
|
|
3786
|
+
"elcrm-module.mdc",
|
|
3787
|
+
"elcrm-theme.mdc",
|
|
3788
|
+
"elcrm-tokens.mdc"
|
|
3789
|
+
];
|
|
3790
|
+
var SERVER = ["elcrm-server.mdc", "elcrm-rpc.mdc"];
|
|
3791
|
+
var LIB = ["elcrm-lib.mdc"];
|
|
3792
|
+
function writeOne(dest, body, dry, force, label) {
|
|
3793
|
+
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
3794
|
+
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
3795
|
+
console.log(` ${mark} ${label}`);
|
|
3796
|
+
}
|
|
3797
|
+
async function cmdCursor(parsed) {
|
|
3798
|
+
const cwd = resolve4(parsed.options.dir || process.cwd());
|
|
3799
|
+
const dry = hasFlag(parsed, "dry");
|
|
3800
|
+
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3801
|
+
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
3802
|
+
const kind = detectProjectKind(cwd);
|
|
3803
|
+
const ruleNames = [
|
|
3804
|
+
...ALWAYS,
|
|
3805
|
+
...kind === "server" ? [] : UI,
|
|
3806
|
+
...kind === "front" ? [] : SERVER,
|
|
3807
|
+
...lib ? LIB : []
|
|
3808
|
+
];
|
|
3809
|
+
console.log(`${dry ? "[dry] " : ""}elcrm cursor \u2192 ${cwd}/.cursor (${kind}${lib ? ", lib" : ""})`);
|
|
3810
|
+
for (const name of ruleNames) {
|
|
3811
|
+
let body = readBundled(join14("elcrm-cursor", "rules", name));
|
|
3812
|
+
if (kind === "server" && (name === "elcrm-server.mdc" || name === "elcrm-rpc.mdc")) {
|
|
3813
|
+
body = body.replace("alwaysApply: false", "alwaysApply: true").replace(/^globs:.*\n/m, "");
|
|
3814
|
+
}
|
|
3815
|
+
writeOne(join14(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
|
|
3816
|
+
}
|
|
3817
|
+
const docs = docsForProject(kind, lib);
|
|
3818
|
+
for (const name of docs) {
|
|
3819
|
+
const body = readBundled(join14("elcrm-docs", name));
|
|
3820
|
+
writeOne(join14(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
|
|
3149
3821
|
}
|
|
3822
|
+
writeOne(join14(cwd, "AGENTS.md"), readBundled(join14("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
|
|
3823
|
+
console.log(c.gray("\u0410\u0433\u0435\u043D\u0442: AGENTS.md + rules (\u0443\u0437\u043A\u0438\u0435 glob) + .cursor/docs. \u0421\u0434\u0430\u0447\u0430: elcrm test."));
|
|
3150
3824
|
}
|
|
3151
3825
|
|
|
3152
3826
|
// src/commands/doctor.ts
|
|
3153
|
-
init_socket_server();
|
|
3154
|
-
init_pkg();
|
|
3155
3827
|
async function cmdDoctor(parsed) {
|
|
3156
|
-
const cwd = process.cwd();
|
|
3157
|
-
const
|
|
3828
|
+
const cwd = resolve5(parsed.options.dir || process.cwd());
|
|
3829
|
+
const dry = hasFlag(parsed, "dry");
|
|
3830
|
+
const doDocs = hasFlag(parsed, "docs");
|
|
3831
|
+
const doTest = hasFlag(parsed, "test");
|
|
3832
|
+
const hacks = hasFlag(parsed, "hacks");
|
|
3158
3833
|
const pkg = readPackageJson(cwd);
|
|
3159
3834
|
if (!pkg) {
|
|
3160
3835
|
console.error("package.json \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.");
|
|
3161
3836
|
process.exit(1);
|
|
3162
3837
|
}
|
|
3838
|
+
console.log(`elcrm doctor \u2192 ${cwd}`);
|
|
3839
|
+
console.log(c.dim("\u0441\u043A\u0440\u0438\u043F\u0442\u044B: package.json \u2192 migrate front (\u0441\u0442\u0430\u0440\u043E\u0435\u2192\u043D\u043E\u0432\u043E\u0435, \u2212\u043D\u0435\u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u043C\u043E\u0435) \u2192 css (\u2212\u0431\u0438\u0442\u044B\u0435 @import, +\u0442\u043E\u043A\u0435\u043D\u044B)"));
|
|
3840
|
+
if (dry) {
|
|
3841
|
+
console.log(c.gray("\u043F\u0440\u0435\u0432\u044C\u044E (--dry), \u0444\u0430\u0439\u043B\u044B \u043D\u0435 \u043F\u0438\u0448\u0435\u043C."));
|
|
3842
|
+
}
|
|
3843
|
+
const workspaces = listWorkspaceDirs(cwd, pkg);
|
|
3844
|
+
let errors = 0;
|
|
3845
|
+
const rootUiDeps = listElcrmDeps(pkg).filter((d) => d.name !== "@elcrm/server");
|
|
3846
|
+
const scanRootFront = workspaces.length === 0 ? !hasElcrmServer(pkg) : rootUiDeps.length > 0;
|
|
3163
3847
|
if (hasElcrmServer(pkg)) {
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
if (result.findings.some((f) => f.auto)) {
|
|
3168
|
-
console.log(`
|
|
3169
|
-
\u0410\u0432\u0442\u043E\u0437\u0430\u043C\u0435\u043D\u044B: bunx elcrm-server update (\u0438\u043B\u0438 elcrm migrate \u2026)`);
|
|
3170
|
-
}
|
|
3171
|
-
if (errors)
|
|
3172
|
-
process.exit(1);
|
|
3173
|
-
return;
|
|
3174
|
-
}
|
|
3175
|
-
console.log("doctor --fix \u043D\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435: \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 bunx elcrm-server update");
|
|
3176
|
-
if (errors)
|
|
3177
|
-
process.exit(1);
|
|
3178
|
-
return;
|
|
3848
|
+
console.log(`
|
|
3849
|
+
\u0441\u043A\u0430\u043D @elcrm/server:`);
|
|
3850
|
+
errors += printServerFindings(scanServerProject(cwd));
|
|
3179
3851
|
}
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3852
|
+
if (scanRootFront) {
|
|
3853
|
+
console.log(`
|
|
3854
|
+
\u0441\u043A\u0430\u043D UI:`);
|
|
3855
|
+
errors += printIssues(collectFrontIssues(cwd, pkg));
|
|
3184
3856
|
}
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3857
|
+
for (const dir of workspaces) {
|
|
3858
|
+
const child = readPackageJson(dir);
|
|
3859
|
+
if (!child)
|
|
3860
|
+
continue;
|
|
3861
|
+
if (hasElcrmServer(child)) {
|
|
3862
|
+
console.log(`
|
|
3863
|
+
\u0441\u043A\u0430\u043D server ${dir}:`);
|
|
3864
|
+
errors += printServerFindings(scanServerProject(dir));
|
|
3865
|
+
} else {
|
|
3189
3866
|
console.log(`
|
|
3190
|
-
\
|
|
3867
|
+
\u0441\u043A\u0430\u043D UI ${dir}:`);
|
|
3868
|
+
errors += printIssues(collectFrontIssues(dir, child));
|
|
3191
3869
|
}
|
|
3192
|
-
if (issues.some((i) => i.level === "error"))
|
|
3193
|
-
process.exit(1);
|
|
3194
|
-
return;
|
|
3195
|
-
}
|
|
3196
|
-
let pkgDirty = false;
|
|
3197
|
-
if (pkg.type !== "module") {
|
|
3198
|
-
pkg.type = "module";
|
|
3199
|
-
pkgDirty = true;
|
|
3200
|
-
}
|
|
3201
|
-
if (!pkg.engines)
|
|
3202
|
-
pkg.engines = {};
|
|
3203
|
-
if (!pkg.engines.node && !pkg.engines.bun) {
|
|
3204
|
-
pkg.engines.node = ">=18";
|
|
3205
|
-
pkgDirty = true;
|
|
3206
3870
|
}
|
|
3207
|
-
const
|
|
3208
|
-
if (
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3871
|
+
const tidy = await tidyFrontProject({ cwd, pkg, dry, hacks });
|
|
3872
|
+
if (doDocs) {
|
|
3873
|
+
const flags = dry ? ["dry"] : [];
|
|
3874
|
+
const child = {
|
|
3875
|
+
command: "docs",
|
|
3876
|
+
positionals: [],
|
|
3877
|
+
options: { dir: cwd },
|
|
3878
|
+
flags
|
|
3879
|
+
};
|
|
3880
|
+
console.log(`
|
|
3881
|
+
${dry ? "[dry] " : ""}docs + cursor`);
|
|
3882
|
+
await cmdDocs(child);
|
|
3883
|
+
await cmdCursor({ ...child, command: "cursor" });
|
|
3215
3884
|
}
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3885
|
+
const n = tidy.hygiene.length + tidy.migrate.length + tidy.sanitize.length + tidy.hacks.length + (tidy.css ? Object.values(tidy.css.added).reduce((a, t) => a + t.length, 0) + tidy.css.imports.length + tidy.css.removedImports.length : 0);
|
|
3886
|
+
if (dry) {
|
|
3887
|
+
console.log(`
|
|
3888
|
+
\u043F\u0440\u0435\u0432\u044C\u044E: ${n} \u043F\u043E\u0442\u0435\u043D\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u043F\u0440\u0430\u0432\u043E\u043A. \u041F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C: elcrm doctor`);
|
|
3889
|
+
} else {
|
|
3890
|
+
console.log(c.green(`
|
|
3891
|
+
doctor: \u0433\u043E\u0442\u043E\u0432\u043E (${n} \u043F\u0440\u0430\u0432\u043E\u043A).`));
|
|
3221
3892
|
}
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3893
|
+
if (doTest && !dry) {
|
|
3894
|
+
console.log(`
|
|
3895
|
+
--test: elcrm test\u2026`);
|
|
3896
|
+
await cmdTest(parseArgs(["test", cwd]));
|
|
3897
|
+
return;
|
|
3226
3898
|
}
|
|
3227
|
-
|
|
3228
|
-
|
|
3899
|
+
if (errors && dry)
|
|
3900
|
+
process.exit(1);
|
|
3229
3901
|
}
|
|
3230
3902
|
|
|
3231
3903
|
// src/commands/build.ts
|
|
3232
|
-
import { existsSync as
|
|
3904
|
+
import { existsSync as existsSync13 } from "fs";
|
|
3233
3905
|
|
|
3234
3906
|
// src/lib/nextVersion.ts
|
|
3235
|
-
init_pkg();
|
|
3236
3907
|
async function nextVersion() {
|
|
3237
3908
|
const pkg = readPackageJson();
|
|
3238
3909
|
if (!pkg?.version) {
|
|
@@ -3253,9 +3924,9 @@ async function nextVersion() {
|
|
|
3253
3924
|
|
|
3254
3925
|
// src/commands/build.ts
|
|
3255
3926
|
function resolveEntrypoint() {
|
|
3256
|
-
if (
|
|
3927
|
+
if (existsSync13("./src/index.js"))
|
|
3257
3928
|
return "./src/index.js";
|
|
3258
|
-
if (
|
|
3929
|
+
if (existsSync13("./src/index.ts"))
|
|
3259
3930
|
return "./src/index.ts";
|
|
3260
3931
|
return "./src/index.js";
|
|
3261
3932
|
}
|
|
@@ -3333,22 +4004,22 @@ async function cmdUuid() {
|
|
|
3333
4004
|
}
|
|
3334
4005
|
|
|
3335
4006
|
// src/commands/postbuild.ts
|
|
3336
|
-
import { resolve as
|
|
4007
|
+
import { resolve as resolve6 } from "path";
|
|
3337
4008
|
|
|
3338
4009
|
// src/vite/postbuild.ts
|
|
3339
4010
|
import {
|
|
3340
|
-
existsSync as
|
|
3341
|
-
readdirSync as
|
|
3342
|
-
readFileSync as
|
|
4011
|
+
existsSync as existsSync14,
|
|
4012
|
+
readdirSync as readdirSync10,
|
|
4013
|
+
readFileSync as readFileSync21,
|
|
3343
4014
|
rmSync,
|
|
3344
4015
|
statSync as statSync8,
|
|
3345
|
-
writeFileSync as
|
|
4016
|
+
writeFileSync as writeFileSync8
|
|
3346
4017
|
} from "fs";
|
|
3347
|
-
import { join as
|
|
4018
|
+
import { join as join16 } from "path";
|
|
3348
4019
|
|
|
3349
4020
|
// src/vite/concat-css.ts
|
|
3350
|
-
import { readdirSync as
|
|
3351
|
-
import { join as
|
|
4021
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync7 } from "fs";
|
|
4022
|
+
import { join as join15 } from "path";
|
|
3352
4023
|
var SKIP_CSS = new Set([
|
|
3353
4024
|
"index.css",
|
|
3354
4025
|
"tokens.css",
|
|
@@ -3363,11 +4034,11 @@ function concatDistCss(options) {
|
|
|
3363
4034
|
outFile,
|
|
3364
4035
|
...options.skip ?? []
|
|
3365
4036
|
]);
|
|
3366
|
-
const files =
|
|
3367
|
-
const css = files.map((f) =>
|
|
4037
|
+
const files = readdirSync9(options.distDir).filter((f) => f.endsWith(".css") && !skip.has(f)).sort();
|
|
4038
|
+
const css = files.map((f) => readFileSync20(join15(options.distDir, f), "utf8")).join(`
|
|
3368
4039
|
`);
|
|
3369
|
-
const outPath =
|
|
3370
|
-
|
|
4040
|
+
const outPath = join15(options.distDir, outFile);
|
|
4041
|
+
writeFileSync7(outPath, css);
|
|
3371
4042
|
console.log(`[concat-css] ${files.length} \u0444\u0430\u0439\u043B\u043E\u0432 \u2192 ${outFile}`);
|
|
3372
4043
|
return outPath;
|
|
3373
4044
|
}
|
|
@@ -3384,19 +4055,19 @@ function postbuildLib(options) {
|
|
|
3384
4055
|
distDir: dist,
|
|
3385
4056
|
outFile: options.cssOutFile ?? "index.css"
|
|
3386
4057
|
});
|
|
3387
|
-
for (const name of
|
|
3388
|
-
const dir =
|
|
4058
|
+
for (const name of readdirSync10(dist)) {
|
|
4059
|
+
const dir = join16(dist, name);
|
|
3389
4060
|
if (!statSync8(dir).isDirectory())
|
|
3390
4061
|
continue;
|
|
3391
4062
|
if (keep.has(name))
|
|
3392
4063
|
continue;
|
|
3393
|
-
const impl =
|
|
3394
|
-
const nestedIndex =
|
|
3395
|
-
const flat =
|
|
3396
|
-
const src =
|
|
4064
|
+
const impl = join16(dir, `${name}.d.ts`);
|
|
4065
|
+
const nestedIndex = join16(dir, "index.d.ts");
|
|
4066
|
+
const flat = join16(dist, `${name}.d.ts`);
|
|
4067
|
+
const src = existsSync14(impl) ? impl : existsSync14(nestedIndex) ? nestedIndex : null;
|
|
3397
4068
|
if (src) {
|
|
3398
|
-
const text =
|
|
3399
|
-
|
|
4069
|
+
const text = readFileSync21(src, "utf8").replace(/from ['"]\.\.\/([^'"]+)['"]/g, `from './$1'`);
|
|
4070
|
+
writeFileSync8(flat, text);
|
|
3400
4071
|
console.log(`[postbuild] types \u2192 ${name}.d.ts`);
|
|
3401
4072
|
}
|
|
3402
4073
|
rmSync(dir, { recursive: true, force: true });
|
|
@@ -3407,14 +4078,12 @@ function postbuildLib(options) {
|
|
|
3407
4078
|
// src/commands/postbuild.ts
|
|
3408
4079
|
async function cmdPostbuild(parsed) {
|
|
3409
4080
|
const dir = parsed.options.dir || "./dist";
|
|
3410
|
-
const distDir =
|
|
4081
|
+
const distDir = resolve6(process.cwd(), dir);
|
|
3411
4082
|
postbuildLib({ distDir });
|
|
3412
4083
|
console.log(`[postbuild] \u0433\u043E\u0442\u043E\u0432\u043E: ${distDir}`);
|
|
3413
4084
|
}
|
|
3414
4085
|
|
|
3415
4086
|
// src/commands/css.ts
|
|
3416
|
-
init_pkg();
|
|
3417
|
-
init_css_sanitize();
|
|
3418
4087
|
async function cmdCss(parsed) {
|
|
3419
4088
|
const cwd = parsed.options.dir || process.cwd();
|
|
3420
4089
|
const pkg = readPackageJson(cwd);
|
|
@@ -3477,14 +4146,8 @@ css-sanitize: \u043F\u043E\u0447\u0438\u043D\u0435\u043D\u043E ${cleaned.length}
|
|
|
3477
4146
|
}
|
|
3478
4147
|
|
|
3479
4148
|
// src/commands/audit.ts
|
|
3480
|
-
import { existsSync as
|
|
3481
|
-
import { join as
|
|
3482
|
-
init_pkg();
|
|
3483
|
-
init_walk();
|
|
3484
|
-
init_front();
|
|
3485
|
-
init_form_tokens();
|
|
3486
|
-
init_components();
|
|
3487
|
-
init_css_sanitize();
|
|
4149
|
+
import { existsSync as existsSync15, readFileSync as readFileSync22 } from "fs";
|
|
4150
|
+
import { join as join17, relative as relative4 } from "path";
|
|
3488
4151
|
function scan(cwd) {
|
|
3489
4152
|
const out = [];
|
|
3490
4153
|
const pkg = readPackageJson(cwd);
|
|
@@ -3515,7 +4178,7 @@ function scan(cwd) {
|
|
|
3515
4178
|
}
|
|
3516
4179
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
3517
4180
|
for (const file of files) {
|
|
3518
|
-
const text =
|
|
4181
|
+
const text = readFileSync22(file, "utf8");
|
|
3519
4182
|
const rel2 = relative4(cwd, file);
|
|
3520
4183
|
const lines = text.split(/\r?\n/);
|
|
3521
4184
|
lines.forEach((line, i) => {
|
|
@@ -3542,6 +4205,26 @@ function scan(cwd) {
|
|
|
3542
4205
|
fix: "elcrm migrate modal-create"
|
|
3543
4206
|
});
|
|
3544
4207
|
}
|
|
4208
|
+
if (/<(?:input|textarea|select)\b/.test(line)) {
|
|
4209
|
+
out.push({
|
|
4210
|
+
level: "error",
|
|
4211
|
+
code: "native-html-input",
|
|
4212
|
+
message: "\u043D\u0430\u0442\u0438\u0432\u043D\u044B\u0439 <input|textarea|select> \u2192 @elcrm/form",
|
|
4213
|
+
file: rel2,
|
|
4214
|
+
line: n,
|
|
4215
|
+
fix: "elcrm migrate native-html"
|
|
4216
|
+
});
|
|
4217
|
+
}
|
|
4218
|
+
if (/(?:^|\s)native(?:\s|$|=|\/|>)/.test(line) && !/\bnavigator\b|\bnativeEvent\b|\bcreateNative/.test(line) && !/['"`]native['"`]/.test(line) && !(/\binstallMode\b/.test(line) && /\bnative\b/.test(line))) {
|
|
4219
|
+
out.push({
|
|
4220
|
+
level: "warn",
|
|
4221
|
+
code: "form-native-prop",
|
|
4222
|
+
message: "prop native \u0443 \u043F\u043E\u043B\u044F \u0444\u043E\u0440\u043C\u044B \u2014 \u0443\u0431\u0435\u0440\u0438\u0442\u0435",
|
|
4223
|
+
file: rel2,
|
|
4224
|
+
line: n,
|
|
4225
|
+
fix: "elcrm migrate form-native"
|
|
4226
|
+
});
|
|
4227
|
+
}
|
|
3545
4228
|
if (/key=\{Date\.now\(\)\}/.test(line) && /Modal/.test(text)) {
|
|
3546
4229
|
out.push({
|
|
3547
4230
|
level: "info",
|
|
@@ -3597,8 +4280,8 @@ function scan(cwd) {
|
|
|
3597
4280
|
return false;
|
|
3598
4281
|
if (/theme(-light|-dark)?\.css$/.test(f))
|
|
3599
4282
|
return false;
|
|
3600
|
-
const t =
|
|
3601
|
-
return t.includes("--
|
|
4283
|
+
const t = readFileSync22(f, "utf8");
|
|
4284
|
+
return t.includes("--field-border:") && t.includes("--button-secondary-bg:") && t.includes("transparent");
|
|
3602
4285
|
});
|
|
3603
4286
|
if (toolbarMarkers.length > 1) {
|
|
3604
4287
|
out.push({
|
|
@@ -3608,8 +4291,8 @@ function scan(cwd) {
|
|
|
3608
4291
|
fix: "\u043E\u0431\u0449\u0438\u0439 \u043A\u043B\u0430\u0441\u0441 + theme tokens"
|
|
3609
4292
|
});
|
|
3610
4293
|
}
|
|
3611
|
-
const styleDir = ["src/style", "src/styles", "style"].map((d) =>
|
|
3612
|
-
if (styleDir && !
|
|
4294
|
+
const styleDir = ["src/style", "src/styles", "style"].map((d) => join17(cwd, d)).find(existsSync15);
|
|
4295
|
+
if (styleDir && !existsSync15(join17(styleDir, "elcrm.css"))) {
|
|
3613
4296
|
out.push({
|
|
3614
4297
|
level: "info",
|
|
3615
4298
|
code: "elcrm-css",
|
|
@@ -3617,8 +4300,8 @@ function scan(cwd) {
|
|
|
3617
4300
|
fix: "elcrm css"
|
|
3618
4301
|
});
|
|
3619
4302
|
}
|
|
3620
|
-
if (styleDir &&
|
|
3621
|
-
const elcrmCss =
|
|
4303
|
+
if (styleDir && existsSync15(join17(styleDir, "elcrm.css"))) {
|
|
4304
|
+
const elcrmCss = readFileSync22(join17(styleDir, "elcrm.css"), "utf8");
|
|
3622
4305
|
for (const m of elcrmCss.matchAll(/@import\s+["'](@elcrm\/[^"']+)["']/g)) {
|
|
3623
4306
|
const spec = m[1];
|
|
3624
4307
|
if (!resolveElcrmCssImport(spec, cwd)) {
|
|
@@ -3626,7 +4309,7 @@ function scan(cwd) {
|
|
|
3626
4309
|
level: "error",
|
|
3627
4310
|
code: "elcrm-import-missing",
|
|
3628
4311
|
message: `\u0431\u0438\u0442\u044B\u0439 @import "${spec}" \u2014 \u0444\u0430\u0439\u043B\u0430 \u043D\u0435\u0442 \u0432 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u043C \u043F\u0430\u043A\u0435\u0442\u0435`,
|
|
3629
|
-
file: relative4(cwd,
|
|
4312
|
+
file: relative4(cwd, join17(styleDir, "elcrm.css")),
|
|
3630
4313
|
fix: "elcrm css"
|
|
3631
4314
|
});
|
|
3632
4315
|
}
|
|
@@ -3638,8 +4321,8 @@ function scan(cwd) {
|
|
|
3638
4321
|
"theme-light.css",
|
|
3639
4322
|
"theme-dark.css",
|
|
3640
4323
|
"theme.css"
|
|
3641
|
-
].map((f) =>
|
|
3642
|
-
const themeText = themeFiles.filter(
|
|
4324
|
+
].map((f) => join17(styleDir, f));
|
|
4325
|
+
const themeText = themeFiles.filter(existsSync15).map((f) => readFileSync22(f, "utf8")).join(`
|
|
3643
4326
|
`);
|
|
3644
4327
|
if (themeText && !/--popup-shadow\s*:/.test(themeText) && /--date-popup-shadow\s*:|--select-background\s*:/.test(themeText)) {
|
|
3645
4328
|
out.push({
|
|
@@ -3661,12 +4344,16 @@ function scan(cwd) {
|
|
|
3661
4344
|
for (const file of files) {
|
|
3662
4345
|
if (!file.endsWith(".css"))
|
|
3663
4346
|
continue;
|
|
3664
|
-
const text =
|
|
4347
|
+
const text = readFileSync22(file, "utf8");
|
|
3665
4348
|
const relPath = relative4(cwd, file);
|
|
3666
4349
|
const lines = text.split(/\r?\n/);
|
|
4350
|
+
let prevNonEmpty = "";
|
|
3667
4351
|
lines.forEach((line, i) => {
|
|
3668
|
-
if (/:\s*var\(\s*--field-padding/.test(line))
|
|
4352
|
+
if (/:\s*var\(\s*--field-padding/.test(line)) {
|
|
4353
|
+
if (line.trim())
|
|
4354
|
+
prevNonEmpty = line;
|
|
3669
4355
|
return;
|
|
4356
|
+
}
|
|
3670
4357
|
if (lineHasDeprecatedFormToken(line)) {
|
|
3671
4358
|
out.push({
|
|
3672
4359
|
level: "warn",
|
|
@@ -3687,7 +4374,7 @@ function scan(cwd) {
|
|
|
3687
4374
|
fix: "elcrm migrate components"
|
|
3688
4375
|
});
|
|
3689
4376
|
}
|
|
3690
|
-
if (lineHasOrphanColorMix(line)) {
|
|
4377
|
+
if (lineHasOrphanColorMix(line, prevNonEmpty)) {
|
|
3691
4378
|
out.push({
|
|
3692
4379
|
level: "error",
|
|
3693
4380
|
code: "css-orphan-mix",
|
|
@@ -3697,6 +4384,8 @@ function scan(cwd) {
|
|
|
3697
4384
|
fix: "elcrm migrate css-sanitize"
|
|
3698
4385
|
});
|
|
3699
4386
|
}
|
|
4387
|
+
if (line.trim())
|
|
4388
|
+
prevNonEmpty = line;
|
|
3700
4389
|
});
|
|
3701
4390
|
}
|
|
3702
4391
|
return out;
|
|
@@ -3744,160 +4433,6 @@ ${c.cyan("\u2192")} elcrm migrate front${hasFlag(parsed, "dry") ? " --dry" : ""}
|
|
|
3744
4433
|
console.log("\u0420\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F: elcrm css && elcrm doctor");
|
|
3745
4434
|
}
|
|
3746
4435
|
|
|
3747
|
-
// src/commands/docs.ts
|
|
3748
|
-
import { join as join16, resolve as resolve4 } from "path";
|
|
3749
|
-
|
|
3750
|
-
// src/lib/projectKind.ts
|
|
3751
|
-
function detectProjectKind(cwd) {
|
|
3752
|
-
const pkg = readPkgAt(cwd);
|
|
3753
|
-
if (!pkg)
|
|
3754
|
-
return "front";
|
|
3755
|
-
const workspaces = listWorkspaceDirs(cwd, pkg);
|
|
3756
|
-
if (workspaces.length) {
|
|
3757
|
-
const modes = new Set;
|
|
3758
|
-
for (const dir of workspaces) {
|
|
3759
|
-
const w = readPkgAt(dir);
|
|
3760
|
-
if (w)
|
|
3761
|
-
modes.add(detectTestMode(w));
|
|
3762
|
-
}
|
|
3763
|
-
if (modes.has("front") && modes.has("server"))
|
|
3764
|
-
return "mixed";
|
|
3765
|
-
if (modes.has("server") && !modes.has("front"))
|
|
3766
|
-
return "server";
|
|
3767
|
-
if (modes.has("front"))
|
|
3768
|
-
return "front";
|
|
3769
|
-
}
|
|
3770
|
-
return hasElcrmServer(pkg) ? "server" : "front";
|
|
3771
|
-
}
|
|
3772
|
-
function isElcrmLibPackage(cwd) {
|
|
3773
|
-
const pkg = readPkgAt(cwd);
|
|
3774
|
-
const name = pkg?.name;
|
|
3775
|
-
return typeof name === "string" && name.startsWith("@elcrm/");
|
|
3776
|
-
}
|
|
3777
|
-
|
|
3778
|
-
// src/lib/elcrmDocsCatalog.ts
|
|
3779
|
-
var ALL_ELCRM_DOCS = [
|
|
3780
|
-
"CLI.elCRM.md",
|
|
3781
|
-
"API.elCRM.md",
|
|
3782
|
-
"ALERT.elCRM.md",
|
|
3783
|
-
"BUTTON.elCRM.md",
|
|
3784
|
-
"MODAL.elCRM.md",
|
|
3785
|
-
"NOTICE.elCRM.md",
|
|
3786
|
-
"NOTIFICATIONS.elCRM.md",
|
|
3787
|
-
"PASSKEY.elCRM.md",
|
|
3788
|
-
"ROUTER.elCRM.md",
|
|
3789
|
-
"SOCKET.elCRM.md",
|
|
3790
|
-
"TOOLTIP.elCRM.md",
|
|
3791
|
-
"ICONS.elCRM.md",
|
|
3792
|
-
"FORM.elCRM.md",
|
|
3793
|
-
"COMPONENTS.elCRM.md",
|
|
3794
|
-
"SERVER.elCRM.md"
|
|
3795
|
-
];
|
|
3796
|
-
var SERVER_DOCS = [
|
|
3797
|
-
"SERVER.elCRM.md",
|
|
3798
|
-
"CLI.elCRM.md",
|
|
3799
|
-
"API.elCRM.md",
|
|
3800
|
-
"SOCKET.elCRM.md"
|
|
3801
|
-
];
|
|
3802
|
-
function docsForProject(kind, lib) {
|
|
3803
|
-
if (lib || kind === "front" || kind === "mixed")
|
|
3804
|
-
return ALL_ELCRM_DOCS;
|
|
3805
|
-
return SERVER_DOCS;
|
|
3806
|
-
}
|
|
3807
|
-
|
|
3808
|
-
// src/lib/scaffoldFiles.ts
|
|
3809
|
-
import {
|
|
3810
|
-
existsSync as existsSync15,
|
|
3811
|
-
mkdirSync as mkdirSync2,
|
|
3812
|
-
readdirSync as readdirSync10,
|
|
3813
|
-
readFileSync as readFileSync20,
|
|
3814
|
-
writeFileSync as writeFileSync8
|
|
3815
|
-
} from "fs";
|
|
3816
|
-
import { dirname as dirname3, join as join15 } from "path";
|
|
3817
|
-
function writeScaffoldFile(dest, body, opts) {
|
|
3818
|
-
if (opts.dry)
|
|
3819
|
-
return "dry";
|
|
3820
|
-
if (!opts.force && existsSync15(dest))
|
|
3821
|
-
return "skip";
|
|
3822
|
-
mkdirSync2(dirname3(dest), { recursive: true });
|
|
3823
|
-
writeFileSync8(dest, body, "utf8");
|
|
3824
|
-
return "write";
|
|
3825
|
-
}
|
|
3826
|
-
function readBundled(relPath) {
|
|
3827
|
-
const full = join15(packageRoot(), "templates", relPath);
|
|
3828
|
-
if (!existsSync15(full)) {
|
|
3829
|
-
throw new Error(`\u0428\u0430\u0431\u043B\u043E\u043D \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${relPath}`);
|
|
3830
|
-
}
|
|
3831
|
-
return readFileSync20(full, "utf8");
|
|
3832
|
-
}
|
|
3833
|
-
|
|
3834
|
-
// src/commands/docs.ts
|
|
3835
|
-
async function cmdDocs(parsed) {
|
|
3836
|
-
const cwd = resolve4(parsed.options.dir || process.cwd());
|
|
3837
|
-
const dry = hasFlag(parsed, "dry");
|
|
3838
|
-
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3839
|
-
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
3840
|
-
const kind = detectProjectKind(cwd);
|
|
3841
|
-
const names = docsForProject(kind, lib);
|
|
3842
|
-
console.log(`${dry ? "[dry] " : ""}elcrm docs \u2192 ${cwd}/docs (${kind}${lib ? ", lib" : ""})`);
|
|
3843
|
-
for (const name of names) {
|
|
3844
|
-
const body = readBundled(join16("elcrm-docs", name));
|
|
3845
|
-
const dest = join16(cwd, "docs", name);
|
|
3846
|
-
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
3847
|
-
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
3848
|
-
console.log(` ${mark} docs/${name}`);
|
|
3849
|
-
}
|
|
3850
|
-
if (kind === "server" && !lib) {
|
|
3851
|
-
console.log(c.gray("\u0441\u0435\u0440\u0432\u0435\u0440: SERVER, CLI, API, SOCKET"));
|
|
3852
|
-
}
|
|
3853
|
-
console.log("\u0414\u0430\u043B\u044C\u0448\u0435: elcrm cursor \u2014 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0432 .cursor/rules (+ .cursor/docs)");
|
|
3854
|
-
}
|
|
3855
|
-
|
|
3856
|
-
// src/commands/cursor.ts
|
|
3857
|
-
import { join as join17, resolve as resolve5 } from "path";
|
|
3858
|
-
var ALWAYS = ["elcrm.mdc", "elcrm-packages.mdc", "elcrm-jsdoc.mdc"];
|
|
3859
|
-
var UI = [
|
|
3860
|
-
"elcrm-ui.mdc",
|
|
3861
|
-
"elcrm-module.mdc",
|
|
3862
|
-
"elcrm-theme.mdc",
|
|
3863
|
-
"elcrm-tokens.mdc"
|
|
3864
|
-
];
|
|
3865
|
-
var SERVER = ["elcrm-server.mdc", "elcrm-rpc.mdc"];
|
|
3866
|
-
var LIB = ["elcrm-lib.mdc"];
|
|
3867
|
-
function writeOne(dest, body, dry, force, label) {
|
|
3868
|
-
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
3869
|
-
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
3870
|
-
console.log(` ${mark} ${label}`);
|
|
3871
|
-
}
|
|
3872
|
-
async function cmdCursor(parsed) {
|
|
3873
|
-
const cwd = resolve5(parsed.options.dir || process.cwd());
|
|
3874
|
-
const dry = hasFlag(parsed, "dry");
|
|
3875
|
-
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3876
|
-
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
3877
|
-
const kind = detectProjectKind(cwd);
|
|
3878
|
-
const ruleNames = [
|
|
3879
|
-
...ALWAYS,
|
|
3880
|
-
...kind === "server" ? [] : UI,
|
|
3881
|
-
...kind === "front" ? [] : SERVER,
|
|
3882
|
-
...lib ? LIB : []
|
|
3883
|
-
];
|
|
3884
|
-
console.log(`${dry ? "[dry] " : ""}elcrm cursor \u2192 ${cwd}/.cursor (${kind}${lib ? ", lib" : ""})`);
|
|
3885
|
-
for (const name of ruleNames) {
|
|
3886
|
-
let body = readBundled(join17("elcrm-cursor", "rules", name));
|
|
3887
|
-
if (kind === "server" && (name === "elcrm-server.mdc" || name === "elcrm-rpc.mdc")) {
|
|
3888
|
-
body = body.replace("alwaysApply: false", "alwaysApply: true").replace(/^globs:.*\n/m, "");
|
|
3889
|
-
}
|
|
3890
|
-
writeOne(join17(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
|
|
3891
|
-
}
|
|
3892
|
-
const docs = docsForProject(kind, lib);
|
|
3893
|
-
for (const name of docs) {
|
|
3894
|
-
const body = readBundled(join17("elcrm-docs", name));
|
|
3895
|
-
writeOne(join17(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
|
|
3896
|
-
}
|
|
3897
|
-
writeOne(join17(cwd, "AGENTS.md"), readBundled(join17("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
|
|
3898
|
-
console.log(c.gray("\u0410\u0433\u0435\u043D\u0442: AGENTS.md + rules (\u0443\u0437\u043A\u0438\u0435 glob) + .cursor/docs. \u0421\u0434\u0430\u0447\u0430: elcrm test."));
|
|
3899
|
-
}
|
|
3900
|
-
|
|
3901
4436
|
// src/index.ts
|
|
3902
4437
|
function cliVersion() {
|
|
3903
4438
|
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
@@ -3906,7 +4441,7 @@ function cliVersion() {
|
|
|
3906
4441
|
join18(here, "package.json")
|
|
3907
4442
|
]) {
|
|
3908
4443
|
try {
|
|
3909
|
-
const v = JSON.parse(
|
|
4444
|
+
const v = JSON.parse(readFileSync23(p, "utf8")).version;
|
|
3910
4445
|
if (typeof v === "string" && v)
|
|
3911
4446
|
return v;
|
|
3912
4447
|
} catch {}
|
|
@@ -3928,7 +4463,7 @@ function showHelp() {
|
|
|
3928
4463
|
\u041A\u043E\u043C\u0430\u043D\u0434\u044B:
|
|
3929
4464
|
update [--dry] [--core] [--no-install] [--fix] [--test]
|
|
3930
4465
|
bun i -g elcrm@latest + @elcrm/* \u2192 install
|
|
3931
|
-
--fix =
|
|
4466
|
+
--fix = doctor --fix (migrate + css)
|
|
3932
4467
|
--test = elcrm test
|
|
3933
4468
|
|
|
3934
4469
|
css [--dry] [--dir=\u2026]
|
|
@@ -3943,22 +4478,24 @@ function showHelp() {
|
|
|
3943
4478
|
--lib: \u0447\u0435\u043A\u043B\u0438\u0441\u0442 \u0430\u0432\u0442\u043E\u0440\u0430 @elcrm/*
|
|
3944
4479
|
|
|
3945
4480
|
migrate <name> [--dry] | migrate --list
|
|
3946
|
-
front|ui = \u043F\u0430\u043A\u0435\u0442 \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u0439 (aliases,
|
|
3947
|
-
\u043F\u043E \u043E\u0434\u043D\u043E\u0439: form-aliases, form-
|
|
3948
|
-
|
|
4481
|
+
front|ui = \u043F\u0430\u043A\u0435\u0442 \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u0439 (aliases, form-native, native-html, tokens, \u2026)
|
|
4482
|
+
\u043F\u043E \u043E\u0434\u043D\u043E\u0439: form-aliases, form-native, native-html, form-tokens, components,
|
|
4483
|
+
css-sanitize, size-sml, field-border, modal-create,
|
|
4484
|
+
legacy-hacks, socket-server
|
|
3949
4485
|
|
|
3950
4486
|
audit [--fix] [--dry] [--dir=\u2026]
|
|
3951
|
-
\u0421\u0442\u0430\u0440\u044B\u0435 API,
|
|
4487
|
+
\u0421\u0442\u0430\u0440\u044B\u0435 API, native input, prop native, orphan color-mix; --fix = migrate front
|
|
3952
4488
|
\u041F\u043E\u0441\u043B\u0435 --fix \u0434\u043B\u044F imports: elcrm css
|
|
3953
4489
|
|
|
3954
|
-
doctor [--
|
|
3955
|
-
\
|
|
4490
|
+
doctor [--dry] [--docs] [--test] [--hacks] [--dir=\u2026]
|
|
4491
|
+
\u041D\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u043F\u043E\u0440\u044F\u0434\u043A\u0430 (\u043F\u0440\u043E\u0441\u0442\u043E \u0432\u044B\u0437\u0432\u0430\u0442\u044C). \u041F\u0440\u0435\u0432\u044C\u044E: --dry
|
|
4492
|
+
package.json \u2192 migrate front \u2192 css. --docs / --test \u043F\u043E \u0436\u0435\u043B\u0430\u043D\u0438\u044E
|
|
3956
4493
|
|
|
3957
|
-
test [dir] [--front|--server] [--no-scripts]
|
|
3958
|
-
\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0430\u043D\u0430\u043B\u0438\u0437 + scripts \u043F\u0440\u043E\u0435\u043A\
|
|
4494
|
+
test [dir] [--front|--server] [--no-scripts] [--fix]
|
|
4495
|
+
\u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439 \u0430\u043D\u0430\u043B\u0438\u0437 + scripts; --fix = migrate front \u043F\u0435\u0440\u0435\u0434 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u043E\u0439
|
|
3959
4496
|
|
|
3960
|
-
create <name> [--template app|lib|panel] [--no-install]
|
|
3961
|
-
init [--template app|lib|panel] [--force] [--no-install]
|
|
4497
|
+
create <name> [--template app|lib|panel|orbit] [--no-install]
|
|
4498
|
+
init [--template app|lib|panel|orbit] [--force] [--no-install]
|
|
3962
4499
|
build [--client] [--url=\u2026] [--name=\u2026] [--dir=\u2026] [--folder=\u2026]
|
|
3963
4500
|
postbuild [--dir=./dist]
|
|
3964
4501
|
uuid
|
|
@@ -3966,6 +4503,8 @@ function showHelp() {
|
|
|
3966
4503
|
\u0424\u043B\u0430\u0433\u0438: -v/--version, -h/--help
|
|
3967
4504
|
|
|
3968
4505
|
\u041F\u0440\u0438\u043C\u0435\u0440\u044B:
|
|
4506
|
+
elcrm doctor
|
|
4507
|
+
elcrm doctor --docs --test
|
|
3969
4508
|
elcrm update --fix --test && elcrm css && elcrm docs && elcrm cursor
|
|
3970
4509
|
elcrm css # ENOENT @elcrm/\u2026/light.css \u2192 \u0441\u043D\u0438\u043C\u0435\u0442 \u0431\u0438\u0442\u044B\u0439 import
|
|
3971
4510
|
elcrm audit
|