@unocss/core 0.41.2 → 0.43.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
@@ -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.41.2";
489
+ const version = "0.43.0";
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 = {};
@@ -590,15 +617,13 @@ class UnoGenerator {
590
617
  generator: this,
591
618
  theme: this.config.theme
592
619
  };
593
- const preflightLayerSet = /* @__PURE__ */ new Set(["default"]);
594
- this.config.preflights.forEach(({ layer }) => {
595
- if (layer) {
596
- layerSet.add(layer);
597
- preflightLayerSet.add(layer);
598
- }
620
+ const preflightLayerSet = /* @__PURE__ */ new Set([]);
621
+ this.config.preflights.forEach(({ layer = LAYER_PREFLIGHTS }) => {
622
+ layerSet.add(layer);
623
+ preflightLayerSet.add(layer);
599
624
  });
600
625
  preflightsMap = Object.fromEntries(await Promise.all(Array.from(preflightLayerSet).map(async (layer) => {
601
- const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "default") === 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)));
602
627
  const css = preflights2.filter(Boolean).join(nl);
603
628
  return [layer, css];
604
629
  })));
@@ -614,7 +639,7 @@ class UnoGenerator {
614
639
  return layerCache[layer];
615
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]) => {
616
641
  const size = items.length;
617
- 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]) => {
618
643
  const scopedSelector = selector ? applyScope(selector, scope) : selector;
619
644
  return [
620
645
  [[scopedSelector ?? "", meta?.sort ?? 0]],
@@ -635,7 +660,7 @@ class UnoGenerator {
635
660
  }
636
661
  }
637
662
  }
638
- 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)) : [];
639
664
  return selectors.length ? `${selectors.join(`,${nl}`)}{${body}}` : body;
640
665
  }).filter(Boolean).reverse().join(nl);
641
666
  if (!parent)
@@ -646,7 +671,8 @@ class UnoGenerator {
646
671
  if (preflights) {
647
672
  css = [preflightsMap[layer], css].filter(Boolean).join(nl);
648
673
  }
649
- return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
674
+ const layerMark = minify ? "" : `/* layer: ${layer} */${nl}`;
675
+ return layerCache[layer] = css ? layerMark + css : "";
650
676
  };
651
677
  const getLayers = (includes = layers, excludes) => {
652
678
  return includes.filter((i) => !excludes?.includes(i)).map((i) => getLayer(i) || "").filter(Boolean).join(nl);
@@ -656,9 +682,9 @@ class UnoGenerator {
656
682
  return getLayers();
657
683
  },
658
684
  layers,
685
+ matched,
659
686
  getLayers,
660
- getLayer,
661
- matched
687
+ getLayer
662
688
  };
663
689
  }
