dispersa 0.2.0 → 0.3.0

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.
package/dist/index.cjs CHANGED
@@ -3420,32 +3420,55 @@ function filterTokensBySource(tokens, expectedSource) {
3420
3420
  }
3421
3421
  return filtered;
3422
3422
  }
3423
- function interpolatePattern(pattern, modifierInputs, modifierName, context) {
3424
- let result = pattern;
3425
- if (modifierName !== void 0) {
3426
- result = result.replace(/\{modifierName\}/g, modifierName);
3423
+ function filterTokensFromSets(tokens) {
3424
+ const filtered = {};
3425
+ for (const [name, token] of Object.entries(tokens)) {
3426
+ const hasModifierSource = typeof token._sourceModifier === "string" && token._sourceModifier !== "";
3427
+ if (!hasModifierSource) {
3428
+ filtered[name] = token;
3429
+ }
3427
3430
  }
3428
- if (context !== void 0) {
3429
- result = result.replace(/\{context\}/g, context);
3431
+ return filtered;
3432
+ }
3433
+ function resolveBaseFileName(fileName, defaults) {
3434
+ if (typeof fileName === "function") {
3435
+ return fileName({ ...defaults, _base: "true" });
3436
+ }
3437
+ if (/\{.+?\}/.test(fileName)) {
3438
+ const baseInputs = Object.fromEntries(Object.keys(defaults).map((k) => [k, "base"]));
3439
+ return collapseBaseSegments(interpolatePattern(fileName, baseInputs));
3440
+ }
3441
+ const extMatch = fileName.match(/(\.[^.]+)$/);
3442
+ const extension = extMatch ? extMatch[1] : "";
3443
+ const baseName = extension ? fileName.slice(0, -extension.length) : fileName;
3444
+ return `${baseName}-base${extension}`;
3445
+ }
3446
+ function collapseBaseSegments(value) {
3447
+ let result = value;
3448
+ let previous = "";
3449
+ while (result !== previous) {
3450
+ previous = result;
3451
+ result = result.replace(/\bbase([/-])base\b/, "base");
3430
3452
  }
3453
+ return result;
3454
+ }
3455
+ function interpolatePattern(pattern, modifierInputs) {
3456
+ let result = pattern;
3431
3457
  for (const [key, value] of Object.entries(modifierInputs)) {
3432
3458
  result = result.replaceAll(`{${key}}`, value);
3433
3459
  }
3434
3460
  return result;
3435
3461
  }
3436
- function resolveFileName(fileName, modifierInputs, modifierName, context) {
3462
+ function resolveFileName(fileName, modifierInputs) {
3437
3463
  if (typeof fileName === "function") {
3438
3464
  return fileName(modifierInputs);
3439
3465
  }
3440
3466
  if (/\{.+?\}/.test(fileName)) {
3441
- return interpolatePattern(fileName, modifierInputs, modifierName, context);
3467
+ return interpolatePattern(fileName, modifierInputs);
3442
3468
  }
3443
3469
  const extMatch = fileName.match(/(\.[^.]+)$/);
3444
3470
  const extension = extMatch ? extMatch[1] : "";
3445
3471
  const baseName = extension ? fileName.slice(0, -extension.length) : fileName;
3446
- if (modifierName !== void 0 && context !== void 0) {
3447
- return `${baseName}-${modifierName}-${context}${extension}`;
3448
- }
3449
3472
  const modifierSuffix = Object.entries(modifierInputs).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)).map(([key, value]) => `${key}-${value}`).join("-");
3450
3473
  if (modifierSuffix) {
3451
3474
  return `${baseName}-${modifierSuffix}${extension}`;
@@ -7360,6 +7383,33 @@ function collectRemainder(tokens, included) {
7360
7383
  }
7361
7384
  return result;
7362
7385
  }
7386
+ function buildSetLayerBlocks(tokens, resolver) {
7387
+ const blocks = [];
7388
+ const included = /* @__PURE__ */ new Set();
7389
+ const addBlock = (key, blockTokens, description) => {
7390
+ if (Object.keys(blockTokens).length === 0) {
7391
+ return;
7392
+ }
7393
+ for (const k of Object.keys(blockTokens)) {
7394
+ included.add(k);
7395
+ }
7396
+ blocks.push({ key, description, tokens: blockTokens });
7397
+ };
7398
+ for (const item of resolver.resolutionOrder) {
7399
+ const ref = item.$ref;
7400
+ if (typeof ref !== "string" || !ref.startsWith("#/sets/")) {
7401
+ continue;
7402
+ }
7403
+ const setName = ref.slice("#/sets/".length);
7404
+ addBlock(
7405
+ `Set: ${setName}`,
7406
+ collectSetTokens(tokens, setName, included),
7407
+ resolver.sets?.[setName]?.description
7408
+ );
7409
+ }
7410
+ addBlock("Unattributed", collectRemainder(tokens, included));
7411
+ return blocks;
7412
+ }
7363
7413
  function buildDefaultLayerBlocks(tokens, baseModifierInputs, resolver) {
7364
7414
  const blocks = [];
7365
7415
  const included = /* @__PURE__ */ new Set();
@@ -8080,6 +8130,10 @@ var CssRenderer = class _CssRenderer {
8080
8130
  throw new exports.ConfigurationError("Modifier preset requires modifiers to be defined in resolver");
8081
8131
  }
8082
8132
  const files = {};
8133
+ const baseResult = await this.buildModifierBaseFile(context, options);
8134
+ if (baseResult) {
8135
+ files[baseResult.fileName] = baseResult.content;
8136
+ }
8083
8137
  for (const [modifierName, modifierDef] of Object.entries(context.resolver.modifiers)) {
8084
8138
  for (const contextValue of Object.keys(modifierDef.contexts)) {
8085
8139
  const result = await this.buildModifierContextFile(
@@ -8095,6 +8149,59 @@ var CssRenderer = class _CssRenderer {
8095
8149
  }
8096
8150
  return { kind: "outputTree", files };
8097
8151
  }
8152
+ async buildModifierBaseFile(context, options) {
8153
+ const basePermutation = context.permutations.find(
8154
+ ({ modifierInputs }) => this.isBasePermutation(modifierInputs, context.meta.defaults)
8155
+ );
8156
+ if (!basePermutation) {
8157
+ return void 0;
8158
+ }
8159
+ const setTokens = filterTokensFromSets(basePermutation.tokens);
8160
+ if (Object.keys(setTokens).length === 0) {
8161
+ return void 0;
8162
+ }
8163
+ const setBlocks = buildSetLayerBlocks(setTokens, context.resolver);
8164
+ if (setBlocks.length === 0) {
8165
+ return void 0;
8166
+ }
8167
+ const modifiers = context.resolver.modifiers;
8168
+ const firstModifierName = Object.keys(modifiers)[0] ?? "";
8169
+ const firstModifierContext = context.meta.defaults[firstModifierName] ?? "";
8170
+ const baseModifierInputs = { ...context.meta.defaults };
8171
+ const selector = resolveSelector(
8172
+ options.selector,
8173
+ firstModifierName,
8174
+ firstModifierContext,
8175
+ true,
8176
+ baseModifierInputs
8177
+ );
8178
+ const mediaQuery = resolveMediaQuery(
8179
+ options.mediaQuery,
8180
+ firstModifierName,
8181
+ firstModifierContext,
8182
+ true,
8183
+ baseModifierInputs
8184
+ );
8185
+ const referenceTokens = basePermutation.tokens;
8186
+ const cssBlocks = [];
8187
+ for (const block of setBlocks) {
8188
+ const cleanTokens = stripInternalMetadata(block.tokens);
8189
+ const css2 = await this.formatTokens(cleanTokens, {
8190
+ selector,
8191
+ mediaQuery,
8192
+ minify: options.minify ?? false,
8193
+ preserveReferences: options.preserveReferences ?? false,
8194
+ referenceTokens
8195
+ });
8196
+ const header = block.description ? `/* ${block.key} */
8197
+ /* ${block.description} */` : `/* ${block.key} */`;
8198
+ cssBlocks.push(`${header}
8199
+ ${css2}`);
8200
+ }
8201
+ const content = cssBlocks.join("\n");
8202
+ const fileName = context.output.file ? resolveBaseFileName(context.output.file, context.meta.defaults) : `${context.output.name}-base.css`;
8203
+ return { fileName, content };
8204
+ }
8098
8205
  collectTokensForModifierContext(modifierName, contextValue, permutations) {
8099
8206
  const expectedSource = `${modifierName}-${contextValue}`;
8100
8207
  let tokensFromSource = {};
@@ -8141,7 +8248,7 @@ var CssRenderer = class _CssRenderer {
8141
8248
  preserveReferences: options.preserveReferences ?? false,
8142
8249
  referenceTokens
8143
8250
  });
8144
- const fileName = context.output.file ? resolveFileName(context.output.file, modifierInputs, modifierName, contextValue) : buildInMemoryOutputKey({
8251
+ const fileName = context.output.file ? resolveFileName(context.output.file, modifierInputs) : buildInMemoryOutputKey({
8145
8252
  outputName: context.output.name,
8146
8253
  extension: "css",
8147
8254
  modifierInputs,