pasika 0.10.111 → 0.10.113

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.
@@ -10376,12 +10376,21 @@ function applyOperationCount(utility) {
10376
10376
  return count;
10377
10377
  }
10378
10378
  function themeCandidate(name, utilityText) {
10379
- const match = /^@utility\s+[\w-]+\s*\{\s*@apply\s+\[(?<property>font-size|letter-spacing):(?<value>[^\]\r\n;{}]+)\];?\s*\}$/u.exec(
10380
- utilityText.trim()
10379
+ const source = utilityText.trim();
10380
+ const arbitrary = /^@utility\s+[\w-]+\s*\{\s*@apply\s+\[(?<property>font-size|letter-spacing):(?<value>[^\]\r\n;{}]+)\];?\s*\}$/u.exec(
10381
+ source
10381
10382
  );
10382
- if (!match) return void 0;
10383
- const property = match.groups?.property;
10384
- const value = match.groups?.value?.trim();
10383
+ const typed = /^@utility\s+[\w-]+\s*\{\s*@apply\s+(?<kind>text|tracking)-\((?<hint>length:)?(?<variable>--[a-z][a-z0-9-]*)\);?\s*\}$/u.exec(
10384
+ source
10385
+ );
10386
+ const kind = typed?.groups?.kind;
10387
+ const hint = typed?.groups?.hint;
10388
+ if (kind === "text" && hint !== "length:") return void 0;
10389
+ if (kind === "tracking" && hint !== void 0) return void 0;
10390
+ let property = arbitrary?.groups?.property;
10391
+ if (!property && kind === "text") property = "font-size";
10392
+ if (!property && kind === "tracking") property = "letter-spacing";
10393
+ const value = arbitrary?.groups?.value?.trim() ?? (typed?.groups?.variable ? `var(${typed.groups.variable})` : void 0);
10385
10394
  if (!property || !value) return void 0;
10386
10395
  const prefix = property === "font-size" ? "text-" : "tracking-";
10387
10396
  if (!name.startsWith(prefix) || name.length === prefix.length) return void 0;
@@ -10391,37 +10400,124 @@ function themeCandidate(name, utilityText) {
10391
10400
  if (property === "font-size" && value.startsWith("-")) return void 0;
10392
10401
  return { token: `--${name}`, property, value };
10393
10402
  }