664
690
  matchVariants(raw, current) {
@@ -679,7 +705,7 @@ class UnoGenerator {
679
705
  let handler = v.match(processed, context);
680
706
  if (!handler)
681
707
  continue;
682
- if (typeof handler === "string")
708
+ if (isString(handler))
683
709
  handler = { matcher: handler };
684
710
  processed = handler.matcher;
685
711
  handlers.unshift(handler);
@@ -734,7 +760,7 @@ class UnoGenerator {
734
760
  }
735
761
  constructCustomCSS(context, body, overrideSelector) {
736
762
  const normalizedBody = normalizeCSSEntries(body);
737
- if (typeof normalizedBody === "string")
763
+ if (isString(normalizedBody))
738
764
  return normalizedBody;
739
765
  const { selector, entries, parent } = this.applyVariants([0, overrideSelector || context.rawSelector, normalizedBody, void 0, context.variantHandlers]);
740
766
  const cssBody = `${selector}{${entriesToCss(entries)}}`;
@@ -743,7 +769,7 @@ class UnoGenerator {
743
769
  return cssBody;
744
770
  }
745
771
  async parseUtil(input, context, internal = false) {
746
- const [raw, processed, variantHandlers] = typeof input === "string" ? this.matchVariants(input) : input;
772
+ const [raw, processed, variantHandlers] = isString(input) ? this.matchVariants(input) : input;
747
773
  const recordRule = this.config.details ? (r) => {
748
774
  context.rules = context.rules ?? [];
749
775
  context.rules.push(r);
@@ -755,7 +781,7 @@ class UnoGenerator {
755
781
  const index = staticMatch[0];
756
782
  const entry = normalizeCSSEntries(staticMatch[1]);
757
783
  const meta = staticMatch[2];
758
- if (typeof entry === "string")
784
+ if (isString(entry))
759
785
  return [[index, entry, meta]];
760
786
  else
761
787
  return [[index, raw, entry, meta, variantHandlers]];
@@ -770,7 +796,10 @@ class UnoGenerator {
770
796
  if (rule[2]?.internal && !internal)
771
797
  continue;
772
798
  const [matcher, handler, meta] = rule;
773
- 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);
774
803
  if (!match)
775
804
  continue;
776
805
  const result = await handler(match, context);
@@ -780,7 +809,7 @@ class UnoGenerator {
780
809
  const entries = normalizeCSSValues(result).filter((i2) => i2.length);
781
810
  if (entries.length) {
782
811
  return entries.map((e2) => {
783
- if (typeof e2 === "string")
812
+ if (isString(e2))
784
813
  return [i, e2, meta];
785
814
  else
786
815
  return [i, raw, e2, meta, variantHandlers];
@@ -805,7 +834,7 @@ class UnoGenerator {
805
834
  };
806
835
  return [parsed[0], selector, body, parent, ruleMeta, this.config.details ? context : void 0];
807
836
  }
808
- expandShortcut(processed, context, depth = 3) {
837
+ expandShortcut(input, context, depth = 5) {
809
838
  if (depth === 0)
810
839
  return;
811
840
  const recordShortcut = this.config.details ? (s) => {
@@ -815,15 +844,16 @@ class UnoGenerator {
815
844
  let meta;
816
845
  let result;
817
846
  for (const s of this.config.shortcuts) {
847
+ const unprefixed = s[2]?.prefix ? input.slice(s[2].prefix.length) : input;
818
848
  if (isStaticShortcut(s)) {
819
- if (s[0] === processed) {
849
+ if (s[0] === unprefixed) {
820
850
  meta = meta || s[2];
821
851
  result = s[1];
822
852
  recordShortcut(s);
823
853
  break;
824
854
  }
825
855
  } else {
826
- const match = processed.match(s[0]);
856
+ const match = unprefixed.match(s[0]);
827
857
  if (match)
828
858
  result = s[1](match, context);
829
859
  if (result) {
@@ -833,19 +863,27 @@ class UnoGenerator {
833
863
  }
834
864
  }
835
865
  }
836
- if (typeof result === "string")
866
+ if (isString(result))
837
867
  result = expandVariantGroup(result).split(/\s+/g);
868
+ if (!result) {
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);
874
+ }
875
+ }
838
876
  if (!result)
839
877
  return;
840
878
  return [
841
- 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),
842
880
  meta
843
881
  ];
844
882
  }
845
883
  async stringifyShortcuts(parent, context, expanded, meta = { layer: this.config.shortcutsLayer }) {
846
884
  const selectorMap = new TwoKeyMap();
847
885
  const parsed = (await Promise.all(uniq(expanded).map(async (i) => {
848
- 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, []]];
849
887
  if (!result)
850
888
  warnOnce(`unmatched utility "${i}" in shortcut "${parent[1]}"`);
851
889
  return result || [];
@@ -883,7 +921,7 @@ class UnoGenerator {
883
921
  }).flat(2).filter(Boolean));
884
922
  }
885
923
  isBlocked(raw) {
886
- 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));
887
925
  }
888
926
  }
889
927
  function createGenerator(config, defaults) {
@@ -939,6 +977,7 @@ exports.isObject = isObject;
939
977
  exports.isRawUtil = isRawUtil;
940
978
  exports.isStaticRule = isStaticRule;
941
979
  exports.isStaticShortcut = isStaticShortcut;
980
+ exports.isString = isString;
942
981
  exports.isValidSelector = isValidSelector;
943
982
  exports.matchingPair = matchingPair;
944
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.41.2";
485
+ const version = "0.43.0";
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 = {};
@@ -586,15 +613,13 @@ class UnoGenerator {
586
613
  generator: this,
587
614
  theme: this.config.theme
588
615
  };
589
- const preflightLayerSet = /* @__PURE__ */ new Set(["default"]);
590
- this.config.preflights.forEach(({ layer }) => {
591
- if (layer) {
592
- layerSet.add(layer);
593
- preflightLayerSet.add(layer);
594
- }
616
+ const preflightLayerSet = /* @__PURE__ */ new Set([]);
617
+ this.config.preflights.forEach(({ layer = LAYER_PREFLIGHTS }) => {
618
+ layerSet.add(layer);
619
+ preflightLayerSet.add(layer);
595
620
  });
596
621
  preflightsMap = Object.fromEntries(await Promise.all(Array.from(preflightLayerSet).map(async (layer) => {
597
- const preflights2 = await Promise.all(this.config.preflights.filter((i) => (i.layer || "default") === 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)));
598
623
  const css = preflights2.filter(Boolean).join(nl);
599
624
  return [layer, css];
600
625
  })));
@@ -610,7 +635,7 @@ class UnoGenerator {
610
635
  return layerCache[layer];
611
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]) => {
612
637
  const size = items.length;
613
- 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]) => {
614
639
  const scopedSelector = selector ? applyScope(selector, scope) : selector;
615
640
  return [
616
641
  [[scopedSelector ?? "", meta?.sort ?? 0]],
@@ -631,7 +656,7 @@ class UnoGenerator {
631
656
  }
632
657
  }
633
658
  }
634
- 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)) : [];
635
660
  return selectors.length ? `${selectors.join(`,${nl}`)}{${body}}` : body;
636
661
  }).filter(Boolean).reverse().join(nl);
637
662
  if (!parent)
@@ -642,7 +667,8 @@ class UnoGenerator {
642
667
  if (preflights) {
643
668
  css = [preflightsMap[layer], css].filter(Boolean).join(nl);
644
669
  }
645
- return layerCache[layer] = !minify && css ? `/* layer: ${layer} */${nl}${css}` : css;
670
+ const layerMark = minify ? "" : `/* layer: ${layer} */${nl}`;
671
+ return layerCache[layer] = css ? layerMark + css : "";
646
672
  };
647
673
  const getLayers = (includes = layers, excludes) => {
648
674
  return includes.filter((i) => !excludes?.includes(i)).map((i) => getLayer(i) || "").filter(Boolean).join(nl);
@@ -652,9 +678,9 @@ class UnoGenerator {
652
678
  return getLayers();
653
679
  },
654
680
  layers,
681
+ matched,
655
682
  getLayers,
656
- getLayer,
657
- matched
683
+ getLayer
658
684
  };
659
685
  }
660
686
  matchVariants(raw, current) {
@@ -675,7 +701,7 @@ class UnoGenerator {
675
701
  let handler = v.match(processed, context);
676
702
  if (!handler)
677
703
  continue;
678
- if (typeof handler === "string")
704
+ if (isString(handler))
679
705
  handler = { matcher: handler };
680
706
  processed = handler.matcher;
681
707
  handlers.unshift(handler);
@@ -730,7 +756,7 @@ class UnoGenerator {
730
756
  }
731
757
  constructCustomCSS(context, body, overrideSelector) {
732
758
  const normalizedBody = normalizeCSSEntries(body);
733
- if (typeof normalizedBody === "string")
759
+ if (isString(normalizedBody))
734
760
  return normalizedBody;
735
761
  const { selector, entries, parent } = this.applyVariants([0, overrideSelector || context.rawSelector, normalizedBody, void 0, context.variantHandlers]);
736
762
  const cssBody = `${selector}{${entriesToCss(entries)}}`;
@@ -739,7 +765,7 @@ class UnoGenerator {
739
765
  return cssBody;
740
766
  }
741
767
  async parseUtil(input, context, internal = false) {
742
- const [raw, processed, variantHandlers] = typeof input === "string" ? this.matchVariants(input) : input;
768
+ const [raw, processed, variantHandlers] = isString(input) ? this.matchVariants(input) : input;
743
769
  const recordRule = this.config.details ? (r) => {
744
770
  context.rules = context.rules ?? [];
745
771
  context.rules.push(r);
@@ -751,7 +777,7 @@ class UnoGenerator {
751
777
  const index = staticMatch[0];
752
778
  const entry = normalizeCSSEntries(staticMatch[1]);
753
779
  const meta = staticMatch[2];
754
- if (typeof entry === "string")
780
+ if (isString(entry))
755
781
  return [[index, entry, meta]];
756
782
  else
757
783
  return [[index, raw, entry, meta, variantHandlers]];
@@ -766,7 +792,10 @@ class UnoGenerator {
766
792
  if (rule[2]?.internal && !internal)
767
793
  continue;
768
794
  const [matcher, handler, meta] = rule;
769
- 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);
770
799
  if (!match)
771
800
  continue;
772
801
  const result = await handler(match, context);
@@ -776,7 +805,7 @@ class UnoGenerator {
776
805
  const entries = normalizeCSSValues(result).filter((i2) => i2.length);
777
806
  if (entries.length) {
778
807
  return entries.map((e2) => {
779
- if (typeof e2 === "string")
808
+ if (isString(e2))
780
809
  return [i, e2, meta];
781
810
  else
782
811
  return [i, raw, e2, meta, variantHandlers];
@@ -801,7 +830,7 @@ class UnoGenerator {
801
830
  };
802
831
  return [parsed[0], selector, body, parent, ruleMeta, this.config.details ? context : void 0];
803
832
  }
804
- expandShortcut(processed, context, depth = 3) {
833
+ expandShortcut(input, context, depth = 5) {
805
834
  if (depth === 0)
806
835
  return;
807
836
  const recordShortcut = this.config.details ? (s) => {
@@ -811,15 +840,16 @@ class UnoGenerator {
811
840
  let meta;
812
841
  let result;
813
842
  for (const s of this.config.shortcuts) {
843
+ const unprefixed = s[2]?.prefix ? input.slice(s[2].prefix.length) : input;
814
844
  if (isStaticShortcut(s)) {
815
- if (s[0] === processed) {
845
+ if (s[0] === unprefixed) {
816
846
  meta = meta || s[2];
817
847
  result = s[1];
818
848
  recordShortcut(s);
819
849
  break;
820
850
  }
821
851
  } else {
822
- const match = processed.match(s[0]);
852
+ const match = unprefixed.match(s[0]);
823
853
  if (match)
824
854
  result = s[1](match, context);
825
855
  if (result) {
@@ -829,19 +859,27 @@ class UnoGenerator {
829
859
  }
830
860
  }
831
861
  }
832
- if (typeof result === "string")
862
+ if (isString(result))
833
863
  result = expandVariantGroup(result).split(/\s+/g);
864
+ if (!result) {
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);
870
+ }
871
+ }
834
872
  if (!result)
835
873
  return;
836
874
  return [
837
- 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),
838
876
  meta
839
877
  ];
840
878
  }
841
879
  async stringifyShortcuts(parent, context, expanded, meta = { layer: this.config.shortcutsLayer }) {
842
880
  const selectorMap = new TwoKeyMap();
843
881
  const parsed = (await Promise.all(uniq(expanded).map(async (i) => {
844
- 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, []]];
845
883
  if (!result)
846
884
  warnOnce(`unmatched utility "${i}" in shortcut "${parent[1]}"`);
847
885
  return result || [];
@@ -879,7 +917,7 @@ class UnoGenerator {
879
917
  }).flat(2).filter(Boolean));
880
918
  }
881
919
  isBlocked(raw) {
882
- 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));
883
921
  }
884
922
  }
885
923
  function createGenerator(config, defaults) {
@@ -911,4 +949,4 @@ function defaultVariantHandler(input, next) {
911
949
  return next(input);
912
950
  }
913
951
 
914
- 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.41.2",
3
+ "version": "0.43.0",
4
4
  "description": "The instant on-demand Atomic CSS engine.",
5
5
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",