elcrm 1.1.6 → 1.1.7
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.
|
@@ -21,8 +21,24 @@ export type MinifyCssVarsOptions = {
|
|
|
21
21
|
css?: boolean;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
export declare function toIndex(value: unknown, fallback?: number): number;
|
|
25
|
+
|
|
24
26
|
export declare function encodeName(index: number, length: number): string;
|
|
25
27
|
|
|
28
|
+
export declare function namespaceSize(length: number): number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Короткие имена без коллизий: пропускает `reserved`, не выдаёт одно `to` дважды.
|
|
32
|
+
*/
|
|
33
|
+
export declare function allocateUnique(
|
|
34
|
+
originals: string[],
|
|
35
|
+
reserved: Set<string>,
|
|
36
|
+
make: (index: number) => string,
|
|
37
|
+
start: number,
|
|
38
|
+
capacity: number,
|
|
39
|
+
kind: string,
|
|
40
|
+
): Map<string, string>;
|
|
41
|
+
|
|
26
42
|
export declare function minifyCssVars(
|
|
27
43
|
options?: MinifyCssVarsOptions,
|
|
28
44
|
): import("vite").Plugin;
|
|
@@ -30,10 +30,16 @@ function collectJsVars(texts) {
|
|
|
30
30
|
}
|
|
31
31
|
return set;
|
|
32
32
|
}
|
|
33
|
+
function toIndex(value, fallback = 0) {
|
|
34
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
35
|
+
if (!Number.isFinite(n) || n < 0)
|
|
36
|
+
return fallback;
|
|
37
|
+
return Math.floor(n);
|
|
38
|
+
}
|
|
33
39
|
function encodeName(index, length) {
|
|
34
40
|
const n = LETTERS.length;
|
|
35
41
|
const len = Math.max(1, Math.min(8, Math.floor(length)));
|
|
36
|
-
let i =
|
|
42
|
+
let i = toIndex(index, 0);
|
|
37
43
|
let s = "";
|
|
38
44
|
for (let k = 0;k < len; k++) {
|
|
39
45
|
s = LETTERS[i % n] + s;
|
|
@@ -55,6 +61,47 @@ function shouldMinifyClass(name, minLen, prefix) {
|
|
|
55
61
|
return false;
|
|
56
62
|
return /[-_]/.test(name);
|
|
57
63
|
}
|
|
64
|
+
function namespaceSize(length) {
|
|
65
|
+
const len = Math.max(1, Math.min(8, Math.floor(length)));
|
|
66
|
+
let n = 1;
|
|
67
|
+
for (let i = 0;i < len; i++)
|
|
68
|
+
n *= LETTERS.length;
|
|
69
|
+
return n;
|
|
70
|
+
}
|
|
71
|
+
function allocateUnique(originals, reserved, make, start, capacity, kind) {
|
|
72
|
+
const taken = new Set(reserved);
|
|
73
|
+
const out = new Map;
|
|
74
|
+
let cursor = start;
|
|
75
|
+
for (const from of originals) {
|
|
76
|
+
if (out.has(from))
|
|
77
|
+
continue;
|
|
78
|
+
let found;
|
|
79
|
+
for (let n = 0;n < capacity; n++) {
|
|
80
|
+
const candidate = make(cursor);
|
|
81
|
+
cursor++;
|
|
82
|
+
if (taken.has(candidate) || candidate === from)
|
|
83
|
+
continue;
|
|
84
|
+
found = candidate;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
if (!found) {
|
|
88
|
+
throw new Error(`[minify-css-vars] нет свободных имён для ${kind}: нужно ${originals.length}, ёмкость ${capacity}, занято ${taken.size}. Увеличьте var/name или сдвиньте start.`);
|
|
89
|
+
}
|
|
90
|
+
out.set(from, found);
|
|
91
|
+
taken.add(found);
|
|
92
|
+
}
|
|
93
|
+
const used = new Set;
|
|
94
|
+
for (const [from, to] of out) {
|
|
95
|
+
if (used.has(to)) {
|
|
96
|
+
throw new Error(`[minify-css-vars] коллизия ${kind}: «${from}» и ещё одно имя → «${to}»`);
|
|
97
|
+
}
|
|
98
|
+
used.add(to);
|
|
99
|
+
if (reserved.has(to)) {
|
|
100
|
+
throw new Error(`[minify-css-vars] «${from}» → «${to}» затирает существующее имя ${kind}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
58
105
|
function replaceVarsInCss(text, map) {
|
|
59
106
|
let out = text;
|
|
60
107
|
for (const [from, to] of map)
|
|
@@ -101,12 +148,12 @@ function normalizeOpts(raw) {
|
|
|
101
148
|
const o = raw ?? {};
|
|
102
149
|
const varLen = o.var ?? 3;
|
|
103
150
|
const nameLen = o.name ?? 2;
|
|
104
|
-
const start = o.start
|
|
151
|
+
const start = toIndex(o.start, 0);
|
|
105
152
|
return {
|
|
106
153
|
varLen,
|
|
107
154
|
nameLen,
|
|
108
|
-
varStart: o.varStart
|
|
109
|
-
nameStart: o.nameStart
|
|
155
|
+
varStart: toIndex(o.varStart, start),
|
|
156
|
+
nameStart: toIndex(o.nameStart, start),
|
|
110
157
|
vars: o.vars !== false,
|
|
111
158
|
classes: o.classes !== false,
|
|
112
159
|
minVar: o.minVar ?? Math.max(4, varLen + 2),
|
|
@@ -143,37 +190,44 @@ function minifyCssVars(options) {
|
|
|
143
190
|
...collect(cssTexts, VAR_RE),
|
|
144
191
|
...collectJsVars(jsTexts)
|
|
145
192
|
]);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
continue;
|
|
152
|
-
if (name.length < opt.minVar)
|
|
193
|
+
const remap = [];
|
|
194
|
+
const reserved = new Set;
|
|
195
|
+
for (const name of names) {
|
|
196
|
+
if (alreadyShortVar(name, opt.varLen) || /^--[a-zA-Z_]$/.test(name) || name.length < opt.minVar) {
|
|
197
|
+
reserved.add(name);
|
|
153
198
|
continue;
|
|
154
|
-
|
|
155
|
-
|
|
199
|
+
}
|
|
200
|
+
remap.push(name);
|
|
156
201
|
}
|
|
202
|
+
const cap = namespaceSize(opt.varLen);
|
|
203
|
+
const allocated = allocateUnique(byLongest(remap), reserved, (i) => `--${encodeName(i, opt.varLen)}`, opt.varStart, cap, "vars");
|
|
204
|
+
for (const [k, v] of allocated)
|
|
205
|
+
varMap.set(k, v);
|
|
157
206
|
}
|
|
158
207
|
const classMap = new Map;
|
|
159
208
|
if (opt.classes) {
|
|
160
|
-
const
|
|
209
|
+
const allClasses = new Set;
|
|
161
210
|
for (const file of files) {
|
|
162
211
|
if (!file.isCss)
|
|
163
212
|
continue;
|
|
164
213
|
CLASS_SEL_RE.lastIndex = 0;
|
|
165
214
|
let m;
|
|
166
|
-
while (m = CLASS_SEL_RE.exec(file.raw))
|
|
167
|
-
|
|
168
|
-
classNames.add(m[1]);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
215
|
+
while (m = CLASS_SEL_RE.exec(file.raw))
|
|
216
|
+
allClasses.add(m[1]);
|
|
171
217
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
218
|
+
const remap = [];
|
|
219
|
+
const reserved = new Set;
|
|
220
|
+
for (const name of allClasses) {
|
|
221
|
+
if (shouldMinifyClass(name, opt.minClass, opt.classPrefix)) {
|
|
222
|
+
remap.push(name);
|
|
223
|
+
} else {
|
|
224
|
+
reserved.add(name);
|
|
225
|
+
}
|
|
176
226
|
}
|
|
227
|
+
const cap = namespaceSize(opt.nameLen);
|
|
228
|
+
const allocated = allocateUnique(byLongest(remap), reserved, (i) => `${opt.classPrefix}${encodeName(i, opt.nameLen)}`, opt.nameStart, cap, "classes");
|
|
229
|
+
for (const [k, v] of allocated)
|
|
230
|
+
classMap.set(k, v);
|
|
177
231
|
}
|
|
178
232
|
if (!varMap.size && !classMap.size) {
|
|
179
233
|
if (opt.report) {
|
|
@@ -218,6 +272,9 @@ function minifyCssVars(options) {
|
|
|
218
272
|
};
|
|
219
273
|
}
|
|
220
274
|
export {
|
|
275
|
+
toIndex,
|
|
276
|
+
namespaceSize,
|
|
221
277
|
minifyCssVars,
|
|
222
|
-
encodeName
|
|
278
|
+
encodeName,
|
|
279
|
+
allocateUnique
|
|
223
280
|
};
|
package/package.json
CHANGED
|
@@ -90,6 +90,23 @@ elcrm test # статический анализ + scripts п
|
|
|
90
90
|
elcrm test --front|--server|--no-scripts
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
### Vite-плагины из пакета `elcrm`
|
|
94
|
+
|
|
95
|
+
Нужен **elcrm ≥ 1.1.6** в `devDependencies` приложения (не только глобальный `bun i -g`). Иначе Vite: `Missing "./vite/minify-css-vars" specifier`.
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
import { minifyCssVars } from "elcrm/vite/minify-css-vars";
|
|
99
|
+
|
|
100
|
+
// только command === "build"
|
|
101
|
+
minifyCssVars({ var: 2, name: 3, classPrefix: "x" })
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`nameStart` / `varStart` — **числа** (индекс алфавита), не `"x"`. Префикс класса — `classPrefix`. В JS плагин не трогает декремент `--n` (иначе `aqt is not defined`).
|
|
105
|
+
|
|
106
|
+
Короткие имена **уникальны**: занятые `--aa` / `xaa` пропускаются, одно `to` не выдаётся дважды; если слотов нет — сборка падает, а не молча затирает токены.
|
|
107
|
+
|
|
108
|
+
Также: `elcrm/vite/plugin-css-scoped`, `discover-lib`, `concat-css`, `check-tokens`, `postbuild`.
|
|
109
|
+
|
|
93
110
|
### Прочее
|
|
94
111
|
|
|
95
112
|
```bash
|