elcrm 1.1.7 → 1.1.9

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.
@@ -3,7 +3,7 @@
3
3
  * @see minifyCssVars
4
4
  */
5
5
  export type MinifyCssVarsOptions = {
6
- /** Длина короткого `--xx` (`2` → `--ab`). По умолчанию 3 */
6
+ /** Длина короткого `--xx` (`2` → `--aa`, `--ab`). По умолчанию 2 */
7
7
  var?: number;
8
8
  /** Длина суффикса класса после prefix (`3` + prefix `x` → `xabc`) */
9
9
  name?: number;
@@ -39,6 +39,17 @@ export declare function allocateUnique(
39
39
  kind: string,
40
40
  ): Map<string, string>;
41
41
 
42
+ export declare function replaceCssVarToken(
43
+ text: string,
44
+ from: string,
45
+ to: string,
46
+ ): string;
47
+
48
+ /** Имена `--*` в CSS, без суффиксов BEM-классов. */
49
+ export declare function collectCssVarNames(texts: string[]): string[];
50
+
51
+ export declare function isVendorJsChunk(code: string): boolean;
52
+
42
53
  export declare function minifyCssVars(
43
54
  options?: MinifyCssVarsOptions,
44
55
  ): import("vite").Plugin;
@@ -1,5 +1,5 @@
1
1
  // src/vite/minify-css-vars.ts
2
- var VAR_RE = /--[a-zA-Z_][\w-]*/g;
2
+ var VAR_RE = /(?<![\w-])--[a-zA-Z_][\w-]*/g;
3
3
  var VAR_IN_JS_RE = /var\(\s*(--[a-zA-Z_][\w-]*)|["'](--[a-zA-Z_][\w-]*)["']/g;
4
4
  var CLASS_SEL_RE = /\.(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)/g;
5
5
  var LETTERS = "abcdefghijklmnopqrstuvwxyz";
@@ -24,7 +24,7 @@ function collectJsVars(texts) {
24
24
  let m;
25
25
  while (m = VAR_IN_JS_RE.exec(text)) {
26
26
  const name = m[1] ?? m[2];
27
- if (name)
27
+ if (name && !/^--[a-zA-Z_]{1,3}$/.test(name))
28
28
  set.add(name);
29
29
  }
30
30
  }
@@ -102,30 +102,46 @@ function allocateUnique(originals, reserved, make, start, capacity, kind) {
102
102
  }
103
103
  return out;
104
104
  }
105
+ function escapeRe(s) {
106
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
107
+ }
108
+ function replaceCssVarToken(text, from, to) {
109
+ return text.replace(new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, "g"), to);
110
+ }
111
+ function collectCssVarNames(texts) {
112
+ return [...collect(texts, VAR_RE)].sort();
113
+ }
105
114
  function replaceVarsInCss(text, map) {
106
115
  let out = text;
107
116
  for (const [from, to] of map)
108
- out = out.split(from).join(to);
117
+ out = replaceCssVarToken(out, from, to);
109
118
  return out;
110
119
  }
111
120
  function replaceVarsInJs(text, map) {
112
121
  let out = text;
113
122
  for (const [from, to] of map) {
114
- const esc = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
115
- out = out.replace(new RegExp(`var\\(\\s*${esc}\\b`, "g"), (m) => m.replace(from, to));
123
+ const esc = escapeRe(from);
124
+ out = out.replace(new RegExp(`var\\(\\s*${esc}(?=[\\s,)])`, "g"), (m) => m.replace(from, to));
116
125
  out = out.replace(new RegExp(`(["'])${esc}\\1`, "g"), `$1${to}$1`);
117
126
  }
118
127
  return out;
119
128
  }
129
+ function isVendorJsChunk(code) {
130
+ return /ZipFileWorker|\bJSZip\b|pako deflate|readable-stream/.test(code);
131
+ }
120
132
  function replaceClasses(text, map, inCss) {
121
133
  let out = text;
122
- for (const [from, to] of map) {
134
+ const entries = byLongest(map.keys()).map((k) => [
135
+ k,
136
+ map.get(k)
137
+ ]);
138
+ for (const [from, to] of entries) {
139
+ const esc = escapeRe(from);
123
140
  if (inCss) {
124
- out = out.split(`.${from}`).join(`.${to}`);
141
+ out = out.replace(new RegExp(`\\.${esc}(?![\\w-])`, "g"), `.${to}`);
125
142
  continue;
126
143
  }
127
- const re = new RegExp(`(^|[^\\w-])(${from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})(?=[^\\w-]|$)`, "g");
128
- out = out.replace(re, `$1${to}`);
144
+ out = out.replace(new RegExp(`(^|[^\\w-])(${esc})(?=[^\\w-]|$)`, "g"), `$1${to}`);
129
145
  }
130
146
  return out;
131
147
  }
@@ -146,7 +162,7 @@ function pct(before, after) {
146
162
  }
147
163
  function normalizeOpts(raw) {
148
164
  const o = raw ?? {};
149
- const varLen = o.var ?? 3;
165
+ const varLen = o.var ?? 2;
150
166
  const nameLen = o.name ?? 2;
151
167
  const start = toIndex(o.start, 0);
152
168
  return {
@@ -200,7 +216,7 @@ function minifyCssVars(options) {
200
216
  remap.push(name);
201
217
  }
202
218
  const cap = namespaceSize(opt.varLen);
203
- const allocated = allocateUnique(byLongest(remap), reserved, (i) => `--${encodeName(i, opt.varLen)}`, opt.varStart, cap, "vars");
219
+ const allocated = allocateUnique([...remap].sort(), reserved, (i) => `--${encodeName(i, opt.varLen)}`, opt.varStart, cap, "vars");
204
220
  for (const [k, v] of allocated)
205
221
  varMap.set(k, v);
206
222
  }
@@ -225,7 +241,7 @@ function minifyCssVars(options) {
225
241
  }
226
242
  }
227
243
  const cap = namespaceSize(opt.nameLen);
228
- const allocated = allocateUnique(byLongest(remap), reserved, (i) => `${opt.classPrefix}${encodeName(i, opt.nameLen)}`, opt.nameStart, cap, "classes");
244
+ const allocated = allocateUnique([...remap].sort(), reserved, (i) => `${opt.classPrefix}${encodeName(i, opt.nameLen)}`, opt.nameStart, cap, "classes");
229
245
  for (const [k, v] of allocated)
230
246
  classMap.set(k, v);
231
247
  }
@@ -235,17 +251,18 @@ function minifyCssVars(options) {
235
251
  }
236
252
  return;
237
253
  }
