isml-linter 5.39.4 → 5.40.2
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/.gitattributes +1 -0
- package/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/src/isml_tree/IsmlNode.js +8 -0
- package/src/isml_tree/ParseUtils.js +20 -2
- package/src/rules/prototypes/TreeRulePrototype.js +1 -1
- package/src/rules/tree/indent.js +3 -0
- package/src/rules/tree/one-element-per-line.js +41 -35
- package/src/util/ExceptionUtils.js +24 -0
package/.gitattributes
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bin/isml-linter.js text eol=lf
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
## [5.40.2] - 2022-09-05
|
|
5
|
+
|
|
6
|
+
### Fixed
|
|
7
|
+
- [Issue #35][issue#35] - Set bin file linebreak to LF;
|
|
8
|
+
|
|
9
|
+
## [5.40.1] - 2022-09-01
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- HTML-element embedded `<isif>` condition scenario;
|
|
13
|
+
- Added mechanism to prevent infinite loops in case of unexpected errors;
|
|
14
|
+
|
|
15
|
+
## [5.40.0] - 2022-02-05
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- "one-element-per-line" rule autofix;
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- Small "indent" rule issue;
|
|
22
|
+
- Tree build edge case;
|
|
23
|
+
|
|
3
24
|
## [5.39.4] - 2022-01-30
|
|
4
25
|
|
|
5
26
|
### Fixed
|
|
@@ -1002,6 +1023,9 @@
|
|
|
1002
1023
|
### Added
|
|
1003
1024
|
- Linter is published;
|
|
1004
1025
|
|
|
1026
|
+
[5.40.2]: https://github.com/FabiowQuixada/isml-linter/compare/v5.40.1...v5.40.2
|
|
1027
|
+
[5.40.1]: https://github.com/FabiowQuixada/isml-linter/compare/v5.40.0...v5.40.1
|
|
1028
|
+
[5.40.0]: https://github.com/FabiowQuixada/isml-linter/compare/v5.39.4...v5.40.0
|
|
1005
1029
|
[5.39.4]: https://github.com/FabiowQuixada/isml-linter/compare/v5.39.3...v5.39.4
|
|
1006
1030
|
[5.39.3]: https://github.com/FabiowQuixada/isml-linter/compare/v5.39.2...v5.39.3
|
|
1007
1031
|
[5.39.2]: https://github.com/FabiowQuixada/isml-linter/compare/v5.39.1...v5.39.2
|
|
@@ -1152,6 +1176,7 @@
|
|
|
1152
1176
|
[issue#29]: https://github.com/FabiowQuixada/isml-linter/issues/29
|
|
1153
1177
|
[issue#30]: https://github.com/FabiowQuixada/isml-linter/issues/30
|
|
1154
1178
|
[issue#31]: https://github.com/FabiowQuixada/isml-linter/issues/31
|
|
1179
|
+
[issue#35]: https://github.com/FabiowQuixada/isml-linter/issues/35
|
|
1155
1180
|
|
|
1156
1181
|
[cli-docs]: <docs/cli.md>
|
|
1157
1182
|
[api-docs]: <docs/api.md>
|
package/package.json
CHANGED
|
@@ -251,6 +251,14 @@ class IsmlNode {
|
|
|
251
251
|
return this.parent && this.parent.isIsmlComment();
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
isHardCodedText() {
|
|
255
|
+
return !this.isRoot()
|
|
256
|
+
&& !this.isContainer()
|
|
257
|
+
&& !this.isConditionalComment()
|
|
258
|
+
&& !this.isTag()
|
|
259
|
+
&& !this.isExpression();
|
|
260
|
+
}
|
|
261
|
+
|
|
254
262
|
getPreviousSibling() {
|
|
255
263
|
if (!this.parent || !this.parent.isContainer() && this.isFirstChild() || this.parent.isContainer() && this.parent.isFirstChild() && this.isFirstChild()) {
|
|
256
264
|
return null;
|
|
@@ -132,6 +132,15 @@ const parseNextElement = state => {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
state.elementList.push(newElement);
|
|
135
|
+
|
|
136
|
+
if (newElement.type === 'htmlTag' && newElement.value.indexOf('<isif') >= 0 && newElement.value.indexOf('</isif') < 0) {
|
|
137
|
+
throw ExceptionUtils.invalidNestedIsifError(
|
|
138
|
+
newElement.tagType,
|
|
139
|
+
newElement.lineNumber,
|
|
140
|
+
newElement.globalPos,
|
|
141
|
+
state.templatePath
|
|
142
|
+
);
|
|
143
|
+
}
|
|
135
144
|
|
|
136
145
|
return newElement;
|
|
137
146
|
};
|
|
@@ -193,6 +202,7 @@ const getElementType = trimmedElement => {
|
|
|
193
202
|
const typeValueLastPos = Math.min(...[
|
|
194
203
|
trimmedElement.indexOf(' '),
|
|
195
204
|
trimmedElement.indexOf('/'),
|
|
205
|
+
trimmedElement.indexOf(Constants.EOL),
|
|
196
206
|
trimmedElement.indexOf('>')
|
|
197
207
|
].filter(j => j >= 0));
|
|
198
208
|
|
|
@@ -453,13 +463,21 @@ const getNewElement = state => {
|
|
|
453
463
|
|
|
454
464
|
const getElementList = (templateContent, templatePath, isCrlfLineBreak) => {
|
|
455
465
|
|
|
456
|
-
const state
|
|
457
|
-
const elementList
|
|
466
|
+
const state = getInitialState(templateContent, templatePath, isCrlfLineBreak);
|
|
467
|
+
const elementList = state.elementList;
|
|
468
|
+
let previousStateContent = state.remainingShadowContent;
|
|
458
469
|
|
|
459
470
|
do {
|
|
460
471
|
initLoopState(state);
|
|
461
472
|
parseNextElement(state);
|
|
462
473
|
finishLoopState(state);
|
|
474
|
+
|
|
475
|
+
if (previousStateContent.length === state.remainingShadowContent.length) {
|
|
476
|
+
throw ExceptionUtils.unkownError(templatePath);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
previousStateContent = state.remainingShadowContent;
|
|
480
|
+
|
|
463
481
|
} while (state.remainingShadowContent.length > 0);
|
|
464
482
|
|
|
465
483
|
adjustTrailingSpaces(state);
|
package/src/rules/tree/indent.js
CHANGED
|
@@ -754,6 +754,9 @@ const checkIfShouldAddIndentationToTail = node => {
|
|
|
754
754
|
!isTailInSameLineAsChild &&
|
|
755
755
|
!isInSameLineAsChild &&
|
|
756
756
|
!isLastClause
|
|
757
|
+
// TODO Works for a specific case only. Might have side effects;
|
|
758
|
+
||
|
|
759
|
+
node.isOfType('iscomment') && !isTailInSameLineAsChild
|
|
757
760
|
||
|
|
758
761
|
isBrokenIntoMultipleLines;
|
|
759
762
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
|
|
2
|
+
const IndentRule = require('../tree/indent');
|
|
2
3
|
const ConfigUtils = require('../../util/ConfigUtils');
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
const Constants = require('../../Constants');
|
|
5
|
+
const GeneralUtils = require('../../util/GeneralUtils');
|
|
6
|
+
const TreeBuilder = require('../../isml_tree/TreeBuilder');
|
|
5
7
|
|
|
6
8
|
const ruleId = require('path').basename(__filename).slice(0, -3);
|
|
7
9
|
const description = 'Only one element per line is allowed';
|
|
@@ -28,49 +30,53 @@ Rule.isBroken = function(node) {
|
|
|
28
30
|
|
|
29
31
|
return !node.isRoot() &&
|
|
30
32
|
!node.parent.isContainer() &&
|
|
31
|
-
node.lineNumber === node.parent.
|
|
33
|
+
node.lineNumber === node.parent.endLineNumber;
|
|
32
34
|
};
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
Rule.getFixedContent = rootNode => {
|
|
37
|
+
addLineBreaks(rootNode);
|
|
36
38
|
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
+
// Rebuilding the tree automatically updates all node data, such as column number,
|
|
40
|
+
// line number, global position, etc;
|
|
41
|
+
const stringifiedTree = rootNode.toString();
|
|
42
|
+
const newRootNode = TreeBuilder.build(null, stringifiedTree).rootNode;
|
|
43
|
+
const partialFixContent = IndentRule.getFixedContent(newRootNode);
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// const child = node.children[i];
|
|
43
|
-
|
|
44
|
-
// if (child.isInSameLineAsParent() && !node.isIsmlComment()) {
|
|
45
|
-
// const indentation = getCorrectIndentation(child);
|
|
46
|
-
// const parentIndentation = getCorrectIndentation(node);
|
|
45
|
+
return GeneralUtils.applyActiveLineBreaks(partialFixContent);
|
|
46
|
+
};
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const addLineBreaks = node => {
|
|
49
|
+
const config = ConfigUtils.load();
|
|
50
|
+
const ruleConfig = config.rules[ruleId];
|
|
51
|
+
const shouldIgnoreNonTags = ruleConfig && ruleConfig.except && ruleConfig.except.indexOf('non-tag') >= 0;
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// }
|
|
53
|
-
// }
|
|
53
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
54
|
+
const child = node.children[i];
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
if (shouldAddLeadingLineBreakToChildHead(node, child, shouldIgnoreNonTags)) {
|
|
57
|
+
child.head = Constants.EOL + child.head;
|
|
58
|
+
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// let indentation = '';
|
|
63
|
-
// let indentUnit = '';
|
|
60
|
+
if (shouldAddLeadingLineBreakToParentTail(node, child, shouldIgnoreNonTags)) {
|
|
61
|
+
node.tail = Constants.EOL + node.tail;
|
|
62
|
+
}
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
addLineBreaks(child);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
const shouldAddLeadingLineBreakToChildHead = (node, child, shouldIgnoreNonTags) => {
|
|
69
|
+
return (child.isFirstChild() && child.isInSameLineAsParentEnd() || child.isTag() && child.isInSameLineAsPreviousSibling())
|
|
70
|
+
&& !node.isIsmlComment()
|
|
71
|
+
&& (child.isTag() || !child.isTag() && !shouldIgnoreNonTags);
|
|
72
|
+
};
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
const shouldAddLeadingLineBreakToParentTail = (node, child, shouldIgnoreNonTags) => {
|
|
75
|
+
return child.isLastChild()
|
|
76
|
+
&& child.endLineNumber === node.tailLineNumber
|
|
77
|
+
&& !node.isIsmlComment()
|
|
78
|
+
&& !node.tail.startsWith(Constants.EOL)
|
|
79
|
+
&& (child.isTag() || !child.isTag() && !shouldIgnoreNonTags);
|
|
80
|
+
};
|
|
75
81
|
|
|
76
82
|
module.exports = Rule;
|
|
@@ -5,6 +5,7 @@ const types = {
|
|
|
5
5
|
UNKNOWN_ERROR : 'UNKNOWN_ERROR',
|
|
6
6
|
UNCLOSED_DEPRECATED_ISML_COMMENT : 'UNCLOSED_DEPRECATED_ISML_COMMENT',
|
|
7
7
|
INVALID_TEMPLATE : 'INVALID_TEMPLATE',
|
|
8
|
+
INVALID_NESTED_ISIF : 'INVALID_NESTED_ISIF',
|
|
8
9
|
INVALID_CHARACTER : 'INVALID_CHARACTER',
|
|
9
10
|
RULE_ERROR : 'RULE_ERROR',
|
|
10
11
|
NO_CONFIG : 'NO_CONFIG',
|
|
@@ -99,6 +100,18 @@ const invalidCharacterError = (character, lineNumber, globalPos, length, templat
|
|
|
99
100
|
};
|
|
100
101
|
};
|
|
101
102
|
|
|
103
|
+
const invalidNestedIsifError = (tagType, lineNumber, globalPos, templatePath) => {
|
|
104
|
+
return {
|
|
105
|
+
message : `An error occurred while parsing element "<${tagType}>" in line ${lineNumber}. Try moving the closing character ">" of the "<${tagType}>" element to outside of the "<isif>" condition.`,
|
|
106
|
+
templatePath : templatePath,
|
|
107
|
+
globalPos,
|
|
108
|
+
length : tagType.length,
|
|
109
|
+
lineNumber : lineNumber,
|
|
110
|
+
isCustom : true,
|
|
111
|
+
type : types.INVALID_NESTED_ISIF
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
102
115
|
const parseError = (elementType, lineNumber, globalPos, length, templatePath) => {
|
|
103
116
|
return {
|
|
104
117
|
message : `An unexpected error happened while parsing element ${elementType} at ${templatePath}:${lineNumber}.`,
|
|
@@ -111,6 +124,15 @@ const parseError = (elementType, lineNumber, globalPos, length, templatePath) =>
|
|
|
111
124
|
};
|
|
112
125
|
};
|
|
113
126
|
|
|
127
|
+
const unkownError = (templatePath) => {
|
|
128
|
+
return {
|
|
129
|
+
message : `An unexpected error happened while parsing template ${templatePath}. Please consider adding it to the ignore list for now.`,
|
|
130
|
+
templatePath : templatePath,
|
|
131
|
+
isCustom : true,
|
|
132
|
+
type : types.UNKNOWN_ERROR
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
|
|
114
136
|
const noConfigError = () => {
|
|
115
137
|
return {
|
|
116
138
|
message : `No configuration found. Please run the following command: ${Constants.EOL}${Constants.EOL}\t./node_modules/.bin/isml-linter --init${Constants.EOL}${Constants.EOL}`,
|
|
@@ -137,6 +159,8 @@ module.exports = {
|
|
|
137
159
|
parseError,
|
|
138
160
|
unbalancedQuotesError,
|
|
139
161
|
ruleApplianceError,
|
|
162
|
+
unkownError,
|
|
163
|
+
invalidNestedIsifError,
|
|
140
164
|
unclosedDeprecatedIsmlComment,
|
|
141
165
|
unbalancedElementError,
|
|
142
166
|
unexpectedClosingElementError,
|