isml-linter 5.42.0 → 5.42.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.42.1] - 2023-01-28
4
+
5
+ ### Fixed
6
+ - Keep template original linebreak if one is not explictly set in the ISML Linter configuration file. It was forcing a Unix linebreak;
7
+
3
8
  ## [5.42.0] - 2023-01-25
4
9
 
5
10
  ### Added
@@ -1059,6 +1064,7 @@
1059
1064
  ### Added
1060
1065
  - Linter is published;
1061
1066
 
1067
+ [5.42.1]: https://github.com/FabiowQuixada/isml-linter/compare/v5.42.0...v5.42.1
1062
1068
  [5.42.0]: https://github.com/FabiowQuixada/isml-linter/compare/v5.41.0...v5.42.0
1063
1069
  [5.41.0]: https://github.com/FabiowQuixada/isml-linter/compare/v5.40.5...v5.41.0
1064
1070
  [5.40.5]: https://github.com/FabiowQuixada/isml-linter/compare/v5.40.4...v5.40.5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isml-linter",
3
- "version": "5.42.0",
3
+ "version": "5.42.1",
4
4
  "author": "Fabiow Quixadá <ftquixada@gmail.com>",
5
5
  "license": "MIT",
6
6
  "main": "src/publicApi.js",
@@ -6,6 +6,7 @@ const SfccTagContainer = require('../enums/SfccTagContainer');
6
6
  const ParseUtils = require('./ParseUtils');
7
7
  const MaskUtils = require('./MaskUtils');
8
8
  const ExceptionUtils = require('../util/ExceptionUtils');
9
+ const GeneralUtils = require('../util/GeneralUtils');
9
10
 
10
11
  let ID_COUNTER = 0;
11
12
 
@@ -383,24 +384,11 @@ class IsmlNode {
383
384
  return rootNode;
384
385
  }
385
386
 