238
- const varEntries = [...varMap.entries()];
254
+ const varEntries = byLongest(varMap.keys()).map((k) => [k, varMap.get(k)]);
239
255
  let beforeAll = 0;
240
256
  let afterAll = 0;
241
257
  const rows = [];
242
258
  for (const file of files) {
243
259
  const before = bytes(file.raw);
244
260
  let next = file.raw;
245
- if (varMap.size) {
261
+ const skipJsVendor = file.isJs && isVendorJsChunk(next);
262
+ if (varMap.size && !skipJsVendor) {
246
263
  next = file.isCss ? replaceVarsInCss(next, varEntries) : replaceVarsInJs(next, varEntries);
247
264
  }
248
- if (classMap.size) {
265
+ if (classMap.size && !skipJsVendor) {
249
266
  next = replaceClasses(next, classMap, file.isCss);
250
267
  }
251
268
  const after = bytes(next);
@@ -273,8 +290,11 @@ function minifyCssVars(options) {
273
290
  }
274
291
  export {
275
292
  toIndex,
293
+ replaceCssVarToken,
276
294
  namespaceSize,
277
295
  minifyCssVars,
296
+ isVendorJsChunk,
278
297
  encodeName,
298
+ collectCssVarNames,
279
299
  allocateUnique
280
300
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elcrm",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "CLI @elcrm/*: update --fix --test, css (prune imports), docs, cursor, migrate, audit",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -92,7 +92,7 @@ elcrm test --front|--server|--no-scripts
92
92
 
93
93
  ### Vite-плагины из пакета `elcrm`
94
94
 
95
- Нужен **elcrm ≥ 1.1.6** в `devDependencies` приложения (не только глобальный `bun i -g`). Иначе Vite: `Missing "./vite/minify-css-vars" specifier`.
95
+ Нужен **elcrm ≥ 1.1.9** в `devDependencies` приложения (не только глобальный `bun i -g`). Иначе Vite: `Missing "./vite/minify-css-vars"` или BEM-классы ломаются (`--wide` в `.account--wide`).
96
96
 
97
97
  ```js
98
98
  import { minifyCssVars } from "elcrm/vite/minify-css-vars";
@@ -101,9 +101,9 @@ import { minifyCssVars } from "elcrm/vite/minify-css-vars";
101
101
  minifyCssVars({ var: 2, name: 3, classPrefix: "x" })
102
102
  ```
103
103
 
104
- `nameStart` / `varStart` — **числа** (индекс алфавита), не `"x"`. Префикс класса — `classPrefix`. В JS плагин не трогает декремент `--n` (иначе `aqt is not defined`).
104
+ `nameStart` / `varStart` — **числа** (индекс алфавита), не `"x"`. Префикс класса — `classPrefix`. В JS плагин не трогает декремент `--n` (иначе `aqt is not defined`). BEM `.account--wide` — это класс, не переменная `--wide` (иначе CSS и `className` разъедутся).
105
105
 
106
- Короткие имена **уникальны**: занятые `--aa` / `xaa` пропускаются, одно `to` не выдаётся дважды; если слотов нет сборка падает, а не молча затирает токены.
106
+ Короткие имена **уникальны и подряд**: `--aa`, `--ab`, `--ac`… Занятые слоты пропускаются; `--field` не затирает `--field-border`. Чанки JSZip не минифицируются (декремент `--n`). Если слотов нет сборка падает.
107
107
 
108
108
  Также: `elcrm/vite/plugin-css-scoped`, `discover-lib`, `concat-css`, `check-tokens`, `postbuild`.
109
109