10403
+ var builtInTextSizes = /* @__PURE__ */ new Set([
10404
+ "xs",
10405
+ "sm",
10406
+ "base",
10407
+ "lg",
10408
+ "xl",
10409
+ "2xl",
10410
+ "3xl",
10411
+ "4xl",
10412
+ "5xl",
10413
+ "6xl",
10414
+ "7xl",
10415
+ "8xl",
10416
+ "9xl"
10417
+ ]);
10418
+ var builtInTracking = /* @__PURE__ */ new Set(["tighter", "tight", "normal", "wide", "wider", "widest"]);
10419
+ function lengthIdentity(value) {
10420
+ const match = /^(?<number>-?(?:\d+(?:\.\d*)?|\.\d+))(?<unit>px|rem|em|%)$/u.exec(value);
10421
+ const number = match?.groups?.number;
10422
+ const unit = match?.groups?.unit;
10423
+ if (!number || !unit) return void 0;
10424
+ return `${String(Number(number))}${unit}`;
10425
+ }
10426
+ function declarationValue(text) {
10427
+ const match = /^--[\w-]+\s*:\s*(?<value>[^;{}]+);?$/u.exec(text.trim());
10428
+ return match?.groups?.value?.trim();
10429
+ }
10430
+ function canonicalToken(name) {
10431
+ if (name.startsWith("--text-")) return builtInTextSizes.has(name.slice("--text-".length));
10432
+ if (name.startsWith("--tracking-")) return builtInTracking.has(name.slice("--tracking-".length));
10433
+ return false;
10434
+ }
10435
+ function isTypographySize(name) {
10436
+ return /^--text-(?!.*--)(?:[a-z0-9]+-)*[a-z0-9]+$/u.test(name);
10437
+ }
10394
10438
  var utilityMappingRule = {
10395
10439
  meta: {
10396
- schema: [
10397
- {
10398
- type: "object",
10399
- properties: { preferThemeTokens: { type: "boolean" } },
10400
- additionalProperties: false
10401
- }
10402
- ],
10440
+ schema: [],
10403
10441
  type: "problem",
10404
10442
  docs: {
10405
- description: "Require one styling operation per custom utility; optionally suggest theme-generated utilities."
10443
+ description: "Require one styling operation per custom utility and enforce theme tokens instead of redundant mappings."
10406
10444
  }
10407
10445
  },
10408
10446
  create(context) {
10409
- const option = context.options[0];
10410
- const preferThemeTokens = typeof option === "object" && option !== null && "preferThemeTokens" in option && option.preferThemeTokens === true;
10411
10447
  return {
10412
10448
  "StyleSheet:exit"(node) {
10413
10449
  const utilities = atrulesNamed(node, "utility");
10414
10450
  const themeTokens = /* @__PURE__ */ new Set();
10415
10451
  const nameCounts = /* @__PURE__ */ new Map();
10416
- if (preferThemeTokens) {
10417
- for (const theme of atrulesNamed(node, "theme")) {
10418
- for (const child of blockChildren2(theme)) {
10419
- if (child.type === "Declaration") themeTokens.add(child.property);
10452
+ for (const theme of atrulesNamed(node, "theme")) {
10453
+ for (const child of blockChildren2(theme)) {
10454
+ if (child.type === "Declaration") themeTokens.add(child.property);
10455
+ }
10456
+ }
10457
+ for (const utility of utilities) {
10458
+ const name = preludeIdentifiers(utility)[0] ?? "";
10459
+ nameCounts.set(name, (nameCounts.get(name) ?? 0) + 1);
10460
+ }
10461
+ const themeDefinitions = /* @__PURE__ */ new Map();
10462
+ for (const theme of atrulesNamed(node, "theme")) {
10463
+ for (const child of blockChildren2(theme)) {
10464
+ if (child.type !== "Declaration") continue;
10465
+ const value = declarationValue(context.sourceCode.getText(child));
10466
+ if (!value) continue;
10467
+ const definitions = themeDefinitions.get(child.property) ?? [];
10468
+ definitions.push({ node: child, value });
10469
+ themeDefinitions.set(child.property, definitions);
10470
+ }
10471
+ }
10472
+ const rootValues = /* @__PURE__ */ new Map();
10473
+ const overriddenVariables = /* @__PURE__ */ new Set();
10474
+ for (const cssRule of rules(node)) {
10475
+ if (!("prelude" in cssRule) || !cssRule.prelude) continue;
10476
+ const isRoot = context.sourceCode.getText(cssRule.prelude).trim() === ":root";
10477
+ for (const child of blockChildren2(cssRule)) {
10478
+ if (child.type !== "Declaration" || !child.property.startsWith("--")) continue;
10479
+ if (!isRoot) {
10480
+ overriddenVariables.add(child.property);
10481
+ continue;
10420
10482
  }
10483
+ const value = declarationValue(context.sourceCode.getText(child));
10484
+ if (!value) continue;
10485
+ const definitions = rootValues.get(child.property) ?? [];
10486
+ definitions.push(value);
10487
+ rootValues.set(child.property, definitions);
10421
10488
  }
10422
- for (const utility of utilities) {
10423
- const name = preludeIdentifiers(utility)[0] ?? "";
10424
- nameCounts.set(name, (nameCounts.get(name) ?? 0) + 1);
10489
+ }
10490
+ function identity(value) {
10491
+ const variable = /^var\((?<name>--[a-z][a-z0-9-]*)\)$/u.exec(value);
10492
+ if (!variable) return lengthIdentity(value);
10493
+ const name = variable.groups?.name;
10494
+ if (!name || overriddenVariables.has(name)) return void 0;
10495
+ const definitions = rootValues.get(name);
10496
+ const definition = definitions?.length === 1 ? definitions[0] : void 0;
10497
+ return definition ? lengthIdentity(definition) : void 0;
10498
+ }
10499
+ for (const [name, definitions] of themeDefinitions) {
10500
+ const definition = definitions.length === 1 ? definitions[0] : void 0;
10501
+ if (!definition || canonicalToken(name)) continue;
10502
+ if (!isTypographySize(name) && !name.startsWith("--tracking-")) continue;
10503
+ if (name.includes("--", 2)) continue;
10504
+ const value = identity(definition.value);
10505
+ if (!value) continue;
10506
+ const prefix = name.startsWith("--text-") ? "--text-" : "--tracking-";
10507
+ for (const [other, otherDefinitions] of themeDefinitions) {
10508
+ const otherDefinition = otherDefinitions.length === 1 ? otherDefinitions[0] : void 0;
10509
+ if (!canonicalToken(other) || !other.startsWith(prefix) || !otherDefinition) continue;
10510
+ if (identity(otherDefinition.value) !== value) continue;
10511
+ if (prefix === "--text-" && ["--line-height", "--letter-spacing", "--font-weight"].some(
10512
+ (suffix) => themeDefinitions.has(`${name}${suffix}`) || themeDefinitions.has(`${other}${suffix}`)
10513
+ )) {
10514
+ continue;
10515
+ }
10516
+ context.report({
10517
+ node: definition.node,
10518
+ message: `Theme token "${name}" duplicates the configured built-in "${other}" (${value}); reuse the "${other.slice(2)}" utility instead of defining an equivalent theme token.`
10519
+ });
10520
+ break;
10425
10521
  }
10426
10522
  }
10427
10523
  for (const utility of utilities) {
@@ -10434,7 +10530,7 @@ var utilityMappingRule = {
10434
10530
  });
10435
10531
  continue;
10436
10532
  }
10437
- if (!preferThemeTokens || nameCounts.get(name) !== 1) continue;
10533
+ if (nameCounts.get(name) !== 1) continue;
10438
10534
  const candidate = themeCandidate(name, context.sourceCode.getText(utility));
10439
10535
  if (!candidate || themeTokens.has(candidate.token)) continue;
10440
10536
  if (candidate.property === "font-size" && themeTokens.has(`--color-${name.slice(5)}`)) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pasika",
3
- "version": "0.10.111",
3
+ "version": "0.10.113",
4
4
  "description": "Reusable agent setup package",
5
5
  "repository": {
6
6
  "type": "git",