isml-linter 5.39.3 → 5.40.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +1184 -1159
  2. package/LICENSE +21 -21
  3. package/README.md +245 -245
  4. package/bin/isml-linter.js +32 -32
  5. package/ismllinter.config.js +33 -33
  6. package/package.json +53 -53
  7. package/scaffold_files/ismllinter.config.js +47 -47
  8. package/src/Builder.js +15 -15
  9. package/src/Constants.js +139 -139
  10. package/src/IsmlLinter.js +255 -255
  11. package/src/enums/ParseStatus.js +5 -5
  12. package/src/enums/SfccTagContainer.js +287 -287
  13. package/src/isml_tree/ContainerNode.js +38 -38
  14. package/src/isml_tree/IsmlNode.js +692 -684
  15. package/src/isml_tree/MaskUtils.js +421 -421
  16. package/src/isml_tree/ParseUtils.js +532 -506
  17. package/src/isml_tree/TreeBuilder.js +273 -273
  18. package/src/publicApi.js +24 -24
  19. package/src/rules/line_by_line/enforce-isprint.js +53 -53
  20. package/src/rules/line_by_line/enforce-require.js +35 -35
  21. package/src/rules/line_by_line/lowercase-filename.js +29 -29
  22. package/src/rules/line_by_line/max-lines.js +37 -37
  23. package/src/rules/line_by_line/no-br.js +36 -36
  24. package/src/rules/line_by_line/no-git-conflict.js +43 -43
  25. package/src/rules/line_by_line/no-import-package.js +34 -34
  26. package/src/rules/line_by_line/no-inline-style.js +34 -34
  27. package/src/rules/line_by_line/no-isscript.js +34 -34
  28. package/src/rules/line_by_line/no-space-only-lines.js +47 -47
  29. package/src/rules/line_by_line/no-tabs.js +38 -38
  30. package/src/rules/line_by_line/no-trailing-spaces.js +52 -52
  31. package/src/rules/prototypes/RulePrototype.js +79 -79
  32. package/src/rules/prototypes/SingleLineRulePrototype.js +47 -47
  33. package/src/rules/prototypes/TreeRulePrototype.js +84 -84
  34. package/src/rules/tree/align-isset.js +87 -87
  35. package/src/rules/tree/contextual-attrs.js +105 -105
  36. package/src/rules/tree/custom-tags.js +54 -54
  37. package/src/rules/tree/disallow-tags.js +39 -39
  38. package/src/rules/tree/empty-eof.js +66 -66
  39. package/src/rules/tree/enforce-security.js +85 -85
  40. package/src/rules/tree/eslint-to-isscript.js +179 -179
  41. package/src/rules/tree/indent.js +856 -853
  42. package/src/rules/tree/leading-iscache.js +39 -39
  43. package/src/rules/tree/leading-iscontent.js +35 -35
  44. package/src/rules/tree/max-depth.js +54 -54
  45. package/src/rules/tree/no-deprecated-attrs.js +67 -67
  46. package/src/rules/tree/no-embedded-isml.js +17 -17
  47. package/src/rules/tree/no-hardcode.js +51 -51
  48. package/src/rules/tree/no-iselse-slash.js +35 -35
  49. package/src/rules/tree/no-redundant-context.js +134 -134
  50. package/src/rules/tree/no-require-in-loop.js +63 -63
  51. package/src/rules/tree/one-element-per-line.js +82 -76
  52. package/src/util/CommandLineUtils.js +19 -19
  53. package/src/util/ConfigUtils.js +219 -219
  54. package/src/util/ConsoleUtils.js +327 -327
  55. package/src/util/CustomTagContainer.js +45 -45
  56. package/src/util/ExceptionUtils.js +173 -149
  57. package/src/util/FileUtils.js +79 -79
  58. package/src/util/GeneralUtils.js +60 -60
  59. package/src/util/NativeExtensionUtils.js +6 -6
  60. package/src/util/RuleUtils.js +295 -295
  61. package/src/util/TempRuleUtils.js +232 -232
