@shuvi/eslint-plugin-shuvi 1.0.23 → 1.0.25

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/lib/index.js CHANGED
@@ -3,15 +3,19 @@ module.exports = {
3
3
  rules: {
4
4
  'no-head-element': require('./rules/no-head-element').default,
5
5
  'no-html-link-for-pages': require('./rules/no-html-link-for-pages').default,
6
- 'no-typos': require('./rules/no-typos').default
6
+ 'no-typos-page': require('./rules/no-typos-page').default,
7
+ 'no-typos-custom-app': require('./rules/no-typos-custom-app').default,
8
+ 'no-typos-custom-server': require('./rules/no-typos-custom-server').default
7
9
  },
8
10
  configs: {
9
11
  recommended: {
10
12
  rules: {
11
13
  // warnings
12
14
  '@shuvi/shuvi/no-head-element': 'warn',
13
- '@shuvi/shuvi/no-typos': 'error',
14
15
  // errors
16
+ '@shuvi/shuvi/no-typos-page': 'error',
17
+ '@shuvi/shuvi/no-typos-custom-app': 'error',
18
+ '@shuvi/shuvi/no-typos-custom-server': 'error',
15
19
  '@shuvi/shuvi/no-html-link-for-pages': 'error'
16
20
  }
17
21
  }
@@ -1,2 +1,3 @@
1
+ export const url: "https://shuvijs.github.io/shuvijs.org/docs/guides/rules/no-html-link-for-pages";
1
2
  declare const _default: import("eslint").Rule.RuleModule;
2
3
  export default _default;
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.url = void 0;
3
4
  const define_rule_1 = require("../utils/define-rule");
5
+ exports.url = 'https://shuvijs.github.io/shuvijs.org/docs/guides/rules/no-html-link-for-pages';
4
6
  exports.default = (0, define_rule_1.defineRule)({
5
7
  meta: {
6
8
  docs: {
7
9
  description: 'Prevent usage of `<head>` element.',
8
10
  category: 'HTML',
9
- recommended: true
11
+ recommended: true,
12
+ url: exports.url
10
13
  },
11
14
  type: 'problem',
12
15
  schema: []
@@ -24,7 +27,7 @@ exports.default = (0, define_rule_1.defineRule)({
24
27
  }
25
28
  context.report({
26
29
  node,
27
- message: `Do not use \`<head>\` element. Use \`<Head />\` from \`shuvi/runtime\` instead.`
30
+ message: `Do not use \`<head>\` element. Use \`<Head />\` from \`shuvi/runtime\` instead. See: ${exports.url}`
28
31
  });
29
32
  }
30
33
  };
@@ -1,2 +1,3 @@
1
+ export const url: "https://shuvijs.github.io/shuvijs.org/docs/guides/rules/no-html-link-for-pages";
1
2
  declare const _default: import("eslint").Rule.RuleModule;
2
3
  export default _default;
@@ -23,6 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.url = void 0;
26
27
  const define_rule_1 = require("../utils/define-rule");
27
28
  const path = __importStar(require("path"));
28
29
  const fs = __importStar(require("fs"));
@@ -35,12 +36,14 @@ const pagesDirWarning = (0, url_1.execOnce)(pagesDirs => {
35
36
  // Cache for fs.existsSync lookup.
36
37
  // Prevent multiple blocking IO requests that have already been calculated.
37
38
  const fsExistsSyncCache = {};
39
+ exports.url = 'https://shuvijs.github.io/shuvijs.org/docs/guides/rules/no-html-link-for-pages';
38
40
  exports.default = (0, define_rule_1.defineRule)({
39
41
  meta: {
40
42
  docs: {
41
43
  description: 'Prevent usage of `<a>` elements to navigate to internal Shuvi.js pages.',
42
44
  category: 'HTML',
43
- recommended: true
45
+ recommended: true,
46
+ url: exports.url
44
47
  },
45
48
  type: 'problem',
46
49
  schema: [
@@ -115,7 +118,7 @@ exports.default = (0, define_rule_1.defineRule)({
115
118
  if (match) {
116
119
  context.report({
117
120
  node,
118
- message: `Do not use an \`<a>\` element to navigate to \`${hrefPath}\`. Use \`<Link />\` from \`shuvi/runtime\` instead.`
121
+ message: `Do not use an \`<a>\` element to navigate to \`${hrefPath}\`. Use \`<Link />\` from \`shuvi/runtime\` instead. See: ${exports.url}`
119
122
  });
120
123
  }
121
124
  }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const define_rule_1 = require("../utils/define-rule");
4
+ const url_1 = require("../utils/url");
5
+ const EXPORT_FUNCTIONS = ['init', 'appContext', 'appComponent', 'dispose'];
6
+ const FILEREG = /src\/app\.(j|t)s?$/;
7
+ exports.default = (0, define_rule_1.defineRule)({
8
+ meta: {
9
+ docs: {
10
+ description: 'Prevent common typos in custom app.',
11
+ recommended: true
12
+ },
13
+ type: 'problem',
14
+ schema: []
15
+ },
16
+ create(context) {
17
+ function checkTypos(node, name) {
18
+ if (EXPORT_FUNCTIONS.includes(name)) {
19
+ return;
20
+ }
21
+ const potentialTypos = EXPORT_FUNCTIONS.map(o => ({
22
+ option: o,
23
+ distance: (0, url_1.minDistance)(o, name)
24
+ }))
25
+ .filter(({ distance }) => distance <= url_1.THRESHOLD && distance > 0)
26
+ .sort((a, b) => a.distance - b.distance);
27
+ if (potentialTypos.length) {
28
+ context.report({
29
+ node,
30
+ message: `${name} may be a typo. Did you mean ${potentialTypos[0].option}?`
31
+ });
32
+ }
33
+ }
34
+ return {
35
+ ExportNamedDeclaration(node) {
36
+ var _a;
37
+ const fileName = context.getFilename();
38
+ if (!fileName || !FILEREG.test(fileName)) {
39
+ return;
40
+ }
41
+ const decl = node.declaration;
42
+ if (!decl) {
43
+ return;
44
+ }
45
+ switch (decl.type) {
46
+ case 'FunctionDeclaration': {
47
+ checkTypos(node, (_a = decl.id) === null || _a === void 0 ? void 0 : _a.name);
48
+ break;
49
+ }
50
+ case 'VariableDeclaration': {
51
+ decl.declarations.forEach(d => {
52
+ if (d.id.type !== 'Identifier') {
53
+ return;
54
+ }
55
+ checkTypos(node, d.id.name);
56
+ });
57
+ break;
58
+ }
59
+ default: {
60
+ break;
61
+ }
62
+ }
63
+ return;
64
+ }
65
+ };
66
+ }
67
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const define_rule_1 = require("../utils/define-rule");
4
+ const url_1 = require("../utils/url");
5
+ const EXPORT_FUNCTIONS = [
6
+ 'getPageData',
7
+ 'handlePageRequest',
8
+ 'modifyHtml',
9
+ 'sendHtml'
10
+ ];
11
+ const FILEREG = /src\/server\.(j|t)s?$/;
12
+ exports.default = (0, define_rule_1.defineRule)({
13
+ meta: {
14
+ docs: {
15
+ description: 'Prevent common typos in custom server',
16
+ recommended: true
17
+ },
18
+ type: 'problem',
19
+ schema: []
20
+ },
21
+ create(context) {
22
+ function checkTypos(node, name) {
23
+ if (EXPORT_FUNCTIONS.includes(name)) {
24
+ return;
25
+ }
26
+ const potentialTypos = EXPORT_FUNCTIONS.map(o => ({
27
+ option: o,
28
+ distance: (0, url_1.minDistance)(o, name)
29
+ }))
30
+ .filter(({ distance }) => distance <= url_1.THRESHOLD && distance > 0)
31
+ .sort((a, b) => a.distance - b.distance);
32
+ if (potentialTypos.length) {
33
+ context.report({
34
+ node,
35
+ message: `${name} may be a typo. Did you mean ${potentialTypos[0].option}?`
36
+ });
37
+ }
38
+ }
39
+ return {
40
+ ExportNamedDeclaration(node) {
41
+ var _a;
42
+ const fileName = context.getFilename();
43
+ if (!fileName || !FILEREG.test(fileName)) {
44
+ return;
45
+ }
46
+ const decl = node.declaration;
47
+ if (!decl) {
48
+ return;
49
+ }
50
+ switch (decl.type) {
51
+ case 'FunctionDeclaration': {
52
+ checkTypos(node, (_a = decl.id) === null || _a === void 0 ? void 0 : _a.name);
53
+ break;
54
+ }
55
+ case 'VariableDeclaration': {
56
+ decl.declarations.forEach(d => {
57
+ if (d.id.type !== 'Identifier') {
58
+ return;
59
+ }
60
+ checkTypos(node, d.id.name);
61
+ });
62
+ break;
63
+ }
64
+ default: {
65
+ break;
66
+ }
67
+ }
68
+ return;
69
+ }
70
+ };
71
+ }
72
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("eslint").Rule.RuleModule;
2
+ export default _default;
@@ -1,36 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const define_rule_1 = require("../utils/define-rule");
4
+ const url_1 = require("../utils/url");
4
5
  const EXPORT_FUNCTIONS = ['loader'];
5
6
  const PAGEREG = /routes\/.*page\.(j|t)sx?$/;
6
- // 0 is the exact match
7
- const THRESHOLD = 1;
8
- // the minimum number of operations required to convert string a to string b.
9
- function minDistance(a, b) {
10
- const m = a.length;
11
- const n = b.length;
12
- if (m < n) {
13
- return minDistance(b, a);
14
- }
15
- if (n === 0) {
16
- return m;
17
- }
18
- let previousRow = Array.from({ length: n + 1 }, (_, i) => i);
19
- for (let i = 0; i < m; i++) {
20
- const s1 = a[i];
21
- let currentRow = [i + 1];
22
- for (let j = 0; j < n; j++) {
23
- const s2 = b[j];
24
- const insertions = previousRow[j + 1] + 1;
25
- const deletions = currentRow[j] + 1;
26
- const substitutions = previousRow[j] + Number(s1 !== s2);
27
- currentRow.push(Math.min(insertions, deletions, substitutions));
28
- }
29
- previousRow = currentRow;
30
- }
31
- return previousRow[previousRow.length - 1];
32
- }
33
- /* eslint-disable eslint-plugin/require-meta-docs-url */
34
7
  exports.default = (0, define_rule_1.defineRule)({
35
8
  meta: {
36
9
  docs: {
@@ -47,9 +20,9 @@ exports.default = (0, define_rule_1.defineRule)({
47
20
  }
48
21
  const potentialTypos = EXPORT_FUNCTIONS.map(o => ({
49
22
  option: o,
50
- distance: minDistance(o, name)
23
+ distance: (0, url_1.minDistance)(o, name)
51
24
  }))
52
- .filter(({ distance }) => distance <= THRESHOLD && distance > 0)
25
+ .filter(({ distance }) => distance <= url_1.THRESHOLD && distance > 0)
53
26
  .sort((a, b) => a.distance - b.distance);
54
27
  if (potentialTypos.length) {
55
28
  context.report({
@@ -12,3 +12,5 @@ export declare function getUrlFromPagesDirectories(urlPrefix: string, directorie
12
12
  path: string;
13
13
  }[];
14
14
  export declare function execOnce<TArgs extends any[], TResult extends unknown>(fn: (...args: TArgs) => TResult): (...args: TArgs) => TResult;
15
+ export declare const THRESHOLD = 1;
16
+ export declare function minDistance(a: string, b: string): number;
package/lib/utils/url.js CHANGED
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.execOnce = exports.getUrlFromPagesDirectories = exports.normalizeURL = void 0;
26
+ exports.minDistance = exports.THRESHOLD = exports.execOnce = exports.getUrlFromPagesDirectories = exports.normalizeURL = void 0;
27
27
  const path = __importStar(require("path"));
28
28
  const fs = __importStar(require("fs"));
29
29
  const helpers_1 = require("@shuvi/platform-shared/node/route/helpers");
@@ -124,3 +124,31 @@ function execOnce(fn) {
124
124
  };
125
125
  }
126
126
  exports.execOnce = execOnce;
127
+ // 0 is the exact match
128
+ exports.THRESHOLD = 1;
129
+ // the minimum number of operations required to convert string a to string b.
130
+ function minDistance(a, b) {
131
+ const m = a.length;
132
+ const n = b.length;
133
+ if (m < n) {
134
+ return minDistance(b, a);
135
+ }
136
+ if (n === 0) {
137
+ return m;
138
+ }
139
+ let previousRow = Array.from({ length: n + 1 }, (_, i) => i);
140
+ for (let i = 0; i < m; i++) {
141
+ const s1 = a[i];
142
+ let currentRow = [i + 1];
143
+ for (let j = 0; j < n; j++) {
144
+ const s2 = b[j];
145
+ const insertions = previousRow[j + 1] + 1;
146
+ const deletions = currentRow[j] + 1;
147
+ const substitutions = previousRow[j] + Number(s1 !== s2);
148
+ currentRow.push(Math.min(insertions, deletions, substitutions));
149
+ }
150
+ previousRow = currentRow;
151
+ }
152
+ return previousRow[previousRow.length - 1];
153
+ }
154
+ exports.minDistance = minDistance;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuvi/eslint-plugin-shuvi",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "ESLint plugin for Shuvi.",
5
5
  "main": "lib/index.js",
6
6
  "license": "MIT",
@@ -18,8 +18,8 @@
18
18
  "build": "tsc -p tsconfig.json"
19
19
  },
20
20
  "dependencies": {
21
- "@shuvi/router": "1.0.23",
22
- "@shuvi/platform-shared": "1.0.23"
21
+ "@shuvi/router": "1.0.25",
22
+ "@shuvi/platform-shared": "1.0.25"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/eslint": "7.28.0",