@unocss/core 0.21.2 → 0.22.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
@@ -161,6 +161,7 @@ function hex2rgba(hex = "") {
161
161
 
162
162
  const attributifyRE = /^\[(.+?)~?="(.*)"\]$/;
163
163
  const validateFilterRE = /(?!\d|-{2}|-\d)[a-zA-Z0-9\u00A0-\uFFFF-_:%-?]/;
164
+ const CONTROL_SHORTCUT_NO_MERGE = "$$shortcut-no-merge";
164
165
  function isAttributifySelector(selector) {
165
166
  return selector.match(attributifyRE);
166
167
  }
@@ -387,7 +388,7 @@ function resolveConfig(userConfig = {}, defaults = {}) {
387
388
  };
388
389
  }
389
390
 
390
- const version = "0.21.2";
391
+ const version = "0.22.0";
391
392
 
392
393
  class UnoGenerator {
393
394
  constructor(userConfig = {}, defaults = {}) {
@@ -499,12 +500,20 @@ class UnoGenerator {
499
500
  }
500
501
  const layerCache = {};
501
502
  const layers = this.config.sortLayers(Array.from(layerSet).sort((a, b) => (this.config.layers[a] ?? 0) - (this.config.layers[b] ?? 0) || a.localeCompare(b)));
503
+ let preflightsMap = {};
504
+ if (preflights) {
505
+ preflightsMap = Object.fromEntries(await Promise.all(layers.map(async (layer) => {
506
+ const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "default") === layer).map(async (i) => await i.getCSS()));
507
+ const css = preflights2.filter(Boolean).join(nl);
508
+ return [layer, css];
509
+ })));
510
+ }
502
511
  const getLayer = (layer) => {
503
512
  if (layerCache[layer])
504
513
  return layerCache[layer];
505
514
  let css = Array.from(sheet).sort((a, b) => (this.parentOrders.get(a[0]) ?? 0) - (this.parentOrders.get(b[0]) ?? 0) || a[0]?.localeCompare(b[0] || "") || 0).map(([parent, items]) => {
506
515
  const size = items.length;
507
- const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || a[1]?.localeCompare(b[1] || "") || 0).map((a) => [a[1] ? applyScope(a[1], scope) : a[1], a[2]]);
516
+ const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || a[1]?.localeCompare(b[1] || "") || 0).map((a) => [a[1] ? applyScope(a[1], scope) : a[1], a[2]]).map((a) => [a[0] == null ? a[0] : [a[0]], a[1]]);
508
517
  if (!sorted.length)
509
518
  return void 0;
510
519
  const rules = sorted.reverse().map(([selector, body], idx) => {
@@ -512,20 +521,17 @@ class UnoGenerator {
512
521
  for (let i = idx + 1; i < size; i++) {
513
522
  const current = sorted[i];
514
523
  if (current && current[0] && current[1] === body) {
515
- current[0] = `${current[0]},${nl}${selector}`;
524
+ current[0].push(...selector);
516
525
  return null;
517
526
  }
518
527
  }
519
528
  }
520
- return selector ? `${selector}{${body}}` : body;
529
+ return selector ? `${[...new Set(selector)].join(`,${nl}`)}{${body}}` : body;
521
530
  }).filter(Boolean).reverse().join(nl);
522
531
  return parent ? `${parent}{${nl}${rules}${nl}}` : rules;
523
532
  }).filter(Boolean).join(nl);
524
533
  if (preflights) {
525
- css = [
526
- ...this.config.preflights.filter((i) => (i.layer || "default") === layer).map((i) => i.getCSS()).filter(Boolean),
527
- css
528
- ].join(nl);
534
+ css = [preflightsMap[layer], css].filter(Boolean).join(nl);
529
535
  }
530
536
  return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
531
537
  };
@@ -684,16 +690,18 @@ class UnoGenerator {
684
690
  continue;
685
691
  const { selector, entries, parent: parent2 } = this.applyVariants(item, [...item[4], ...parentVariants], raw);
686
692
  const mapItem = selectorMap.getFallback(selector, parent2, [[], item[0]]);
687
- mapItem[0].push(...entries);
688
- if (item[0] > mapItem[1])
689
- mapItem[1] = item[0];
693
+ mapItem[0].push(entries);
690
694
  }
