eslint-plugin-ember-template-lint 0.1.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/LICENSE.md ADDED
@@ -0,0 +1,15 @@
1
+ ISC License (ISC)
2
+
3
+ Copyright 2017, Patrick Pircher
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
11
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # eslint-plugin-hbs-template
2
+
3
+ Provide linting for hbs templates files
4
+
5
+ ## Installation
6
+
7
+ You'll first need to install [ESLint](http://eslint.org):
8
+
9
+ ```
10
+ $ npm i eslint --save-dev
11
+ ```
12
+
13
+ Next, install `eslint-plugin-ember-template-lint`:
14
+
15
+ ```
16
+ $ npm install eslint-plugin-ember-template-lint --save-dev
17
+ ```
18
+
19
+ **Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-ember-template-lint` globally.
20
+
21
+ ## Usage
22
+
23
+ Add `hbs` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
24
+
25
+ ### 2. Modify your `.eslintrc.js`
26
+
27
+ ```js
28
+ // .eslintrc.js
29
+ // optional:
30
+ require('eslint-plugin-ember-template-lint/lib/ember-teplate-lint/config').registerPlugin('ember-template-lint-plugin-prettier');
31
+
32
+ module.exports = {
33
+ extends: [
34
+ 'eslint:recommended',
35
+ 'plugin:ember-template-lint/recommended',
36
+ //optional:
37
+ 'plugin:ember-template-lint/ember-template-lint-plugin-prettier:recommended'
38
+ ]
39
+ };
40
+ ```
41
+
42
+
43
+
44
+
package/lib/index.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @fileoverview Provide linting for hbs template literals inside of JavaScript
3
+ * @author Peter Banka
4
+ */
5
+ 'use strict';
6
+
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const configs = require('./config');
12
+ const base = require('./config/base');
13
+ const templateRules = require('./ember-teplate-lint/info');
14
+ const processor = require('./processor');
15
+
16
+ //------------------------------------------------------------------------------
17
+ // Plugin Definition
18
+ //------------------------------------------------------------------------------
19
+
20
+
21
+ module.exports = {
22
+ rules: {
23
+ ...templateRules.rules
24
+ },
25
+ configs: {
26
+ base,
27
+ ...configs
28
+ },
29
+ processors: {
30
+ 'noop': processor,
31
+ }
32
+ };
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+ const synckit = require('synckit');
3
+ const DocumentLines = require('../utils/document');
4
+
5
+ //------------------------------------------------------------------------------
6
+ // Rule Definition
7
+ //------------------------------------------------------------------------------
8
+
9
+ const runTemplateLint = (text, filename, context, scopeVars=[], offset=0, options) => {
10
+ try {
11
+ const syncFn = synckit.createSyncFn(require.resolve('./hbs-worker'));
12
+ const response = syncFn(filename, text, options);
13
+ const lintMessages = response.messages;
14
+ const diffs = response.diff;
15
+ const document = new DocumentLines(text);
16
+ diffs.forEach((d) => {
17
+ d.range = [d.offset, d.offset + d.deleteText.length];
18
+ });
19
+ lintMessages.forEach((m) => {
20
+ m.range = [
21
+ document.positionToOffset({
22
+ line: m.line - 1,
23
+ character: m.column - 1
24
+ }),
25
+ document.positionToOffset({
26
+ line: m.endLine - 1,
27
+ character: m.endColumn - 1
28
+ })];
29
+ const isInside = (d) => d.range[0] >= m.range[0] && d.range[1] <= m.range[1];
30
+ const doesContain = (d) => d.range[0] < m.range[0] && d.range[1] > m.range[1];
31
+ const idx = diffs.findIndex(d => isInside(d) || doesContain(d));
32
+ if (idx !== -1) {
33
+ const d = diffs.splice(idx, 1);
34
+ m.fix = d[0];
35
+ m.fix.range = m.fix.range.map(x => offset + x);
36
+ }
37
+ m.range = m.range.map(x => offset + x);
38
+ });
39
+
40
+ if (diffs.length) {
41
+ diffs.forEach((d) => {
42
+ const range = d.range[0];
43
+ const [start, end] = range.map(index =>
44
+ context.getSourceCode().getLocFromIndex(index)
45
+ );
46
+ context.report({
47
+ fix: (fixer) => {
48
+ return fixer.replaceTextRange(range, d.fix.insertText || '');
49
+ },
50
+ loc: { start, end },
51
+ message: 'template error',
52
+ });
53
+ });
54
+ }
55
+
56
+ lintMessages.forEach((msg) => {
57
+ if (msg.rule === 'no-implicit-this') {
58
+ if (scopeVars.includes(msg.source)) {
59
+ return;
60
+ }
61
+ }
62
+ const [start, end] = msg.range.map(index =>
63
+ context.getSourceCode().getLocFromIndex(index)
64
+ );
65
+
66
+ context.report({
67
+ rule: msg.rule,
68
+ fix: (fixer) => {
69
+ if (!msg.isFixable || !msg.fix) {
70
+ return null;
71
+ }
72
+ const range = msg.range;
73
+ return fixer.replaceTextRange(range, msg.fix.insertText || '');
74
+ },
75
+ loc: { start, end },
76
+ message: msg.message,
77
+ });
78
+ });
79
+ } catch(e) {
80
+ console.error(e);
81
+ }
82
+ };
83
+
84
+ module.exports = {
85
+ runTemplateLint
86
+ };
@@ -0,0 +1,21 @@
1
+ const { runAsWorker } = require('synckit');
2
+ const { generateDifferences } = require('prettier-linter-helpers');
3
+
4
+ runAsWorker(async (filename, text, options) => {
5
+ const Lint = await import('ember-template-lint');
6
+ const lint = new Lint.default(options);
7
+ process.env.emberTemplateLintFileName = filename;
8
+ process.env.emberTemplateLintFixMode = false;
9
+ const messages = await lint.verify({
10
+ source: text
11
+ });
12
+ process.env.emberTemplateLintFixMode = true;
13
+ const fixedText = (await lint.verifyAndFix({
14
+ source: text
15
+ })).output;
16
+ const diff = generateDifferences(text, fixedText);
17
+ return {
18
+ messages,
19
+ diff
20
+ };
21
+ });
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+ const synckit = require('synckit');
3
+ const DocumentLines = require('../utils/document');
4
+ const { templateLintConfig } = require('../ember-teplate-lint/config');
5
+
6
+ function runTemplateLint(text, filename, context, scopeVars=[], offset=0) {
7
+ try {
8
+ const syncFn = synckit.createSyncFn(require.resolve('./hbs-worker'));
9
+ const response = syncFn(filename, text, { config: templateLintConfig });
10
+ const lintMessages = response.messages;
11
+ const diffs = response.diff;
12
+ const document = new DocumentLines(text);
13
+ diffs.forEach((d) => {
14
+ d.range = [d.offset, d.offset + d.deleteText.length];
15
+ });
16
+ lintMessages.forEach((m) => {
17
+ m.range = [
18
+ document.positionToOffset({
19
+ line: m.line - 1,
20
+ character: m.column - 1
21
+ }),
22
+ document.positionToOffset({
23
+ line: m.endLine - 1,
24
+ character: m.endColumn - 1
25
+ })];
26
+ const isInside = (d) => d.range[0] >= m.range[0] && d.range[1] <= m.range[1];
27
+ const doesContain = (d) => d.range[0] <= m.range[0] && d.range[1] >= m.range[1];
28
+ const idx = diffs.findIndex(d => isInside(d) || doesContain(d));
29
+ if (idx !== -1) {
30
+ const d = diffs.splice(idx, 1);
31
+ m.fix = d[0];
32
+ m.fix.range = m.fix.range.map(x => offset + x);
33
+ }
34
+ m.range = m.range.map(x => offset + x);
35
+ });
36
+
37
+ if (diffs.length) {
38
+ diffs.forEach((d) => {
39
+ const range = d.range;
40
+ const [start, end] = range.map(index =>
41
+ context.getSourceCode().getLocFromIndex(index)
42
+ );
43
+ context.report({
44
+ fix: (fixer) => {
45
+ return fixer.replaceTextRange(range, d.fix.insertText || '');
46
+ },
47
+ loc: { start, end },
48
+ message: 'template error',
49
+ });
50
+ });
51
+ }
52
+
53
+ lintMessages.forEach((msg) => {
54
+ if (msg.rule === 'no-implicit-this') {
55
+ if (scopeVars.includes(msg.source)) {
56
+ return;
57
+ }
58
+ }
59
+ const [start, end] = msg.range.map(index =>
60
+ context.getSourceCode().getLocFromIndex(index)
61
+ );
62
+
63
+ context.report({
64
+ rule: msg.rule,
65
+ fix: (fixer) => {
66
+ if (!msg.isFixable || !msg.fix) {
67
+ return null;
68
+ }
69
+ const range = msg.range;
70
+ return fixer.replaceTextRange(range, msg.fix.insertText || '');
71
+ },
72
+ loc: { start, end },
73
+ message: msg.message,
74
+ });
75
+ });
76
+ } catch(e) {
77
+ console.error(e);
78
+ }
79
+ }
80
+
81
+ module.exports = {
82
+ runTemplateLint
83
+ };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "eslint-plugin-ember-template-lint",
3
+ "version": "0.1.0",
4
+ "description": "Provide linting for ember template",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslintplugin",
8
+ "eslint-plugin"
9
+ ],
10
+ "author": "Patrick Pircher",
11
+ "main": "lib/index.js",
12
+ "repository": "patricklx/eslint-plugin-ember-template-lint",
13
+ "scripts": {
14
+ "test": "jest",
15
+ "lint:js": "eslint --cache .",
16
+ "test:watch": "jest --watchAll"
17
+ },
18
+ "dependencies": {
19
+ "@glimmer/syntax": "^0.84.3",
20
+ "typescript": "^5.0.4",
21
+ "@typescript-eslint/parser": "^5.59.7",
22
+ "@typescript-eslint/typescript-estree": "^5.59.7",
23
+ "ember-template-imports": "^3.4.2",
24
+ "prettier-linter-helpers": "^1.0.0",
25
+ "ember-template-lint": "^5.7.3",
26
+ "synckit": "^0.8.5"
27
+ },
28
+ "peerDependencies": {
29
+ "ember-template-lint": "^5.7.3"
30
+ },
31
+ "devDependencies": {
32
+ "ember-template-lint-plugin-prettier": "^4.1.0",
33
+ "eslint": "^8.41.0",
34
+ "eslint-plugin-jest": "^27.2.1",
35
+ "eslint-plugin-node": "^11.1.0",
36
+ "jest": "^29.5.0"
37
+ },
38
+ "jest": {
39
+ "testMatch": [
40
+ "**/tests/**/*.js"
41
+ ]
42
+ },
43
+ "engines": {
44
+ "node": ">=12.0.0"
45
+ },
46
+ "license": "ISC",
47
+ "files": [
48
+ "lib/rules/*.js"
49
+ ]
50
+ }