@unocss/core 0.53.6 → 0.54.1

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
@@ -233,27 +233,71 @@ function makeRegexClassGroup(separators = ["-", ":"]) {
233
233
  }
234
234
  function parseVariantGroup(str, separators = ["-", ":"], depth = 5) {
235
235
  const regexClassGroup = makeRegexClassGroup(separators);
236
- let hasChanged = false;
236
+ let hasChanged;
237
237
  let content = str.toString();
238
238
  const prefixes = /* @__PURE__ */ new Set();
239
+ const groupsByOffset = /* @__PURE__ */ new Map();
239
240
  do {
240
- const before = content;
241
+ hasChanged = false;
241
242
  content = content.replace(
242
243
  regexClassGroup,
243
- (from, pre, sep, body) => {
244
+ (from, pre, sep, body, groupOffset) => {
244
245
  if (!separators.includes(sep))
245
246
  return from;
247
+ hasChanged = true;
246
248
  prefixes.add(pre + sep);
247
- return body.split(/\s/g).filter(Boolean).map((i) => i === "~" ? pre : i.replace(/^(!?)(.*)/, `$1${pre}${sep}$2`)).join(" ");
249
+ const bodyOffset = groupOffset + pre.length + sep.length + 1;
250
+ const group = { length: from.length, items: [] };
251
+ groupsByOffset.set(groupOffset, group);
252
+ for (const itemMatch of [...body.matchAll(/\S+/g)]) {
253
+ const itemOffset = bodyOffset + itemMatch.index;
254
+ let innerItems = groupsByOffset.get(itemOffset)?.items;
255
+ if (innerItems) {
256
+ groupsByOffset.delete(itemOffset);
257
+ } else {
258
+ innerItems = [{
259
+ offset: itemOffset,
260
+ length: itemMatch[0].length,
261
+ className: itemMatch[0]
262
+ }];
263
+ }
264
+ for (const item of innerItems) {
265
+ item.className = item.className === "~" ? pre : item.className.replace(/^(!?)(.*)/, `$1${pre}${sep}$2`);
266
+ group.items.push(item);
267
+ }
268
+ }
269
+ return "$".repeat(from.length);
248
270
  }
249
271
  );
250
- hasChanged = content !== before;
251
272
  depth -= 1;
252
273
  } while (hasChanged && depth);
274
+ let expanded;
275
+ if (typeof str === "string") {
276
+ expanded = "";
277
+ let prevOffset = 0;
278
+ for (const [offset, group] of groupsByOffset) {
279
+ expanded += str.slice(prevOffset, offset);
280
+ expanded += group.items.map((item) => item.className).join(" ");
281
+ prevOffset = offset + group.length;
282
+ }
283
+ expanded += str.slice(prevOffset);
284
+ } else {
285
+ expanded = str;
286
+ for (const [offset, group] of groupsByOffset) {
287
+ expanded.overwrite(
288
+ offset,
289
+ offset + group.length,
290
+ group.items.map((item) => item.className).join(" ")
291
+ );
292
+ }
293
+ }
253
294
  return {
254
295
  prefixes: Array.from(prefixes),
255
- expanded: content,
256
- hasChanged
296
+ hasChanged,
297
+ groupsByOffset,
298
+ get expanded() {
299
+ return expanded.toString();
300
+ }
257
301
  };
258
302
  }
259
303
  function collapseVariantGroup(str, prefixes) {
@@ -282,14 +326,8 @@ function collapseVariantGroup(str, prefixes) {
282
326
  }).join(" ");
283
327
  }
284
328
  function expandVariantGroup(str, separators = ["-", ":"], depth = 5) {
285
- const {
286
- expanded
287
- } = parseVariantGroup(str.toString(), separators, depth);
288
- if (typeof str === "string") {
289
- return expanded;
290
- } else {
291
- return str.length() ? str.overwrite(0, str.original.length, expanded) : str;
292
- }
329
+ const res = parseVariantGroup(str, separators, depth);
330
+ return typeof str === "string" ? res.expanded : str;
293
331
  }
294
332
 
295
333
  const warned = /* @__PURE__ */ new Set();