691
- return selectorMap.map(([entries, index], selector, mediaQuery) => {
692
- const body = entriesToCss(entries);
693
- if (body)
694
- return [index, selector, body, mediaQuery, meta];
695
- return void 0;
696
- }).filter(Boolean);
695
+ return selectorMap.map(([e2, index], selector, mediaQuery) => {
696
+ const split = e2.filter((entries) => entries.some((entry) => entry[0] === CONTROL_SHORTCUT_NO_MERGE));
697
+ const rest = e2.filter((entries) => entries.every((entry) => entry[0] !== CONTROL_SHORTCUT_NO_MERGE));
698
+ return [...split, rest.flat(1)].map((entries) => {
699
+ const body = entriesToCss(entries);
700
+ if (body)
701
+ return [index, selector, body, mediaQuery, meta];
702
+ return void 0;
703
+ });
704
+ }).flat(1).filter(Boolean);
697
705
  }
698
706
  isBlocked(raw) {
699
707
  return !raw || this.config.blocklist.some((e2) => typeof e2 === "string" ? e2 === raw : e2.test(raw));
@@ -718,6 +726,7 @@ function toEscapedSelector(raw) {
718
726
  }
719
727
 
720
728
  exports.BetterMap = BetterMap;
729
+ exports.CONTROL_SHORTCUT_NO_MERGE = CONTROL_SHORTCUT_NO_MERGE;
721
730
  exports.TwoKeyMap = TwoKeyMap;
722
731
  exports.UnoGenerator = UnoGenerator;
723
732
  exports.attributifyRE = attributifyRE;
package/dist/index.d.ts CHANGED
@@ -38,7 +38,7 @@ declare type RequiredByKey<T, K extends keyof T = keyof T> = FlatObjectTuple<Req
38
38
  declare type CSSObject = Record<string, string | number | undefined>;
39
39
  declare type CSSEntries = [string, string | number | undefined][];
40
40
  declare type RGBAColorValue = [number, number, number, number] | [number, number, number];
41
- declare type ParsedColorValue = {
41
+ interface ParsedColorValue {
42
42
  /**
43
43
  * Parsed color value.
44
44
  */
@@ -63,7 +63,7 @@ declare type ParsedColorValue = {
63
63
  * Parsed rgba's alpha value.
64
64
  */
65
65
  alpha?: number | string;
66
- };
66
+ }
67
67
  declare type PresetOptions = Record<string, any>;
68
68
  interface RuleContext<Theme extends {} = {}> {
69
69
  /**
@@ -142,7 +142,7 @@ declare type UserShortcuts<Theme extends {} = {}> = StaticShortcutMap | (StaticS
142
142
  declare type Shortcut<Theme extends {} = {}> = StaticShortcut | DynamicShortcut<Theme>;
143
143
  declare type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null;
144
144
  interface Preflight {
145
- getCSS: () => string | undefined;
145
+ getCSS: () => Promise<string | undefined> | string | undefined;
146
146
  layer?: string;
147
147
  }
148
148
  declare type BlocklistRule = string | RegExp;
@@ -169,7 +169,7 @@ interface VariantHandler {
169
169
  order?: number;
170
170
  }
171
171
  declare type VariantFunction<Theme extends {} = {}> = (matcher: string, context: Readonly<VariantContext<Theme>>) => string | VariantHandler | undefined;
172
- declare type VariantObject<Theme extends {} = {}> = {
172
+ interface VariantObject<Theme extends {} = {}> {
173
173
  /**
174
174
  * The entry function to match and rewrite the selector for futher processing.
175
175
  */
@@ -180,7 +180,7 @@ declare type VariantObject<Theme extends {} = {}> = {
180
180
  * @default false
181
181
  */
182
182
  multiPass?: boolean;
183
- };
183
+ }
184
184
  declare type Variant<Theme extends {} = {}> = VariantFunction<Theme> | VariantObject<Theme>;
185
185
  declare type Preprocessor = (matcher: string) => string | undefined;
186
186
  declare type Postprocessor = (util: UtilObject) => void;
@@ -410,6 +410,7 @@ declare function hex2rgba(hex?: string): RGBAColorValue | undefined;
410
410
 
411
411
  declare const attributifyRE: RegExp;
412
412
  declare const validateFilterRE: RegExp;
413
+ declare const CONTROL_SHORTCUT_NO_MERGE = "$$shortcut-no-merge";
413
414
  declare function isAttributifySelector(selector: string): RegExpMatchArray | null;
414
415
  declare function isValidSelector(selector?: string): selector is string;
415
416
  declare function normalizeVariant(variant: Variant): VariantObject;
@@ -452,4 +453,4 @@ declare const extractorSplit: Extractor;
452
453
 
453
454
  declare const extractorSvelte: Extractor;
454
455
 
455
- export { ArgumentType, Arrayable, Awaitable, BetterMap, BlocklistRule, CSSEntries, CSSObject, CSSValues, ConfigBase, DeepPartial, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, Preprocessor, Preset, PresetOptions, RGBAColorValue, RawUtil, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, ThemeExtender, TwoKeyMap, UnoGenerator, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit, extractorSvelte, hasScopePlaceholder, hex2rgba, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, mergeDeep, mergeSet, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, toArray, uniq, validateFilterRE, warnOnce, withLayer };
456
+ export { ArgumentType, Arrayable, Awaitable, BetterMap, BlocklistRule, CONTROL_SHORTCUT_NO_MERGE, CSSEntries, CSSObject, CSSValues, ConfigBase, DeepPartial, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, Preprocessor, Preset, PresetOptions, RGBAColorValue, RawUtil, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, ThemeExtender, TwoKeyMap, UnoGenerator, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit, extractorSvelte, hasScopePlaceholder, hex2rgba, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, mergeDeep, mergeSet, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, toArray, uniq, validateFilterRE, warnOnce, withLayer };
package/dist/index.mjs CHANGED
@@ -157,6 +157,7 @@ function hex2rgba(hex = "") {
157
157
 
158
158
  const attributifyRE = /^\[(.+?)~?="(.*)"\]$/;
159
159
  const validateFilterRE = /(?!\d|-{2}|-\d)[a-zA-Z0-9\u00A0-\uFFFF-_:%-?]/;
160
+ const CONTROL_SHORTCUT_NO_MERGE = "$$shortcut-no-merge";
160
161
  function isAttributifySelector(selector) {
161
162
  return selector.match(attributifyRE);
162
163
  }
@@ -383,7 +384,7 @@ function resolveConfig(userConfig = {}, defaults = {}) {
383
384
  };
384
385
  }
385
386
 
386
- const version = "0.21.2";
387
+ const version = "0.22.0";
387
388
 
388
389
  class UnoGenerator {
389
390
  constructor(userConfig = {}, defaults = {}) {
@@ -495,12 +496,20 @@ class UnoGenerator {
495
496
  }
496
497
  const layerCache = {};
497
498
  const layers = this.config.sortLayers(Array.from(layerSet).sort((a, b) => (this.config.layers[a] ?? 0) - (this.config.layers[b] ?? 0) || a.localeCompare(b)));
499
+ let preflightsMap = {};
500
+ if (preflights) {
501
+ preflightsMap = Object.fromEntries(await Promise.all(layers.map(async (layer) => {
502
+ const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "default") === layer).map(async (i) => await i.getCSS()));
503
+ const css = preflights2.filter(Boolean).join(nl);
504
+ return [layer, css];
505
+ })));
506
+ }
498
507
  const getLayer = (layer) => {
499
508
  if (layerCache[layer])
500
509
  return layerCache[layer];
501
510
  let css = Array.from(sheet).sort((a, b) => (this.parentOrders.get(a[0]) ?? 0) - (this.parentOrders.get(b[0]) ?? 0) || a[0]?.localeCompare(b[0] || "") || 0).map(([parent, items]) => {
502
511
  const size = items.length;
503
- const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || a[1]?.localeCompare(b[1] || "") || 0).map((a) => [a[1] ? applyScope(a[1], scope) : a[1], a[2]]);
512
+ const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || a[1]?.localeCompare(b[1] || "") || 0).map((a) => [a[1] ? applyScope(a[1], scope) : a[1], a[2]]).map((a) => [a[0] == null ? a[0] : [a[0]], a[1]]);
504
513
  if (!sorted.length)
505
514
  return void 0;
506
515
  const rules = sorted.reverse().map(([selector, body], idx) => {
@@ -508,20 +517,17 @@ class UnoGenerator {
508
517
  for (let i = idx + 1; i < size; i++) {
509
518
  const current = sorted[i];
510
519
  if (current && current[0] && current[1] === body) {
511
- current[0] = `${current[0]},${nl}${selector}`;
520
+ current[0].push(...selector);
512
521
  return null;
513
522
  }
514
523
  }
515
524
  }
516
- return selector ? `${selector}{${body}}` : body;
525
+ return selector ? `${[...new Set(selector)].join(`,${nl}`)}{${body}}` : body;
517
526
  }).filter(Boolean).reverse().join(nl);
518
527
  return parent ? `${parent}{${nl}${rules}${nl}}` : rules;
519
528
  }).filter(Boolean).join(nl);
