@pikacss/core 0.0.44 → 0.0.46

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.
Files changed (3) hide show
  1. package/dist/index.d.mts +8277 -112
  2. package/dist/index.mjs +140 -54
  3. package/package.json +2 -4
package/dist/index.mjs CHANGED
@@ -60,6 +60,7 @@ function numberToChars(num) {
60
60
  }
61
61
  const UPPER_CASE = /[A-Z]/g;
62
62
  function toKebab(str) {
63
+ if (str.startsWith("--")) return str;
63
64
  return str.replace(UPPER_CASE, (c) => `-${c.toLowerCase()}`);
64
65
  }
65
66
  function isNotNullish(value) {
@@ -69,9 +70,9 @@ function isNotString(value) {
69
70
  return typeof value !== "string";
70
71
  }
71
72
  function isPropertyValue(v) {
72
- if (Array.isArray(v)) return v.length === 2 && isPropertyValue(v[0]) && Array.isArray(v[1]) && v[1].every(isPropertyValue);
73
+ if (Array.isArray(v)) return v.length === 2 && typeof v[0] === "string" && Array.isArray(v[1]) && v[1].every((i) => typeof i === "string");
73
74
  if (v == null) return true;
74
- if (typeof v === "string" || typeof v === "number") return true;
75
+ if (typeof v === "string") return true;
75
76
  return false;
76
77
  }
77
78
  function serialize(value) {
@@ -135,7 +136,22 @@ function normalizeSelectors({ selectors, defaultSelector }) {
135
136
  }
136
137
  function normalizeValue(value) {
137
138
  if (value == null) return value;
138
- return [...new Set([value].flat(2).map((v) => String(v).trim()))];
139
+ if (Array.isArray(value)) {
140
+ const [primary, fallbacks] = value;
141
+ const p = primary.trim();
142
+ const seen = new Set([p]);
143
+ const result = [];
144
+ for (const v of fallbacks) {
145
+ const s = v.trim();
146
+ if (!seen.has(s)) {
147
+ seen.add(s);
148
+ result.push(s);
149
+ }
150
+ }
151
+ result.push(p);
152
+ return result;
153
+ }
154
+ return [value.trim()];
139
155
  }
140
156
  async function extract({ styleDefinition, levels = [], result = [], defaultSelector, transformSelectors, transformStyleItems, transformStyleDefinitions }) {
141
157
  for (const definition of await transformStyleDefinitions([styleDefinition])) for (const [k, v] of Object.entries(definition)) if (isPropertyValue(v)) {
@@ -183,35 +199,41 @@ function createExtractFn(options) {
183
199
  //#region src/internal/plugin.ts
184
200
  async function execAsyncHook(plugins, hook, payload) {
185
201
  log.debug(`Executing async hook: ${hook}`);
202
+ let current = payload;
186
203
  for (const plugin of plugins) {
187
- if (plugin[hook] == null) continue;
204
+ const pluginRecord = plugin;
205
+ if (pluginRecord[hook] == null) continue;
188
206
  try {
189
207
  log.debug(` - Plugin "${plugin.name}" executing ${hook}`);
190
- const newPayload = await plugin[hook](payload);
191
- if (newPayload != null) payload = newPayload;
208
+ const hookFn = pluginRecord[hook];
209
+ const newPayload = await hookFn(current);
210
+ if (newPayload != null) current = newPayload;
192
211
  log.debug(` - Plugin "${plugin.name}" completed ${hook}`);
193
212
  } catch (error) {
194
- log.error(`Plugin "${plugin.name}" failed to execute hook "${hook}": ${error.message}`, error);
213
+ log.error(`Plugin "${plugin.name}" failed to execute hook "${hook}": ${error instanceof Error ? error.message : error}`, error);
195
214
  }
196
215
  }
197
216
  log.debug(`Async hook "${hook}" completed`);
198
- return payload;
217
+ return current;
199
218
  }
200
219
  function execSyncHook(plugins, hook, payload) {
201
220
  log.debug(`Executing sync hook: ${hook}`);
221
+ let current = payload;
202
222
  for (const plugin of plugins) {
203
- if (plugin[hook] == null) continue;
223
+ const pluginRecord = plugin;
224
+ if (pluginRecord[hook] == null) continue;
204
225
  try {
205
226
  log.debug(` - Plugin "${plugin.name}" executing ${hook}`);
206
- const newPayload = plugin[hook](payload);
207
- if (newPayload != null) payload = newPayload;
227
+ const hookFn = pluginRecord[hook];
228
+ const newPayload = hookFn(current);
229
+ if (newPayload != null) current = newPayload;
208
230
  log.debug(` - Plugin "${plugin.name}" completed ${hook}`);
209
231
  } catch (error) {
210
- log.error(`Plugin "${plugin.name}" failed to execute hook "${hook}": ${error.message}`, error);
232
+ log.error(`Plugin "${plugin.name}" failed to execute hook "${hook}": ${error instanceof Error ? error.message : error}`, error);
211
233
  }
212
234
  }
213
235
  log.debug(`Sync hook "${hook}" completed`);
214
- return payload;
236
+ return current;
215
237
  }
216
238
  const hooks = {
217
239
  configureRawConfig: (plugins, config) => execAsyncHook(plugins, "configureRawConfig", config),
@@ -231,7 +253,7 @@ const orderMap = new Map([
231
253
  ["post", 2]
232
254
  ]);
233
255
  function resolvePlugins(plugins) {
234
- return plugins.sort((a, b) => orderMap.get(a.order) - orderMap.get(b.order));
256
+ return [...plugins].sort((a, b) => orderMap.get(a.order) - orderMap.get(b.order));
235
257
  }
236
258
  /* c8 ignore start */
237
259
  function defineEnginePlugin(plugin) {
@@ -241,10 +263,13 @@ function defineEnginePlugin(plugin) {
241
263
 
242
264
  //#endregion
243
265
  //#region src/internal/plugins/important.ts
266
+ function appendImportant(v) {
267
+ return v.endsWith("!important") ? v : `${v} !important`;
268
+ }
244
269
  function modifyPropertyValue(value) {
245
270
  if (value == null) return null;
246
- if (Array.isArray(value)) return [`${value[0]} !important`, value[1].map((i) => `${i} !important`)];
247
- return `${value} !important`;
271
+ if (Array.isArray(value)) return [appendImportant(value[0]), value[1].map((i) => appendImportant(i))];
272
+ return appendImportant(value);
248
273
  }
249
274
  function important() {
250
275
  let defaultValue;
@@ -301,7 +326,7 @@ function keyframes() {
301
326
  engine.addPreflight((engine) => {
302
327
  const maybeUsedName = /* @__PURE__ */ new Set();
303
328
  engine.store.atomicStyles.forEach(({ content: { property, value } }) => {
304
- if (property === "animationName") {
329
+ if (property === "animation-name") {
305
330
  value.forEach((name) => maybeUsedName.add(name));
306
331
  return;
307
332
  }
@@ -350,6 +375,10 @@ function createResolveConfigFn({ pruneUnused: defaultPruneUnused = true } = {})
350
375
 
351
376
  //#endregion
352
377
  //#region src/internal/resolver.ts
378
+ function stripGlobalFlag(re) {
379
+ if (!re.global) return re;
380
+ return new RegExp(re.source, re.flags.replace("g", ""));
381
+ }
353
382
  var AbstractResolver = class {
354
383
  _resolvedResultsMap = /* @__PURE__ */ new Map();
355
384
  staticRulesMap = /* @__PURE__ */ new Map();
@@ -389,7 +418,10 @@ var AbstractResolver = class {
389
418
  return this;
390
419
  }
391
420
  log.debug(`Removing dynamic rule: ${key}`);
392
- const matchedResolvedStringList = Array.from(this._resolvedResultsMap.keys()).filter((string) => rule.stringPattern.test(string));
421
+ const matchedResolvedStringList = Array.from(this._resolvedResultsMap.keys()).filter((string) => {
422
+ rule.stringPattern.lastIndex = 0;
423
+ return rule.stringPattern.test(string);
424
+ });
393
425
  this.dynamicRulesMap.delete(key);
394
426
  matchedResolvedStringList.forEach((string) => this._resolvedResultsMap.delete(string));
395
427
  log.debug(` - Cleared ${matchedResolvedStringList.length} cached results`);
@@ -412,7 +444,8 @@ var AbstractResolver = class {
412
444
  let dynamicRule;
413
445
  let matched;
414
446
  for (const rule of this.dynamicRulesMap.values()) {
415
- matched = string.match(rule.stringPattern);
447
+ rule.stringPattern.lastIndex = 0;
448
+ matched = rule.stringPattern.exec(string);
416
449
  if (matched != null) {
417
450
  dynamicRule = rule;
418
451
  break;
@@ -437,13 +470,19 @@ var AbstractResolver = class {
437
470
  }
438
471
  };
439
472
  var RecursiveResolver = class extends AbstractResolver {
440
- async resolve(string) {
473
+ async resolve(string, _visited) {
474
+ const visited = _visited ?? /* @__PURE__ */ new Set();
475
+ if (visited.has(string)) {
476
+ log.warn(`Circular reference detected for "${string}", returning as-is`);
477
+ return [string];
478
+ }
479
+ visited.add(string);
441
480
  const resolved = await this._resolve(string).catch((error) => {
442
481
  log.warn(`Failed to resolve "${string}": ${error.message}`, error);
443
482
  });
444
483
  if (resolved == null) return [string];
445
484
  const result = [];
446
- for (const partial of resolved.value) if (typeof partial === "string") result.push(...await this.resolve(partial));
485
+ for (const partial of resolved.value) if (typeof partial === "string") result.push(...await this.resolve(partial, new Set(visited)));
447
486
  else result.push(partial);
448
487
  this._setResolvedResult(string, result);
449
488
  return result;
@@ -467,7 +506,7 @@ function resolveRuleConfig(config, keyName) {
467
506
  type: "dynamic",
468
507
  rule: {
469
508
  key: config[0].source,
470
- stringPattern: config[0],
509
+ stringPattern: stripGlobalFlag(config[0]),
471
510
  createResolved: async (match) => [await fn(match)].flat(1)
472
511
  },
473
512
  autocomplete: config[2] != null ? [config[2]].flat(1) : []
@@ -492,7 +531,7 @@ function resolveRuleConfig(config, keyName) {
492
531
  type: "dynamic",
493
532
  rule: {
494
533
  key: configKey.source,
495
- stringPattern: configKey,
534
+ stringPattern: stripGlobalFlag(configKey),
496
535
  createResolved: async (match) => [await fn(match)].flat(1)
497
536
  },
498
537
  autocomplete: "autocomplete" in config && config.autocomplete != null ? [config.autocomplete].flat(1) : []
@@ -645,23 +684,46 @@ function variables() {
645
684
  }
646
685
  };
647
686
  rawVariables.forEach((variables) => engine.variables.add(variables));
648
- engine.addPreflight(async (engine) => {
649
- const used = /* @__PURE__ */ new Set();
650
- engine.store.atomicStyles.forEach(({ content: { value } }) => {
651
- value.flatMap(extractUsedVarNames).forEach((name) => used.add(normalizeVariableName(name)));
652
- });
653
- const usedVariables = Array.from(engine.variables.store.values()).flat().filter(({ name, pruneUnused, value }) => (safeSet.has(name) || pruneUnused === false || used.has(name)) && value != null);
654
- const preflightDefinition = {};
655
- for (const { name, value, selector: _selector } of usedVariables) {
656
- const selector = await engine.pluginHooks.transformSelectors(engine.config.plugins, _selector);
657
- let current = preflightDefinition;
658
- selector.forEach((s) => {
659
- current[s] ||= {};
660
- current = current[s];
687
+ engine.addPreflight({
688
+ id: "core:variables",
689
+ preflight: async (engine) => {
690
+ const used = /* @__PURE__ */ new Set();
691
+ engine.store.atomicStyles.forEach(({ content: { value } }) => {
692
+ value.flatMap(extractUsedVarNames).forEach((name) => used.add(normalizeVariableName(name)));
693
+ });
694
+ const otherPreflights = engine.config.preflights.filter((p) => p.id !== "core:variables");
695
+ (await Promise.all(otherPreflights.map(({ fn }) => Promise.resolve(fn(engine, false)).catch(() => null)))).forEach((result) => {
696
+ if (result == null) return;
697
+ extractUsedVarNamesFromPreflightResult(result).forEach((name) => used.add(name));
661
698
  });
662
- Object.assign(current, { [name]: value });
699
+ const varMap = /* @__PURE__ */ new Map();
700
+ for (const [name, list] of engine.variables.store.entries()) varMap.set(name, list);
701
+ const queue = Array.from(used);
702
+ while (queue.length > 0) {
703
+ const name = queue.pop();
704
+ const entries = varMap.get(name);
705
+ if (!entries) continue;
706
+ for (const { value } of entries) {
707
+ if (value == null) continue;
708
+ for (const refName of extractUsedVarNames(String(value)).map(normalizeVariableName)) if (!used.has(refName)) {
709
+ used.add(refName);
710
+ queue.push(refName);
711
+ }
712
+ }
713
+ }
714
+ const usedVariables = Array.from(engine.variables.store.values()).flat().filter(({ name, pruneUnused, value }) => (safeSet.has(name) || pruneUnused === false || used.has(name)) && value != null);
715
+ const preflightDefinition = {};
716
+ for (const { name, value, selector: _selector } of usedVariables) {
717
+ const selector = await engine.pluginHooks.transformSelectors(engine.config.plugins, _selector);
718
+ let current = preflightDefinition;
719
+ selector.forEach((s) => {
720
+ current[s] ||= {};
721
+ current = current[s];
722
+ });
723
+ Object.assign(current, { [name]: value });
724
+ }
725
+ return preflightDefinition;
663
726
  }
664
- return preflightDefinition;
665
727
  });
666
728
  }
667
729
  });
@@ -689,17 +751,26 @@ function createResolveVariablesFn({ pruneUnused: defaultPruneUnused = true } = {
689
751
  }
690
752
  const VAR_NAME_RE = /var\((--[\w-]+)/g;
691
753
  function extractUsedVarNames(input) {
692
- const matched = input.match(VAR_NAME_RE);
693
- if (!matched) return [];
694
- return matched.map((match) => {
695
- const varNameMatch = match.match(/--[^,)]+/);
696
- return varNameMatch ? varNameMatch[0] : "";
697
- }).filter(Boolean);
754
+ return Array.from(input.matchAll(VAR_NAME_RE), (m) => m[1]);
698
755
  }
699
756
  function normalizeVariableName(name) {
700
757
  if (name.startsWith("--")) return name;
701
758
  return `--${name}`;
702
759
  }
760
+ /**
761
+ * Recursively extract all CSS variable names referenced inside a preflight
762
+ * result (either a plain CSS string or a `PreflightDefinition` object).
763
+ */
764
+ function extractUsedVarNamesFromPreflightResult(result) {
765
+ if (typeof result === "string") return extractUsedVarNames(result).map(normalizeVariableName);
766
+ const names = [];
767
+ for (const value of Object.values(result)) {
768
+ if (value == null) continue;
769
+ if (typeof value === "string" || typeof value === "number") extractUsedVarNames(String(value)).forEach((n) => names.push(normalizeVariableName(n)));
770
+ else if (typeof value === "object") extractUsedVarNamesFromPreflightResult(value).forEach((n) => names.push(n));
771
+ }
772
+ return names;
773
+ }
703
774
 
704
775
  //#endregion
705
776
  //#region src/internal/engine.ts
@@ -720,10 +791,13 @@ async function createEngine(config = {}) {
720
791
  ];
721
792
  log.debug("Core plugins loaded:", corePlugins.length);
722
793
  const plugins = resolvePlugins([...corePlugins, ...config.plugins || []]);
723
- config.plugins = plugins;
794
+ config = {
795
+ ...config,
796
+ plugins
797
+ };
724
798
  log.debug(`Total plugins resolved: ${plugins.length}`);
725
799
  config = await hooks.configureRawConfig(config.plugins, config);
726
- hooks.rawConfigConfigured(resolvePlugins(config.plugins || []), config);
800
+ hooks.rawConfigConfigured(resolvePlugins(config.plugins ?? []), config);
727
801
  let resolvedConfig = await resolveEngineConfig(config);
728
802
  log.debug("Engine config resolved with prefix:", resolvedConfig.prefix);
729
803
  resolvedConfig = await hooks.configureResolvedConfig(resolvedConfig.plugins, resolvedConfig);
@@ -886,18 +960,29 @@ function sortLayerNames(layers) {
886
960
  function isWithLayer(p) {
887
961
  if (typeof p !== "object" || p === null) return false;
888
962
  const record = p;
889
- return typeof record.layer === "string" && "preflight" in record;
963
+ return typeof record.layer === "string" && record.preflight !== void 0;
964
+ }
965
+ function isWithId(p) {
966
+ if (typeof p !== "object" || p === null) return false;
967
+ const record = p;
968
+ return typeof record.id === "string" && record.preflight !== void 0;
890
969
  }
891
970
  function resolvePreflight(preflight) {
971
+ let layer;
972
+ let id;
892
973
  if (isWithLayer(preflight)) {
893
- const inner = preflight.preflight;
894
- const fn = typeof inner === "function" ? inner : () => inner;
895
- return {
896
- layer: preflight.layer,
897
- fn
898
- };
974
+ layer = preflight.layer;
975
+ preflight = preflight.preflight;
976
+ }
977
+ if (isWithId(preflight)) {
978
+ id = preflight.id;
979
+ preflight = preflight.preflight;
899
980
  }
900
- return { fn: typeof preflight === "function" ? preflight : () => preflight };
981
+ return {
982
+ layer,
983
+ id,
984
+ fn: typeof preflight === "function" ? preflight : () => preflight
985
+ };
901
986
  }
902
987
  async function resolveEngineConfig(config) {
903
988
  const { prefix = "", defaultSelector = `.${ATOMIC_STYLE_ID_PLACEHOLDER}`, plugins = [], preflights = [] } = config;
@@ -1063,6 +1148,7 @@ async function _renderPreflightDefinition({ engine, preflightDefinition, blocks
1063
1148
  selectors: await hooks.transformSelectors(engine.config.plugins, [selector]),
1064
1149
  defaultSelector: ""
1065
1150
  }).filter(Boolean);
1151
+ if (selectors.length === 0) continue;
1066
1152
  let currentBlocks = blocks;
1067
1153
  let currentBlockBody = null;
1068
1154
  selectors.forEach((s, i) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pikacss/core",
3
3
  "type": "module",
4
- "version": "0.0.44",
4
+ "version": "0.0.46",
5
5
  "author": "DevilTea <ch19980814@gmail.com>",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -34,10 +34,8 @@
34
34
  "files": [
35
35
  "dist"
36
36
  ],
37
- "dependencies": {
38
- "csstype": "^3.2.3"
39
- },
40
37
  "scripts": {
38
+ "generate:csstype": "tsx ./scripts/generate-csstype.ts",
41
39
  "build": "tsdown && pnpm exec publint",
42
40
  "build:watch": "tsdown --watch",
43
41
  "typecheck": "pnpm typecheck:package && pnpm typecheck:test",