elcrm 1.1.10 → 1.1.12

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.
@@ -53,6 +53,12 @@ export declare function replaceCssVarToken(
53
53
  /** Имена `--*` в CSS, без суффиксов BEM-классов. */
54
54
  export declare function collectCssVarNames(texts: string[]): string[];
55
55
 
56
+ /** Один словарь: длинные `--*` первыми, граница токена (CSS и JS). */
57
+ export declare function applyVarDictionary(
58
+ text: string,
59
+ map: Iterable<[string, string]>,
60
+ ): string;
61
+
56
62
  export declare function isVendorJsChunk(code: string): boolean;
57
63
 
58
64
  export declare function minifyCssVars(
@@ -1,6 +1,6 @@
1
1
  // src/vite/minify-css-vars.ts
2
2
  var VAR_RE = /(?<![\w-])--[a-zA-Z_][\w-]*/g;
3
- var VAR_IN_JS_RE = /var\(\s*(--[a-zA-Z_][\w-]*)|["'](--[a-zA-Z_][\w-]*)["']/g;
3
+ var VAR_IN_JS_RE = /var\(\s*(--[a-zA-Z_][\w-]*)|["'](--[a-zA-Z_][\w-]*)["']|(?<![\w-])(--[a-zA-Z_][\w-]*)\s*:/g;
4
4
  var CLASS_SEL_RE = /\.(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)/g;
5
5
  var LETTERS = "abcdefghijklmnopqrstuvwxyz";
6
6
  function collect(texts, re) {
@@ -23,7 +23,7 @@ function collectJsVars(texts) {
23
23
  VAR_IN_JS_RE.lastIndex = 0;
24
24
  let m;
25
25
  while (m = VAR_IN_JS_RE.exec(text)) {
26
- const name = m[1] ?? m[2];
26
+ const name = m[1] ?? m[2] ?? m[3];
27
27
  if (name && !/^--[a-zA-Z_]{1,3}$/.test(name))
28
28
  set.add(name);
29
29
  }
@@ -70,6 +70,8 @@ function namespaceSize(length) {
70
70
  }
71
71
  function allocateUnique(originals, reserved, make, start, capacity, kind) {
72
72
  const taken = new Set(reserved);
73
+ for (const from of originals)
74
+ taken.add(from);
73
75
  const out = new Map;
74
76
  let cursor = start;
75
77
  for (const from of originals) {
@@ -91,12 +93,13 @@ function allocateUnique(originals, reserved, make, start, capacity, kind) {
91
93
  taken.add(found);
92
94
  }
93
95
  const used = new Set;
96
+ const originalSet = new Set(originals);
94
97
  for (const [from, to] of out) {
95
98
  if (used.has(to)) {
96
99
  throw new Error(`[minify-css-vars] коллизия ${kind}: «${from}» и ещё одно имя → «${to}»`);
97
100
  }
98
101
  used.add(to);
99
- if (reserved.has(to)) {
102
+ if (reserved.has(to) || originalSet.has(to)) {
100
103
  throw new Error(`[minify-css-vars] «${from}» → «${to}» затирает существующее имя ${kind}`);
101
104
  }
102
105
  }
@@ -111,18 +114,15 @@ function replaceCssVarToken(text, from, to) {
111
114
  function collectCssVarNames(texts) {
112
115
  return [...collect(texts, VAR_RE)].sort();
113
116
  }
114
- function replaceVarsInCss(text, map) {
117
+ function applyVarDictionary(text, map) {
118
+ const entries = [...map].sort((a, b) => b[0].length - a[0].length || a[0].localeCompare(b[0]));
119
+ const mark = (i) => `${i.toString(36)}`;
115
120
  let out = text;
116
- for (const [from, to] of map)
117
- out = replaceCssVarToken(out, from, to);
118
- return out;
119
- }
120
- function replaceVarsInJs(text, map) {
121
- let out = text;
122
- for (const [from, to] of map) {
123
- const esc = escapeRe(from);
124
- out = out.replace(new RegExp(`var\\(\\s*${esc}(?=[\\s,)])`, "g"), (m) => m.replace(from, to));
125
- out = out.replace(new RegExp(`(["'])${esc}\\1`, "g"), `$1${to}$1`);
121
+ for (let i = 0;i < entries.length; i++) {
122
+ out = replaceCssVarToken(out, entries[i][0], mark(i));
123
+ }
124
+ for (let i = 0;i < entries.length; i++) {
125
+ out = out.split(mark(i)).join(entries[i][1]);
126
126
  }
127
127
  return out;
128
128
  }
@@ -199,7 +199,7 @@ function minifyCssVars(options) {
199
199
  files.push({ item, fileName, raw, isCss, isJs });
200
200
  }
201
201
  const cssTexts = files.filter((f) => f.isCss).map((f) => f.raw);
202
- const jsTexts = files.filter((f) => f.isJs).map((f) => f.raw);
202
+ const jsTexts = files.filter((f) => f.isJs && !isVendorJsChunk(f.raw)).map((f) => f.raw);
203
203
  const varMap = new Map;
204
204
  if (opt.vars) {
205
205
  const names = new Set([
@@ -260,7 +260,7 @@ function minifyCssVars(options) {
260
260
  let next = file.raw;
261
261
  const skipJsVendor = file.isJs && isVendorJsChunk(next);
262
262
  if (varMap.size && !skipJsVendor) {
263
- next = file.isCss ? replaceVarsInCss(next, varEntries) : replaceVarsInJs(next, varEntries);
263
+ next = applyVarDictionary(next, varEntries);
264
264
  }
265
265
  if (classMap.size && !skipJsVendor) {
266
266
  next = replaceClasses(next, classMap, file.isCss);
@@ -296,5 +296,6 @@ export {
296
296
  isVendorJsChunk,
297
297
  encodeName,
298
298
  collectCssVarNames,
299
+ applyVarDictionary,
299
300
  allocateUnique
300
301
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elcrm",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
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.10** в `devDependencies` приложения (не только глобальный `bun i -g`). Иначе Vite: `Missing "./vite/minify-css-vars"` или BEM/классы ломают стили.
95
+ Нужен **elcrm ≥ 1.1.12** в `devDependencies` приложения (не только глобальный `bun i -g`). Иначе Vite: `Missing "./vite/minify-css-vars"` или CSS-in-JS / цепочка замен схлопывает токены.
96
96
 
97
97
  ```js
98
98
  import { minifyCssVars } from "elcrm/vite/minify-css-vars";
@@ -102,7 +102,7 @@ minifyCssVars({ var: 2 })
102
102
  // classes: true — только если нет className={\`foo--${x}\`}
103
103
  ```
104
104
 
105
- `nameStart` / `varStart` — **числа** (индекс алфавита), не `"x"`. Префикс класса — `classPrefix`. В JS плагин не трогает декремент `--n` (иначе `aqt is not defined`). BEM `.account--wide` — это класс, не переменная `--wide`. **`classes: true` нельзя** при динамических модификаторах (`account-passkey-status--${tone}`) — CSS сожмёт полное имя, шаблон в JS останется.
105
+ `nameStart` / `varStart` — **числа** (индекс алфавита), не `"x"`. Префикс класса — `classPrefix`. Словарь один на CSS+JS: `var(--token)`, `"--token"` и объявления `--token:` (в т.ч. CSS внутри JS от `@elcrm/form` size). Чанки JSZip не трогаем (`--n`). BEM `.account--wide` — класс, не переменная `--wide`. **`classes: true` нельзя** при динамических модификаторах (`account-passkey-status--${tone}`).
106
106
 
107
107
  Короткие имена **уникальны и подряд**: `--aa`, `--ab`, `--ac`… Занятые слоты пропускаются; `--field` не затирает `--field-border`. Чанки JSZip не минифицируются (декремент `--n`). Если слотов нет — сборка падает.
108
108