@unocss/autocomplete 0.58.8 → 0.59.0-beta.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/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@unocss/autocomplete",
3
- "version": "0.58.8",
3
+ "type": "module",
4
+ "version": "0.59.0-beta.1",
4
5
  "description": "Autocomplete utils for UnoCSS",
5
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
6
7
  "license": "MIT",
@@ -21,12 +22,11 @@
21
22
  "sideEffects": false,
22
23
  "exports": {
23
24
  ".": {
24
- "types": "./dist/index.d.ts",
25
- "import": "./dist/index.mjs",
26
- "require": "./dist/index.cjs"
25
+ "types": "./dist/index.d.mts",
26
+ "default": "./dist/index.mjs"
27
27
  }
28
28
  },
29
- "main": "./dist/index.cjs",
29
+ "main": "./dist/index.mjs",
30
30
  "module": "./dist/index.mjs",
31
31
  "types": "./dist/index.d.ts",
32
32
  "files": [
@@ -37,7 +37,7 @@
37
37
  "lru-cache": "^10.2.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@unocss/core": "0.58.8"
40
+ "@unocss/core": "0.59.0-beta.1"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "unbuild",
package/dist/index.cjs DELETED
@@ -1,371 +0,0 @@
1
- 'use strict';
2
-
3
- const core = require('@unocss/core');
4
- const lruCache = require('lru-cache');
5
- const fzf = require('fzf');
6
-
7
- function searchUsageBoundary(line, index) {
8
- let start = index;
9
- let end = index;
10
- const regex = /[^\s>"'`;]/;
11
- while (start && regex.test(line.charAt(start - 1)))
12
- --start;
13
- while (end < line.length && regex.test(line.charAt(end)))
14
- ++end;
15
- return {
16
- content: line.slice(start, end),
17
- start,
18
- end
19
- };
20
- }
21
- function searchAttrKey(content, cursor) {
22
- const text = content.substring(0, cursor);
23
- if (/(<\w+\s*)[^>]*$/.test(text))
24
- return text.match(/\S+(?=\s*=\s*["']?[^"']*$)/)?.[0];
25
- }
26
- function cartesian(arr) {
27
- return arr.reduce(
28
- (a, b) => {
29
- const ret = [];
30
- a.forEach((a2) => {
31
- b.forEach((b2) => {
32
- ret.push(a2.concat([b2]));
33
- });
34
- });
35
- return ret;
36
- },
37
- [[]]
38
- );
39
- }
40
-
41
- const shorthands = {
42
- directions: "(x|y|t|b|l|r|s|e)",
43
- num: `(${[0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 24, 36].join("|")})`,
44
- percent: `(${[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100].join("|")})`,
45
- percentage: `(${["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"].join("|")})`
46
- };
47
- const ignoredThemeKeys = ["DEFAULT"];
48
- function handleRegexMatch(str, regex, onMatched, onNotMatched) {
49
- let lastIndex = 0;
50
- Array.from(str.matchAll(regex)).forEach((m) => {
51
- const index = m.index;
52
- if (lastIndex !== index)
53
- onNotMatched(str.slice(lastIndex, index), lastIndex, index);
54
- onMatched(m);
55
- lastIndex = index + m[0].length;
56
- });
57
- if (lastIndex !== str.length)
58
- onNotMatched(str.slice(lastIndex), lastIndex, str.length);
59
- }
60
- function parseAutocomplete(template, theme = {}, extraShorthands = {}) {
61
- const parts = [];
62
- const newShorthands = {
63
- ...shorthands,
64
- ...extraShorthands
65
- };
66
- template = template.replace(/<(\w+)>/g, (_, key) => {
67
- if (!newShorthands[key])
68
- throw new Error(`Unknown template shorthand: ${key}`);
69
- return newShorthands[key];
70
- });
71
- handleGroups(template);
72
- const fzf$1 = new fzf.Fzf(getAllCombination(parts));
73
- return {
74
- parts,
75
- suggest
76
- };
77
- function handleNonGroup(input) {
78
- handleRegexMatch(
79
- input,
80
- /\$([\w\.\|]+)/g,
81
- (m) => {
82
- parts.push({
83
- type: "theme",
84
- objects: m[1].split("|").map((i) => {
85
- return i.split(".").reduce((v, k) => {
86
- if (!k || !v[k])
87
- throw new Error(`Invalid theme key ${k}`);
88
- return v[k];
89
- }, theme);
90
- })
91
- });
92
- },
93
- (str) => {
94
- parts.push({
95
- type: "static",
96
- value: str
97
- });
98
- }
99
- );
100
- }
101
- function handleGroups(input) {
102
- handleRegexMatch(
103
- input,
104
- /\((.*?)\)/g,
105
- (m) => {
106
- parts.push({
107
- type: "group",
108
- values: m[1].split("|")
109
- });
110
- },
111
- (str) => {
112
- handleNonGroup(str);
113
- }
114
- );
115
- }
116
- function suggest(input, matchType = "prefix") {
117
- if (input.length > 1 && matchType === "fuzzy")
118
- return fzf$1.find(input).map((i) => i.item);
119
- let rest = input.replace(/-/g, "");
120
- let matched = [""];
121
- let combinations = [""];
122
- const tempParts = [...parts];
123
- while (tempParts.length) {
124
- const part = tempParts.shift();
125
- if (part.type === "static") {
126
- const temp = part.value.replace(/-/g, "");
127
- if (!rest.startsWith(temp) && !part.value.startsWith(rest))
128
- return [""];
129
- matched = matched.map((m) => m + part.value);
130
- rest = rest.slice(temp.length);
131
- } else if (part.type === "group") {
132
- const fullMatched = part.values.find((i) => i && rest.startsWith(i));
133
- if (fullMatched) {
134
- matched = matched.map((m) => m + fullMatched);
135
- rest = rest.slice(fullMatched.length);
136
- if (!tempParts[0] && rest)
137
- return [];
138
- continue;
139
- } else {
140
- if (tempParts[0]) {
141
- const values = part.values.filter((i) => i && i.startsWith(rest));
142
- rest = "";
143
- if (values.length) {
144
- matched = matched.map((m) => values.map((n) => m + n)).flat();
145
- continue;
146
- }
147
- break;
148
- }
149
- if (matched[0] === "")
150
- break;
151
- combinations = part.values.filter((p) => p.startsWith(rest));
152
- break;
153
- }
154
- } else if (part.type === "theme") {
155
- const keys = part.objects.flatMap((i) => Object.keys(i)).filter((i) => i && !ignoredThemeKeys.includes(i) && i[0] !== "_");
156
- const fullMatched = keys.find((i) => i && rest.startsWith(i));
157
- if (fullMatched != null) {
158
- rest = rest.slice(fullMatched.length);
159
- const subObjects = part.objects.map((i) => i[fullMatched]).filter((i) => !!i && typeof i === "object");
160
- if (subObjects.length) {
161
- matched = matched.map((m) => `${m + fullMatched}-`);
162
- tempParts.unshift({
163
- type: "theme",
164
- objects: subObjects
165
- });
166
- } else {
167
- combinations = keys.filter((i) => i.startsWith(rest));
168
- }
169
- } else {
170
- if (tempParts[0] && tempParts[0].type !== "static") {
171
- const values = tempParts[0].values;
172
- if (values)
173
- matched = matched.filter((i) => i && rest.startsWith(i)).map((m) => values.map((n) => m + n)).flat();
174
- } else {
175
- combinations = keys.filter((i) => i.startsWith(rest));
176
- }
177
- break;
178
- }
179
- }
180
- }
181
- return combinations.map((i) => matched.map((m) => m + i)).flat().filter((i) => i.length >= input.length);
182
- }
183
- }
184
- function getValuesFromPartTemplate(part) {
185
- if (part.type === "static")
186
- return [part.value];
187
- if (part.type === "theme") {
188
- return part.objects.flatMap((i) => {
189
- const keys = Object.keys(i).filter((i2) => i2 && i2[0] !== "_");
190
- for (const key in i) {
191
- const value = i[key];
192
- if (value === null || value === void 0)
193
- continue;
194
- if (typeof value === "object" && !Array.isArray(value)) {
195
- const subKeys = getValuesFromPartTemplate({
196
- type: "theme",
197
- objects: [value]
198
- }).map((i2) => `${key}-${i2}`);
199
- keys.push(...subKeys);
200
- }
201
- }
202
- return keys;
203
- });
204
- }
205
- if (part.type === "group")
206
- return [...part.values];
207
- return [];
208
- }
209
- function getAllCombination(parts) {
210
- const values = parts.map((i) => getValuesFromPartTemplate(i));
211
- const list = core.uniq(cartesian(values).flatMap((i) => i.join("").replace("-DEFAULT", "")));
212
- return list;
213
- }
214
-
215
- function createAutocomplete(uno, options = {}) {
216
- const templateCache = /* @__PURE__ */ new Map();
217
- const cache = new lruCache.LRUCache({ max: 5e3 });
218
- let staticUtils = [];
219
- const templates = [];
220
- const matchType = options.matchType ?? "prefix";
221
- reset();
222
- return {
223
- suggest,
224
- suggestInFile,
225
- templates,
226
- cache,
227
- reset,
228
- /**
229
- * Enumerate possible suggestions from 'aa' - 'zz'
230
- */
231
- enumerate
232
- };
233
- async function enumerate() {
234
- const matched = /* @__PURE__ */ new Set();
235
- const a2z = Array.from("abcdefghijklmnopqrstuvwxyz");
236
- const a2zd = [...a2z, "-"];
237
- const keys = a2z.flatMap((i) => [
238
- i,
239
- ...a2zd.map((j) => `${i}${j}`)
240
- ]);
241
- await Promise.all(
242
- keys.map((key) => suggest(key).then((i) => i.forEach((j) => matched.add(j))))
243
- );
244
- await Promise.all(
245
- [...matched].filter((i) => /^\w+$/.test(i) && i.length > 3).map((i) => suggest(`${i}-`).then((i2) => i2.forEach((j) => matched.add(j))))
246
- );
247
- return matched;
248
- }
249
- function getParsed(template) {
250
- if (!templateCache.has(template))
251
- templateCache.set(template, parseAutocomplete(template, uno.config.theme, uno.config.autocomplete.shorthands));
252
- return templateCache.get(template).suggest;
253
- }
254
- async function suggest(input, allowsEmptyInput = false) {
255
- if (!allowsEmptyInput && input.length < 1)
256
- return [];
257
- if (cache.has(input))
258
- return cache.get(input);
259
- const [, processed, , variants] = await uno.matchVariants(input);
260
- let idx = processed ? input.search(core.escapeRegExp(processed)) : input.length;
261
- if (idx === -1)
262
- idx = 0;
263
- const variantPrefix = input.slice(0, idx);
264
- const variantSuffix = input.slice(idx + input.length);
265
- let result = processSuggestions(
266
- await Promise.all([
267
- suggestSelf(processed),
268
- suggestStatic(processed),
269
- suggestUnoCache(processed),
270
- ...suggestFromPreset(processed),
271
- ...suggestVariant(processed, variants)
272
- ]),
273
- variantPrefix,
274
- variantSuffix
275
- );
276
- if (matchType === "fuzzy") {
277
- const fzf$1 = new fzf.Fzf(result, {
278
- tiebreakers: [fzf.byStartAsc, fzf.byLengthAsc]
279
- });
280
- result = fzf$1.find(input).map((i) => i.item);
281
- }
282
- cache.set(input, result);
283
- return result;
284
- }
285
- async function suggestInFile(content, cursor) {
286
- const isInsideAttrValue = searchAttrKey(content, cursor) !== void 0;
287
- const byExtractor = await searchUsageByExtractor(content, cursor);
288
- if (byExtractor) {
289
- const suggestions2 = await suggest(byExtractor.extracted, isInsideAttrValue);
290
- const formatted = byExtractor.transformSuggestions ? byExtractor.transformSuggestions(suggestions2) : suggestions2;
291
- return {
292
- suggestions: suggestions2.map((v, i) => [v, formatted[i]]),
293
- resolveReplacement: byExtractor.resolveReplacement
294
- };
295
- }
296
- const regular = searchUsageBoundary(content, cursor);
297
- const suggestions = await suggest(regular.content, isInsideAttrValue);
298
- return {
299
- suggestions: suggestions.map((v) => [v, v]),
300
- resolveReplacement: (suggestion) => ({
301
- start: regular.start,
302
- end: regular.end,
303
- replacement: suggestion
304
- })
305
- };
306
- }
307
- async function searchUsageByExtractor(content, cursor) {
308
- if (!uno.config.autocomplete.extractors.length)
309
- return null;
310
- for (const extractor of uno.config.autocomplete.extractors) {
311
- const res = await extractor.extract({ content, cursor });
312
- if (res)
313
- return res;
314
- }
315
- return null;
316
- }
317
- async function suggestSelf(input) {
318
- const i = await uno.parseToken(input, "-");
319
- return i ? [input] : [];
320
- }
321
- async function suggestStatic(input) {
322
- if (matchType === "fuzzy")
323
- return staticUtils;
324
- return staticUtils.filter((i) => i.startsWith(input));
325
- }
326
- async function suggestUnoCache(input) {
327
- const keys = Array.from(uno._cache.entries());
328
- return keys.filter((i) => i[1] && i[0].startsWith(input)).map((i) => i[0]);
329
- }
330
- function suggestFromPreset(input) {
331
- return templates.map((fn) => typeof fn === "function" ? fn(input) : getParsed(fn)(input, matchType)) || [];
332
- }
333
- function suggestVariant(input, used) {
334
- return uno.config.variants.filter((v) => v.autocomplete && (v.multiPass || !used.has(v))).flatMap((v) => core.toArray(v.autocomplete || [])).map((fn) => typeof fn === "function" ? fn(input) : getParsed(fn)(input, matchType));
335
- }
336
- function reset() {
337
- templateCache.clear();
338
- cache.clear();
339
- staticUtils = [
340
- ...Object.keys(uno.config.rulesStaticMap),
341
- ...uno.config.shortcuts.filter((i) => typeof i[0] === "string").map((i) => i[0])
342
- ];
343
- templates.length = 0;
344
- templates.push(
345
- ...uno.config.autocomplete.templates || [],
346
- ...uno.config.rulesDynamic.flatMap((i) => core.toArray(i?.[3]?.autocomplete || [])),
347
- ...uno.config.shortcuts.flatMap((i) => core.toArray(i?.[2]?.autocomplete || []))
348
- );
349
- }
350
- function processSuggestions(suggestions, prefix = "", suffix = "") {
351
- return core.uniq(suggestions.flat()).filter((i) => !!(i && !i.endsWith("-") && !uno.isBlocked(i))).sort((a, b) => {
352
- if (/\d/.test(a) && /\D/.test(b))
353
- return 1;
354
- if (/\D/.test(a) && /\d/.test(b))
355
- return -1;
356
- const numA = +(a.match(/\d+$/)?.[0] || Number.NaN);
357
- const numB = +(b.match(/\d+$/)?.[0] || Number.NaN);
358
- if (!Number.isNaN(numA) && !Number.isNaN(numB))
359
- return numA - numB;
360
- return a.localeCompare(b);
361
- }).map((i) => prefix + i + suffix);
362
- }
363
- }
364
-
365
- exports.cartesian = cartesian;
366
- exports.createAutocomplete = createAutocomplete;
367
- exports.ignoredThemeKeys = ignoredThemeKeys;
368
- exports.parseAutocomplete = parseAutocomplete;
369
- exports.searchAttrKey = searchAttrKey;
370
- exports.searchUsageBoundary = searchUsageBoundary;
371
- exports.shorthands = shorthands;
package/dist/index.d.cts DELETED
@@ -1,48 +0,0 @@
1
- import { SuggestResult, AutoCompleteFunction, UnoGenerator } from '@unocss/core';
2
- import { LRUCache } from 'lru-cache';
3
-
4
- type AutoCompleteMatchType = 'prefix' | 'fuzzy';
5
- interface AutocompleteOptions {
6
- matchType?: AutoCompleteMatchType;
7
- }
8
- type AutocompleteTemplatePart = AutocompleteTemplateStatic | AutocompleteTemplateGroup | AutocompleteTemplateTheme;
9
- interface AutocompleteTemplateStatic {
10
- type: 'static';
11
- value: string;
12
- }
13
- interface AutocompleteTemplateGroup {
14
- type: 'group';
15
- values: string[];
16
- }
17
- interface AutocompleteTemplateTheme {
18
- type: 'theme';
19
- objects: Record<string, unknown>[];
20
- }
21
- interface ParsedAutocompleteTemplate {
22
- parts: AutocompleteTemplatePart[];
23
- suggest: (input: string, matchType?: AutoCompleteMatchType) => string[] | undefined;
24
- }
25
- interface UnocssAutocomplete {
26
- suggest: (input: string, allowsEmptyInput?: boolean) => Promise<string[]>;
27
- suggestInFile: (content: string, cursor: number) => Promise<SuggestResult>;
28
- templates: (string | AutoCompleteFunction)[];
29
- cache: LRUCache<string, string[]>;
30
- reset: () => void;
31
- enumerate: () => Promise<Set<string>>;
32
- }
33
-
34
- declare function createAutocomplete(uno: UnoGenerator, options?: AutocompleteOptions): UnocssAutocomplete;
35
-
36
- declare const shorthands: Record<string, string>;
37
- declare const ignoredThemeKeys: string[];
38
- declare function parseAutocomplete(template: string, theme?: any, extraShorthands?: Record<string, string>): ParsedAutocompleteTemplate;
39
-
40
- declare function searchUsageBoundary(line: string, index: number): {
41
- content: string;
42
- start: number;
43
- end: number;
44
- };
45
- declare function searchAttrKey(content: string, cursor: number): string | undefined;
46
- declare function cartesian<T>(arr: T[][]): T[][];
47
-
48
- export { type AutoCompleteMatchType, type AutocompleteOptions, type AutocompleteTemplateGroup, type AutocompleteTemplatePart, type AutocompleteTemplateStatic, type AutocompleteTemplateTheme, type ParsedAutocompleteTemplate, type UnocssAutocomplete, cartesian, createAutocomplete, ignoredThemeKeys, parseAutocomplete, searchAttrKey, searchUsageBoundary, shorthands };