520
529
  if (preflights) {
521
- css = [
522
- ...this.config.preflights.filter((i) => (i.layer || "default") === layer).map((i) => i.getCSS()).filter(Boolean),
523
- css
524
- ].join(nl);
530
+ css = [preflightsMap[layer], css].filter(Boolean).join(nl);
525
531
  }
526
532
  return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
527
533
  };
@@ -680,16 +686,18 @@ class UnoGenerator {
680
686
  continue;
681
687
  const { selector, entries, parent: parent2 } = this.applyVariants(item, [...item[4], ...parentVariants], raw);
682
688
  const mapItem = selectorMap.getFallback(selector, parent2, [[], item[0]]);
683
- mapItem[0].push(...entries);
684
- if (item[0] > mapItem[1])
685
- mapItem[1] = item[0];
689
+ mapItem[0].push(entries);
686
690
  }
687
- return selectorMap.map(([entries, index], selector, mediaQuery) => {
688
- const body = entriesToCss(entries);
689
- if (body)
690
- return [index, selector, body, mediaQuery, meta];
691
- return void 0;
692
- }).filter(Boolean);
691
+ return selectorMap.map(([e2, index], selector, mediaQuery) => {
692
+ const split = e2.filter((entries) => entries.some((entry) => entry[0] === CONTROL_SHORTCUT_NO_MERGE));
693
+ const rest = e2.filter((entries) => entries.every((entry) => entry[0] !== CONTROL_SHORTCUT_NO_MERGE));
694
+ return [...split, rest.flat(1)].map((entries) => {
695
+ const body = entriesToCss(entries);
696
+ if (body)
697
+ return [index, selector, body, mediaQuery, meta];
698
+ return void 0;
699
+ });
700
+ }).flat(1).filter(Boolean);
693
701
  }
694
702
  isBlocked(raw) {
695
703
  return !raw || this.config.blocklist.some((e2) => typeof e2 === "string" ? e2 === raw : e2.test(raw));
@@ -713,4 +721,4 @@ function toEscapedSelector(raw) {
713
721
  return `.${e(raw)}`;
714
722
  }
715
723
 
716
- export { BetterMap, TwoKeyMap, UnoGenerator, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit, extractorSvelte, hasScopePlaceholder, hex2rgba, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, mergeDeep, mergeSet, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, toArray, uniq, validateFilterRE, warnOnce, withLayer };
724
+ export { BetterMap, CONTROL_SHORTCUT_NO_MERGE, TwoKeyMap, UnoGenerator, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit, extractorSvelte, hasScopePlaceholder, hex2rgba, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, mergeDeep, mergeSet, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, toArray, uniq, validateFilterRE, warnOnce, withLayer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unocss/core",
3
- "version": "0.21.2",
3
+ "version": "0.22.0",
4
4
  "description": "The instant on-demand Atomic CSS engine.",
5
5
  "keywords": [
6
6
  "unocss",