386
- toString(stream = '') {
387
+ toString() {
387
388
 
388
- if (!this.isContainer() && this.isEmpty() && !this.isLastChild()) {
389
- return stream;
390
- }
391
-
392
- if (!this.isRoot() && !this.isContainer()) {
393
- stream += this.head;
394
- }
395
-
396
- for (let i = 0; i < this.children.length; i++) {
397
- const child = this.children[i];
398
- stream = child.toString(stream);
399
- }
389
+ let stream = privateToString(this);
400
390
 
401
- if (!this.isRoot() && !this.isContainer()) {
402
- stream += this.tail;
403
- }
391
+ stream = GeneralUtils.applyLineBreak(stream, this.getRoot().tree.originalLineBreak);
404
392
 
405
393
  return stream;
406
394
  }
@@ -429,6 +417,27 @@ class IsmlNode {
429
417
  * will be available for use only within IsmlNode methods;
430
418
  */
431
419
 
420
+ const privateToString = (node, stream = '') => {
421
+ if (!node.isContainer() && node.isEmpty() && !node.isLastChild()) {
422
+ return stream;
423
+ }
424
+
425
+ if (!node.isRoot() && !node.isContainer()) {
426
+ stream += node.head;
427
+ }
428
+
429
+ for (let i = 0; i < node.children.length; i++) {
430
+ const child = node.children[i];
431
+ stream = privateToString(child, stream);
432
+ }
433
+
434
+ if (!node.isRoot() && !node.isContainer()) {
435
+ stream += node.tail;
436
+ }
437
+
438
+ return stream;
439
+ };
440
+
432
441
  const getAttributes = node => {
433
442
  const trimmedHead = node.head.trim();
434
443
  const nodeHead = trimmedHead.substring(1, trimmedHead.length - 1);
@@ -275,6 +275,7 @@ const getNextClosingTagOrExpressionEndPos = content => {
275
275
  };
276
276
 
277
277
  const getInitialState = (templateContent, templatePath, isCrlfLineBreak) => {
278
+ // TODO Check if "GeneralUtils.toLF" can be removed;
278
279
  const originalContent = GeneralUtils.toLF(templateContent);
279
280
  const originalShadowContent = MaskUtils.maskIgnorableContent(originalContent, null, templatePath);
280
281
 
@@ -32,6 +32,10 @@ const parse = (content, templatePath, isCrlfLineBreak, isEmbeddedNode) => {
32
32
 
33
33
  ParseUtils.checkBalance(rootNode, templatePath);
34
34
 
35
+ rootNode.tree = {
36
+ originalLineBreak : GeneralUtils.getFileLineBreakStyle(content),
37
+ };
38
+
35
39
  return rootNode;
36
40
  };
37
41
 
@@ -203,15 +207,17 @@ const build = (templatePath, content, isCrlfLineBreak) => {
203
207
 
204
208
  const ParseStatus = require('../enums/ParseStatus');
205
209
 
206
- const result = {
210
+ const templateContent = content || fs.readFileSync(templatePath, 'utf-8');
211
+ const result = {
212
+ originalLineBreak : GeneralUtils.getFileLineBreakStyle(templateContent),
207
213
  templatePath,
208
214
  status : ParseStatus.NO_ERRORS
209
215
  };
210
216
 
211
217
  try {
212
- const templateContent = GeneralUtils.toLF(content || fs.readFileSync(templatePath, 'utf-8'));
213
- result.rootNode = parse(templateContent, templatePath, isCrlfLineBreak);
214
- result.data = postProcess(result.rootNode);
218
+ const formattedTemplateContent = templateContent;
219
+ result.rootNode = parse(formattedTemplateContent, templatePath, isCrlfLineBreak);
220
+ result.data = postProcess(result.rootNode);
215
221
 
216
222
  result.rootNode.tree = result;
217
223
 
@@ -1,5 +1,4 @@
1
1
  const SingleLineRulePrototype = require('../prototypes/SingleLineRulePrototype');
2
- const Constants = require('../../Constants');
3
2
  const GeneralUtils = require('../../util/GeneralUtils');
4
3
 
5
4
  const ruleId = require('path').basename(__filename).slice(0, -3);
@@ -21,8 +20,9 @@ Rule.getColumnNumber = function() {
21
20
 
22
21
  Rule.check = function(templateContent) {
23
22
 
23
+ const lineBreak = GeneralUtils.getFileLineBreakStyle(templateContent);
24
24
  const maxLines = this.getConfigs().max;
25
- const lineArray = GeneralUtils.toLF(templateContent).split(Constants.EOL);
25
+ const lineArray = templateContent.split(lineBreak);
26
26
  const columnNumber = this.getColumnNumber();
27
27
  const occurrenceList = [];
28
28
 
@@ -17,9 +17,9 @@ Rule.getColumnNumber = function() {
17
17
  Rule.getFixedContent = function(templateContent) {
18
18
  const GeneralUtils = require('../../util/GeneralUtils');
19
19
 
20
- const activeLineBreak = GeneralUtils.getActiveLineBreak();
21
- const lineArray = templateContent.split(Constants.EOL);
22
- const result = [];
20
+ const lineBreak = GeneralUtils.getFileLineBreakStyle(templateContent);
21
+ const lineArray = templateContent.split(lineBreak);
22
+ const result = [];
23
23
 
24
24
  for (let i = 0; i < lineArray.length; i++) {
25
25
  const line = lineArray[i];
@@ -27,7 +27,7 @@ Rule.getFixedContent = function(templateContent) {
27
27
  result.push(line.trim() ? line : line.trim());
28
28
  }
29
29
 
30
- return result.join(activeLineBreak);
30
+ return GeneralUtils.applyLineBreak(result.join(lineBreak));
31
31
  };
32
32
 
33
33
  Rule.getFirstOccurrence = function(line) {
@@ -16,9 +16,11 @@ Rule.getColumnNumber = function(line) {
16
16
  };
17
17
 
18
18
  Rule.getFixedContent = function(templateContent) {
19
+ const lineBreak = GeneralUtils.getFileLineBreakStyle(templateContent);
19
20
  const indent = IndentRule.getIndentation();
20
21
  const fixedContent = templateContent.replace(/\t/g, indent);
21
- return GeneralUtils.applyActiveLineBreaks(fixedContent);
22
+
23
+ return GeneralUtils.applyLineBreak(fixedContent, lineBreak);
22
24
  };
23
25
 
24
26
  Rule.getFirstOccurrence = function(line) {
@@ -1,5 +1,4 @@
1
1
  const SingleLineRulePrototype = require('../prototypes/SingleLineRulePrototype');
2
- const Constants = require('../../Constants');
3
2
  const ParseUtils = require('../../isml_tree/ParseUtils');
4
3
 
5
4
  const ruleId = require('path').basename(__filename).slice(0, -3);
@@ -19,9 +18,9 @@ Rule.getColumnNumber = function(line) {
19
18
  Rule.getFixedContent = function(templateContent) {
20
19
  const GeneralUtils = require('../../util/GeneralUtils');
21
20
 
22
- const activeLineBreak = GeneralUtils.getActiveLineBreak();
23
- const lineArray = GeneralUtils.toLF(templateContent).split(Constants.EOL);
24
- const result = [];
21
+ const lineBreak = GeneralUtils.getFileLineBreakStyle(templateContent);
22
+ const lineArray = templateContent.split(lineBreak);
23
+ const result = [];
25
24
 
26
25
  for (let i = 0; i < lineArray.length; i++) {
27
26
  const line = lineArray[i];
@@ -29,7 +28,7 @@ Rule.getFixedContent = function(templateContent) {
29
28
  result.push(line.replace(/\s+$/g, ''));
30
29
  }
31
30
 
32
- return result.join(activeLineBreak);
31
+ return GeneralUtils.applyLineBreak(result.join(lineBreak), lineBreak);
33
32
  };
34
33
 
35
34
  Rule.getFirstOccurrence = function(line) {
@@ -1,14 +1,14 @@
1
1
  const RulePrototype = require('./RulePrototype');
2
2
  const ConfigUtils = require('../../util/ConfigUtils');
3
- const Constants = require('../../Constants');
4
3
  const GeneralUtils = require('../../util/GeneralUtils');
5
4
 
6
5
  const SingleLineRulePrototype = Object.create(RulePrototype);
7
6
 
8
7
  SingleLineRulePrototype.check = function(templateContent, data = { isCrlfLineBreak : false }) {
9
8
 
9
+ const lineBreak = GeneralUtils.getFileLineBreakStyle(templateContent);
10
10
  const config = ConfigUtils.load();
11
- const lineArray = GeneralUtils.toLF(templateContent).split(Constants.EOL);
11
+ const lineArray = templateContent.split(lineBreak);
12
12
  const occurrenceList = [];
13
13
  let globalPos = 0;
14
14
 
@@ -65,20 +65,4 @@ TreeRulePrototype.return = function(node, occurrenceList, config) {
65
65
  }
66
66
  };
67
67
 
68
- TreeRulePrototype.fix = function(stream = '') {
69
-
70
- if (!this.isRoot() && !this.isContainer()) {
71
- stream += this.head;
72
- }
73
-
74
- for (let i = 0; i < this.children.length; i++) {
75
- const node = this.children[i];
76
- stream = node.isBroken() ?
77
- node.toString(stream) :
78
- this.getFixedContent(node, stream);
79
- }
80
-
81
- return stream;
82
- };
83
-
84
68
  module.exports = TreeRulePrototype;
@@ -2,7 +2,6 @@ const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
2
2
  const ParseUtils = require('../../isml_tree/ParseUtils');
3
3
  const Constants = require('../../Constants');
4
4
  const ConfigUtils = require('../../util/ConfigUtils');
5
- const GeneralUtils = require('../../util/GeneralUtils');
6
5
 
7
6
  const ruleId = require('path').basename(__filename).slice(0, -3);
8
7
  const description = 'Not eslint-valid';
@@ -121,7 +120,7 @@ Rule.getFixedContent = function(node) {
121
120
  node.head = reIndent(content, ismlOffset);
122
121
  }
123
122
 
124
- return GeneralUtils.applyActiveLineBreaks(node.toString());
123
+ return node.toString();
125
124
  };
126
125
 
127
126
  const unindent = (content, indentSize) => {
@@ -161,10 +161,11 @@ Rule.isQuoteClosingCharBroken = function(node) {
161
161
  '';
162
162
 
163
163
  if (message) {
164
- const line = node
164
+ const lineBreak = node.getRoot().tree.originalLineBreak;
165
+ const line = node
165
166
  .getRoot()
166
167
  .toString()
167
- .split(Constants.EOL)[lineNumber - 1];
168
+ .split(lineBreak)[lineNumber - 1];
168
169
 
169
170
  result.push({
170
171
  quoteChar : attribute.quoteChar,
@@ -1,7 +1,6 @@
1
1
  const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
2
2
  const RuleUtils = require('../../util/TempRuleUtils');
3
3
  const Constants = require('../../Constants');
4
- const GeneralUtils = require('../../util/GeneralUtils');
5
4
 
6
5
  const TAG_TYPE = 'iscache';
7
6
  const ruleId = require('path').basename(__filename).slice(0, -3);
@@ -33,7 +32,7 @@ Rule.getFixedContent = function(rootNode) {
33
32
  }
34
33
  }
35
34
 
36
- return GeneralUtils.applyActiveLineBreaks(rootNode.toString());
35
+ return rootNode.toString();
37
36
  };
38
37
 
39
38
  module.exports = Rule;
@@ -1,7 +1,6 @@
1
1
  const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
2
2
  const Constants = require('../../Constants');
3
3
  const RuleUtils = require('../../util/TempRuleUtils');
4
- const GeneralUtils = require('../../util/GeneralUtils');
5
4
 
6
5
  const TAG_TYPE = 'iscontent';
7
6
  const ruleId = require('path').basename(__filename).slice(0, -3);
@@ -29,7 +28,7 @@ Rule.getFixedContent = function(rootNode) {
29
28
  }
30
29
  }
31
30
 
32
- return GeneralUtils.applyActiveLineBreaks(rootNode.toString());
31
+ return rootNode.toString();
33
32
  };
34
33
 
35
34
  module.exports = Rule;
@@ -1,6 +1,5 @@
1
1
  const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
2
2
  const MaskUtils = require('../../isml_tree/MaskUtils');
3
- const GeneralUtils = require('../../util/GeneralUtils');
4
3
 
5
4
  const ruleId = require('path').basename(__filename).slice(0, -3);
6
5
  const description = 'Slash is not allowed for "iselse" nor "iselseif" tags';
@@ -29,7 +28,7 @@ Rule.getFixedContent = function(node) {
29
28
  this.getFixedContent(child);
30
29
  }
31
30
 
32
- return GeneralUtils.applyActiveLineBreaks(node.toString());
31
+ return node.toString();
33
32
  };
34
33
 
35
34
  module.exports = Rule;
@@ -2,7 +2,6 @@ const TreeRulePrototype = require('../prototypes/TreeRulePrototype');
2
2
  const IndentRule = require('../tree/indent');
3
3
  const ConfigUtils = require('../../util/ConfigUtils');
4
4
  const Constants = require('../../Constants');
5
- const GeneralUtils = require('../../util/GeneralUtils');
6
5
  const TreeBuilder = require('../../isml_tree/TreeBuilder');
7
6
 
8
7
  const ruleId = require('path').basename(__filename).slice(0, -3);
@@ -42,7 +41,7 @@ Rule.getFixedContent = rootNode => {
42
41
  const newRootNode = TreeBuilder.build(null, stringifiedTree).rootNode;
43
42
  const partialFixContent = IndentRule.getFixedContent(newRootNode);
44
43
 
45
- return GeneralUtils.applyActiveLineBreaks(partialFixContent);
44
+ return partialFixContent;
46
45
  };
47
46
 
48
47
  const addLineBreaks = node => {
@@ -126,6 +126,8 @@ const displayUnknownErrors = lintResult => {
126
126
  return partialSum;
127
127
  };
128
128
 
129
+ const getPluralTermString = (singularTerm, qty) => `${qty} ${singularTerm}${qty > 1 ? 's' : ''}`;
130
+
129
131
  const displayOccurrenceList = lintResult => {
130
132
 
131
133
  displayUnparseableErrors(lintResult);
@@ -148,19 +150,19 @@ const displayOccurrenceList = lintResult => {
148
150
  console.log(Constants.EOL + chalk`{bold Linted ${lintResult.totalTemplatesQty} templates in ${lintResult.elapsedTime} seconds.}`);
149
151
 
150
152
  if (occurrenceList.error.qty > 0) {
151
- console.log(chalk`{bold ${occurrenceList.error.qty} error(s) found.}`);
153
+ console.log(chalk`{bold ${getPluralTermString('error', occurrenceList.error.qty)} found.}`);
152
154
  }
153
155
 
154
156
  if (occurrenceList.warning.qty > 0) {
155
- console.log(chalk`{bold ${occurrenceList.warning.qty} warning(s) found.}`);
157
+ console.log(chalk`{bold ${getPluralTermString('warning', occurrenceList.warning.qty)} found.}`);
156
158
  }
157
159
 
158
160
  if (occurrenceList.info.qty > 0) {
159
- console.log(chalk`{bold ${occurrenceList.info.qty} info(s) found.}`);
161
+ console.log(chalk`{bold ${getPluralTermString('info', occurrenceList.info.qty)} found.}`);
160
162
  }
161
163
 
162
164
  if (lintResult.INVALID_TEMPLATE && lintResult.INVALID_TEMPLATE.length > 0) {
163
- console.log(chalk`{bold ${lintResult.INVALID_TEMPLATE.length} template(s) have an invalid ISML tree.}`);
165
+ console.log(chalk`{bold ${getPluralTermString('template', lintResult.INVALID_TEMPLATE.length)} have an invalid ISML tree.}`);
164
166
  }
165
167
 
166
168
  if (lintResult.UNKNOWN_ERROR && lintResult.UNKNOWN_ERROR.length > 0) {
@@ -34,12 +34,52 @@ const getActiveLineBreak = () => {
34
34
  return configLineBreak || Constants.EOL;
35
35
  };
36
36
 
37
+ const getFileLineBreakStyle = templateContent => {
38
+ const indexOfLF = templateContent.indexOf(Constants.lineBreak.unix, 1);
39
+
40
+ if (indexOfLF === -1) {
41
+ if (templateContent.indexOf('\r') !== -1) {
42
+ return '\r';
43
+ }
44
+
45
+ return Constants.lineBreak.unix;
46
+ }
47
+
48
+ if (templateContent[indexOfLF - 1] === '\r') {
49
+ return Constants.lineBreak.windows;
50
+ }
51
+
52
+ return Constants.lineBreak.unix;
53
+ };
54
+
37
55
  module.exports.formatTemplatePath = filePath => {
38
56
  return filePath.replace(/\//g, path.sep);
39
57
  };
40
58
 
41
59
  module.exports.toLF = content => {
42
- return content.replace(/\r\n/g, '\n');
60
+ return content.replace(/\r\n/g, Constants.lineBreak.unix);
61
+ };
62
+
63
+ module.exports.getFileLineBreakStyle = getFileLineBreakStyle;
64
+
65
+ module.exports.applyLineBreak = (content, lineBreak) => {
66
+ const config = ConfigUtils.load();
67
+ const configLineBreak = config.linebreakStyle && Constants.lineBreak[config.linebreakStyle];
68
+ const templateHasWindowsLineBreak = content.indexOf(Constants.lineBreak.windows) >= 0;
69
+
70
+ if (configLineBreak) {
71
+ lineBreak = configLineBreak;
72
+ }
73
+
74
+ if (lineBreak === Constants.lineBreak.windows && !templateHasWindowsLineBreak) {
75
+ return content
76
+ .replace(new RegExp(Constants.lineBreak.unix, 'g'), lineBreak);
77
+ } else if (lineBreak === Constants.lineBreak.unix && templateHasWindowsLineBreak) {
78
+ return content
79
+ .replace(new RegExp(Constants.lineBreak.windows, 'g'), lineBreak);
80
+ }
81
+
82
+ return content;
43
83
  };
44
84
 
45
85
  module.exports.applyActiveLineBreaks = content => {
@@ -6,7 +6,6 @@ const ConfigUtils = require('./ConfigUtils');
6
6
  const lowercaseFilenameRule = require('../rules/line_by_line/lowercase-filename');
7
7
  const CustomTagContainer = require('./CustomTagContainer');
8
8
  const CustomModulesRule = require('../rules/tree/custom-tags');
9
- const GeneralUtils = require('./GeneralUtils');
10
9
  const ConsoleUtils = require('./ConsoleUtils');
11
10
  const ExceptionUtils = require('./ExceptionUtils');
12
11
 
@@ -225,7 +224,7 @@ const checkCustomModules = () => {
225
224
  const parseAndPossiblyFixTemplate = (templatePath, data, content = '', templateName = '') => {
226
225
  ConsoleUtils.displayVerboseMessage(`\nChecking "${templatePath}" template`);
227
226
  const config = ConfigUtils.load();
228
- const templateContent = GeneralUtils.toLF(content || fs.readFileSync(templatePath, 'utf-8'));
227
+ const templateContent = content || fs.readFileSync(templatePath, 'utf-8');
229
228
  const lineResults = checkAndPossiblyFixLineByLineRules(templatePath, templateContent, config, data);
230
229
  const treeResults = checkAndPossiblyFixTreeRules(templatePath, lineResults.finalContent, config, data) || { errors : [] };
231
230
  const filenameResults = checkFileName(templateName, templateContent);