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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isml-linter",
3
- "version": "5.39.4",
3
+ "version": "5.40.2",
4
4
  "author": "Fabiow Quixadá <ftquixada@gmail.com>",
5
5
  "license": "MIT",
6
6
  "main": "src/publicApi.js",
@@ -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 = getInitialState(templateContent, templatePath, isCrlfLineBreak);
457
- const elementList = state.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);
@@ -58,7 +58,7 @@ TreeRulePrototype.return = function(node, occurrenceList, config) {
58
58
 
59
59
  return {
60
60
  occurrenceList
61
- } ;
61
+ };
62
62
 
63
63
  } else {
64
64
  return occurrenceList;
@@ -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
- // const Constants = require('../../Constants');
4
- // const GeneralUtils = require('../../util/GeneralUtils');
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.lineNumber;
33
+ node.lineNumber === node.parent.endLineNumber;
32
34
  };
33
35
 
34
- // Rule.getFixedContent = rootNode => {
35
- // fixContent(rootNode);
36
+ Rule.getFixedContent = rootNode => {
37
+ addLineBreaks(rootNode);
36
38
 
37
- // return GeneralUtils.applyActiveLineBreaks(rootNode.toString());
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
- // const fixContent = node => {
41
- // for (let i = 0; i < node.children.length; i++) {
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
- // child.head = `${Constants.EOL}${indentation}${child.head}${Constants.EOL}${parentIndentation}`;
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
- // if (child.tail) {
51
- // child.setTail(`${Constants.EOL}${indentation}${child.tail}${Constants.EOL}`);
52
- // }
53
- // }
53
+ for (let i = 0; i < node.children.length; i++) {
54
+ const child = node.children[i];
54
55
 
55
- // fixContent(child);
56
- // }
57
- // };
56
+ if (shouldAddLeadingLineBreakToChildHead(node, child, shouldIgnoreNonTags)) {
57
+ child.head = Constants.EOL + child.head;
58
+ }
58
59
 
59
- // const getCorrectIndentation = node => {
60
- // const indentSize = node.depth - 1;
61
- // const config = ConfigUtils.load();
62
- // let indentation = '';
63
- // let indentUnit = '';
60
+ if (shouldAddLeadingLineBreakToParentTail(node, child, shouldIgnoreNonTags)) {
61
+ node.tail = Constants.EOL + node.tail;
62
+ }
64
63
 
65
- // for (let i = 0; i < (config.indent || 4); ++i) {
66
- // indentUnit += ' ';
67
- // }
64
+ addLineBreaks(child);
65
+ }
66
+ };
68
67
 
69
- // for (let i = 0; i < indentSize; ++i) {
70
- // indentation += indentUnit;
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
- // return indentation;
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,