eslint-plugin-import-template 1.0.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/README.md +22 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +117 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# eslint-plugin-import-template
|
|
2
|
+
|
|
3
|
+
An eslint plugin that checks the existence of static resources in the template, for example, checks whether the static resource files introduced in the sfc module exist.
|
|
4
|
+
|
|
5
|
+
This plugin currently only supports static resource checking of the vue-sfc template.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install eslint-plugin-import-template --save-dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
module.exports = {
|
|
17
|
+
plugins: ['import-template'],
|
|
18
|
+
rules: {
|
|
19
|
+
'import-template/vue-template-no-unresolved': 'error',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
```
|
package/dist/index.d.mts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
//#region src/index.ts
|
|
5
|
+
function isUrlOrData(v) {
|
|
6
|
+
return /^(https?:|data:|\/\/)/.test(v);
|
|
7
|
+
}
|
|
8
|
+
const plugin = { rules: { "vue-template-no-unresolved": {
|
|
9
|
+
meta: {
|
|
10
|
+
type: "problem",
|
|
11
|
+
docs: {
|
|
12
|
+
description: "检查 Vue 模板中静态 `src`/`href` 引用的文件是否存在",
|
|
13
|
+
category: "Possible Errors"
|
|
14
|
+
},
|
|
15
|
+
schema: [{
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
aliases: {
|
|
19
|
+
type: "object",
|
|
20
|
+
additionalProperties: { type: "string" }
|
|
21
|
+
},
|
|
22
|
+
extensions: {
|
|
23
|
+
type: "array",
|
|
24
|
+
items: { type: "string" }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
additionalProperties: false
|
|
28
|
+
}]
|
|
29
|
+
},
|
|
30
|
+
create(context) {
|
|
31
|
+
const options = context.options && context.options[0] || {};
|
|
32
|
+
const aliases = options.aliases || { "@/": "./src/" };
|
|
33
|
+
const extensions = options.extensions || [
|
|
34
|
+
".png",
|
|
35
|
+
".webp",
|
|
36
|
+
".jpg",
|
|
37
|
+
".jpeg",
|
|
38
|
+
".svg",
|
|
39
|
+
".gif",
|
|
40
|
+
".ico"
|
|
41
|
+
];
|
|
42
|
+
function resolveWithAliases(raw, filename) {
|
|
43
|
+
if (isUrlOrData(raw)) return null;
|
|
44
|
+
for (const a of Object.keys(aliases)) if (raw.startsWith(a)) {
|
|
45
|
+
const target = aliases[a];
|
|
46
|
+
return path.resolve(process.cwd(), target, raw.slice(a.length));
|
|
47
|
+
}
|
|
48
|
+
if (raw.startsWith(".")) {
|
|
49
|
+
if (!filename || filename === "<input>") return null;
|
|
50
|
+
return path.resolve(path.dirname(filename), raw);
|
|
51
|
+
}
|
|
52
|
+
if (raw.startsWith("/")) return path.resolve(process.cwd(), `.${raw}`);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function checkRaw(raw, nodeForReport) {
|
|
56
|
+
if (!raw || typeof raw !== "string") return;
|
|
57
|
+
const resolved = resolveWithAliases(raw, context.getFilename());
|
|
58
|
+
if (!resolved) return;
|
|
59
|
+
if (path.extname(resolved)) {
|
|
60
|
+
if (!fs.existsSync(resolved)) context.report({
|
|
61
|
+
node: nodeForReport,
|
|
62
|
+
message: `Asset not found: ${raw}`
|
|
63
|
+
});
|
|
64
|
+
} else {
|
|
65
|
+
let found = false;
|
|
66
|
+
for (const e of extensions) if (fs.existsSync(resolved + e)) {
|
|
67
|
+
found = true;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
if (!found) context.report({
|
|
71
|
+
node: nodeForReport,
|
|
72
|
+
message: `Asset not found (tried ${extensions.join(", ")}): ${raw}`
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function traverseTemplateBody(templateBody) {
|
|
77
|
+
if (!templateBody || !templateBody.children) return;
|
|
78
|
+
const stack = [...templateBody.children];
|
|
79
|
+
while (stack.length) {
|
|
80
|
+
const n = stack.shift();
|
|
81
|
+
if (!n) continue;
|
|
82
|
+
if (n.type === "VElement" && n.startTag && Array.isArray(n.startTag.attributes)) for (const attr of n.startTag.attributes) {
|
|
83
|
+
if (!attr) continue;
|
|
84
|
+
if (attr.type === "VAttribute") {
|
|
85
|
+
const name = attr.key && attr.key.name;
|
|
86
|
+
if (name === "src" || name === "href") {
|
|
87
|
+
if (attr.value && attr.value.type === "VLiteral") checkRaw(attr.value.value, attr);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (n.children && n.children.length) stack.push(...n.children);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
VAttribute(node) {
|
|
96
|
+
const key = node.key && (node.key.name || node.key.argument && node.key.argument.name);
|
|
97
|
+
if (!key) return;
|
|
98
|
+
if (key !== "src" && key !== "href") return;
|
|
99
|
+
if (!node.value || node.value.type !== "VLiteral") return;
|
|
100
|
+
const raw = node.value.value;
|
|
101
|
+
checkRaw(raw, node);
|
|
102
|
+
},
|
|
103
|
+
"Program:exit"() {
|
|
104
|
+
try {
|
|
105
|
+
const ast = context.getSourceCode().ast;
|
|
106
|
+
if (ast && ast.templateBody) traverseTemplateBody(ast.templateBody);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error("local/check-vue-asset-exists error:", err && err.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
} } };
|
|
114
|
+
var src_default = plugin;
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
export { src_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-import-template",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "A starter for creating a TypeScript package.",
|
|
6
|
+
"author": "TRIS-H <2218975525@qq.com>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/TRIS-H/eslint-plugin-import-template#readme",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/TRIS-H/eslint-plugin-import-template/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/TRIS-H/eslint-plugin-import-template"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"eslint",
|
|
18
|
+
"eslintplugin",
|
|
19
|
+
"eslint-plugin",
|
|
20
|
+
"es6",
|
|
21
|
+
"jsnext",
|
|
22
|
+
"modules",
|
|
23
|
+
"assets",
|
|
24
|
+
"import",
|
|
25
|
+
"export"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./dist/index.mjs",
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.mjs",
|
|
32
|
+
"module": "./dist/index.mjs",
|
|
33
|
+
"types": "./dist/index.d.mts",
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsdown",
|
|
39
|
+
"dev": "tsdown --watch",
|
|
40
|
+
"test": "vitest",
|
|
41
|
+
"typecheck": "tsc --noEmit",
|
|
42
|
+
"prepublishOnly": "pnpm run build"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^25.0.3",
|
|
46
|
+
"bumpp": "^10.3.2",
|
|
47
|
+
"tsdown": "^0.18.1",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vitest": "^4.0.16"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"vue-eslint-parser": "^10.1.4"
|
|
53
|
+
}
|
|
54
|
+
}
|