eslint-plugin-ember-template-lint 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -57,14 +57,24 @@ require('eslint-plugin-ember-template-lint/lib/ember-teplate-lint/config').regis
57
57
 
58
58
 
59
59
  module.exports = {
60
- extends: [
61
- 'eslint:recommended',
62
- 'plugin:@typescript-eslint/base',
63
- 'plugin:ember-template-lint/config',
64
- 'plugin:ember-template-lint/recommended',
65
- //optional:
66
- 'plugin:ember-template-lint/ember-template-lint-plugin-prettier:recommended'
67
- ]
60
+ overrides: [
61
+ {
62
+ files: ['**/*.hbs'],
63
+ parser: 'ember-template-lint/lib/parser/hbs-parser',
64
+ extends: [
65
+ 'plugin:ember-template-lint/config',
66
+ 'plugin:ember-template-lint/recommended',
67
+ ],
68
+ },
69
+ {
70
+ files: ['**/*.gjs'],
71
+ parser: 'ember-eslint-parser',
72
+ extends: [
73
+ 'plugin:ember-template-lint/config',
74
+ 'plugin:ember-template-lint/recommended',
75
+ ],
76
+ },
77
+ ],
68
78
  };
69
79
  ```
70
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-ember-template-lint",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Provide linting for ember template",
5
5
  "keywords": [
6
6
  "eslint",
@@ -19,18 +19,18 @@
19
19
  "@glimmer/syntax": "^0.84.3",
20
20
  "@typescript-eslint/parser": "^5.59.7",
21
21
  "@typescript-eslint/typescript-estree": "^5.59.7",
22
- "ember-template-imports": "^3.4.2",
23
- "ember-template-lint": "^5.7.3",
24
- "ember-template-recast": "^6.1.4",
22
+ "ember-eslint-parser": "^0.5.6",
23
+ "ember-template-recast": "^6.1.5",
24
+ "ember-template-lint": "^6.0.0",
25
25
  "prettier-linter-helpers": "^1.0.0",
26
26
  "synckit": "^0.8.5",
27
27
  "typescript": "^5.0.4"
28
28
  },
29
29
  "peerDependencies": {
30
- "ember-template-lint": "^5.7.3"
30
+ "ember-template-lint": "^6.0.0"
31
31
  },
32
32
  "devDependencies": {
33
- "ember-template-lint-plugin-prettier": "^4.1.0",
33
+ "ember-template-lint-plugin-prettier": "^5.0.0",
34
34
  "eslint": "^8.41.0",
35
35
  "eslint-plugin-jest": "^27.2.1",
36
36
  "eslint-plugin-node": "^11.1.0",
@@ -46,6 +46,6 @@
46
46
  },
47
47
  "license": "ISC",
48
48
  "files": [
49
- "lib/**/*.js"
49
+ "lib/rules/*.js"
50
50
  ]
51
51
  }
@@ -1,20 +0,0 @@
1
- module.exports = {
2
- root: true,
3
-
4
- plugins: ['ember-template-lint'],
5
-
6
- rules: {},
7
-
8
- overrides: [
9
- {
10
- files: ['**/*.hbs'],
11
- parser: require.resolve('../parser/hbs-parser'),
12
- processor: 'ember-template-lint/noop'
13
- },
14
- {
15
- files: ['**/*.gts', '**/*.gjs'],
16
- parser: require.resolve('../parser/gts-parser'),
17
- processor: 'ember-template-lint/noop'
18
- },
19
- ],
20
- };
@@ -1,20 +0,0 @@
1
- const info = require('../ember-teplate-lint/info');
2
- const base = require('./base');
3
-
4
- const configs = {};
5
-
6
- Object.entries(info.configs).forEach(([name, config]) => {
7
- Object.entries(config.rules).forEach(([name, conf]) => {
8
- if (typeof conf == 'boolean') {
9
- config.rules[name] = [conf ? 'error' : 'off'];
10
- }
11
- });
12
- configs[name] = {...base, rules: config.rules};
13
- });
14
- configs['config'] = {
15
- ...base,
16
- rules: info.configuredRules
17
- };
18
-
19
- module.exports = configs;
20
-
@@ -1,18 +0,0 @@
1
- const templateLintConfig = {
2
- rules: {},
3
- plugins: [],
4
- };
5
-
6
- function registerRule(name, config) {
7
- templateLintConfig.rules[name] = Array.isArray(config) ? config[0] : config;
8
- }
9
-
10
- function registerPlugin(name) {
11
- templateLintConfig.plugins.push(name);
12
- }
13
-
14
- module.exports = {
15
- registerRule,
16
- registerPlugin,
17
- templateLintConfig
18
- };
@@ -1,106 +0,0 @@
1
- const synckit = require('synckit');
2
- const syncFn = synckit.createSyncFn(require.resolve('./worker'));
3
- const { runTemplateLint } = require('../rules/lint');
4
- const { registerRule, templateLintConfig } = require('../ember-teplate-lint/config');
5
-
6
- const lintWithEslintConfigs = syncFn({ config: templateLintConfig });
7
- const lintConfigs = syncFn();
8
-
9
- const activeRules = new Map();
10
- const allMessages = {};
11
-
12
- const reporter = {
13
- setup(context) {
14
- this.getSourceCode = context.getSourceCode;
15
- this.getPhysicalFilename = context.getPhysicalFilename;
16
- },
17
- report(message) {
18
- message.meta = {
19
- fixable: 'code'
20
- };
21
- allMessages[message.rule] = allMessages[message.rule] || [];
22
- allMessages[message.rule].push(message);
23
- }
24
- };
25
-
26
- class Rule {
27
-
28
- constructor(name) {
29
- this.create = this.create.bind(this);
30
- this.name = name;
31
- this.meta = {
32
- fixable: 'code'
33
- };
34
- }
35
- create(context) {
36
- const rule = this;
37
- let options = context.options;
38
- if (options.length === 0) {
39
- options = true;
40
- }
41
- registerRule(this.name, options);
42
- const visitor = {
43
- enter(node) {
44
- if (!activeRules.get(node)) {
45
- activeRules.set(node, 0);
46
- reporter.setup(context);
47
- runTemplateLint(node, reporter);
48
- }
49
- activeRules.set(node, activeRules.get(node) + 1);
50
- },
51
- exit(node) {
52
- const messages = allMessages[rule.name] || [];
53
- messages.forEach(m => context.report(m));
54
- activeRules.set(node, activeRules.get(node) - 1);
55
- allMessages[rule.name] = [];
56
- },
57
- };
58
- return {
59
- 'Program': (node) => node.isHbs && visitor.enter(node),
60
- 'Program:exit': (node) => node.isHbs && visitor.exit(node),
61
- '__TEMPLATE__Template': visitor.enter,
62
- '__TEMPLATE__Template:exit': visitor.exit,
63
- };
64
- }
65
- }
66
-
67
- function createRules(rules) {
68
- const created = rules.map(r => new Rule(r));
69
- const map = {};
70
- created.forEach(r => {
71
- map[r.name] = r;
72
- });
73
- return map;
74
- }
75
-
76
- const configs = {
77
- ...lintWithEslintConfigs.configs,
78
- ...lintConfigs.configs
79
- };
80
-
81
- const rules = [...new Set([...lintConfigs.rules, ...lintWithEslintConfigs.rules])];
82
-
83
- delete configs.recommended.overrides;
84
-
85
- Object.values(configs).forEach((config) => {
86
- const rules = {};
87
- Object.entries(config.rules).forEach(([rule, conf]) => {
88
- rules['ember-template-lint/' + rule] = conf;
89
- });
90
- config.rules = rules;
91
- });
92
-
93
-
94
- const configuredRules = {};
95
- Object.entries(lintConfigs.configuredRules).forEach(([name, conf]) => {
96
- configuredRules['ember-template-lint/' + name] = conf.config && [conf.severity];
97
- if (typeof conf.config !== 'boolean') {
98
- configuredRules['ember-template-lint/' + name].push(conf.config);
99
- }
100
- });
101
-
102
- module.exports = {
103
- configs: configs,
104
- rules: createRules(rules),
105
- configuredRules: configuredRules
106
- };
@@ -1,12 +0,0 @@
1
- const { runAsWorker } = require('synckit');
2
-
3
- runAsWorker(async (options) => {
4
- const Lint = await import('ember-template-lint');
5
- const lint = new Lint.default(options);
6
- await lint.loadConfig();
7
- return {
8
- configs: lint.config.loadedConfigurations,
9
- rules: Object.keys(lint.config.loadedRules),
10
- configuredRules: lint.config.rules,
11
- };
12
- });
@@ -1,57 +0,0 @@
1
- const gts = require('ember-template-imports');
2
- const typescriptParser = require('@typescript-eslint/parser');
3
- const typescriptEstree = require('@typescript-eslint/typescript-estree');
4
-
5
-
6
- function replaceRange(s, start, end, substitute) {
7
- return s.substring(0, start) + substitute + s.substring(end);
8
- }
9
-
10
- module.exports = {
11
- parseForESLint(code, options) {
12
- let jsCode = code;
13
- const templateInfos = gts.parseTemplates(jsCode, options.filePath);
14
- templateInfos.forEach((tpl) => {
15
- const range = [tpl.start.index, tpl.end.index + tpl.end[0].length];
16
- tpl.range = range;
17
- const template = jsCode.slice(...range);
18
- const lines = template.split('\n');
19
- lines.forEach((line, i) => {
20
- lines[i] = ' '.repeat(line.length);
21
- });
22
- const emptyText = '[`' + lines.join('\n').slice(4) + '`]';
23
- jsCode = replaceRange(jsCode, ...range, emptyText);
24
- const ast = {
25
- type: '__TEMPLATE__Template',
26
- };
27
- ast.range = range;
28
- ast.contents = template;
29
- tpl.ast = ast;
30
- });
31
- const result = typescriptParser.parseForESLint(jsCode, options);
32
- const visitorKeys = {...result.visitorKeys, '__TEMPLATE__Template': []};
33
- result.ast.tokens.forEach((token) => {
34
- if (token.type === 'Template') {
35
- const range = [token.range[0] - 1, token.range[1] + 1];
36
- const template = templateInfos.find(t => t.range[0] >= range[0] && t.range[1] <= range[1]);
37
- if (!template) return;
38
- const ast = template.ast;
39
- ast.loc = token.loc;
40
- Object.assign(token, ast);
41
- }
42
- });
43
- typescriptEstree.simpleTraverse(result.ast, {
44
- enter(node) {
45
- if (node.type === 'TemplateLiteral') {
46
- const range = [node.range[0] - 1, node.range[1] + 1];
47
- const template = templateInfos.find(t => t.range[0] >= range[0] && t.range[1] <= range[1]);
48
- if (!template) return;
49
- const ast = template.ast;
50
- Object.assign(node, ast);
51
- }
52
- }
53
- });
54
-
55
- return { ...result, visitorKeys };
56
- }
57
- };
@@ -1,57 +0,0 @@
1
-
2
- class Scope {
3
- type = 'global';
4
- variables = [];
5
- through= [];
6
- set = new Map();
7
- upper = null;
8
- childScopes = [];
9
- references = [];
10
- block = null;
11
- }
12
-
13
- class ScopeManager {
14
- globalScope = new Scope();
15
- scopes = [this.globalScope];
16
-
17
- acquire() {
18
- return;
19
- }
20
-
21
- getDeclaredVariables() {
22
- return [];
23
- }
24
- }
25
-
26
- module.exports = {
27
- parseForESLint(code) {
28
- const comments = [];
29
- const types = new Set(['Program']);
30
- const ast = {};
31
- ast.body = [];
32
- ast.tokens = [ast];
33
- ast.range = [0, code.length];
34
- const lines = code.split('\n');
35
- ast.loc = {
36
- start: {
37
- line: 1,
38
- column: 1
39
- },
40
- end: {
41
- line: lines.length,
42
- column: lines[lines.length - 1].length
43
- }
44
- };
45
- ast.comments = comments;
46
- const visitorKeys = {};
47
- types.forEach((t) => {
48
- visitorKeys[t] = [];
49
- });
50
- ast.type = 'Program';
51
- ast.isHbs = true;
52
- ast.contents = code;
53
- const scope = new ScopeManager();
54
- scope.globalScope.block = ast;
55
- return { ast, scopeManager: scope, visitorKeys };
56
- }
57
- };
package/lib/processor.js DELETED
@@ -1,11 +0,0 @@
1
-
2
-
3
- module.exports = {
4
- preprocess: (text, filename) => {
5
- return [{text: text, filename}];
6
- },
7
- postprocess: (messages) => {
8
- return messages.flat();
9
- },
10
- supportsAutofix: true
11
- };
@@ -1,100 +0,0 @@
1
- /**
2
- * @typedef {{ line: number; character: number }} Position
3
- */
4
-
5
- // Helper class to convert line/column from and to offset
6
- // taken and adapt from https://github.com/typed-ember/glint/blob/main/packages/core/src/language-server/util/position.ts
7
- class DocumentLines {
8
- /**
9
- * @param {string} contents
10
- */
11
- constructor(contents) {
12
- this.lineStarts = computeLineStarts(contents);
13
- }
14
-
15
- /**
16
- * @param {Position} position
17
- * @return {number}
18
- */
19
- positionToOffset(position) {
20
- const { line, character } = position;
21
- return this.lineStarts[line] + character;
22
- }
23
-
24
- /**
25
- *
26
- * @param {number} position
27
- * @return {Position}
28
- */
29
- offsetToPosition(position) {
30
- const lineStarts = this.lineStarts;
31
- let line = 0;
32
- while (line + 1 < lineStarts.length && lineStarts[line + 1] <= position) {
33
- line++;
34
- }
35
- const character = position - lineStarts[line];
36
- return { line, character };
37
- }
38
- }
39
-
40
- /**
41
- * @returns {number[]}
42
- * @param {string} text
43
- */
44
- function computeLineStarts(text) {
45
- const result = [];
46
- let pos = 0;
47
- let lineStart = 0;
48
- while (pos < text.length) {
49
- const ch = text.codePointAt(pos);
50
- pos++;
51
- switch (ch) {
52
- case 13 /* carriageReturn */: {
53
- if (text.codePointAt(pos) === 10 /* lineFeed */) {
54
- pos++;
55
- }
56
- }
57
- // falls through
58
- case 10 /* lineFeed */: {
59
- result.push(lineStart);
60
- lineStart = pos;
61
- break;
62
- }
63
- default: {
64
- if (ch > 127 /* maxAsciiCharacter */ && isLineBreak(ch)) {
65
- result.push(lineStart);
66
- lineStart = pos;
67
- }
68
- break;
69
- }
70
- }
71
- }
72
- result.push(lineStart);
73
- return result;
74
- }
75
-
76
- /* istanbul ignore next */
77
- /**
78
- * @param {number} ch
79
- * @return {boolean}
80
- */
81
- function isLineBreak(ch) {
82
- // ES5 7.3:
83
- // The ECMAScript line terminator characters are listed in Table 3.
84
- // Table 3: Line Terminator Characters
85
- // Code Unit Value Name Formal Name
86
- // \u000A Line Feed <LF>
87
- // \u000D Carriage Return <CR>
88
- // \u2028 Line separator <LS>
89
- // \u2029 Paragraph separator <PS>
90
- // Only the characters in Table 3 are treated as line terminators. Other new line or line
91
- // breaking characters are treated as white space but not as line terminators.
92
- return (
93
- ch === 10 /* lineFeed */ ||
94
- ch === 13 /* carriageReturn */ ||
95
- ch === 8232 /* lineSeparator */ ||
96
- ch === 8233 /* paragraphSeparator */
97
- );
98
- }
99
-
100
- module.exports = DocumentLines;