@unocss/core 0.42.1 → 0.43.2

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
@@ -39,8 +39,22 @@ function escapeSelector(str) {
39
39
  }
40
40
  const e = escapeSelector;
41
41
 
42
+ function toArray(value = []) {
43
+ return Array.isArray(value) ? value : [value];
44
+ }
45
+ function uniq(value) {
46
+ return Array.from(new Set(value));
47
+ }
48
+ function mergeSet(target, append) {
49
+ append.forEach((i) => target.add(i));
50
+ return target;
51
+ }
52
+ function isString(s) {
53
+ return typeof s === "string";
54
+ }
55
+
42
56
  function normalizeCSSEntries(obj) {
43
- if (typeof obj === "string")
57
+ if (isString(obj))
44
58
  return obj;
45
59
  return (!Array.isArray(obj) ? Object.entries(obj) : obj).filter((i) => i[1] != null);
46
60
  }
@@ -118,21 +132,10 @@ function clone(val) {
118
132
  return val;
119
133
  }
120
134
  function isStaticRule(rule) {
121
- return typeof rule[0] === "string";
135
+ return isString(rule[0]);
122
136
  }
123
137
  function isStaticShortcut(sc) {
124
- return typeof sc[0] === "string";
125
- }
126
-
127
- function toArray(value = []) {
128
- return Array.isArray(value) ? value : [value];
129
- }
130
- function uniq(value) {
131
- return Array.from(new Set(value));
132
- }
133
- function mergeSet(target, append) {
134
- append.forEach((i) => target.add(i));
135
- return target;
138
+ return isString(sc[0]);
136
139
  }
137
140
 
138
141
  const attributifyRE = /^\[(.+?)~?="(.*)"\]$/;
@@ -386,6 +389,15 @@ function createNanoEvents() {
386
389
  };
387
390
  }
388
391
 
