isml-linter 5.42.0 → 5.42.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.42.2] - 2023-01-29
4
+
5
+ ### Fixed
6
+ - HTML conditional comment children indentation;
7
+
8
+ ## [5.42.1] - 2023-01-28
9
+
10
+ ### Fixed
11
+ - Keep template original linebreak if one is not explictly set in the ISML Linter configuration file. It was forcing a Unix linebreak;
12
+
3
13
  ## [5.42.0] - 2023-01-25
4
14
 
5
15
  ### Added
@@ -1059,6 +1069,8 @@
1059
1069
  ### Added
1060
1070
  - Linter is published;
1061
1071
 
1072
+ [5.42.2]: https://github.com/FabiowQuixada/isml-linter/compare/v5.42.1...v5.42.2
1073
+ [5.42.1]: https://github.com/FabiowQuixada/isml-linter/compare/v5.42.0...v5.42.1
1062
1074
  [5.42.0]: https://github.com/FabiowQuixada/isml-linter/compare/v5.41.0...v5.42.0
1063
1075
  [5.41.0]: https://github.com/FabiowQuixada/isml-linter/compare/v5.40.5...v5.41.0
1064
1076
  [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.2",
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
 
@@ -53,7 +54,9 @@ class IsmlNode {
53
54
 
54
55
  const head = this.head.trim();
55
56
 
56
- if (head.startsWith('<!--')) {
57
+ if (head.startsWith('<!--[if')) {
58
+ return 'html_conditional_comment';
59
+ } else if (head.startsWith('<!--')) {
57
60
  return 'html_comment';
58
61
  } else if (this.isDocType()) {
59
62
  return 'doctype';
@@ -383,24 +386,11 @@ class IsmlNode {
383
386
  return rootNode;
384
387
  }
385
388
 
386
- toString(stream = '') {
389
+ toString() {
387
390
 
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
- }
391
+ let stream = privateToString(this);
400
392
 
401
- if (!this.isRoot() && !this.isContainer()) {
402
- stream += this.tail;
403
- }
393
+ stream = GeneralUtils.applyLineBreak(stream, this.getRoot().tree.originalLineBreak);
404
394
 
405
395
  return stream;
406
396
  }
@@ -429,6 +419,27 @@ class IsmlNode {
429
419
  * will be available for use only within IsmlNode methods;
430
420
  */
431
421
 
422
+ const privateToString = (node, stream = '') => {
423
+ if (!node.isContainer() && node.isEmpty() && !node.isLastChild()) {
424
+ return stream;
425
+ }
426
+
427
+ if (!node.isRoot() && !node.isContainer()) {
428
+ stream += node.head;
429
+ }
430
+
431
+ for (let i = 0; i < node.children.length; i++) {
432
+ const child = node.children[i];
433
+ stream = privateToString(child, stream);
434
+ }
435
+
436
+ if (!node.isRoot() && !node.isContainer()) {
437
+ stream += node.tail;
438
+ }
439
+
440
+ return stream;
441
+ };
442
+
432
443
  const getAttributes = node => {
433
444
  const trimmedHead = node.head.trim();
434
445
  const nodeHead = trimmedHead.substring(1, trimmedHead.length - 1);
@@ -128,8 +128,9 @@ const parseNextElement = state => {
128
128
  parseTextElement(state, newElement);
129
129
  }
130
130
 
131
- newElement.columnNumber = getElementColumnNumber(newElement, state);
132
- newElement.isVoidElement = !config.disableHtml5 && Constants.voidElementsArray.indexOf(newElement.tagType) >= 0;
131
+ newElement.columnNumber = getElementColumnNumber(newElement, state);
132
+ newElement.isVoidElement = !config.disableHtml5 && Constants.voidElementsArray.indexOf(newElement.tagType) >= 0;
133
+ newElement.isHtmlConditionalComment = !!(newElement.type === 'htmlOrIsmlComment' && (newElement.value.indexOf('<!--[if') >= 0 || newElement.value.indexOf('<!--<![endif]' >= 0)));
133
134
 
134
135
  if (state.isCrlfLineBreak) {
135
136
  newElement.globalPos += newElement.lineNumber - 1;
@@ -158,10 +159,11 @@ const parseNextElement = state => {
158
159
  };
159
160
 
160
161
  const parseTagOrExpressionElement = (state, newElement) => {
161
- const trimmedElement = newElement.value.trim().toLowerCase();
162
- const isTag = trimmedElement.startsWith('<') && !trimmedElement.startsWith('<!--');
163
- const isExpression = trimmedElement.startsWith('${');
164
- const isHtmlOrIsmlComment = trimmedElement.startsWith('<!--');
162
+ const trimmedElement = newElement.value.trim().toLowerCase();
163
+ const isTag = trimmedElement.startsWith('<') && !trimmedElement.startsWith('<!--');
164
+ const isExpression = trimmedElement.startsWith('${');
165
+ const isHtmlOrIsmlComment = trimmedElement.startsWith('<!--');
166
+ const isConditionalComment = trimmedElement.indexOf('<!--[if') >= 0 || trimmedElement.indexOf('<![endif') >= 0;
165
167
 
166
168
  if (isTag) {
167
169
  if (trimmedElement.startsWith('<is') || trimmedElement.startsWith('</is')) {
@@ -171,6 +173,8 @@ const parseTagOrExpressionElement = (state, newElement) => {
171
173
  } else {
172
174
  newElement.type = 'htmlTag';
173
175
  }
176
+ } else if (isConditionalComment) {
177
+ newElement.type = 'htmlConditionalComment';
174
178
  } else if (isHtmlOrIsmlComment) {
175
179
  newElement.type = 'htmlOrIsmlComment';
176
180
  } else if (isExpression) {
@@ -180,16 +184,24 @@ const parseTagOrExpressionElement = (state, newElement) => {
180
184
  }
181
185
 
182
186
  if (isTag) {
183
- newElement.tagType = getElementType(trimmedElement);
184
-
187
+ newElement.tagType = getElementType(trimmedElement);
185
188
  newElement.isCustomTag = newElement.type === 'ismlTag' && !SfccTagContainer[newElement.tagType];
186
189
  }
187
190
 
188
191
  newElement.isSelfClosing = isSelfClosing(trimmedElement);
192
+ newElement.isClosingTag = isTag && trimmedElement.startsWith('</');
193
+ newElement.lineNumber = getLineBreakQty(state.pastContent) + getLeadingLineBreakQty(newElement.value) + 1;
194
+ newElement.globalPos = state.pastContent.length + getLeadingEmptyChars(newElement.value).length;
195
+
196
+ // TODO Refactor this, remove this post-processing;
197
+ if (newElement.type === 'htmlConditionalComment') {
198
+ newElement.tagType = 'html_conditional_comment';
199
+ newElement.isSelfClosing = false;
189
200
 
190
- newElement.isClosingTag = isTag && trimmedElement.startsWith('</');
191
- newElement.lineNumber = getLineBreakQty(state.pastContent) + getLeadingLineBreakQty(newElement.value) + 1;
192
- newElement.globalPos = state.pastContent.length + getLeadingEmptyChars(newElement.value).length;
201
+ if (trimmedElement.indexOf('<!--<![endif]') >= 0) {
202
+ newElement.isClosingTag = true;
203
+ }
204
+ }
193
205
  };
194
206
 
195
207
  const parseTextElement = (state, newElement) => {
@@ -275,6 +287,7 @@ const getNextClosingTagOrExpressionEndPos = content => {
275
287
  };
276
288
 
277
289
  const getInitialState = (templateContent, templatePath, isCrlfLineBreak) => {
290
+ // TODO Check if "GeneralUtils.toLF" can be removed;
278
291
  const originalContent = GeneralUtils.toLF(templateContent);
279
292
  const originalShadowContent = MaskUtils.maskIgnorableContent(originalContent, null, templatePath);
280
293
 
@@ -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,
@@ -612,7 +613,7 @@ const addIndentation = (node, isOpeningTag) => {
612
613
  const fullLeadingContent = content.substring(0, startingPos);
613
614
  const preLineBreakContent = fullLeadingContent.substring(0, fullLeadingContent.lastIndexOf(Constants.EOL) + 1);
614
615
  const fullTrailingContent = content.substring(endingPos);
615
- const nodeIndentation = node.isInSameLineAsParent() && isOpeningTag ? '' : Rule.getIndentation(node.depth - 1);
616
+ let nodeIndentation = node.isInSameLineAsParent() && isOpeningTag ? '' : Rule.getIndentation(node.depth - 1);
616
617
  const attributeOffset = Rule.getAttributeIndentationOffset();
617
618
  const attributeList = node.getAttributeList();
618
619
  let contentResult = '';
@@ -641,7 +642,20 @@ const addIndentation = (node, isOpeningTag) => {
641
642
  contentResult = node.head.trim();
642
643
  }
643
644
  } else {
644
- contentResult = node.tail.trim();
645
+ const nodeLastChild = node.getLastChild();
646
+
647
+ if (nodeLastChild) {
648
+ const lastChildLineNumber = nodeLastChild.isContainer() ?
649
+ nodeLastChild.getLastChild().getLastLineNumber() :
650
+ nodeLastChild.getLastLineNumber();
651
+
652
+ if (node.tailLineNumber === lastChildLineNumber) {
653
+ contentResult = Constants.EOL + nodeIndentation;
654
+ nodeIndentation = '';
655
+ }
656
+ }
657
+
658
+ contentResult += node.tail.trim();
645
659
  }
646
660
 
647
661
  return preLineBreakContent + nodeIndentation + contentResult + fullTrailingContent;
@@ -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);