@@ -1,421 +1,421 @@
1
- /**
2
- * Replaces '${...}' with '${___}', so it facilitates next processes. For Example,
3
- * if ${ 3 < 4 } is present, the '<' symbol might be thought as an opening tag
4
- * symbol. The same is valid for <isscript> and <iscomment> tags;
5
- */
6
-
7
- const ParseUtils = require('./ParseUtils');
8
- const ExceptionUtils = require('../util/ExceptionUtils');
9
-
10
- const placeholderSymbol = '_';
11
-
12
- const maskIgnorableContent = (content, shouldMaskBorders, templatePath) => {
13
-
14
- let maskedContent = content;
15
-
16
- maskedContent = maskInBetween(maskedContent, 'iscomment', shouldMaskBorders);
17
- maskedContent = maskExpressionContent(maskedContent);
18
- maskedContent = maskInBetween(maskedContent, '<!---', '--->', shouldMaskBorders);
19
- maskedContent = maskInBetween(maskedContent, '<!--', '-->', shouldMaskBorders);
20
- maskedContent = maskInBetweenIsscriptTags(maskedContent);
21
- maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script', 'type=\'text/javascript\'');
22
- maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script', 'type="text/javascript"');
23
- maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'isscript');
24
-
25
- checkTagBalance(maskedContent, content, templatePath);
26
-
27
- maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script');
28
- maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'style');
29
- maskedContent = maskInBetween2(maskedContent, '<', '>');
30
- maskedContent = maskQuoteContent(maskedContent);
31
- maskedContent = maskIsifTagContent(maskedContent);
32
- maskedContent = maskIsprintTagContent(maskedContent);
33
-
34
- return maskedContent;
35
- };
36
-
37
- const checkTagBalance = (maskedContent, content, templatePath) => {
38
- let depth = 0;
39
-
40
- for (let globalPos = 0; globalPos < maskedContent.length; globalPos++) {
41
- const char = maskedContent[globalPos];
42
- const remainingContent = maskedContent.substring(globalPos);
43
-
44
- if (char === '<') {
45
- depth++;
46
- }
47
-
48
- if (char === '>') {
49
- depth--;
50
- }
51
-
52
- // Only ISML tags can be within HTML tags;
53
- if (depth === 2 &&
54
- remainingContent.startsWith('<') &&
55
- !remainingContent.startsWith('<is') &&
56
- !remainingContent.startsWith('<!') &&
57
- !remainingContent.startsWith('</is')
58
- ) {
59
- const lineNumber = ParseUtils.getLineBreakQty(content.substring(0, globalPos)) + 1;
60
-
61
- throw ExceptionUtils.invalidCharacterError(
62
- '<',
63
- lineNumber,
64
- globalPos,
65
- 1,
66
- templatePath
67
- );
68
- }
69
- }
70
- };
71
-
72
- const maskInBetween = (content, startString, endString, shouldMaskBorders) => {
73
-
74
- let processedStartingString = startString;
75
- let processedEndString = endString;
76
-
77
- if (!endString) {
78
- processedStartingString = startString === 'isif' ? `<${startString}` : `<${startString}>`;
79
- processedEndString = `</${startString}>`;
80
- }
81
-
82
- return getMatchingIndexes(content, processedStartingString, processedEndString, shouldMaskBorders);
83
- };
84
-
85
- const getMatchingLists = (content, startString, endString) => {
86
- const openingMatchList = [];
87
- const closingMatchList = [];
88
- const emptyElementPattern = startString + endString;
89
-
90
- for (let i = 0; i < content.length; i++) {
91
- const substring = content.substring(i);
92
-
93
- if (substring.startsWith(startString)) {
94
- if (openingMatchList.length === closingMatchList.length && !substring.startsWith(emptyElementPattern)) {
95
- openingMatchList.push(i);
96
- }
97
- } else if (substring.startsWith(endString)) {
98
- if (openingMatchList.length === closingMatchList.length + 1) {
99
- closingMatchList.push(i);
100
- }
101
- }
102
- }
103
-
104
- return {
105
- openingMatchList,
106
- closingMatchList
107
- };
108
- };
109
-
110
- const maskInBetweenForTagWithAttributes = (content, rawStartString, attributes = '') => {
111
-
112
- const startingString = `<${rawStartString + (attributes ? ' ' + attributes : '')}>`;
113
- const endString = `</${rawStartString}>`;
114
- return getMatchingIndexes(content, startingString, endString);
115
- };
116
-
117
- const checkIfDeprecatedIsmlCommentIsUnbalanced = (content, startString, openingMatchList, closingMatchList) => {
118
- if (startString === '<!---' && openingMatchList.length !== closingMatchList.length) {
119
- let globalPos;
120
- let length;
121
-
122
- for (let i = 0; i < openingMatchList.length; i++) {
123
- const openingElementPos = openingMatchList[i];
124
- const closingElementPos = closingMatchList[i];
125
-
126
- if (!closingElementPos || closingElementPos < openingElementPos) {
127
- const elemContent = content.substring(openingElementPos, content.indexOf('-->') + 3);
128
- globalPos = openingElementPos;
129
- length = elemContent.length;
130
- }
131
- }
132
-
133
- const lineNumber = ParseUtils.getLineBreakQty(content.substring(0, globalPos)) + 1;
134
-
135
- throw {
136
- type : ExceptionUtils.types.UNCLOSED_DEPRECATED_ISML_COMMENT,
137
- globalPos,
138
- lineNumber,
139
- length
140
- };
141
- }
142
-
143
- return false;
144
- };
145
-
146
- // TODO Rename and reuse;
147
- const maskInBetween2 = (content, startString, endString) => {
148
- let depth = 0;
149
- let result = '';
150
-
151
- for (let i = 0; i < content.length; i++) {
152
- const element = content[i];
153
-
154
- if (element === endString) {
155
- depth--;
156
- }
157
-
158
- result += depth > 0 ? '_' : element;
159
-
160
- if (element === startString) {
161
- depth++;
162
- }
163
- }
164
-
165
- return result;
166
- };
167
-
168
- const maskInBetweenIsscriptTags = content => {
169
- let result = '';
170
-
171
- const startString = '<isscript>';
172
- const endString = '</isscript>';
173
-
174
- const contentToBeMaskedStartPos = content.indexOf(startString) + startString.length - 1;
175
- const contentToBeMaskedEndPos = content.indexOf(endString);
176
-
177
-
178
- for (let i = 0; i < content.length; i++) {
179
- const element = content[i];
180
-
181
- result += contentToBeMaskedStartPos < i && i < contentToBeMaskedEndPos ?
182
- '_' :
183
- element;
184
- }
185
-
186
- return result;
187
- };
188
-
189
- const getMatchingIndexes = (content, startString, endString, isMaskBorders) => {
190
- const matchingLists = getMatchingLists(content, startString, endString);
191
- const openingMatchList = matchingLists.openingMatchList;
192
- const closingMatchList = matchingLists.closingMatchList;
193
- let result = '';
194
- let isInBetween = false;
195
- const currentOpeningTag = {
196
- endingGlobalPos : null,
197
- arrayIndex : null
198
- };
199
-
200
- const isDeprecatedIsmlCommentUnbalanced = checkIfDeprecatedIsmlCommentIsUnbalanced(content, startString, openingMatchList, closingMatchList);
201
-
202
- if (isDeprecatedIsmlCommentUnbalanced) {
203
- return isDeprecatedIsmlCommentUnbalanced;
204
- }
205
-
206
- for (let i = 0; i < content.length; ++i) {
207
- if (isInBetween) {
208
- if (closingMatchList.indexOf(i) >= 0) {
209
- currentOpeningTag.endingGlobalPos = null;
210
- isInBetween = false;
211
- result += content[i];
212
- } else {
213
- result += placeholderSymbol;
214
- }
215
- } else {
216
- const firstMatchPos = openingMatchList.indexOf(i - 1);
217
- if (firstMatchPos >= 0) {
218
- currentOpeningTag.endingGlobalPos = i;
219
- currentOpeningTag.arrayIndex = firstMatchPos;
220
- }
221
-
222
- isInBetween = currentOpeningTag.endingGlobalPos &&
223
- i >= currentOpeningTag.endingGlobalPos + startString.length - 1;
224
-
225
- if (openingMatchList[currentOpeningTag.arrayIndex] === closingMatchList[currentOpeningTag.arrayIndex]) {
226
- isInBetween = false;
227
- currentOpeningTag.arrayIndex = null;
228
- currentOpeningTag.endingGlobalPos = null;
229
- }
230
-
231
- if (isInBetween) {
232
- result += placeholderSymbol;
233
- } else {
234
- result += content[i];
235
- }
236
- }
237
- }
238
-
239
- if (isMaskBorders) {
240
- const maskedStartString = mask(startString);
241
- const maskedEndString = mask(endString);
242
-
243
- result = result
244
- .replace(new RegExp(startString, 'g'), maskedStartString)
245
- .replace(new RegExp(endString, 'g'), maskedEndString);
246
- }
247
-
248
- return result;
249
- };
250
-
251
- const mask = content => {
252
- let maskedContent = '';
253
-
254
- for (let i = 0; i < content.length; i++) {
255
- maskedContent += '_';
256
- }
257
-
258
- return maskedContent;
259
- };
260
-
261
- const maskQuoteContent = content => {
262
-
263
- let maskedContent = '';
264
- let isWithinQuotes = false;
265
-
266
- for (let i = 0; i < content.length; i++) {
267
- const char = content[i];
268
-
269
- maskedContent += isWithinQuotes ?
270
- '_' :
271
- char;
272
-
273
- if (char === '"') {
274
- isWithinQuotes = !isWithinQuotes;
275
-
276
- if (!isWithinQuotes) {
277
- maskedContent = maskedContent.slice(0, -1);
278
- maskedContent += '"';
279
- }
280
- }
281
- }
282
-
283
- return maskedContent;
284
- };
285
-
286
- // TODO Try to generalize this function;
287
- const maskIsifTagContent = content => {
288
-
289
- const openingTag = '<isif';
290
- const closingTag = '</isif>';
291
- let depthLevel = 0;
292
- let maskedContent = '';
293
-
294
- for (let i = 0; i < content.length; i++) {
295
- const remainingContent = content.substring(i);
296
-
297
- if (remainingContent.startsWith(openingTag)) {
298
- maskedContent += depthLevel > 0 ? '_____' : openingTag;
299
- i += openingTag.length;
300
- depthLevel++;
301
- }
302
-
303
- maskedContent += depthLevel > 0 ?
304
- '_' :
305
- content[i];
306
-
307
- if (remainingContent.startsWith(closingTag)) {
308
- depthLevel--;
309
- maskedContent += depthLevel > 0 ? '_______' : closingTag;
310
- i += closingTag.length - 1;
311
- }
312
- }
313
-
314
- return maskedContent;
315
- };
316
-
317
- const maskIsprintTagContent = content => {
318
-
319
- const openingTag = '<isprint';
320
- let isWithinIsprintTag = false;
321
- let maskedContent = '';
322
-
323
- if (content.indexOf(openingTag) < 0) {
324
- return content;
325
- }
326
-
327
- for (let i = 0; i < content.length; i++) {
328
- const remainingContent = content.substring(i);
329
- const char = content[i];
330
-
331
- if (remainingContent.startsWith(openingTag)) {
332
- isWithinIsprintTag = true;
333
- maskedContent += openingTag;
334
- i += openingTag.length;
335
- }
336
-
337
- maskedContent += isWithinIsprintTag ?
338
- '_' :
339
- char;
340
-
341
- if (char === '>' && isWithinIsprintTag) {
342
- isWithinIsprintTag = !isWithinIsprintTag;
343
-
344
- if (!isWithinIsprintTag) {
345
- maskedContent = maskedContent.slice(0, -1);
346
- maskedContent += '>';
347
- }
348
- }
349
- }
350
-
351
- return maskedContent;
352
- };
353
-
354
- const maskExpressionContent = content => {
355
- const openingTag = '${';
356
- const closingTag = '}';
357
- let isWithinExpression = false;
358
- let maskedContent = '';
359
-
360
- for (let i = 0; i < content.length; i++) {
361
- const remainingContent = content.substring(i);
362
-
363
- if (remainingContent.startsWith(openingTag)) {
364
- isWithinExpression = true;
365
- maskedContent += openingTag;
366
- i += openingTag.length;
367
-
368
- if (remainingContent.startsWith('${}')) {
369
- isWithinExpression = false;
370
- maskedContent += '}';
371
- continue;
372
- }
373
- }
374
-
375
- maskedContent += isWithinExpression ?
376
- '_' :
377
- content[i];
378
-
379
- if (remainingContent.startsWith(closingTag)) {
380
- isWithinExpression = false;
381
- maskedContent = maskedContent.slice(0, -1) + closingTag;
382
- }
383
- }
384
-
385
- return maskedContent;
386
- };
387
-
388
- const maskJsonContent = content => {
389
- let maskedContent = '';
390
- let depth = 0;
391
-
392
- for (let i = 0; i < content.length; i++) {
393
- const char = content[i];
394
-
395
- if (char === '}') {
396
- depth -= 1;
397
- }
398
-
399
- maskedContent += depth > 0 ?
400
- '_' :
401
- char;
402
-
403
- if (char === '{') {
404
- depth += 1;
405
- }
406
- }
407
-
408
- return maskedContent;
409
- };
410
-
411
- module.exports = {
412
- maskIgnorableContent,
413
- maskQuoteContent,
414
- maskExpressionContent,
415
- maskIsprintTagContent,
416
- maskJsonContent,
417
- maskIsifTagContent,
418
- maskInBetween,
419
- maskInBetween2,
420
- maskInBetweenForTagWithAttributes
421
- };
1
+ /**
2
+ * Replaces '${...}' with '${___}', so it facilitates next processes. For Example,
3
+ * if ${ 3 < 4 } is present, the '<' symbol might be thought as an opening tag
4
+ * symbol. The same is valid for <isscript> and <iscomment> tags;
5
+ */
6
+
7
+ const ParseUtils = require('./ParseUtils');
8
+ const ExceptionUtils = require('../util/ExceptionUtils');
9
+
10
+ const placeholderSymbol = '_';
11
+
12
+ const maskIgnorableContent = (content, shouldMaskBorders, templatePath) => {
13
+
14
+ let maskedContent = content;
15
+
16
+ maskedContent = maskInBetween(maskedContent, 'iscomment', shouldMaskBorders);
17
+ maskedContent = maskExpressionContent(maskedContent);
18
+ maskedContent = maskInBetween(maskedContent, '<!---', '--->', shouldMaskBorders);
19
+ maskedContent = maskInBetween(maskedContent, '<!--', '-->', shouldMaskBorders);
20
+ maskedContent = maskInBetweenIsscriptTags(maskedContent);
21
+ maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script', 'type=\'text/javascript\'');
22
+ maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script', 'type="text/javascript"');
23
+ maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'isscript');
24
+
25
+ checkTagBalance(maskedContent, content, templatePath);
26
+
27
+ maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'script');
28
+ maskedContent = maskInBetweenForTagWithAttributes(maskedContent, 'style');
29
+ maskedContent = maskInBetween2(maskedContent, '<', '>');
30
+ maskedContent = maskQuoteContent(maskedContent);
31
+ maskedContent = maskIsifTagContent(maskedContent);
32
+ maskedContent = maskIsprintTagContent(maskedContent);
33
+
34
+ return maskedContent;
35
+ };
36
+
37
+ const checkTagBalance = (maskedContent, content, templatePath) => {
38
+ let depth = 0;
39
+
40
+ for (let globalPos = 0; globalPos < maskedContent.length; globalPos++) {
41
+ const char = maskedContent[globalPos];
42
+ const remainingContent = maskedContent.substring(globalPos);
43
+
44
+ if (char === '<') {
45
+ depth++;
46
+ }
47
+
48
+ if (char === '>') {
49
+ depth--;
50
+ }
51
+
52
+ // Only ISML tags can be within HTML tags;
53
+ if (depth === 2 &&
54
+ remainingContent.startsWith('<') &&
55
+ !remainingContent.startsWith('<is') &&
56
+ !remainingContent.startsWith('<!') &&
57
+ !remainingContent.startsWith('</is')
58
+ ) {
59
+ const lineNumber = ParseUtils.getLineBreakQty(content.substring(0, globalPos)) + 1;
60
+
61
+ throw ExceptionUtils.invalidCharacterError(
62
+ '<',
63
+ lineNumber,
64
+ globalPos,
65
+ 1,
66
+ templatePath
67
+ );
68
+ }
69
+ }
70
+ };
71
+
72
+ const maskInBetween = (content, startString, endString, shouldMaskBorders) => {
73
+
74
+ let processedStartingString = startString;
75
+ let processedEndString = endString;
76
+
77
+ if (!endString) {
78
+ processedStartingString = startString === 'isif' ? `<${startString}` : `<${startString}>`;
79
+ processedEndString = `</${startString}>`;
80
+ }
81
+
82
+ return getMatchingIndexes(content, processedStartingString, processedEndString, shouldMaskBorders);
83
+ };
84
+
85
+ const getMatchingLists = (content, startString, endString) => {
86
+ const openingMatchList = [];
87
+ const closingMatchList = [];
88
+ const emptyElementPattern = startString + endString;
89
+
90
+ for (let i = 0; i < content.length; i++) {
91
+ const substring = content.substring(i);
92
+
93
+ if (substring.startsWith(startString)) {
94
+ if (openingMatchList.length === closingMatchList.length && !substring.startsWith(emptyElementPattern)) {
95
+ openingMatchList.push(i);
96
+ }
97
+ } else if (substring.startsWith(endString)) {
98
+ if (openingMatchList.length === closingMatchList.length + 1) {
99
+ closingMatchList.push(i);
100
+ }
101
+ }
102
+ }
103
+
104
+ return {
105
+ openingMatchList,
106
+ closingMatchList
107
+ };
108
+ };
109
+
110
+ const maskInBetweenForTagWithAttributes = (content, rawStartString, attributes = '') => {
111
+
112
+ const startingString = `<${rawStartString + (attributes ? ' ' + attributes : '')}>`;
113
+ const endString = `</${rawStartString}>`;
114
+ return getMatchingIndexes(content, startingString, endString);
115
+ };
116
+
117
+ const checkIfDeprecatedIsmlCommentIsUnbalanced = (content, startString, openingMatchList, closingMatchList) => {
118
+ if (startString === '<!---' && openingMatchList.length !== closingMatchList.length) {
119
+ let globalPos;
120
+ let length;
121
+
122
+ for (let i = 0; i < openingMatchList.length; i++) {
123
+ const openingElementPos = openingMatchList[i];
124
+ const closingElementPos = closingMatchList[i];
125
+
126
+ if (!closingElementPos || closingElementPos < openingElementPos) {
127
+ const elemContent = content.substring(openingElementPos, content.indexOf('-->') + 3);
128
+ globalPos = openingElementPos;
129
+ length = elemContent.length;
130
+ }
131
+ }
132
+
133
+ const lineNumber = ParseUtils.getLineBreakQty(content.substring(0, globalPos)) + 1;
134
+
135
+ throw {
136
+ type : ExceptionUtils.types.UNCLOSED_DEPRECATED_ISML_COMMENT,
137
+ globalPos,
138
+ lineNumber,
139
+ length
140
+ };
141
+ }
142
+
143
+ return false;
144
+ };
145
+
146
+ // TODO Rename and reuse;
147
+ const maskInBetween2 = (content, startString, endString) => {
148
+ let depth = 0;
149
+ let result = '';
150
+
151
+ for (let i = 0; i < content.length; i++) {
152
+ const element = content[i];
153
+
154
+ if (element === endString) {
155
+ depth--;
156
+ }
157
+
158
+ result += depth > 0 ? '_' : element;
159
+
160
+ if (element === startString) {
161
+ depth++;
162
+ }
163
+ }
164
+
165
+ return result;
166
+ };
167
+
168
+ const maskInBetweenIsscriptTags = content => {
169
+ let result = '';
170
+
171
+ const startString = '<isscript>';
172
+ const endString = '</isscript>';
173
+
174
+ const contentToBeMaskedStartPos = content.indexOf(startString) + startString.length - 1;
175
+ const contentToBeMaskedEndPos = content.indexOf(endString);
176
+
177
+
178
+ for (let i = 0; i < content.length; i++) {
179
+ const element = content[i];
180
+
181
+ result += contentToBeMaskedStartPos < i && i < contentToBeMaskedEndPos ?
182
+ '_' :
183
+ element;
184
+ }
185
+
186
+ return result;
187
+ };
188
+
189
+ const getMatchingIndexes = (content, startString, endString, isMaskBorders) => {
190
+ const matchingLists = getMatchingLists(content, startString, endString);
191
+ const openingMatchList = matchingLists.openingMatchList;
192
+ const closingMatchList = matchingLists.closingMatchList;
193
+ let result = '';
194
+ let isInBetween = false;
195
+ const currentOpeningTag = {
196
+ endingGlobalPos : null,
197
+ arrayIndex : null
198
+ };
199
+
200
+ const isDeprecatedIsmlCommentUnbalanced = checkIfDeprecatedIsmlCommentIsUnbalanced(content, startString, openingMatchList, closingMatchList);
201
+
202
+ if (isDeprecatedIsmlCommentUnbalanced) {
203
+ return isDeprecatedIsmlCommentUnbalanced;
204
+ }
205
+
206
+ for (let i = 0; i < content.length; ++i) {
207
+ if (isInBetween) {
208
+ if (closingMatchList.indexOf(i) >= 0) {
209
+ currentOpeningTag.endingGlobalPos = null;
210
+ isInBetween = false;
211
+ result += content[i];
212
+ } else {
213
+ result += placeholderSymbol;
214
+ }
215
+ } else {
216
+ const firstMatchPos = openingMatchList.indexOf(i - 1);
217
+ if (firstMatchPos >= 0) {
218
+ currentOpeningTag.endingGlobalPos = i;
219
+ currentOpeningTag.arrayIndex = firstMatchPos;
220
+ }
221
+
222
+ isInBetween = currentOpeningTag.endingGlobalPos &&
223
+ i >= currentOpeningTag.endingGlobalPos + startString.length - 1;
224
+
225
+ if (openingMatchList[currentOpeningTag.arrayIndex] === closingMatchList[currentOpeningTag.arrayIndex]) {
226
+ isInBetween = false;
227
+ currentOpeningTag.arrayIndex = null;
228
+ currentOpeningTag.endingGlobalPos = null;
229
+ }
230
+
231
+ if (isInBetween) {
232
+ result += placeholderSymbol;
233
+ } else {
234
+ result += content[i];
235
+ }
236
+ }
237
+ }
238
+
239
+ if (isMaskBorders) {
240
+ const maskedStartString = mask(startString);
241
+ const maskedEndString = mask(endString);
242
+
243
+ result = result
244
+ .replace(new RegExp(startString, 'g'), maskedStartString)
245
+ .replace(new RegExp(endString, 'g'), maskedEndString);
246
+ }
247
+
248
+ return result;
249
+ };
250
+
251
+ const mask = content => {
252
+ let maskedContent = '';
253
+
254
+ for (let i = 0; i < content.length; i++) {
255
+ maskedContent += '_';
256
+ }
257
+
258
+ return maskedContent;
259
+ };
260
+
261
+ const maskQuoteContent = content => {
262
+
263
+ let maskedContent = '';
264
+ let isWithinQuotes = false;
265
+
266
+ for (let i = 0; i < content.length; i++) {
267
+ const char = content[i];
268
+
269
+ maskedContent += isWithinQuotes ?
270
+ '_' :
271
+ char;
272
+
273
+ if (char === '"') {
274
+ isWithinQuotes = !isWithinQuotes;
275
+
276
+ if (!isWithinQuotes) {
277
+ maskedContent = maskedContent.slice(0, -1);
278
+ maskedContent += '"';
279
+ }
280
+ }
281
+ }
282
+
283
+ return maskedContent;
284
+ };
285
+
286
+ // TODO Try to generalize this function;
287
+ const maskIsifTagContent = content => {
288
+
289
+ const openingTag = '<isif';
290
+ const closingTag = '</isif>';
291
+ let depthLevel = 0;
292
+ let maskedContent = '';
293
+
294
+ for (let i = 0; i < content.length; i++) {
295
+ const remainingContent = content.substring(i);
296
+
297
+ if (remainingContent.startsWith(openingTag)) {
298
+ maskedContent += depthLevel > 0 ? '_____' : openingTag;
299
+ i += openingTag.length;
300
+ depthLevel++;
301
+ }
302
+
303
+ maskedContent += depthLevel > 0 ?
304
+ '_' :
305
+ content[i];
306
+
307
+ if (remainingContent.startsWith(closingTag)) {
308
+ depthLevel--;
309
+ maskedContent += depthLevel > 0 ? '_______' : closingTag;
310
+ i += closingTag.length - 1;
311
+ }
312
+ }
313
+
314
+ return maskedContent;
315
+ };
316
+
317
+ const maskIsprintTagContent = content => {
318
+
319
+ const openingTag = '<isprint';
320
+ let isWithinIsprintTag = false;
321
+ let maskedContent = '';
322
+
323
+ if (content.indexOf(openingTag) < 0) {
324
+ return content;
325
+ }
326
+
327
+ for (let i = 0; i < content.length; i++) {
328
+ const remainingContent = content.substring(i);
329
+ const char = content[i];
330
+
331
+ if (remainingContent.startsWith(openingTag)) {
332
+ isWithinIsprintTag = true;
333
+ maskedContent += openingTag;
334
+ i += openingTag.length;
335
+ }
336
+
337
+ maskedContent += isWithinIsprintTag ?
338
+ '_' :
339
+ char;
340
+
341
+ if (char === '>' && isWithinIsprintTag) {
342
+ isWithinIsprintTag = !isWithinIsprintTag;
343
+
344
+ if (!isWithinIsprintTag) {
345
+ maskedContent = maskedContent.slice(0, -1);
346
+ maskedContent += '>';
347
+ }
348
+ }
349
+ }
350
+
351
+ return maskedContent;
352
+ };
353
+
354
+ const maskExpressionContent = content => {
355
+ const openingTag = '${';
356
+ const closingTag = '}';
357
+ let isWithinExpression = false;
358
+ let maskedContent = '';
359
+
360
+ for (let i = 0; i < content.length; i++) {
361
+ const remainingContent = content.substring(i);
362
+
363
+ if (remainingContent.startsWith(openingTag)) {
364
+ isWithinExpression = true;
365
+ maskedContent += openingTag;
366
+ i += openingTag.length;
367
+
368
+ if (remainingContent.startsWith('${}')) {
369
+ isWithinExpression = false;
370
+ maskedContent += '}';
371
+ continue;
372
+ }
373
+ }
374
+
375
+ maskedContent += isWithinExpression ?
376
+ '_' :
377
+ content[i];
378
+
379
+ if (remainingContent.startsWith(closingTag)) {
380
+ isWithinExpression = false;
381
+ maskedContent = maskedContent.slice(0, -1) + closingTag;
382
+ }
383
+ }
384
+
385
+ return maskedContent;
386
+ };
387
+
388
+ const maskJsonContent = content => {
389
+ let maskedContent = '';
390
+ let depth = 0;
391
+
392
+ for (let i = 0; i < content.length; i++) {
393
+ const char = content[i];
394
+
395
+ if (char === '}') {
396
+ depth -= 1;
397
+ }
398
+
399
+ maskedContent += depth > 0 ?
400
+ '_' :
401
+ char;
402
+
403
+ if (char === '{') {
404
+ depth += 1;
405
+ }
406
+ }
407
+
408
+ return maskedContent;
409
+ };
410
+
411
+ module.exports = {
412
+ maskIgnorableContent,
413
+ maskQuoteContent,
414
+ maskExpressionContent,
415
+ maskIsprintTagContent,
416
+ maskJsonContent,
417
+ maskIsifTagContent,
418
+ maskInBetween,
419
+ maskInBetween2,
420
+ maskInBetweenForTagWithAttributes
421
+ };