392
+ const LAYER_DEFAULT = "default";
393
+ const LAYER_PREFLIGHTS = "preflights";
394
+ const LAYER_SHORTCUTS = "shortcuts";
395
+ const DEAFULT_LAYERS = {
396
+ [LAYER_PREFLIGHTS]: -100,
397
+ [LAYER_SHORTCUTS]: -10,
398
+ [LAYER_DEFAULT]: 0
399
+ };
400
+
389
401
  function resolveShortcuts(shortcuts) {
390
402
  return toArray(shortcuts).flatMap((s) => {
391
403
  if (Array.isArray(s))
@@ -393,20 +405,33 @@ function resolveShortcuts(shortcuts) {
393
405
  return Object.entries(s);
394
406
  });
395
407
  }
396
- const defaultLayers = {
397
- preflights: -100,
398
- shortcuts: -10,
399
- default: 0
400
- };
408
+ function resolvePreset(preset) {
409
+ const shortcuts = preset.shortcuts ? resolveShortcuts(preset.shortcuts) : void 0;
410
+ preset.shortcuts = shortcuts;
411
+ if (preset.prefix || preset.layer) {
412
+ const apply = (i) => {
413
+ if (!i[2])
414
+ i[2] = {};
415
+ const meta = i[2];
416
+ if (meta.prefix == null && preset.prefix)
417
+ meta.prefix = preset.prefix;
418
+ if (meta.layer == null && preset.layer)
419
+ meta.prefix = preset.layer;
420
+ };
421
+ shortcuts?.forEach(apply);
422
+ preset.rules?.forEach(apply);
423
+ }
424
+ return preset;
425
+ }
401
426
  function resolveConfig(userConfig = {}, defaults = {}) {
402
427
  const config = Object.assign({}, defaults, userConfig);
403
- const rawPresets = (config.presets || []).flatMap(toArray);
428
+ const rawPresets = (config.presets || []).flatMap(toArray).map(resolvePreset);
404
429
  const sortedPresets = [
405
430
  ...rawPresets.filter((p) => p.enforce === "pre"),
406
431
  ...rawPresets.filter((p) => !p.enforce),
407
432
  ...rawPresets.filter((p) => p.enforce === "post")
408
433
  ];
409
- const layers = Object.assign(defaultLayers, ...rawPresets.map((i) => i.layers), userConfig.layers);
434
+ const layers = Object.assign(DEAFULT_LAYERS, ...rawPresets.map((i) => i.layers), userConfig.layers);
410
435
  function mergePresets(key) {
411
436
  return uniq([
412
437
  ...sortedPresets.flatMap((p) => toArray(p[key] || [])),
@@ -422,7 +447,8 @@ function resolveConfig(userConfig = {}, defaults = {}) {
422
447
  const rulesSize = rules.length;
423
448
  rules.forEach((rule, i) => {
424
449
  if (isStaticRule(rule)) {
425
- rulesStaticMap[rule[0]] = [i, rule[1], rule[2], rule];
450
+ const prefix = rule[2]?.prefix || "";
451
+ rulesStaticMap[prefix + rule[0]] = [i, rule[1], rule[2], rule];
426
452
  delete rules[i];
427
453
  }
428
454
  });
@@ -460,7 +486,7 @@ function resolveConfig(userConfig = {}, defaults = {}) {
460
486
  };
461
487
  }
462
488
 
463
- const version = "0.42.1";
489
+ const version = "0.43.2";
464
490
 
465
491
  class UnoGenerator {
466
492
  constructor(userConfig = {}, defaults = {}) {
@@ -551,18 +577,19 @@ class UnoGenerator {
551
577
  }
552
578
  this._cache.set(cacheKey, null);
553
579
  }
554
- async generate(input = "", {
555
- id,
556
- scope,
557
- preflights = true,
558
- safelist = true,
559
- minify = false
560
- } = {}) {
561
- const tokens = typeof input === "string" ? await this.applyExtractors(input, id) : input;
580
+ async generate(input, options = {}) {
581
+ const {
582
+ id,
583
+ scope,
584
+ preflights = true,
585
+ safelist = true,
586
+ minify = false
587
+ } = options;
588
+ const tokens = isString(input) ? await this.applyExtractors(input, id) : Array.isArray(input) ? new Set(input) : input;
562
589
  if (safelist)
563
590
  this.config.safelist.forEach((s) => tokens.add(s));
564
591
  const nl = minify ? "" : "\n";
565
- const layerSet = /* @__PURE__ */ new Set(["default"]);
592
+ const layerSet = /* @__PURE__ */ new Set([LAYER_DEFAULT]);
566
593
  const matched = /* @__PURE__ */ new Set();
567
594
  const sheet = /* @__PURE__ */ new Map();
568
595
  let preflightsMap = {};
@@ -591,12 +618,12 @@ class UnoGenerator {
591
618
  theme: this.config.theme
592
619
  };
593
620
  const preflightLayerSet = /* @__PURE__ */ new Set([]);
594
- this.config.preflights.forEach(({ layer = "preflights" }) => {
621
+ this.config.preflights.forEach(({ layer = LAYER_PREFLIGHTS }) => {
595
622
  layerSet.add(layer);
596
623
  preflightLayerSet.add(layer);
597
624
  });
598
625
  preflightsMap = Object.fromEntries(await Promise.all(Array.from(preflightLayerSet).map(async (layer) => {
599
- const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "preflights") === layer).map(async (i) => await i.getCSS(preflightContext)));
626
+ const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || LAYER_PREFLIGHTS) === layer).map(async (i) => await i.getCSS(preflightContext)));
600
627
  const css = preflights2.filter(Boolean).join(nl);
601
628
  return [layer, css];
602
629
  })));
@@ -612,7 +639,7 @@ class UnoGenerator {
612
639
  return layerCache[layer];
613
640
  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]) => {
614
641
  const size = items.length;
615
- const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || (a[4]?.sort || 0) - (b[4]?.sort || 0) || a[1]?.localeCompare(b[1] || "") || a[2]?.localeCompare(b[2] || "") || 0).map(([, selector, body, , meta]) => {
642
+ const sorted = items.filter((i) => (i[4]?.layer || LAYER_DEFAULT) === layer).sort((a, b) => a[0] - b[0] || (a[4]?.sort || 0) - (b[4]?.sort || 0) || a[1]?.localeCompare(b[1] || "") || a[2]?.localeCompare(b[2] || "") || 0).map(([, selector, body, , meta]) => {
616
643
  const scopedSelector = selector ? applyScope(selector, scope) : selector;
617
644
  return [
618
645
  [[scopedSelector ?? "", meta?.sort ?? 0]],
@@ -633,7 +660,7 @@ class UnoGenerator {
633
660
  }
634
661
  }
635
662
  }
636
- const selectors = selectorSortPair ? [...new Set(selectorSortPair.sort((a, b) => a[1] - b[1] || a[0]?.localeCompare(b[0] || "") || 0).map((pair) => pair[0]).filter(Boolean))] : [];
663
+ const selectors = selectorSortPair ? uniq(selectorSortPair.sort((a, b) => a[1] - b[1] || a[0]?.localeCompare(b[0] || "") || 0).map((pair) => pair[0]).filter(Boolean)) : [];
637
664
  return selectors.length ? `${selectors.join(`,${nl}`)}{${body}}` : body;
638
665
  }).filter(Boolean).reverse().join(nl);
639
666
  if (!parent)
@@ -644,7 +671,8 @@ class UnoGenerator {
644
671
  if (preflights) {
645
672
  css = [preflightsMap[layer], css].filter(Boolean).join(nl);
646
673
  }
647
- return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
674
+ const layerMark = minify ? "" : `/* layer: ${layer} */${nl}`;
675
+ return layerCache[layer] = css ? layerMark + css : "";
648
676
  };
649
677
  const getLayers = (includes = layers, excludes) => {
650
678
  return includes.filter((i) => !excludes?.includes(i)).map((i) => getLayer(i) || "").filter(Boolean).join(nl);
@@ -654,9 +682,9 @@ class UnoGenerator {
654
682
  return getLayers();
655
683
  },
656
684
  layers,
685
+ matched,
657
686
  getLayers,
658
- getLayer,
659
- matched
687
+ getLayer
660
688
  };
661
689
  }
662
690
  matchVariants(raw, current) {
@@ -677,7 +705,7 @@ class UnoGenerator {
677
705
  let handler = v.match(processed, context);
678
706
  if (!handler)
679
707
  continue;
680
- if (typeof handler === "string")
708
+ if (isString(handler))
681
709
  handler = { matcher: handler };
682
710
  processed = handler.matcher;
683
711
  handlers.unshift(handler);
@@ -732,7 +760,7 @@ class UnoGenerator {
732
760
  }
733
761
  constructCustomCSS(context, body, overrideSelector) {
734
762
  const normalizedBody = normalizeCSSEntries(body);
735
- if (typeof normalizedBody === "string")
763
+ if (isString(normalizedBody))
736
764
  return normalizedBody;
737
765
  const { selector, entries, parent } = this.applyVariants([0, overrideSelector || context.rawSelector, normalizedBody, void 0, context.variantHandlers]);
738
766
  const cssBody = `${selector}{${entriesToCss(entries)}}`;
@@ -741,7 +769,7 @@ class UnoGenerator {
741
769
  return cssBody;
742
770
  }
743
771
  async parseUtil(input, context, internal = false) {
744
- const [raw, processed, variantHandlers] = typeof input === "string" ? this.matchVariants(input) : input;
772
+ const [raw, processed, variantHandlers] = isString(input) ? this.matchVariants(input) : input;
745
773
  const recordRule = this.config.details ? (r) => {
746
774
  context.rules = context.rules ?? [];
747
775
  context.rules.push(r);
@@ -753,7 +781,7 @@ class UnoGenerator {
753
781
  const index = staticMatch[0];
754
782
  const entry = normalizeCSSEntries(staticMatch[1]);
755
783
  const meta = staticMatch[2];
756
- if (typeof entry === "string")
784
+ if (isString(entry))
757
785
  return [[index, entry, meta]];
758
786
  else
759
787
  return [[index, raw, entry, meta, variantHandlers]];
@@ -768,7 +796,10 @@ class UnoGenerator {
768
796
  if (rule[2]?.internal && !internal)
769
797
  continue;
770
798
  const [matcher, handler, meta] = rule;
771
- const match = processed.match(matcher);
799
+ if (meta?.prefix && !processed.startsWith(meta.prefix))
800
+ continue;
801
+ const unprefixed = meta?.prefix ? processed.slice(meta.prefix.length) : processed;
802
+ const match = unprefixed.match(matcher);
772
803
  if (!match)
773
804
  continue;
774
805
  const result = await handler(match, context);
@@ -778,7 +809,7 @@ class UnoGenerator {
778
809
  const entries = normalizeCSSValues(result).filter((i2) => i2.length);
779
810
  if (entries.length) {
780
811
  return entries.map((e2) => {
781
- if (typeof e2 === "string")
812
+ if (isString(e2))
782
813
  return [i, e2, meta];
783
814
  else
784
815
  return [i, raw, e2, meta, variantHandlers];
@@ -803,7 +834,7 @@ class UnoGenerator {
803
834
  };
804
835
  return [parsed[0], selector, body, parent, ruleMeta, this.config.details ? context : void 0];
805
836
  }
806
- expandShortcut(processed, context, depth = 3) {
837
+ expandShortcut(input, context, depth = 5) {
807
838
  if (depth === 0)
808
839
  return;
809
840
  const recordShortcut = this.config.details ? (s) => {
@@ -813,15 +844,16 @@ class UnoGenerator {
813
844
  let meta;
814
845
  let result;
815
846
  for (const s of this.config.shortcuts) {
847
+ const unprefixed = s[2]?.prefix ? input.slice(s[2].prefix.length) : input;
816
848
  if (isStaticShortcut(s)) {
817
- if (s[0] === processed) {
849
+ if (s[0] === unprefixed) {
818
850
  meta = meta || s[2];
819
851
  result = s[1];
820
852
  recordShortcut(s);
821
853
  break;
822
854
  }
823
855
  } else {
824
- const match = processed.match(s[0]);
856
+ const match = unprefixed.match(s[0]);
825
857
  if (match)
826
858
  result = s[1](match, context);
827
859
  if (result) {
@@ -831,30 +863,27 @@ class UnoGenerator {
831
863
  }
832
864
  }
833
865
  }
834
- if (typeof result === "string")
866
+ if (isString(result))
835
867
  result = expandVariantGroup(result).split(/\s+/g);
836
868
  if (!result) {
837
- const [raw, rematchedProcess] = typeof processed === "string" ? this.matchVariants(processed) : processed;
838
- if (raw !== rematchedProcess) {
839
- const expanded = this.expandShortcut(rematchedProcess, context, depth - 1);
840
- if (expanded) {
841
- expanded[0].forEach((item, index) => {
842
- expanded[0][index] = raw.replace(rematchedProcess, item);
843
- });
844
- return expanded;
845
- }
869
+ const [raw, inputWithoutVariant] = isString(input) ? this.matchVariants(input) : input;
870
+ if (raw !== inputWithoutVariant) {
871
+ const expanded = this.expandShortcut(inputWithoutVariant, context, depth - 1);
872
+ if (expanded)
873
+ result = expanded[0].map((item) => isString(item) ? raw.replace(inputWithoutVariant, item) : item);
846
874
  }
847
- return;
848
875
  }
876
+ if (!result)
877
+ return;
849
878
  return [
850
- result.flatMap((r) => this.expandShortcut(r, context, depth - 1)?.[0] || [r]).filter((r) => r !== ""),
879
+ result.flatMap((r) => (isString(r) ? this.expandShortcut(r, context, depth - 1)?.[0] : void 0) || [r]).filter(Boolean),
851
880
  meta
852
881
  ];
853
882
  }
854
883
  async stringifyShortcuts(parent, context, expanded, meta = { layer: this.config.shortcutsLayer }) {
855
884
  const selectorMap = new TwoKeyMap();
856
885
  const parsed = (await Promise.all(uniq(expanded).map(async (i) => {
857
- const result = await this.parseUtil(i, context, true);
886
+ const result = isString(i) ? await this.parseUtil(i, context, true) : [[Infinity, "{inline}", normalizeCSSEntries(i), void 0, []]];
858
887
  if (!result)
859
888
  warnOnce(`unmatched utility "${i}" in shortcut "${parent[1]}"`);
860
889
  return result || [];
@@ -892,7 +921,7 @@ class UnoGenerator {
892
921
  }).flat(2).filter(Boolean));
893
922
  }
894
923
  isBlocked(raw) {
895
- return !raw || this.config.blocklist.some((e2) => typeof e2 === "string" ? e2 === raw : e2.test(raw));
924
+ return !raw || this.config.blocklist.some((e2) => isString(e2) ? e2 === raw : e2.test(raw));
896
925
  }
897
926
  }
898
927
  function createGenerator(config, defaults) {
@@ -948,6 +977,7 @@ exports.isObject = isObject;
948
977
  exports.isRawUtil = isRawUtil;
949
978
  exports.isStaticRule = isStaticRule;
950
979
  exports.isStaticShortcut = isStaticShortcut;
980
+ exports.isString = isString;
951
981
  exports.isValidSelector = isValidSelector;
952
982
  exports.matchingPair = matchingPair;
953
983
  exports.mergeDeep = mergeDeep;
package/dist/index.d.ts CHANGED
@@ -67,14 +67,14 @@ declare class UnoGenerator {
67
67
  applyExtractors(code: string, id?: string, set?: Set<string>): Promise<Set<string>>;
68
68
  makeContext(raw: string, applied: VariantMatchedResult): RuleContext<{}>;
69
69
  parseToken(raw: string, alias?: string): Promise<StringifiedUtil[] | null | undefined>;
70
- generate(input?: string | Set<string>, { id, scope, preflights, safelist, minify, }?: GenerateOptions): Promise<GenerateResult>;
70
+ generate(input: string | Set<string> | string[], options?: GenerateOptions): Promise<GenerateResult>;
71
71
  matchVariants(raw: string, current?: string): VariantMatchedResult;
72
- applyVariants(parsed: ParsedUtil, variantHandlers?: VariantHandler[], raw?: string): UtilObject;
72
+ private applyVariants;
73
73
  constructCustomCSS(context: Readonly<RuleContext>, body: CSSObject | CSSEntries, overrideSelector?: string): string;
74
74
  parseUtil(input: string | VariantMatchedResult, context: RuleContext, internal?: boolean): Promise<(ParsedUtil | RawUtil)[] | undefined>;
75
75
  stringifyUtil(parsed?: ParsedUtil | RawUtil, context?: RuleContext): StringifiedUtil | undefined;
76
- expandShortcut(processed: string, context: RuleContext, depth?: number): [string[], RuleMeta | undefined] | undefined;
77
- stringifyShortcuts(parent: VariantMatchedResult, context: RuleContext, expanded: string[], meta?: RuleMeta): Promise<StringifiedUtil[] | undefined>;
76
+ expandShortcut(input: string, context: RuleContext, depth?: number): [ShortcutValue[], RuleMeta | undefined] | undefined;
77
+ stringifyShortcuts(parent: VariantMatchedResult, context: RuleContext, expanded: ShortcutValue[], meta?: RuleMeta): Promise<StringifiedUtil[] | undefined>;
78
78
  isBlocked(raw: string): boolean;
79
79
  }
80
80
  declare function createGenerator(config?: UserConfig, defaults?: UserConfigDefaults): UnoGenerator;
@@ -103,6 +103,7 @@ declare function isStaticShortcut(sc: Shortcut): sc is StaticShortcut;
103
103
  declare function toArray<T>(value?: T | T[]): T[];
104
104
  declare function uniq<T>(value: T[]): T[];
105
105
  declare function mergeSet<T>(target: Set<T>, append: Set<T>): Set<T>;
106
+ declare function isString(s: any): s is string;
106
107
 
107
108
  declare const attributifyRE: RegExp;
108
109
  declare const cssIdRE: RegExp;
@@ -309,6 +310,10 @@ interface RuleMeta {
309
310
  * Templates to provide autocomplete suggestions
310
311
  */
311
312
  autocomplete?: Arrayable<AutoCompleteTemplate>;
313
+ /**
314
+ * Matching prefix before this util
315
+ */
316
+ prefix?: string;
312
317
  /**
313
318
  * Internal rules will only be matched for shortcuts but not the user code.
314
319
  * @default false
@@ -321,12 +326,13 @@ declare type DynamicMatcher<Theme extends {} = {}> = ((match: RegExpMatchArray,
321
326
  declare type DynamicRule<Theme extends {} = {}> = [RegExp, DynamicMatcher<Theme>] | [RegExp, DynamicMatcher<Theme>, RuleMeta];
322
327
  declare type StaticRule = [string, CSSObject | CSSEntries] | [string, CSSObject | CSSEntries, RuleMeta];
323
328
  declare type Rule<Theme extends {} = {}> = DynamicRule<Theme> | StaticRule;
324
- declare type DynamicShortcutMatcher<Theme extends {} = {}> = ((match: RegExpMatchArray, context: Readonly<RuleContext<Theme>>) => (string | string[] | undefined));
325
- declare type StaticShortcut = [string, string | string[]] | [string, string | string[], RuleMeta];
326
- declare type StaticShortcutMap = Record<string, string | string[]>;
329
+ declare type DynamicShortcutMatcher<Theme extends {} = {}> = ((match: RegExpMatchArray, context: Readonly<RuleContext<Theme>>) => (string | ShortcutValue[] | undefined));
330
+ declare type StaticShortcut = [string, string | ShortcutValue[]] | [string, string | ShortcutValue[], RuleMeta];
331
+ declare type StaticShortcutMap = Record<string, string | ShortcutValue[]>;
327
332
  declare type DynamicShortcut<Theme extends {} = {}> = [RegExp, DynamicShortcutMatcher<Theme>] | [RegExp, DynamicShortcutMatcher<Theme>, RuleMeta];
328
333
  declare type UserShortcuts<Theme extends {} = {}> = StaticShortcutMap | (StaticShortcut | DynamicShortcut<Theme> | StaticShortcutMap)[];
329
334
  declare type Shortcut<Theme extends {} = {}> = StaticShortcut | DynamicShortcut<Theme>;
335
+ declare type ShortcutValue = string | CSSValue;
330
336
  declare type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null;
331
337
  interface Preflight<Theme extends {} = {}> {
332
338
  getCSS: (context: PreflightContext<Theme>) => Promise<string | undefined> | string | undefined;
@@ -564,6 +570,14 @@ interface Preset<Theme extends {} = {}> extends ConfigBase<Theme> {
564
570
  * Preset options for other tools like IDE to consume
565
571
  */
566
572
  options?: PresetOptions;
573
+ /**
574
+ * Apply prefix to all utilities and shortcuts
575
+ */
576
+ prefix?: string;
577
+ /**
578
+ * Apply layer to all utilities and shortcuts
579
+ */
580
+ layer?: string;
567
581
  }
568
582
  interface GeneratorOptions {
569
583
  /**
@@ -772,4 +786,4 @@ declare const extractorSplit: Extractor;
772
786
 
773
787
  declare const extractorSvelte: Extractor;
774
788
 
775
- export { ArgumentType, Arrayable, AutoCompleteExtractor, AutoCompleteExtractorContext, AutoCompleteExtractorResult, AutoCompleteFunction, AutoCompleteTemplate, Awaitable, BetterMap, BlocklistRule, CONTROL_SHORTCUT_NO_MERGE, CSSColorValue, CSSEntries, CSSObject, CSSValue, CSSValues, ConfigBase, DeepPartial, DetailString, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, ExtractStringOptions, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, PreflightContext, PreparedRule, Preprocessor, Preset, PresetOptions, RGBAColorValue, Range, RawUtil, Replacement, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, SourceCodeTransformer, SourceMap, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, SuggestResult, ThemeExtender, TransformResult, TwoKeyMap, UnoGenerator, UnocssPluginContext, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantHandlerContext, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, cssIdRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractQuoted, extractorSplit, extractorSvelte, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, matchingPair, mergeDeep, mergeSet, movePseudoElementsEnd, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, regexScopePlaceholder, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
789
+ export { ArgumentType, Arrayable, AutoCompleteExtractor, AutoCompleteExtractorContext, AutoCompleteExtractorResult, AutoCompleteFunction, AutoCompleteTemplate, Awaitable, BetterMap, BlocklistRule, CONTROL_SHORTCUT_NO_MERGE, CSSColorValue, CSSEntries, CSSObject, CSSValue, CSSValues, ConfigBase, DeepPartial, DetailString, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, ExtractStringOptions, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, PreflightContext, PreparedRule, Preprocessor, Preset, PresetOptions, RGBAColorValue, Range, RawUtil, Replacement, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, ShortcutValue, SourceCodeTransformer, SourceMap, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, SuggestResult, ThemeExtender, TransformResult, TwoKeyMap, UnoGenerator, UnocssPluginContext, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantHandlerContext, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, cssIdRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractQuoted, extractorSplit, extractorSvelte, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isString, isValidSelector, matchingPair, mergeDeep, mergeSet, movePseudoElementsEnd, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, regexScopePlaceholder, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
package/dist/index.mjs CHANGED
@@ -35,8 +35,22 @@ function escapeSelector(str) {
35
35
  }
36
36
  const e = escapeSelector;
37
37
 
38
+ function toArray(value = []) {
39
+ return Array.isArray(value) ? value : [value];
40
+ }
41
+ function uniq(value) {
42
+ return Array.from(new Set(value));
43
+ }
44
+ function mergeSet(target, append) {
45
+ append.forEach((i) => target.add(i));
46
+ return target;
47
+ }
48
+ function isString(s) {
49
+ return typeof s === "string";
50
+ }
51
+
38
52
  function normalizeCSSEntries(obj) {
39
- if (typeof obj === "string")
53
+ if (isString(obj))
40
54
  return obj;
41
55
  return (!Array.isArray(obj) ? Object.entries(obj) : obj).filter((i) => i[1] != null);
42
56
  }
@@ -114,21 +128,10 @@ function clone(val) {
114
128
  return val;
115
129
  }
116
130
  function isStaticRule(rule) {
117
- return typeof rule[0] === "string";
131
+ return isString(rule[0]);
118
132
  }
119
133
  function isStaticShortcut(sc) {
120
- return typeof sc[0] === "string";
121
- }
122
-
123
- function toArray(value = []) {
124
- return Array.isArray(value) ? value : [value];
125
- }
126
- function uniq(value) {
127
- return Array.from(new Set(value));
128
- }
129
- function mergeSet(target, append) {
130
- append.forEach((i) => target.add(i));
131
- return target;
134
+ return isString(sc[0]);
132
135
  }
133
136
 
134
137
  const attributifyRE = /^\[(.+?)~?="(.*)"\]$/;
@@ -382,6 +385,15 @@ function createNanoEvents() {
382
385
  };
383
386
  }
384
387
 
388
+ const LAYER_DEFAULT = "default";
389
+ const LAYER_PREFLIGHTS = "preflights";
390
+ const LAYER_SHORTCUTS = "shortcuts";
391
+ const DEAFULT_LAYERS = {
392
+ [LAYER_PREFLIGHTS]: -100,
393
+ [LAYER_SHORTCUTS]: -10,
394
+ [LAYER_DEFAULT]: 0
395
+ };
396
+
385
397
  function resolveShortcuts(shortcuts) {
386
398
  return toArray(shortcuts).flatMap((s) => {
387
399
  if (Array.isArray(s))
@@ -389,20 +401,33 @@ function resolveShortcuts(shortcuts) {
389
401
  return Object.entries(s);
390
402
  });
391
403
  }
392
- const defaultLayers = {
393
- preflights: -100,
394
- shortcuts: -10,
395
- default: 0
396
- };
404
+ function resolvePreset(preset) {
405
+ const shortcuts = preset.shortcuts ? resolveShortcuts(preset.shortcuts) : void 0;
406
+ preset.shortcuts = shortcuts;
407
+ if (preset.prefix || preset.layer) {
408
+ const apply = (i) => {
409
+ if (!i[2])
410
+ i[2] = {};
411
+ const meta = i[2];
412
+ if (meta.prefix == null && preset.prefix)
413
+ meta.prefix = preset.prefix;
414
+ if (meta.layer == null && preset.layer)
415
+ meta.prefix = preset.layer;
416
+ };
417
+ shortcuts?.forEach(apply);
418
+ preset.rules?.forEach(apply);
419
+ }
420
+ return preset;
421
+ }
397
422
  function resolveConfig(userConfig = {}, defaults = {}) {
398
423
  const config = Object.assign({}, defaults, userConfig);
399
- const rawPresets = (config.presets || []).flatMap(toArray);
424
+ const rawPresets = (config.presets || []).flatMap(toArray).map(resolvePreset);
400
425
  const sortedPresets = [
401
426
  ...rawPresets.filter((p) => p.enforce === "pre"),
402
427
  ...rawPresets.filter((p) => !p.enforce),
403
428
  ...rawPresets.filter((p) => p.enforce === "post")
404
429
  ];
405
- const layers = Object.assign(defaultLayers, ...rawPresets.map((i) => i.layers), userConfig.layers);
430
+ const layers = Object.assign(DEAFULT_LAYERS, ...rawPresets.map((i) => i.layers), userConfig.layers);
406
431
  function mergePresets(key) {
407
432
  return uniq([
408
433
  ...sortedPresets.flatMap((p) => toArray(p[key] || [])),
@@ -418,7 +443,8 @@ function resolveConfig(userConfig = {}, defaults = {}) {
418
443
  const rulesSize = rules.length;
419
444
  rules.forEach((rule, i) => {
420
445
  if (isStaticRule(rule)) {
421
- rulesStaticMap[rule[0]] = [i, rule[1], rule[2], rule];
446
+ const prefix = rule[2]?.prefix || "";
447
+ rulesStaticMap[prefix + rule[0]] = [i, rule[1], rule[2], rule];
422
448
  delete rules[i];
423
449
  }
424
450
  });
@@ -456,7 +482,7 @@ function resolveConfig(userConfig = {}, defaults = {}) {
456
482
  };
457
483
  }
458
484
 
459
- const version = "0.42.1";
485
+ const version = "0.43.2";
460
486
 
461
487
  class UnoGenerator {
462
488
  constructor(userConfig = {}, defaults = {}) {
@@ -547,18 +573,19 @@ class UnoGenerator {
547
573
  }
548
574
  this._cache.set(cacheKey, null);
549
575
  }
550
- async generate(input = "", {
551
- id,
552
- scope,
553
- preflights = true,
554
- safelist = true,
555
- minify = false
556
- } = {}) {
557
- const tokens = typeof input === "string" ? await this.applyExtractors(input, id) : input;
576
+ async generate(input, options = {}) {
577
+ const {
578
+ id,
579
+ scope,
580
+ preflights = true,
581
+ safelist = true,
582
+ minify = false
583
+ } = options;
584
+ const tokens = isString(input) ? await this.applyExtractors(input, id) : Array.isArray(input) ? new Set(input) : input;
558
585
  if (safelist)
559
586
  this.config.safelist.forEach((s) => tokens.add(s));
560
587
  const nl = minify ? "" : "\n";
561
- const layerSet = /* @__PURE__ */ new Set(["default"]);
588
+ const layerSet = /* @__PURE__ */ new Set([LAYER_DEFAULT]);
562
589
  const matched = /* @__PURE__ */ new Set();
563
590
  const sheet = /* @__PURE__ */ new Map();
564
591
  let preflightsMap = {};
@@ -587,12 +614,12 @@ class UnoGenerator {
587
614
  theme: this.config.theme
588
615
  };
589
616
  const preflightLayerSet = /* @__PURE__ */ new Set([]);
590
- this.config.preflights.forEach(({ layer = "preflights" }) => {
617
+ this.config.preflights.forEach(({ layer = LAYER_PREFLIGHTS }) => {
591
618
  layerSet.add(layer);
592
619
  preflightLayerSet.add(layer);
593
620
  });
594
621
  preflightsMap = Object.fromEntries(await Promise.all(Array.from(preflightLayerSet).map(async (layer) => {
595
- const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "preflights") === layer).map(async (i) => await i.getCSS(preflightContext)));
622
+ const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || LAYER_PREFLIGHTS) === layer).map(async (i) => await i.getCSS(preflightContext)));
596
623
  const css = preflights2.filter(Boolean).join(nl);
597
624
  return [layer, css];
598
625
  })));
@@ -608,7 +635,7 @@ class UnoGenerator {
608
635
  return layerCache[layer];
609
636
  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]) => {
610
637
  const size = items.length;
611
- const sorted = items.filter((i) => (i[4]?.layer || "default") === layer).sort((a, b) => a[0] - b[0] || (a[4]?.sort || 0) - (b[4]?.sort || 0) || a[1]?.localeCompare(b[1] || "") || a[2]?.localeCompare(b[2] || "") || 0).map(([, selector, body, , meta]) => {
638
+ const sorted = items.filter((i) => (i[4]?.layer || LAYER_DEFAULT) === layer).sort((a, b) => a[0] - b[0] || (a[4]?.sort || 0) - (b[4]?.sort || 0) || a[1]?.localeCompare(b[1] || "") || a[2]?.localeCompare(b[2] || "") || 0).map(([, selector, body, , meta]) => {
612
639
  const scopedSelector = selector ? applyScope(selector, scope) : selector;
613
640
  return [
614
641
  [[scopedSelector ?? "", meta?.sort ?? 0]],
@@ -629,7 +656,7 @@ class UnoGenerator {
629
656
  }
630
657
  }
631
658
  }
632
- const selectors = selectorSortPair ? [...new Set(selectorSortPair.sort((a, b) => a[1] - b[1] || a[0]?.localeCompare(b[0] || "") || 0).map((pair) => pair[0]).filter(Boolean))] : [];
659
+ const selectors = selectorSortPair ? uniq(selectorSortPair.sort((a, b) => a[1] - b[1] || a[0]?.localeCompare(b[0] || "") || 0).map((pair) => pair[0]).filter(Boolean)) : [];
633
660
  return selectors.length ? `${selectors.join(`,${nl}`)}{${body}}` : body;
634
661
  }).filter(Boolean).reverse().join(nl);
635
662
  if (!parent)
@@ -640,7 +667,8 @@ class UnoGenerator {
640
667
  if (preflights) {
641
668
  css = [preflightsMap[layer], css].filter(Boolean).join(nl);
642
669
  }
643
- return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
670
+ const layerMark = minify ? "" : `/* layer: ${layer} */${nl}`;
671
+ return layerCache[layer] = css ? layerMark + css : "";
644
672
  };
645
673
  const getLayers = (includes = layers, excludes) => {
646
674
  return includes.filter((i) => !excludes?.includes(i)).map((i) => getLayer(i) || "").filter(Boolean).join(nl);
@@ -650,9 +678,9 @@ class UnoGenerator {
650
678
  return getLayers();
651
679
  },
652
680
  layers,
681
+ matched,
653
682
  getLayers,
654
- getLayer,
655
- matched
683
+ getLayer
656
684
  };
657
685
  }
658
686
  matchVariants(raw, current) {
@@ -673,7 +701,7 @@ class UnoGenerator {
673
701
  let handler = v.match(processed, context);
674
702
  if (!handler)
675
703
  continue;
676
- if (typeof handler === "string")
704
+ if (isString(handler))
677
705
  handler = { matcher: handler };
678
706
  processed = handler.matcher;
679
707
  handlers.unshift(handler);
@@ -728,7 +756,7 @@ class UnoGenerator {
728
756
  }
729
757
  constructCustomCSS(context, body, overrideSelector) {
730
758
  const normalizedBody = normalizeCSSEntries(body);
731
- if (typeof normalizedBody === "string")
759
+ if (isString(normalizedBody))
732
760
  return normalizedBody;
733
761
  const { selector, entries, parent } = this.applyVariants([0, overrideSelector || context.rawSelector, normalizedBody, void 0, context.variantHandlers]);
734
762
  const cssBody = `${selector}{${entriesToCss(entries)}}`;
@@ -737,7 +765,7 @@ class UnoGenerator {
737
765
  return cssBody;
738
766
  }
739
767
  async parseUtil(input, context, internal = false) {
740
- const [raw, processed, variantHandlers] = typeof input === "string" ? this.matchVariants(input) : input;
768
+ const [raw, processed, variantHandlers] = isString(input) ? this.matchVariants(input) : input;
741
769
  const recordRule = this.config.details ? (r) => {
742
770
  context.rules = context.rules ?? [];
743
771
  context.rules.push(r);
@@ -749,7 +777,7 @@ class UnoGenerator {
749
777
  const index = staticMatch[0];
750
778
  const entry = normalizeCSSEntries(staticMatch[1]);
751
779
  const meta = staticMatch[2];
752
- if (typeof entry === "string")
780
+ if (isString(entry))
753
781
  return [[index, entry, meta]];
754
782
  else
755
783
  return [[index, raw, entry, meta, variantHandlers]];
@@ -764,7 +792,10 @@ class UnoGenerator {
764
792
  if (rule[2]?.internal && !internal)
765
793
  continue;
766
794
  const [matcher, handler, meta] = rule;
767
- const match = processed.match(matcher);
795
+ if (meta?.prefix && !processed.startsWith(meta.prefix))
796
+ continue;
797
+ const unprefixed = meta?.prefix ? processed.slice(meta.prefix.length) : processed;
798
+ const match = unprefixed.match(matcher);
768
799
  if (!match)
769
800
  continue;
770
801
  const result = await handler(match, context);
@@ -774,7 +805,7 @@ class UnoGenerator {
774
805
  const entries = normalizeCSSValues(result).filter((i2) => i2.length);
775
806
  if (entries.length) {
776
807
  return entries.map((e2) => {
777
- if (typeof e2 === "string")
808
+ if (isString(e2))
778
809
  return [i, e2, meta];
779
810
  else
780
811
  return [i, raw, e2, meta, variantHandlers];
@@ -799,7 +830,7 @@ class UnoGenerator {
799
830
  };
800
831
  return [parsed[0], selector, body, parent, ruleMeta, this.config.details ? context : void 0];
801
832
  }
802
- expandShortcut(processed, context, depth = 3) {
833
+ expandShortcut(input, context, depth = 5) {
803
834
  if (depth === 0)
804
835
  return;
805
836
  const recordShortcut = this.config.details ? (s) => {
@@ -809,15 +840,16 @@ class UnoGenerator {
809
840
  let meta;
810
841
  let result;
811
842
  for (const s of this.config.shortcuts) {
843
+ const unprefixed = s[2]?.prefix ? input.slice(s[2].prefix.length) : input;
812
844
  if (isStaticShortcut(s)) {
813
- if (s[0] === processed) {
845
+ if (s[0] === unprefixed) {
814
846
  meta = meta || s[2];
815
847
  result = s[1];
816
848
  recordShortcut(s);
817
849
  break;
818
850
  }
819
851
  } else {
820
- const match = processed.match(s[0]);
852
+ const match = unprefixed.match(s[0]);
821
853
  if (match)
822
854
  result = s[1](match, context);
823
855
  if (result) {
@@ -827,30 +859,27 @@ class UnoGenerator {
827
859
  }
828
860
  }
829
861
  }
830
- if (typeof result === "string")
862
+ if (isString(result))
831
863
  result = expandVariantGroup(result).split(/\s+/g);
832
864
  if (!result) {
833
- const [raw, rematchedProcess] = typeof processed === "string" ? this.matchVariants(processed) : processed;
834
- if (raw !== rematchedProcess) {
835
- const expanded = this.expandShortcut(rematchedProcess, context, depth - 1);
836
- if (expanded) {
837
- expanded[0].forEach((item, index) => {
838
- expanded[0][index] = raw.replace(rematchedProcess, item);
839
- });
840
- return expanded;
841
- }
865
+ const [raw, inputWithoutVariant] = isString(input) ? this.matchVariants(input) : input;
866
+ if (raw !== inputWithoutVariant) {
867
+ const expanded = this.expandShortcut(inputWithoutVariant, context, depth - 1);
868
+ if (expanded)
869
+ result = expanded[0].map((item) => isString(item) ? raw.replace(inputWithoutVariant, item) : item);
842
870
  }
843
- return;
844
871
  }
872
+ if (!result)
873
+ return;
845
874
  return [
846
- result.flatMap((r) => this.expandShortcut(r, context, depth - 1)?.[0] || [r]).filter((r) => r !== ""),
875
+ result.flatMap((r) => (isString(r) ? this.expandShortcut(r, context, depth - 1)?.[0] : void 0) || [r]).filter(Boolean),
847
876
  meta
848
877
  ];
849
878
  }
850
879
  async stringifyShortcuts(parent, context, expanded, meta = { layer: this.config.shortcutsLayer }) {
851
880
  const selectorMap = new TwoKeyMap();
852
881
  const parsed = (await Promise.all(uniq(expanded).map(async (i) => {
853
- const result = await this.parseUtil(i, context, true);
882
+ const result = isString(i) ? await this.parseUtil(i, context, true) : [[Infinity, "{inline}", normalizeCSSEntries(i), void 0, []]];
854
883
  if (!result)
855
884
  warnOnce(`unmatched utility "${i}" in shortcut "${parent[1]}"`);
856
885
  return result || [];
@@ -888,7 +917,7 @@ class UnoGenerator {
888
917
  }).flat(2).filter(Boolean));
889
918
  }
890
919
  isBlocked(raw) {
891
- return !raw || this.config.blocklist.some((e2) => typeof e2 === "string" ? e2 === raw : e2.test(raw));
920
+ return !raw || this.config.blocklist.some((e2) => isString(e2) ? e2 === raw : e2.test(raw));
892
921
  }
893
922
  }
894
923
  function createGenerator(config, defaults) {
@@ -920,4 +949,4 @@ function defaultVariantHandler(input, next) {
920
949
  return next(input);
921
950
  }
922
951
 
923
- export { BetterMap, CONTROL_SHORTCUT_NO_MERGE, TwoKeyMap, UnoGenerator, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, cssIdRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractQuoted, extractorSplit, extractorSvelte, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isValidSelector, matchingPair, mergeDeep, mergeSet, movePseudoElementsEnd, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, regexScopePlaceholder, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
952
+ export { BetterMap, CONTROL_SHORTCUT_NO_MERGE, TwoKeyMap, UnoGenerator, attributifyRE, clearIdenticalEntries, clone, createGenerator, createValueHandler, cssIdRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractQuoted, extractorSplit, extractorSvelte, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isString, isValidSelector, matchingPair, mergeDeep, mergeSet, movePseudoElementsEnd, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, regexClassGroup, regexScopePlaceholder, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unocss/core",
3
- "version": "0.42.1",
3
+ "version": "0.43.2",
4
4
  "description": "The instant on-demand Atomic CSS engine.",
5
5
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",