@@ -359,7 +397,9 @@ function createNanoEvents() {
359
397
  const LAYER_DEFAULT = "default";
360
398
  const LAYER_PREFLIGHTS = "preflights";
361
399
  const LAYER_SHORTCUTS = "shortcuts";
400
+ const LAYER_IMPORTS = "imports";
362
401
  const DEFAULT_LAYERS = {
402
+ [LAYER_IMPORTS]: -200,
363
403
  [LAYER_PREFLIGHTS]: -100,
364
404
  [LAYER_SHORTCUTS]: -10,
365
405
  [LAYER_DEFAULT]: 0
@@ -448,7 +488,8 @@ function resolveConfig(userConfig = {}, defaults = {}) {
448
488
  theme = extendTheme(theme) || theme;
449
489
  const autocomplete = {
450
490
  templates: uniq(sources.flatMap((p) => toArray(p.autocomplete?.templates))),
451
- extractors: sources.flatMap((p) => toArray(p.autocomplete?.extractors)).sort((a, b) => (a.order || 0) - (b.order || 0))
491
+ extractors: sources.flatMap((p) => toArray(p.autocomplete?.extractors)).sort((a, b) => (a.order || 0) - (b.order || 0)),
492
+ shorthands: mergeAutocompleteShorthands(sources.map((p) => p.autocomplete?.shorthands || {}))
452
493
  };
453
494
  let separators = getMerged("separators");
454
495
  if (!separators.length)
@@ -506,8 +547,27 @@ function mergeConfigs(configs) {
506
547
  function mergeThemes(themes) {
507
548
  return themes.map((theme) => theme ? clone(theme) : {}).reduce((a, b) => mergeDeep(a, b), {});
508
549
  }
550
+ function mergeAutocompleteShorthands(shorthands) {
551
+ return shorthands.reduce(
552
+ (a, b) => {
553
+ const rs = {};
554
+ for (const key in b) {
555
+ const value = b[key];
556
+ if (Array.isArray(value))
557
+ rs[key] = `(${value.join("|")})`;
558
+ else
559
+ rs[key] = value;
560
+ }
561
+ return {
562
+ ...a,
563
+ ...rs
564
+ };
565
+ },
566
+ {}
567
+ );
568
+ }
509
569
 
510
- const version = "0.53.6";
570
+ const version = "0.54.1";
511
571
 
512
572
  class UnoGenerator {
513
573
  constructor(userConfig = {}, defaults = {}) {
@@ -729,8 +789,11 @@ class UnoGenerator {
729
789
  let handler = await v.match(processed, context);
730
790
  if (!handler)
731
791
  continue;
732
- if (isString(handler))
792
+ if (isString(handler)) {
793
+ if (handler === processed)
794
+ continue;
733
795
  handler = { matcher: handler };
796
+ }
734
797
  processed = handler.matcher;
735
798
  handlers.unshift(handler);
736
799
  variants.add(v);
package/dist/index.d.ts CHANGED
@@ -66,7 +66,7 @@ declare class UnoGenerator<Theme extends object = object> {
66
66
  setConfig(userConfig?: UserConfig<Theme>, defaults?: UserConfigDefaults<Theme>): void;
67
67
  applyExtractors(code: string, id?: string, extracted?: Set<string>): Promise<Set<string>>;
68
68
  makeContext(raw: string, applied: VariantMatchedResult<Theme>): RuleContext<Theme>;
69
- parseToken(raw: string, alias?: string): Promise<StringifiedUtil<Theme>[] | null | undefined>;
69
+ parseToken(raw: string, alias?: string): Promise<StringifiedUtil<Theme>[] | undefined | null>;
70
70
  generate(input: string | Set<string> | string[], options?: GenerateOptions): Promise<GenerateResult>;
71
71
  matchVariants(raw: string, current?: string): Promise<VariantMatchedResult<Theme>>;
72
72
  private applyVariants;
@@ -134,10 +134,15 @@ declare class BetterMap<K, V> extends Map<K, V> {
134
134
  declare function withLayer<T extends object>(layer: string, rules: Rule<T>[]): Rule<T>[];
135
135
 
136
136
  declare function makeRegexClassGroup(separators?: string[]): RegExp;
137
- declare function parseVariantGroup(str: string, separators?: string[], depth?: number): {
137
+ interface VariantGroup {
138
+ length: number;
139
+ items: HighlightAnnotation[];
140
+ }
141
+ declare function parseVariantGroup(str: string | MagicString, separators?: string[], depth?: number): {
138
142
  prefixes: string[];
139
- expanded: string;
140
143
  hasChanged: boolean;
144
+ groupsByOffset: Map<number, VariantGroup>;
145
+ readonly expanded: string;
141
146
  };
142
147
  declare function collapseVariantGroup(str: string, prefixes: string[]): string;
143
148
  declare function expandVariantGroup(str: string, separators?: string[], depth?: number): string;
@@ -546,6 +551,11 @@ interface ConfigBase<Theme extends object = object> {
546
551
  * transform class-name style suggestions to the correct format
547
552
  */
548
553
  extractors?: Arrayable<AutoCompleteExtractor>;
554
+ /**
555
+ * Custom shorthands to provide autocomplete suggestions.
556
+ * if values is an array, it will be joined with `|` and wrapped with `()`
557
+ */
558
+ shorthands?: Record<string, string | string[]>;
549
559
  };
550
560
  /**
551
561
  * Hook to modify the resolved config.
@@ -706,12 +716,10 @@ interface SourceMap {
706
716
  sourcesContent?: string[];
707
717
  version?: number;
708
718
  }
709
- interface TransformResult {
710
- code: string;
711
- map?: SourceMap | null;
712
- etag?: string;
713
- deps?: string[];
714
- dynamicDeps?: string[];
719
+ interface HighlightAnnotation {
720
+ offset: number;
721
+ length: number;
722
+ className: string;
715
723
  }
716
724
  type SourceCodeTransformerEnforce = 'pre' | 'post' | 'default';
717
725
  interface SourceCodeTransformer {
@@ -727,7 +735,9 @@ interface SourceCodeTransformer {
727
735
  /**
728
736
  * The transform function
729
737
  */
730
- transform: (code: MagicString, id: string, ctx: UnocssPluginContext) => Awaitable<void>;
738
+ transform: (code: MagicString, id: string, ctx: UnocssPluginContext) => Awaitable<{
739
+ highlightAnnotations?: HighlightAnnotation[];
740
+ } | void>;
731
741
  }
732
742
  interface ContentOptions {
733
743
  /**
@@ -846,6 +856,7 @@ interface ResolvedConfig<Theme extends object = object> extends Omit<RequiredByK
846
856
  autocomplete: {
847
857
  templates: (AutoCompleteFunction | AutoCompleteTemplate)[];
848
858
  extractors: AutoCompleteExtractor[];
859
+ shorthands: Record<string, string>;
849
860
  };
850
861
  separators: string[];
851
862
  }
@@ -945,4 +956,4 @@ declare function resolveConfig<Theme extends object = object>(userConfig?: UserC
945
956
  */
946
957
  declare function mergeConfigs<Theme extends object = object>(configs: UserConfig<Theme>[]): UserConfig<Theme>;
947
958
 
948
- export { ArgumentType, Arrayable, AutoCompleteExtractor, AutoCompleteExtractorContext, AutoCompleteExtractorResult, AutoCompleteFunction, AutoCompleteTemplate, Awaitable, BetterMap, BlocklistRule, CONTROL_SHORTCUT_NO_MERGE, CSSColorValue, CSSEntries, CSSObject, CSSValue, CSSValues, CliEntryItem, CliOptions, ConfigBase, ContentOptions, DeepPartial, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, PreflightContext, PreparedRule, Preprocessor, Preset, PresetOptions, RGBAColorValue, RawUtil, Replacement, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, ShortcutValue, SourceCodeTransformer, SourceCodeTransformerEnforce, SourceMap, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, SuggestResult, ThemeExtender, ToArray, TransformResult, TwoKeyMap, UnoGenerator, UnocssPluginContext, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantHandlerContext, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, collapseVariantGroup, createGenerator, createValueHandler, cssIdRE, defaultSplitRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit as extractorDefault, extractorSplit, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isString, isValidSelector, makeRegexClassGroup, mergeConfigs, mergeDeep, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, parseVariantGroup, regexScopePlaceholder, resolveConfig, resolvePreset, resolvePresets, resolveShortcuts, splitWithVariantGroupRE, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
959
+ export { ArgumentType, Arrayable, AutoCompleteExtractor, AutoCompleteExtractorContext, AutoCompleteExtractorResult, AutoCompleteFunction, AutoCompleteTemplate, Awaitable, BetterMap, BlocklistRule, CONTROL_SHORTCUT_NO_MERGE, CSSColorValue, CSSEntries, CSSObject, CSSValue, CSSValues, CliEntryItem, CliOptions, ConfigBase, ContentOptions, DeepPartial, DynamicMatcher, DynamicRule, DynamicShortcut, DynamicShortcutMatcher, Extractor, ExtractorContext, FilterPattern, FlatObjectTuple, GenerateOptions, GenerateResult, GeneratorOptions, HighlightAnnotation, ParsedColorValue, ParsedUtil, PartialByKeys, PluginOptions, Postprocessor, Preflight, PreflightContext, PreparedRule, Preprocessor, Preset, PresetOptions, RGBAColorValue, RawUtil, Replacement, RequiredByKey, ResolvedConfig, RestArgs, Rule, RuleContext, RuleMeta, Shift, Shortcut, ShortcutValue, SourceCodeTransformer, SourceCodeTransformerEnforce, SourceMap, StaticRule, StaticShortcut, StaticShortcutMap, StringifiedUtil, SuggestResult, ThemeExtender, ToArray, TwoKeyMap, UnoGenerator, UnocssPluginContext, UserConfig, UserConfigDefaults, UserOnlyOptions, UserShortcuts, UtilObject, ValueHandler, ValueHandlerCallback, Variant, VariantContext, VariantFunction, VariantHandler, VariantHandlerContext, VariantMatchedResult, VariantObject, attributifyRE, clearIdenticalEntries, clone, collapseVariantGroup, createGenerator, createValueHandler, cssIdRE, defaultSplitRE, e, entriesToCss, escapeRegExp, escapeSelector, expandVariantGroup, extractorSplit as extractorDefault, extractorSplit, hasScopePlaceholder, isAttributifySelector, isObject, isRawUtil, isStaticRule, isStaticShortcut, isString, isValidSelector, makeRegexClassGroup, mergeConfigs, mergeDeep, noop, normalizeCSSEntries, normalizeCSSValues, normalizeVariant, notNull, parseVariantGroup, regexScopePlaceholder, resolveConfig, resolvePreset, resolvePresets, resolveShortcuts, splitWithVariantGroupRE, toArray, toEscapedSelector, uniq, validateFilterRE, warnOnce, withLayer };
package/dist/index.mjs CHANGED
@@ -229,27 +229,71 @@ function makeRegexClassGroup(separators = ["-", ":"]) {
229
229
  }
230
230
  function parseVariantGroup(str, separators = ["-", ":"], depth = 5) {
231
231
  const regexClassGroup = makeRegexClassGroup(separators);
232
- let hasChanged = false;
232
+ let hasChanged;
233
233
  let content = str.toString();
234
234
  const prefixes = /* @__PURE__ */ new Set();
235
+ const groupsByOffset = /* @__PURE__ */ new Map();
235
236
  do {
236
- const before = content;
237
+ hasChanged = false;
237
238
  content = content.replace(
238
239
  regexClassGroup,
239
- (from, pre, sep, body) => {
240
+ (from, pre, sep, body, groupOffset) => {
240
241
  if (!separators.includes(sep))
241
242
  return from;
243
+ hasChanged = true;
242
244
  prefixes.add(pre + sep);
243
- return body.split(/\s/g).filter(Boolean).map((i) => i === "~" ? pre : i.replace(/^(!?)(.*)/, `$1${pre}${sep}$2`)).join(" ");
245
+ const bodyOffset = groupOffset + pre.length + sep.length + 1;
246
+ const group = { length: from.length, items: [] };
247
+ groupsByOffset.set(groupOffset, group);
248
+ for (const itemMatch of [...body.matchAll(/\S+/g)]) {
249
+ const itemOffset = bodyOffset + itemMatch.index;
250
+ let innerItems = groupsByOffset.get(itemOffset)?.items;
251
+ if (innerItems) {
252
+ groupsByOffset.delete(itemOffset);
253
+ } else {
254
+ innerItems = [{
255
+ offset: itemOffset,
256
+ length: itemMatch[0].length,
257
+ className: itemMatch[0]
258
+ }];
259
+ }
260
+ for (const item of innerItems) {
261
+ item.className = item.className === "~" ? pre : item.className.replace(/^(!?)(.*)/, `$1${pre}${sep}$2`);
262
+ group.items.push(item);
263
+ }
264
+ }
265
+ return "$".repeat(from.length);
244
266
  }
245
267
  );
246
- hasChanged = content !== before;
247
268
  depth -= 1;
248
269
  } while (hasChanged && depth);
270
+ let expanded;
271
+ if (typeof str === "string") {
272
+ expanded = "";
273
+ let prevOffset = 0;
274
+ for (const [offset, group] of groupsByOffset) {
275
+ expanded += str.slice(prevOffset, offset);
276
+ expanded += group.items.map((item) => item.className).join(" ");
277
+ prevOffset = offset + group.length;
278
+ }
279
+ expanded += str.slice(prevOffset);
280
+ } else {
281
+ expanded = str;
282
+ for (const [offset, group] of groupsByOffset) {
283
+ expanded.overwrite(
284
+ offset,
285
+ offset + group.length,
286
+ group.items.map((item) => item.className).join(" ")
287
+ );
288
+ }
289
+ }
249
290
  return {
250
291
  prefixes: Array.from(prefixes),
251
- expanded: content,
252
- hasChanged
292
+ hasChanged,
293
+ groupsByOffset,
294
+ get expanded() {
295
+ return expanded.toString();
296
+ }
253
297
  };
254
298
  }
255
299
  function collapseVariantGroup(str, prefixes) {
@@ -278,14 +322,8 @@ function collapseVariantGroup(str, prefixes) {
278
322
  }).join(" ");
279
323
  }
280
324
  function expandVariantGroup(str, separators = ["-", ":"], depth = 5) {
281
- const {
282
- expanded
283
- } = parseVariantGroup(str.toString(), separators, depth);
284
- if (typeof str === "string") {
285
- return expanded;
286
- } else {
287
- return str.length() ? str.overwrite(0, str.original.length, expanded) : str;
288
- }
325
+ const res = parseVariantGroup(str, separators, depth);
326
+ return typeof str === "string" ? res.expanded : str;
289
327
  }
290
328
 
291
329
  const warned = /* @__PURE__ */ new Set();
@@ -355,7 +393,9 @@ function createNanoEvents() {
355
393
  const LAYER_DEFAULT = "default";
356
394
  const LAYER_PREFLIGHTS = "preflights";
357
395
  const LAYER_SHORTCUTS = "shortcuts";
396
+ const LAYER_IMPORTS = "imports";
358
397
  const DEFAULT_LAYERS = {
398
+ [LAYER_IMPORTS]: -200,
359
399
  [LAYER_PREFLIGHTS]: -100,
360
400
  [LAYER_SHORTCUTS]: -10,
361
401
  [LAYER_DEFAULT]: 0
@@ -444,7 +484,8 @@ function resolveConfig(userConfig = {}, defaults = {}) {
444
484
  theme = extendTheme(theme) || theme;
445
485
  const autocomplete = {
446
486
  templates: uniq(sources.flatMap((p) => toArray(p.autocomplete?.templates))),
447
- extractors: sources.flatMap((p) => toArray(p.autocomplete?.extractors)).sort((a, b) => (a.order || 0) - (b.order || 0))
487
+ extractors: sources.flatMap((p) => toArray(p.autocomplete?.extractors)).sort((a, b) => (a.order || 0) - (b.order || 0)),
488
+ shorthands: mergeAutocompleteShorthands(sources.map((p) => p.autocomplete?.shorthands || {}))
448
489
  };
449
490
  let separators = getMerged("separators");
450
491
  if (!separators.length)
@@ -502,8 +543,27 @@ function mergeConfigs(configs) {
502
543
  function mergeThemes(themes) {
503
544
  return themes.map((theme) => theme ? clone(theme) : {}).reduce((a, b) => mergeDeep(a, b), {});
504
545
  }
546
+ function mergeAutocompleteShorthands(shorthands) {
547
+ return shorthands.reduce(
548
+ (a, b) => {
549
+ const rs = {};
550
+ for (const key in b) {
551
+ const value = b[key];
552
+ if (Array.isArray(value))
553
+ rs[key] = `(${value.join("|")})`;
554
+ else
555
+ rs[key] = value;
556
+ }
557
+ return {
558
+ ...a,
559
+ ...rs
560
+ };
561
+ },
562
+ {}
563
+ );
564
+ }
505
565
 
506
- const version = "0.53.6";
566
+ const version = "0.54.1";
507
567
 
508
568
  class UnoGenerator {
509
569
  constructor(userConfig = {}, defaults = {}) {
@@ -725,8 +785,11 @@ class UnoGenerator {
725
785
  let handler = await v.match(processed, context);
726
786
  if (!handler)
727
787
  continue;
728
- if (isString(handler))
788
+ if (isString(handler)) {
789
+ if (handler === processed)
790
+ continue;
729
791
  handler = { matcher: handler };
792
+ }
730
793
  processed = handler.matcher;
731
794
  handlers.unshift(handler);
732
795
  variants.add(v);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unocss/core",
3
- "version": "0.53.6",
3
+ "version": "0.54.1",
4
4
  "description": "The instant on-demand Atomic CSS engine.",
5
5
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",
@@ -37,8 +37,8 @@
37
37
  "dist"
38
38
  ],
39
39
  "devDependencies": {
40
- "magic-string": "^0.30.1",
41
- "unconfig": "^0.3.9"
40
+ "magic-string": "^0.30.2",
41
+ "unconfig": "^0.3.10"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "unbuild",