@unocss/autocomplete 0.29.1 → 0.29.4
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/README.md +13 -1
- package/dist/index.cjs +33 -20
- package/dist/index.mjs +34 -21
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ rules: [
|
|
|
33
33
|
The template uses a simle DSL to specify the autocomplete suggestions. The syntax is:
|
|
34
34
|
|
|
35
35
|
- `(...|...)`: logic OR groups. `|` as the separator. Will be used as suggestions when the some of the groups match.
|
|
36
|
-
- `<...>`: built-in short hands. currently supports `<num>`, `<
|
|
36
|
+
- `<...>`: built-in short hands. currently supports `<num>`, `<percent>` and `<directions>`
|
|
37
37
|
- `$...`: theme infering. for example, `$colors` will list all the properties of the `colors` object of the theme.
|
|
38
38
|
|
|
39
39
|
For examples:
|
|
@@ -56,6 +56,18 @@ For examples:
|
|
|
56
56
|
- **Input**: `text-r`
|
|
57
57
|
- **Suggestions**: `text-red`, `text-rose` ...
|
|
58
58
|
|
|
59
|
+
###### Example 4
|
|
60
|
+
|
|
61
|
+
For multiple templates
|
|
62
|
+
|
|
63
|
+
- **Template**: `['(border|b)-<num>', '(border|b)-<directions>-<num>']`
|
|
64
|
+
|
|
65
|
+
- **Input**: `b-`
|
|
66
|
+
- **Suggestions**: `b-x`, `b-y`, `b-1`, `b-2` ...
|
|
67
|
+
|
|
68
|
+
- **Input**: `b-x-`
|
|
69
|
+
- **Suggestions**: `b-x-1`, `b-x-2` ...
|
|
70
|
+
|
|
59
71
|
## License
|
|
60
72
|
|
|
61
73
|
MIT License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)
|
package/dist/index.cjs
CHANGED
|
@@ -11,7 +11,7 @@ const LRU__default = /*#__PURE__*/_interopDefaultLegacy(LRU);
|
|
|
11
11
|
|
|
12
12
|
const shorthands = {
|
|
13
13
|
num: `(${[0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 24, 36].join("|")})`,
|
|
14
|
-
|
|
14
|
+
percent: `(${Array.from({ length: 11 }, (_, i) => i * 10).join("|")})`,
|
|
15
15
|
directions: "(x|y|t|b|l|r|s|e)"
|
|
16
16
|
};
|
|
17
17
|
const ignoredThemeKeys = ["DEFAULT"];
|
|
@@ -41,10 +41,9 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
41
41
|
};
|
|
42
42
|
function handleNonGroup(input) {
|
|
43
43
|
handleRegexMatch(input, /\$([\w\|]+)/g, (m) => {
|
|
44
|
-
const keys = m[1].split("|");
|
|
45
44
|
parts.push({
|
|
46
45
|
type: "theme",
|
|
47
|
-
objects:
|
|
46
|
+
objects: m[1].split("|").map((i) => {
|
|
48
47
|
if (!i || !theme[i])
|
|
49
48
|
throw new Error(`Invalid theme key ${i}`);
|
|
50
49
|
return theme[i];
|
|
@@ -75,8 +74,14 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
75
74
|
while (tempParts.length) {
|
|
76
75
|
const part = tempParts.shift();
|
|
77
76
|
if (part.type === "static") {
|
|
78
|
-
if (
|
|
77
|
+
if (combinations.length)
|
|
78
|
+
combinations = combinations.map((i) => i + part.value);
|
|
79
|
+
if (part.value.startsWith(rest) && part.value !== rest && !combinations.length) {
|
|
80
|
+
combinations = [part.value];
|
|
79
81
|
break;
|
|
82
|
+
} else if (!rest.startsWith(part.value)) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
80
85
|
matched += part.value;
|
|
81
86
|
rest = rest.slice(part.value.length);
|
|
82
87
|
} else if (part.type === "group") {
|
|
@@ -86,7 +91,8 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
86
91
|
rest = rest.slice(fullMatched.length);
|
|
87
92
|
} else {
|
|
88
93
|
combinations = part.values.filter((i) => i.startsWith(rest));
|
|
89
|
-
|
|
94
|
+
if (tempParts[0]?.type !== "static")
|
|
95
|
+
break;
|
|
90
96
|
}
|
|
91
97
|
} else if (part.type === "theme") {
|
|
92
98
|
const keys = part.objects.flatMap((i) => Object.keys(i)).filter((i) => i && !ignoredThemeKeys.includes(i) && i[0] !== "_");
|
|
@@ -106,12 +112,11 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
106
112
|
}
|
|
107
113
|
} else {
|
|
108
114
|
combinations = keys.filter((i) => i.startsWith(rest));
|
|
109
|
-
|
|
115
|
+
if (tempParts[0]?.type !== "static")
|
|
116
|
+
break;
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
|
-
if (!matched)
|
|
114
|
-
return [];
|
|
115
120
|
if (combinations.length === 0)
|
|
116
121
|
combinations.push("");
|
|
117
122
|
return combinations.map((i) => matched + i).filter((i) => i.length >= input.length);
|
|
@@ -122,7 +127,7 @@ function createAutocomplete(uno) {
|
|
|
122
127
|
const templateCache = /* @__PURE__ */ new Map();
|
|
123
128
|
const cache = new LRU__default({ max: 1e3 });
|
|
124
129
|
let staticUtils = [];
|
|
125
|
-
|
|
130
|
+
const templates = [];
|
|
126
131
|
reset();
|
|
127
132
|
return {
|
|
128
133
|
suggest,
|
|
@@ -140,11 +145,18 @@ function createAutocomplete(uno) {
|
|
|
140
145
|
return [];
|
|
141
146
|
if (cache.has(input))
|
|
142
147
|
return cache.get(input);
|
|
148
|
+
const [, processed, , variants] = uno.matchVariants(input);
|
|
149
|
+
const idx = input.search(processed);
|
|
150
|
+
if (idx === -1)
|
|
151
|
+
return [];
|
|
152
|
+
const variantPrefix = input.slice(0, idx);
|
|
153
|
+
const variantPostfix = input.slice(idx + input.length);
|
|
143
154
|
const result = processSuggestions(await Promise.all([
|
|
144
|
-
suggestSelf(
|
|
145
|
-
suggestStatic(
|
|
146
|
-
...suggestFromPreset(
|
|
147
|
-
|
|
155
|
+
suggestSelf(processed),
|
|
156
|
+
suggestStatic(processed),
|
|
157
|
+
...suggestFromPreset(processed),
|
|
158
|
+
...suggestVariant(processed, variants)
|
|
159
|
+
]), variantPrefix, variantPostfix);
|
|
148
160
|
cache.set(input, result);
|
|
149
161
|
return result;
|
|
150
162
|
}
|
|
@@ -158,23 +170,24 @@ function createAutocomplete(uno) {
|
|
|
158
170
|
function suggestFromPreset(input) {
|
|
159
171
|
return templates.map((fn) => typeof fn === "function" ? fn(input) : getParsed(fn)(input)) || [];
|
|
160
172
|
}
|
|
173
|
+
function suggestVariant(input, used) {
|
|
174
|
+
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));
|
|
175
|
+
}
|
|
161
176
|
function reset() {
|
|
162
177
|
templateCache.clear();
|
|
163
178
|
cache.clear();
|
|
164
179
|
staticUtils = Object.keys(uno.config.rulesStaticMap);
|
|
165
|
-
templates =
|
|
166
|
-
|
|
167
|
-
...uno.config.rulesDynamic.flatMap((i) => core.toArray(i?.[2]?.autocomplete || []))
|
|
168
|
-
];
|
|
180
|
+
templates.length = 0;
|
|
181
|
+
templates.push(...uno.config.autocomplete || [], ...uno.config.rulesDynamic.flatMap((i) => core.toArray(i?.[2]?.autocomplete || [])));
|
|
169
182
|
}
|
|
170
|
-
function processSuggestions(suggestions) {
|
|
171
|
-
return core.uniq(suggestions.flat()).filter((i) => !!(i && !i.match(
|
|
183
|
+
function processSuggestions(suggestions, prefix = "", suffix = "") {
|
|
184
|
+
return core.uniq(suggestions.flat()).filter((i) => !!(i && !i.match(/-$/))).sort((a, b) => {
|
|
172
185
|
const numA = +(a.match(/\d+$/)?.[0] || NaN);
|
|
173
186
|
const numB = +(b.match(/\d+$/)?.[0] || NaN);
|
|
174
187
|
if (!Number.isNaN(numA) && !Number.isNaN(numB))
|
|
175
188
|
return numA - numB;
|
|
176
189
|
return a.localeCompare(b);
|
|
177
|
-
});
|
|
190
|
+
}).map((i) => prefix + i + suffix);
|
|
178
191
|
}
|
|
179
192
|
}
|
|
180
193
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toArray, uniq } from '@unocss/core';
|
|
2
2
|
import LRU from 'lru-cache';
|
|
3
3
|
|
|
4
4
|
const shorthands = {
|
|
5
5
|
num: `(${[0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 24, 36].join("|")})`,
|
|
6
|
-
|
|
6
|
+
percent: `(${Array.from({ length: 11 }, (_, i) => i * 10).join("|")})`,
|
|
7
7
|
directions: "(x|y|t|b|l|r|s|e)"
|
|
8
8
|
};
|
|
9
9
|
const ignoredThemeKeys = ["DEFAULT"];
|
|
@@ -33,10 +33,9 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
33
33
|
};
|
|
34
34
|
function handleNonGroup(input) {
|
|
35
35
|
handleRegexMatch(input, /\$([\w\|]+)/g, (m) => {
|
|
36
|
-
const keys = m[1].split("|");
|
|
37
36
|
parts.push({
|
|
38
37
|
type: "theme",
|
|
39
|
-
objects:
|
|
38
|
+
objects: m[1].split("|").map((i) => {
|
|
40
39
|
if (!i || !theme[i])
|
|
41
40
|
throw new Error(`Invalid theme key ${i}`);
|
|
42
41
|
return theme[i];
|
|
@@ -67,8 +66,14 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
67
66
|
while (tempParts.length) {
|
|
68
67
|
const part = tempParts.shift();
|
|
69
68
|
if (part.type === "static") {
|
|
70
|
-
if (
|
|
69
|
+
if (combinations.length)
|
|
70
|
+
combinations = combinations.map((i) => i + part.value);
|
|
71
|
+
if (part.value.startsWith(rest) && part.value !== rest && !combinations.length) {
|
|
72
|
+
combinations = [part.value];
|
|
71
73
|
break;
|
|
74
|
+
} else if (!rest.startsWith(part.value)) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
72
77
|
matched += part.value;
|
|
73
78
|
rest = rest.slice(part.value.length);
|
|
74
79
|
} else if (part.type === "group") {
|
|
@@ -78,7 +83,8 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
78
83
|
rest = rest.slice(fullMatched.length);
|
|
79
84
|
} else {
|
|
80
85
|
combinations = part.values.filter((i) => i.startsWith(rest));
|
|
81
|
-
|
|
86
|
+
if (tempParts[0]?.type !== "static")
|
|
87
|
+
break;
|
|
82
88
|
}
|
|
83
89
|
} else if (part.type === "theme") {
|
|
84
90
|
const keys = part.objects.flatMap((i) => Object.keys(i)).filter((i) => i && !ignoredThemeKeys.includes(i) && i[0] !== "_");
|
|
@@ -98,12 +104,11 @@ function parseAutocomplete(template, theme = {}) {
|
|
|
98
104
|
}
|
|
99
105
|
} else {
|
|
100
106
|
combinations = keys.filter((i) => i.startsWith(rest));
|
|
101
|
-
|
|
107
|
+
if (tempParts[0]?.type !== "static")
|
|
108
|
+
break;
|
|
102
109
|
}
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
|
-
if (!matched)
|
|
106
|
-
return [];
|
|
107
112
|
if (combinations.length === 0)
|
|
108
113
|
combinations.push("");
|
|
109
114
|
return combinations.map((i) => matched + i).filter((i) => i.length >= input.length);
|
|
@@ -114,7 +119,7 @@ function createAutocomplete(uno) {
|
|
|
114
119
|
const templateCache = /* @__PURE__ */ new Map();
|
|
115
120
|
const cache = new LRU({ max: 1e3 });
|
|
116
121
|
let staticUtils = [];
|
|
117
|
-
|
|
122
|
+
const templates = [];
|
|
118
123
|
reset();
|
|
119
124
|
return {
|
|
120
125
|
suggest,
|
|
@@ -132,11 +137,18 @@ function createAutocomplete(uno) {
|
|
|
132
137
|
return [];
|
|
133
138
|
if (cache.has(input))
|
|
134
139
|
return cache.get(input);
|
|
140
|
+
const [, processed, , variants] = uno.matchVariants(input);
|
|
141
|
+
const idx = input.search(processed);
|
|
142
|
+
if (idx === -1)
|
|
143
|
+
return [];
|
|
144
|
+
const variantPrefix = input.slice(0, idx);
|
|
145
|
+
const variantPostfix = input.slice(idx + input.length);
|
|
135
146
|
const result = processSuggestions(await Promise.all([
|
|
136
|
-
suggestSelf(
|
|
137
|
-
suggestStatic(
|
|
138
|
-
...suggestFromPreset(
|
|
139
|
-
|
|
147
|
+
suggestSelf(processed),
|
|
148
|
+
suggestStatic(processed),
|
|
149
|
+
...suggestFromPreset(processed),
|
|
150
|
+
...suggestVariant(processed, variants)
|
|
151
|
+
]), variantPrefix, variantPostfix);
|
|
140
152
|
cache.set(input, result);
|
|
141
153
|
return result;
|
|
142
154
|
}
|
|
@@ -150,23 +162,24 @@ function createAutocomplete(uno) {
|
|
|
150
162
|
function suggestFromPreset(input) {
|
|
151
163
|
return templates.map((fn) => typeof fn === "function" ? fn(input) : getParsed(fn)(input)) || [];
|
|
152
164
|
}
|
|
165
|
+
function suggestVariant(input, used) {
|
|
166
|
+
return uno.config.variants.filter((v) => v.autocomplete && (v.multiPass || !used.has(v))).flatMap((v) => toArray(v.autocomplete || [])).map((fn) => typeof fn === "function" ? fn(input) : getParsed(fn)(input));
|
|
167
|
+
}
|
|
153
168
|
function reset() {
|
|
154
169
|
templateCache.clear();
|
|
155
170
|
cache.clear();
|
|
156
171
|
staticUtils = Object.keys(uno.config.rulesStaticMap);
|
|
157
|
-
templates =
|
|
158
|
-
|
|
159
|
-
...uno.config.rulesDynamic.flatMap((i) => toArray(i?.[2]?.autocomplete || []))
|
|
160
|
-
];
|
|
172
|
+
templates.length = 0;
|
|
173
|
+
templates.push(...uno.config.autocomplete || [], ...uno.config.rulesDynamic.flatMap((i) => toArray(i?.[2]?.autocomplete || [])));
|
|
161
174
|
}
|
|
162
|
-
function processSuggestions(suggestions) {
|
|
163
|
-
return uniq(suggestions.flat()).filter((i) => !!(i && !i.match(
|
|
175
|
+
function processSuggestions(suggestions, prefix = "", suffix = "") {
|
|
176
|
+
return uniq(suggestions.flat()).filter((i) => !!(i && !i.match(/-$/))).sort((a, b) => {
|
|
164
177
|
const numA = +(a.match(/\d+$/)?.[0] || NaN);
|
|
165
178
|
const numB = +(b.match(/\d+$/)?.[0] || NaN);
|
|
166
179
|
if (!Number.isNaN(numA) && !Number.isNaN(numB))
|
|
167
180
|
return numA - numB;
|
|
168
181
|
return a.localeCompare(b);
|
|
169
|
-
});
|
|
182
|
+
}).map((i) => prefix + i + suffix);
|
|
170
183
|
}
|
|
171
184
|
}
|
|
172
185
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unocss/autocomplete",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.4",
|
|
4
4
|
"description": "Autocomplete utils for UnoCSS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"unocss",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/lru-cache": "^7.4.0",
|
|
39
|
-
"@unocss/core": "0.29.
|
|
39
|
+
"@unocss/core": "0.29.4"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "unbuild",
|
|
43
43
|
"stub": "unbuild --stub"
|
|
44
44
|
},
|
|
45
|
-
"readme": "# @unocss/autocomplete\n\nAutocomplete utils for UnoCSS. This is embedded in [the playground](https://unocss.antfu.me/) and [the VS Code extension](https://github.com/unocss/unocss/tree/main/packages/vscode).\n\n## Syntax\n\nTo add autocomplete support to your custom rules:\n\n### Static Rules\n\nStatic rules like this will just works without any configuration.\n\n```ts\nrules: [\n ['flex', { display: 'flex' }]\n]\n```\n\n### Dynamic Rules\n\nFor dynamic rules, you can provide an extra `meta` object to the rule and specify the autocomplete template.\n\n```ts\nrules: [\n [\n /^m-(\\d)$/,\n ([, d]) => ({ margin: `${d / 4}rem` }),\n { autocomplete: 'm-<num>' }, // <-- this\n ],\n]\n```\n\nThe template uses a simle DSL to specify the autocomplete suggestions. The syntax is:\n\n- `(...|...)`: logic OR groups. `|` as the separator. Will be used as suggestions when the some of the groups match.\n- `<...>`: built-in short hands. currently supports `<num>`, `<
|
|
45
|
+
"readme": "# @unocss/autocomplete\n\nAutocomplete utils for UnoCSS. This is embedded in [the playground](https://unocss.antfu.me/) and [the VS Code extension](https://github.com/unocss/unocss/tree/main/packages/vscode).\n\n## Syntax\n\nTo add autocomplete support to your custom rules:\n\n### Static Rules\n\nStatic rules like this will just works without any configuration.\n\n```ts\nrules: [\n ['flex', { display: 'flex' }]\n]\n```\n\n### Dynamic Rules\n\nFor dynamic rules, you can provide an extra `meta` object to the rule and specify the autocomplete template.\n\n```ts\nrules: [\n [\n /^m-(\\d)$/,\n ([, d]) => ({ margin: `${d / 4}rem` }),\n { autocomplete: 'm-<num>' }, // <-- this\n ],\n]\n```\n\nThe template uses a simle DSL to specify the autocomplete suggestions. The syntax is:\n\n- `(...|...)`: logic OR groups. `|` as the separator. Will be used as suggestions when the some of the groups match.\n- `<...>`: built-in short hands. currently supports `<num>`, `<percent>` and `<directions>`\n- `$...`: theme infering. for example, `$colors` will list all the properties of the `colors` object of the theme.\n\nFor examples:\n\n###### Example 1\n\n- **Template**: `(border|b)-(solid|dashed|dotted|double|hidden|none)`\n- **Input**: `b-do`\n- **Suggestions**: `b-dashed`, `b-double`\n\n###### Example 2\n\n- **Template**: `m-<num>`\n- **Input**: `m-`\n- **Suggestions**: `m-1`, `m-2`, `m-3` ...\n\n###### Example 3\n\n- **Template**: `text-$colors`\n- **Input**: `text-r`\n- **Suggestions**: `text-red`, `text-rose` ...\n\n###### Example 4\n\nFor multiple templates\n\n- **Template**: `['(border|b)-<num>', '(border|b)-<directions>-<num>']`\n\n- **Input**: `b-`\n- **Suggestions**: `b-x`, `b-y`, `b-1`, `b-2` ...\n\n- **Input**: `b-x-`\n- **Suggestions**: `b-x-1`, `b-x-2` ...\n\n## License\n\nMIT License © 2021-PRESENT [Anthony Fu](https://github.com/antfu)\n"
|
|
46
46
|
}
|