@unocss/eslint-plugin 0.55.6 → 0.56.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/dirs.cjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const node_url = require('node:url');
4
4
 
5
- const distDir = node_url.fileURLToPath(new URL("../dist", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('dirs.cjs', document.baseURI).href))));
5
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
6
+ const distDir = node_url.fileURLToPath(new URL("../dist", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('dirs.cjs', document.baseURI).href))));
6
7
 
7
8
  exports.distDir = distDir;
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const node_path = require('node:path');
4
3
  const utils = require('@typescript-eslint/utils');
4
+ const node_path = require('node:path');
5
5
  const synckit = require('synckit');
6
6
  const dirs = require('./dirs.cjs');
7
7
  const MagicString = require('magic-string');
@@ -14,7 +14,8 @@ const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
14
14
  const CLASS_FIELDS = ["class", "classname"];
15
15
  const AST_NODES_WITH_QUOTES = ["Literal", "VLiteral"];
16
16
 
17
- const sortClasses$1 = synckit.createSyncFn(node_path.join(dirs.distDir, "worker-sort.cjs"));
17
+ const syncAction = synckit.createSyncFn(node_path.join(dirs.distDir, "worker.cjs"));
18
+
18
19
  const order = utils.ESLintUtils.RuleCreator((name) => name)({
19
20
  name: "order",
20
21
  meta: {
@@ -35,7 +36,7 @@ const order = utils.ESLintUtils.RuleCreator((name) => name)({
35
36
  if (typeof node.value !== "string" || !node.value.trim())
36
37
  return;
37
38
  const input = node.value;
38
- const sorted = sortClasses$1(input).trim();
39
+ const sorted = syncAction("sort", input).trim();
39
40
  if (sorted !== input) {
40
41
  context.report({
41
42
  node,
@@ -79,7 +80,6 @@ const order = utils.ESLintUtils.RuleCreator((name) => name)({
79
80
  }
80
81
  });
81
82
 
82
- const sortClasses = synckit.createSyncFn(node_path.join(dirs.distDir, "worker-sort.cjs"));
83
83
  const IGNORE_ATTRIBUTES = ["style", "class", "classname", "value"];
84
84
  const orderAttributify = utils.ESLintUtils.RuleCreator((name) => name)({
85
85
  name: "order-attributify",
@@ -104,7 +104,7 @@ const orderAttributify = utils.ESLintUtils.RuleCreator((name) => name)({
104
104
  if (!valueless.length)
105
105
  return;
106
106
  const input = valueless.map((i) => i.key.name).join(" ").trim();
107
- const sorted = sortClasses(input);
107
+ const sorted = syncAction("sort", input);
108
108
  if (sorted !== input) {
109
109
  context.report({
110
110
  node,
@@ -132,6 +132,87 @@ const orderAttributify = utils.ESLintUtils.RuleCreator((name) => name)({
132
132
  }
133
133
  });
134
134
 
135
+ const blocklist = utils.ESLintUtils.RuleCreator((name) => name)({
136
+ name: "blocklist",
137
+ meta: {
138
+ type: "problem",
139
+ fixable: "code",
140
+ docs: {
141
+ description: "Utilities in UnoCSS blocklist",
142
+ recommended: "recommended"
143
+ },
144
+ messages: {
145
+ "in-blocklist": "Utility '{{ name }}' is in blocklist"
146
+ },
147
+ schema: []
148
+ },
149
+ defaultOptions: [],
150
+ create(context) {
151
+ const checkLiteral = (node) => {
152
+ if (typeof node.value !== "string" || !node.value.trim())
153
+ return;
154
+ const input = node.value;
155
+ const blocked = syncAction("blocklist", input, context.filename);
156
+ blocked.forEach((i) => {
157
+ context.report({
158
+ node,
159
+ messageId: "in-blocklist",
160
+ data: {
161
+ name: i
162
+ }
163
+ });
164
+ });
165
+ };
166
+ const scriptVisitor = {
167
+ JSXAttribute(node) {
168
+ if (typeof node.name.name === "string" && CLASS_FIELDS.includes(node.name.name.toLowerCase()) && node.value) {
169
+ if (node.value.type === "Literal")
170
+ checkLiteral(node.value);
171
+ }
172
+ },
173
+ SvelteAttribute(node) {
174
+ if (node.key.name === "class") {
175
+ if (node.value?.[0].type === "SvelteLiteral")
176
+ checkLiteral(node.value[0]);
177
+ }
178
+ }
179
+ };
180
+ const templateBodyVisitor = {
181
+ VAttribute(node) {
182
+ if (node.key.name === "class") {
183
+ if (node.value.type === "VLiteral")
184
+ checkLiteral(node.value);
185
+ }
186
+ },
187
+ // Attributify
188
+ VStartTag(node) {
189
+ const valueless = node.attributes.filter((i) => typeof i.key?.name === "string" && !IGNORE_ATTRIBUTES.includes(i.key?.name?.toLowerCase()) && i.value == null);
190
+ if (!valueless.length)
191
+ return;
192
+ for (const node2 of valueless) {
193
+ if (!node2?.key?.name)
194
+ continue;
195
+ const blocked = syncAction("blocklist", node2.key.name, context.filename);
196
+ blocked.forEach((i) => {
197
+ context.report({
198
+ node: node2,
199
+ messageId: "in-blocklist",
200
+ data: {
201
+ name: i
202
+ }
203
+ });
204
+ });
205
+ }
206
+ }
207
+ };
208
+ if (context.parserServices == null || context.parserServices.defineTemplateBodyVisitor == null) {
209
+ return scriptVisitor;
210
+ } else {
211
+ return context.parserServices?.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor);
212
+ }
213
+ }
214
+ });
215
+
135
216
  const configsRecommended = {
136
217
  plugins: ["@unocss"],
137
218
  rules: {
@@ -143,7 +224,8 @@ const configsRecommended = {
143
224
  const index = {
144
225
  rules: {
145
226
  order,
146
- "order-attributify": orderAttributify
227
+ "order-attributify": orderAttributify,
228
+ blocklist
147
229
  },
148
230
  configs: {
149
231
  recommended: configsRecommended
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { join } from 'node:path';
2
1
  import { ESLintUtils } from '@typescript-eslint/utils';
2
+ import { join } from 'node:path';
3
3
  import { createSyncFn } from 'synckit';
4
4
  import { distDir } from './dirs.mjs';
5
5
  import MagicString from 'magic-string';
@@ -8,7 +8,8 @@ import 'node:url';
8
8
  const CLASS_FIELDS = ["class", "classname"];
9
9
  const AST_NODES_WITH_QUOTES = ["Literal", "VLiteral"];
10
10
 
11
- const sortClasses$1 = createSyncFn(join(distDir, "worker-sort.cjs"));
11
+ const syncAction = createSyncFn(join(distDir, "worker.cjs"));
12
+
12
13
  const order = ESLintUtils.RuleCreator((name) => name)({
13
14
  name: "order",
14
15
  meta: {
@@ -29,7 +30,7 @@ const order = ESLintUtils.RuleCreator((name) => name)({
29
30
  if (typeof node.value !== "string" || !node.value.trim())
30
31
  return;
31
32
  const input = node.value;
32
- const sorted = sortClasses$1(input).trim();
33
+ const sorted = syncAction("sort", input).trim();
33
34
  if (sorted !== input) {
34
35
  context.report({
35
36
  node,
@@ -73,7 +74,6 @@ const order = ESLintUtils.RuleCreator((name) => name)({
73
74
  }
74
75
  });
75
76
 
76
- const sortClasses = createSyncFn(join(distDir, "worker-sort.cjs"));
77
77
  const IGNORE_ATTRIBUTES = ["style", "class", "classname", "value"];
78
78
  const orderAttributify = ESLintUtils.RuleCreator((name) => name)({
79
79
  name: "order-attributify",
@@ -98,7 +98,7 @@ const orderAttributify = ESLintUtils.RuleCreator((name) => name)({
98
98
  if (!valueless.length)
99
99
  return;
100
100
  const input = valueless.map((i) => i.key.name).join(" ").trim();
101
- const sorted = sortClasses(input);
101
+ const sorted = syncAction("sort", input);
102
102
  if (sorted !== input) {
103
103
  context.report({
104
104
  node,
@@ -126,6 +126,87 @@ const orderAttributify = ESLintUtils.RuleCreator((name) => name)({
126
126
  }
127
127
  });
128
128
 
129
+ const blocklist = ESLintUtils.RuleCreator((name) => name)({
130
+ name: "blocklist",
131
+ meta: {
132
+ type: "problem",
133
+ fixable: "code",
134
+ docs: {
135
+ description: "Utilities in UnoCSS blocklist",
136
+ recommended: "recommended"
137
+ },
138
+ messages: {
139
+ "in-blocklist": "Utility '{{ name }}' is in blocklist"
140
+ },
141
+ schema: []
142
+ },
143
+ defaultOptions: [],
144
+ create(context) {
145
+ const checkLiteral = (node) => {
146
+ if (typeof node.value !== "string" || !node.value.trim())
147
+ return;
148
+ const input = node.value;
149
+ const blocked = syncAction("blocklist", input, context.filename);
150
+ blocked.forEach((i) => {
151
+ context.report({
152
+ node,
153
+ messageId: "in-blocklist",
154
+ data: {
155
+ name: i
156
+ }
157
+ });
158
+ });
159
+ };
160
+ const scriptVisitor = {
161
+ JSXAttribute(node) {
162
+ if (typeof node.name.name === "string" && CLASS_FIELDS.includes(node.name.name.toLowerCase()) && node.value) {
163
+ if (node.value.type === "Literal")
164
+ checkLiteral(node.value);
165
+ }
166
+ },
167
+ SvelteAttribute(node) {
168
+ if (node.key.name === "class") {
169
+ if (node.value?.[0].type === "SvelteLiteral")
170
+ checkLiteral(node.value[0]);
171
+ }
172
+ }
173
+ };
174
+ const templateBodyVisitor = {
175
+ VAttribute(node) {
176
+ if (node.key.name === "class") {
177
+ if (node.value.type === "VLiteral")
178
+ checkLiteral(node.value);
179
+ }
180
+ },
181
+ // Attributify
182
+ VStartTag(node) {
183
+ const valueless = node.attributes.filter((i) => typeof i.key?.name === "string" && !IGNORE_ATTRIBUTES.includes(i.key?.name?.toLowerCase()) && i.value == null);
184
+ if (!valueless.length)
185
+ return;
186
+ for (const node2 of valueless) {
187
+ if (!node2?.key?.name)
188
+ continue;
189
+ const blocked = syncAction("blocklist", node2.key.name, context.filename);
190
+ blocked.forEach((i) => {
191
+ context.report({
192
+ node: node2,
193
+ messageId: "in-blocklist",
194
+ data: {
195
+ name: i
196
+ }
197
+ });
198
+ });
199
+ }
200
+ }
201
+ };
202
+ if (context.parserServices == null || context.parserServices.defineTemplateBodyVisitor == null) {
203
+ return scriptVisitor;
204
+ } else {
205
+ return context.parserServices?.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor);
206
+ }
207
+ }
208
+ });
209
+
129
210
  const configsRecommended = {
130
211
  plugins: ["@unocss"],
131
212
  rules: {
@@ -137,7 +218,8 @@ const configsRecommended = {
137
218
  const index = {
138
219
  rules: {
139
220
  order,
140
- "order-attributify": orderAttributify
221
+ "order-attributify": orderAttributify,
222
+ blocklist
141
223
  },
142
224
  configs: {
143
225
  recommended: configsRecommended
@@ -31,15 +31,34 @@ async function sortRules(rules, uno) {
31
31
  return [...unknown, sorted].join(" ").trim();
32
32
  }
33
33
 
34
- async function getGenerator() {
34
+ let promise;
35
+ async function _getGenerator() {
35
36
  const { config: config$1, sources } = await config.loadConfig();
36
37
  if (!sources.length)
37
38
  throw new Error("[@unocss/eslint-plugin] No config file found, create a `uno.config.ts` file in your project root and try again.");
38
39
  return core.createGenerator(config$1);
39
40
  }
40
- let promise;
41
- synckit.runAsWorker(async (classes) => {
42
- promise = promise || getGenerator();
43
- const uno = await promise;
44
- return await sortRules(classes, uno);
45
- });
41
+ async function getGenerator() {
42
+ promise = promise || _getGenerator();
43
+ return await promise;
44
+ }
45
+ async function actionSort(classes) {
46
+ return await sortRules(classes, await getGenerator());
47
+ }
48
+ async function actionBlocklist(classes, id) {
49
+ const uno = await getGenerator();
50
+ const extracted = await uno.applyExtractors(classes, id);
51
+ return [...extracted.values()].filter((i) => uno.isBlocked(i));
52
+ }
53
+ function run(action, ...args) {
54
+ switch (action) {
55
+ case "sort":
56
+ return actionSort(...args);
57
+ case "blocklist":
58
+ return actionBlocklist(...args);
59
+ }
60
+ }
61
+ synckit.runAsWorker(run);
62
+
63
+ exports.getGenerator = getGenerator;
64
+ exports.run = run;
@@ -29,15 +29,33 @@ async function sortRules(rules, uno) {
29
29
  return [...unknown, sorted].join(" ").trim();
30
30
  }
31
31
 
32
- async function getGenerator() {
32
+ let promise;
33
+ async function _getGenerator() {
33
34
  const { config, sources } = await loadConfig();
34
35
  if (!sources.length)
35
36
  throw new Error("[@unocss/eslint-plugin] No config file found, create a `uno.config.ts` file in your project root and try again.");
36
37
  return createGenerator(config);
37
38
  }
38
- let promise;
39
- runAsWorker(async (classes) => {
40
- promise = promise || getGenerator();
41
- const uno = await promise;
42
- return await sortRules(classes, uno);
43
- });
39
+ async function getGenerator() {
40
+ promise = promise || _getGenerator();
41
+ return await promise;
42
+ }
43
+ async function actionSort(classes) {
44
+ return await sortRules(classes, await getGenerator());
45
+ }
46
+ async function actionBlocklist(classes, id) {
47
+ const uno = await getGenerator();
48
+ const extracted = await uno.applyExtractors(classes, id);
49
+ return [...extracted.values()].filter((i) => uno.isBlocked(i));
50
+ }
51
+ function run(action, ...args) {
52
+ switch (action) {
53
+ case "sort":
54
+ return actionSort(...args);
55
+ case "blocklist":
56
+ return actionBlocklist(...args);
57
+ }
58
+ }
59
+ runAsWorker(run);
60
+
61
+ export { getGenerator, run };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unocss/eslint-plugin",
3
- "version": "0.55.6",
3
+ "version": "0.56.0",
4
4
  "description": "ESLint plugin for UnoCSS",
5
5
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",
@@ -34,14 +34,14 @@
34
34
  "node": ">=14"
35
35
  },
36
36
  "dependencies": {
37
- "@typescript-eslint/utils": "^6.4.1",
37
+ "@typescript-eslint/utils": "^6.7.2",
38
38
  "magic-string": "^0.30.3",
39
39
  "synckit": "^0.8.5",
40
- "@unocss/config": "0.55.6",
41
- "@unocss/core": "0.55.6"
40
+ "@unocss/config": "0.56.0",
41
+ "@unocss/core": "0.56.0"
42
42
  },
43
43
  "devDependencies": {
44
- "@unocss/eslint-plugin": "0.55.6"
44
+ "@unocss/eslint-plugin": "0.56.0"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "unbuild",