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.
- package/CHANGELOG.md +1184 -1159
- package/LICENSE +21 -21
- package/README.md +245 -245
- package/bin/isml-linter.js +32 -32
- package/ismllinter.config.js +33 -33
- package/package.json +53 -53
- package/scaffold_files/ismllinter.config.js +47 -47
- package/src/Builder.js +15 -15
- package/src/Constants.js +139 -139
- package/src/IsmlLinter.js +255 -255
- package/src/enums/ParseStatus.js +5 -5
- package/src/enums/SfccTagContainer.js +287 -287
- package/src/isml_tree/ContainerNode.js +38 -38
- package/src/isml_tree/IsmlNode.js +692 -684
- package/src/isml_tree/MaskUtils.js +421 -421
- package/src/isml_tree/ParseUtils.js +532 -506
- package/src/isml_tree/TreeBuilder.js +273 -273
- package/src/publicApi.js +24 -24
- package/src/rules/line_by_line/enforce-isprint.js +53 -53
- package/src/rules/line_by_line/enforce-require.js +35 -35
- package/src/rules/line_by_line/lowercase-filename.js +29 -29
- package/src/rules/line_by_line/max-lines.js +37 -37
- package/src/rules/line_by_line/no-br.js +36 -36
- package/src/rules/line_by_line/no-git-conflict.js +43 -43
- package/src/rules/line_by_line/no-import-package.js +34 -34
- package/src/rules/line_by_line/no-inline-style.js +34 -34
- package/src/rules/line_by_line/no-isscript.js +34 -34
- package/src/rules/line_by_line/no-space-only-lines.js +47 -47
- package/src/rules/line_by_line/no-tabs.js +38 -38
- package/src/rules/line_by_line/no-trailing-spaces.js +52 -52
- package/src/rules/prototypes/RulePrototype.js +79 -79
- package/src/rules/prototypes/SingleLineRulePrototype.js +47 -47
- package/src/rules/prototypes/TreeRulePrototype.js +84 -84
- package/src/rules/tree/align-isset.js +87 -87
- package/src/rules/tree/contextual-attrs.js +105 -105
- package/src/rules/tree/custom-tags.js +54 -54
- package/src/rules/tree/disallow-tags.js +39 -39
- package/src/rules/tree/empty-eof.js +66 -66
- package/src/rules/tree/enforce-security.js +85 -85
- package/src/rules/tree/eslint-to-isscript.js +179 -179
- package/src/rules/tree/indent.js +856 -853
- package/src/rules/tree/leading-iscache.js +39 -39
- package/src/rules/tree/leading-iscontent.js +35 -35
- package/src/rules/tree/max-depth.js +54 -54
- package/src/rules/tree/no-deprecated-attrs.js +67 -67
- package/src/rules/tree/no-embedded-isml.js +17 -17
- package/src/rules/tree/no-hardcode.js +51 -51
- package/src/rules/tree/no-iselse-slash.js +35 -35
- package/src/rules/tree/no-redundant-context.js +134 -134
- package/src/rules/tree/no-require-in-loop.js +63 -63
- package/src/rules/tree/one-element-per-line.js +82 -76
- package/src/util/CommandLineUtils.js +19 -19
- package/src/util/ConfigUtils.js +219 -219
- package/src/util/ConsoleUtils.js +327 -327
- package/src/util/CustomTagContainer.js +45 -45
- package/src/util/ExceptionUtils.js +173 -149
- package/src/util/FileUtils.js +79 -79
- package/src/util/GeneralUtils.js +60 -60
- package/src/util/NativeExtensionUtils.js +6 -6
- package/src/util/RuleUtils.js +295 -295
- package/src/util/TempRuleUtils.js +232 -232
|
@@ -1,273 +1,273 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const IsmlNode = require('./IsmlNode');
|
|
3
|
-
const ParseUtils = require('./ParseUtils');
|
|
4
|
-
const MaskUtils = require('./MaskUtils');
|
|
5
|
-
const ContainerNode = require('./ContainerNode');
|
|
6
|
-
const ExceptionUtils = require('../util/ExceptionUtils');
|
|
7
|
-
const GeneralUtils = require('../util/GeneralUtils');
|
|
8
|
-
|
|
9
|
-
const parse = (content, templatePath, isCrlfLineBreak, isEmbeddedNode) => {
|
|
10
|
-
|
|
11
|
-
const elementList = ParseUtils.getElementList(content, templatePath, isCrlfLineBreak);
|
|
12
|
-
const rootNode = new IsmlNode(undefined, undefined, undefined, undefined, isEmbeddedNode);
|
|
13
|
-
let currentParent = rootNode;
|
|
14
|
-
|
|
15
|
-
for (let i = 0; i < elementList.length; i++) {
|
|
16
|
-
const element = elementList[i];
|
|
17
|
-
|
|
18
|
-
validateNodeHead(element, templatePath);
|
|
19
|
-
|
|
20
|
-
const newNode = new IsmlNode(element.value, element.lineNumber, element.columnNumber, element.globalPos, isEmbeddedNode);
|
|
21
|
-
|
|
22
|
-
const containerResult = parseContainerElements(element, currentParent, newNode, templatePath);
|
|
23
|
-
|
|
24
|
-
currentParent = containerResult.currentParent;
|
|
25
|
-
|
|
26
|
-
if (containerResult.shouldContinueLoop) {
|
|
27
|
-
continue;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
currentParent = parseNonContainerElements(element, currentParent, newNode, templatePath);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
ParseUtils.checkBalance(rootNode, templatePath);
|
|
34
|
-
|
|
35
|
-
return rootNode;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const parseContainerElements = (element, currentParent, newNode, templatePath) => {
|
|
39
|
-
|
|
40
|
-
if (!currentParent.isContainerChild() && ['iselse', 'iselseif'].indexOf(element.tagType) >= 0) {
|
|
41
|
-
throw ExceptionUtils.unbalancedElementError(
|
|
42
|
-
currentParent.getType(),
|
|
43
|
-
currentParent.lineNumber,
|
|
44
|
-
currentParent.globalPos,
|
|
45
|
-
currentParent.head.trim().length,
|
|
46
|
-
templatePath
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (currentParent.isContainerChild() && ['iselse', 'iselseif'].indexOf(element.tagType) >= 0 && element.isClosingTag) {
|
|
51
|
-
throw ExceptionUtils.unexpectedClosingElementError(
|
|
52
|
-
element.tagType,
|
|
53
|
-
element.lineNumber,
|
|
54
|
-
element.globalPos,
|
|
55
|
-
element.value.trim().length,
|
|
56
|
-
templatePath
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (element.tagType === 'isif' && !element.isClosingTag) {
|
|
61
|
-
const containerNode = new ContainerNode();
|
|
62
|
-
currentParent.addChild(containerNode);
|
|
63
|
-
containerNode.addChild(newNode);
|
|
64
|
-
currentParent = newNode;
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
shouldContinueLoop : true,
|
|
68
|
-
currentParent : currentParent
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
} else if (element.tagType === 'iselse' || element.tagType === 'iselseif') {
|
|
72
|
-
currentParent = currentParent.parent;
|
|
73
|
-
currentParent.addChild(newNode);
|
|
74
|
-
currentParent = newNode;
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
shouldContinueLoop : true,
|
|
78
|
-
currentParent : currentParent
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
} else if (element.tagType === 'isif' && element.isClosingTag) {
|
|
82
|
-
|
|
83
|
-
if (!currentParent.isOfType('iselseif') &&
|
|
84
|
-
!currentParent.isOfType('iselse') &&
|
|
85
|
-
currentParent.getType() !== element.tagType
|
|
86
|
-
) {
|
|
87
|
-
throw ExceptionUtils.unbalancedElementError(
|
|
88
|
-
currentParent.getType(),
|
|
89
|
-
currentParent.lineNumber,
|
|
90
|
-
currentParent.globalPos,
|
|
91
|
-
currentParent.head.trim().length,
|
|
92
|
-
templatePath
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
currentParent.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
97
|
-
currentParent = currentParent.parent.parent;
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
shouldContinueLoop : true,
|
|
101
|
-
currentParent : currentParent
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
shouldContinueLoop : false,
|
|
107
|
-
currentParent : currentParent
|
|
108
|
-
};
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const parseNonContainerElements = (element, currentParent, newNode, templatePath) => {
|
|
112
|
-
if (element.isSelfClosing) {
|
|
113
|
-
currentParent.addChild(newNode);
|
|
114
|
-
} else if (!element.isClosingTag && element.tagType !== 'isif') {
|
|
115
|
-
currentParent.addChild(newNode);
|
|
116
|
-
|
|
117
|
-
if (!element.isSelfClosing) {
|
|
118
|
-
currentParent = newNode;
|
|
119
|
-
}
|
|
120
|
-
} else if (element.isClosingTag) {
|
|
121
|
-
|
|
122
|
-
const parentLastChild = currentParent.getLastChild();
|
|
123
|
-
|
|
124
|
-
if (element.tagType === currentParent.getType()) {
|
|
125
|
-
currentParent.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
126
|
-
|
|
127
|
-
} else if (element.isCustomTag && element.tagType === parentLastChild.getType()) {
|
|
128
|
-
parentLastChild.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
129
|
-
|
|
130
|
-
currentParent = parentLastChild;
|
|
131
|
-
|
|
132
|
-
} else if (element.isClosingTag && currentParent.isRoot()) {
|
|
133
|
-
throw ExceptionUtils.unbalancedElementError(
|
|
134
|
-
element.tagType,
|
|
135
|
-
element.lineNumber,
|
|
136
|
-
element.globalPos,
|
|
137
|
-
element.value.trim().length,
|
|
138
|
-
templatePath
|
|
139
|
-
);
|
|
140
|
-
} else if (element.isClosingTag) {
|
|
141
|
-
throw ExceptionUtils.unexpectedClosingElementError(
|
|
142
|
-
element.tagType,
|
|
143
|
-
element.lineNumber,
|
|
144
|
-
element.globalPos,
|
|
145
|
-
element.value.trim().length,
|
|
146
|
-
templatePath
|
|
147
|
-
);
|
|
148
|
-
} else {
|
|
149
|
-
throw ExceptionUtils.unbalancedElementError(
|
|
150
|
-
currentParent.getType(),
|
|
151
|
-
currentParent.lineNumber,
|
|
152
|
-
currentParent.globalPos,
|
|
153
|
-
currentParent.value.trim().length,
|
|
154
|
-
templatePath
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
currentParent = currentParent.parent;
|
|
159
|
-
|
|
160
|
-
if (element.tagType === 'isif' && element.isClosingTag) {
|
|
161
|
-
currentParent = currentParent.parent;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return currentParent;
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
const postProcess = (node, data = {}) => {
|
|
169
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
170
|
-
const child = node.children[i];
|
|
171
|
-
|
|
172
|
-
if (child.head.indexOf('template="util/modules"') >= 0) {
|
|
173
|
-
data.moduleDefinition = {
|
|
174
|
-
value : child.head,
|
|
175
|
-
lineNumber : child.lineNumber,
|
|
176
|
-
globalPos : child.globalPos,
|
|
177
|
-
length : child.head.trim().length
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (child.isCustomIsmlTag()) {
|
|
182
|
-
data.customModuleArray = data.customModuleArray || [];
|
|
183
|
-
data.customModuleArray.push({
|
|
184
|
-
value : child.head,
|
|
185
|
-
lineNumber : child.lineNumber,
|
|
186
|
-
globalPos : child.globalPos,
|
|
187
|
-
length : child.head.trim().length
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
rectifyNodeIndentation(node, child);
|
|
192
|
-
postProcess(child, data);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return data;
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
const build = (templatePath, content, isCrlfLineBreak) => {
|
|
199
|
-
|
|
200
|
-
const ParseStatus = require('../enums/ParseStatus');
|
|
201
|
-
|
|
202
|
-
const result = {
|
|
203
|
-
templatePath,
|
|
204
|
-
status : ParseStatus.NO_ERRORS
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
try {
|
|
208
|
-
const templateContent = GeneralUtils.toLF(content || fs.readFileSync(templatePath, 'utf-8'));
|
|
209
|
-
result.rootNode = parse(templateContent, templatePath, isCrlfLineBreak);
|
|
210
|
-
result.data = postProcess(result.rootNode);
|
|
211
|
-
|
|
212
|
-
result.rootNode.tree = result;
|
|
213
|
-
|
|
214
|
-
} catch (e) {
|
|
215
|
-
result.rootNode = null;
|
|
216
|
-
result.status = ParseStatus.INVALID_DOM;
|
|
217
|
-
result.exception = e.type === ExceptionUtils.types.UNKNOWN_ERROR ?
|
|
218
|
-
e.message :
|
|
219
|
-
e;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return result;
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* In the main part of tree build, a node A might hold the next node B's indentation in the last part of
|
|
227
|
-
* A, be it in its value or tail value. This function removes that trailing indentation from A and
|
|
228
|
-
* adds it to B as a leading indentation;
|
|
229
|
-
*/
|
|
230
|
-
const rectifyNodeIndentation = (node, child) => {
|
|
231
|
-
const previousSibling = child.getPreviousSibling();
|
|
232
|
-
|
|
233
|
-
if (child.isContainer()) {
|
|
234
|
-
child = child.children[0];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (previousSibling && previousSibling.isOfType('text')) {
|
|
238
|
-
const trailingLineBreakQty = ParseUtils.getTrailingEmptyCharsQty(previousSibling.head);
|
|
239
|
-
|
|
240
|
-
previousSibling.head = previousSibling.head.substring(0, previousSibling.head.length - trailingLineBreakQty);
|
|
241
|
-
child.head = ParseUtils.getBlankSpaceString(trailingLineBreakQty) + child.head;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (child.isLastChild() && child.isOfType('text')) {
|
|
245
|
-
let trailingLineBreakQty = 0;
|
|
246
|
-
|
|
247
|
-
trailingLineBreakQty = ParseUtils.getTrailingEmptyCharsQty(child.head);
|
|
248
|
-
child.head = child.head.substring(0, child.head.length - trailingLineBreakQty);
|
|
249
|
-
|
|
250
|
-
node.tail = ParseUtils.getBlankSpaceString(trailingLineBreakQty) + node.tail;
|
|
251
|
-
}
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const validateNodeHead = (element, templatePath) => {
|
|
255
|
-
|
|
256
|
-
if (element.type !== 'text') {
|
|
257
|
-
const trimmedElement = element.value.trim();
|
|
258
|
-
const maskedElement = MaskUtils.maskQuoteContent(trimmedElement);
|
|
259
|
-
|
|
260
|
-
if (maskedElement.endsWith('_')) {
|
|
261
|
-
throw ExceptionUtils.unbalancedQuotesError(
|
|
262
|
-
element.tagType,
|
|
263
|
-
element.lineNumber,
|
|
264
|
-
element.globalPos,
|
|
265
|
-
trimmedElement.length,
|
|
266
|
-
templatePath
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
module.exports.build = build;
|
|
273
|
-
module.exports.parse = parse;
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const IsmlNode = require('./IsmlNode');
|
|
3
|
+
const ParseUtils = require('./ParseUtils');
|
|
4
|
+
const MaskUtils = require('./MaskUtils');
|
|
5
|
+
const ContainerNode = require('./ContainerNode');
|
|
6
|
+
const ExceptionUtils = require('../util/ExceptionUtils');
|
|
7
|
+
const GeneralUtils = require('../util/GeneralUtils');
|
|
8
|
+
|
|
9
|
+
const parse = (content, templatePath, isCrlfLineBreak, isEmbeddedNode) => {
|
|
10
|
+
|
|
11
|
+
const elementList = ParseUtils.getElementList(content, templatePath, isCrlfLineBreak);
|
|
12
|
+
const rootNode = new IsmlNode(undefined, undefined, undefined, undefined, isEmbeddedNode);
|
|
13
|
+
let currentParent = rootNode;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < elementList.length; i++) {
|
|
16
|
+
const element = elementList[i];
|
|
17
|
+
|
|
18
|
+
validateNodeHead(element, templatePath);
|
|
19
|
+
|
|
20
|
+
const newNode = new IsmlNode(element.value, element.lineNumber, element.columnNumber, element.globalPos, isEmbeddedNode);
|
|
21
|
+
|
|
22
|
+
const containerResult = parseContainerElements(element, currentParent, newNode, templatePath);
|
|
23
|
+
|
|
24
|
+
currentParent = containerResult.currentParent;
|
|
25
|
+
|
|
26
|
+
if (containerResult.shouldContinueLoop) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
currentParent = parseNonContainerElements(element, currentParent, newNode, templatePath);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ParseUtils.checkBalance(rootNode, templatePath);
|
|
34
|
+
|
|
35
|
+
return rootNode;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const parseContainerElements = (element, currentParent, newNode, templatePath) => {
|
|
39
|
+
|
|
40
|
+
if (!currentParent.isContainerChild() && ['iselse', 'iselseif'].indexOf(element.tagType) >= 0) {
|
|
41
|
+
throw ExceptionUtils.unbalancedElementError(
|
|
42
|
+
currentParent.getType(),
|
|
43
|
+
currentParent.lineNumber,
|
|
44
|
+
currentParent.globalPos,
|
|
45
|
+
currentParent.head.trim().length,
|
|
46
|
+
templatePath
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (currentParent.isContainerChild() && ['iselse', 'iselseif'].indexOf(element.tagType) >= 0 && element.isClosingTag) {
|
|
51
|
+
throw ExceptionUtils.unexpectedClosingElementError(
|
|
52
|
+
element.tagType,
|
|
53
|
+
element.lineNumber,
|
|
54
|
+
element.globalPos,
|
|
55
|
+
element.value.trim().length,
|
|
56
|
+
templatePath
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (element.tagType === 'isif' && !element.isClosingTag) {
|
|
61
|
+
const containerNode = new ContainerNode();
|
|
62
|
+
currentParent.addChild(containerNode);
|
|
63
|
+
containerNode.addChild(newNode);
|
|
64
|
+
currentParent = newNode;
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
shouldContinueLoop : true,
|
|
68
|
+
currentParent : currentParent
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
} else if (element.tagType === 'iselse' || element.tagType === 'iselseif') {
|
|
72
|
+
currentParent = currentParent.parent;
|
|
73
|
+
currentParent.addChild(newNode);
|
|
74
|
+
currentParent = newNode;
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
shouldContinueLoop : true,
|
|
78
|
+
currentParent : currentParent
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
} else if (element.tagType === 'isif' && element.isClosingTag) {
|
|
82
|
+
|
|
83
|
+
if (!currentParent.isOfType('iselseif') &&
|
|
84
|
+
!currentParent.isOfType('iselse') &&
|
|
85
|
+
currentParent.getType() !== element.tagType
|
|
86
|
+
) {
|
|
87
|
+
throw ExceptionUtils.unbalancedElementError(
|
|
88
|
+
currentParent.getType(),
|
|
89
|
+
currentParent.lineNumber,
|
|
90
|
+
currentParent.globalPos,
|
|
91
|
+
currentParent.head.trim().length,
|
|
92
|
+
templatePath
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
currentParent.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
97
|
+
currentParent = currentParent.parent.parent;
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
shouldContinueLoop : true,
|
|
101
|
+
currentParent : currentParent
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
shouldContinueLoop : false,
|
|
107
|
+
currentParent : currentParent
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const parseNonContainerElements = (element, currentParent, newNode, templatePath) => {
|
|
112
|
+
if (element.isSelfClosing) {
|
|
113
|
+
currentParent.addChild(newNode);
|
|
114
|
+
} else if (!element.isClosingTag && element.tagType !== 'isif') {
|
|
115
|
+
currentParent.addChild(newNode);
|
|
116
|
+
|
|
117
|
+
if (!element.isSelfClosing) {
|
|
118
|
+
currentParent = newNode;
|
|
119
|
+
}
|
|
120
|
+
} else if (element.isClosingTag) {
|
|
121
|
+
|
|
122
|
+
const parentLastChild = currentParent.getLastChild();
|
|
123
|
+
|
|
124
|
+
if (element.tagType === currentParent.getType()) {
|
|
125
|
+
currentParent.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
126
|
+
|
|
127
|
+
} else if (element.isCustomTag && element.tagType === parentLastChild.getType()) {
|
|
128
|
+
parentLastChild.setTail(element.value, element.lineNumber, element.columnNumber, element.globalPos);
|
|
129
|
+
|
|
130
|
+
currentParent = parentLastChild;
|
|
131
|
+
|
|
132
|
+
} else if (element.isClosingTag && currentParent.isRoot()) {
|
|
133
|
+
throw ExceptionUtils.unbalancedElementError(
|
|
134
|
+
element.tagType,
|
|
135
|
+
element.lineNumber,
|
|
136
|
+
element.globalPos,
|
|
137
|
+
element.value.trim().length,
|
|
138
|
+
templatePath
|
|
139
|
+
);
|
|
140
|
+
} else if (element.isClosingTag) {
|
|
141
|
+
throw ExceptionUtils.unexpectedClosingElementError(
|
|
142
|
+
element.tagType,
|
|
143
|
+
element.lineNumber,
|
|
144
|
+
element.globalPos,
|
|
145
|
+
element.value.trim().length,
|
|
146
|
+
templatePath
|
|
147
|
+
);
|
|
148
|
+
} else {
|
|
149
|
+
throw ExceptionUtils.unbalancedElementError(
|
|
150
|
+
currentParent.getType(),
|
|
151
|
+
currentParent.lineNumber,
|
|
152
|
+
currentParent.globalPos,
|
|
153
|
+
currentParent.value.trim().length,
|
|
154
|
+
templatePath
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
currentParent = currentParent.parent;
|
|
159
|
+
|
|
160
|
+
if (element.tagType === 'isif' && element.isClosingTag) {
|
|
161
|
+
currentParent = currentParent.parent;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return currentParent;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const postProcess = (node, data = {}) => {
|
|
169
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
170
|
+
const child = node.children[i];
|
|
171
|
+
|
|
172
|
+
if (child.head.indexOf('template="util/modules"') >= 0) {
|
|
173
|
+
data.moduleDefinition = {
|
|
174
|
+
value : child.head,
|
|
175
|
+
lineNumber : child.lineNumber,
|
|
176
|
+
globalPos : child.globalPos,
|
|
177
|
+
length : child.head.trim().length
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (child.isCustomIsmlTag()) {
|
|
182
|
+
data.customModuleArray = data.customModuleArray || [];
|
|
183
|
+
data.customModuleArray.push({
|
|
184
|
+
value : child.head,
|
|
185
|
+
lineNumber : child.lineNumber,
|
|
186
|
+
globalPos : child.globalPos,
|
|
187
|
+
length : child.head.trim().length
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
rectifyNodeIndentation(node, child);
|
|
192
|
+
postProcess(child, data);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return data;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const build = (templatePath, content, isCrlfLineBreak) => {
|
|
199
|
+
|
|
200
|
+
const ParseStatus = require('../enums/ParseStatus');
|
|
201
|
+
|
|
202
|
+
const result = {
|
|
203
|
+
templatePath,
|
|
204
|
+
status : ParseStatus.NO_ERRORS
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
const templateContent = GeneralUtils.toLF(content || fs.readFileSync(templatePath, 'utf-8'));
|
|
209
|
+
result.rootNode = parse(templateContent, templatePath, isCrlfLineBreak);
|
|
210
|
+
result.data = postProcess(result.rootNode);
|
|
211
|
+
|
|
212
|
+
result.rootNode.tree = result;
|
|
213
|
+
|
|
214
|
+
} catch (e) {
|
|
215
|
+
result.rootNode = null;
|
|
216
|
+
result.status = ParseStatus.INVALID_DOM;
|
|
217
|
+
result.exception = e.type === ExceptionUtils.types.UNKNOWN_ERROR ?
|
|
218
|
+
e.message :
|
|
219
|
+
e;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return result;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* In the main part of tree build, a node A might hold the next node B's indentation in the last part of
|
|
227
|
+
* A, be it in its value or tail value. This function removes that trailing indentation from A and
|
|
228
|
+
* adds it to B as a leading indentation;
|
|
229
|
+
*/
|
|
230
|
+
const rectifyNodeIndentation = (node, child) => {
|
|
231
|
+
const previousSibling = child.getPreviousSibling();
|
|
232
|
+
|
|
233
|
+
if (child.isContainer()) {
|
|
234
|
+
child = child.children[0];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (previousSibling && previousSibling.isOfType('text')) {
|
|
238
|
+
const trailingLineBreakQty = ParseUtils.getTrailingEmptyCharsQty(previousSibling.head);
|
|
239
|
+
|
|
240
|
+
previousSibling.head = previousSibling.head.substring(0, previousSibling.head.length - trailingLineBreakQty);
|
|
241
|
+
child.head = ParseUtils.getBlankSpaceString(trailingLineBreakQty) + child.head;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (child.isLastChild() && child.isOfType('text')) {
|
|
245
|
+
let trailingLineBreakQty = 0;
|
|
246
|
+
|
|
247
|
+
trailingLineBreakQty = ParseUtils.getTrailingEmptyCharsQty(child.head);
|
|
248
|
+
child.head = child.head.substring(0, child.head.length - trailingLineBreakQty);
|
|
249
|
+
|
|
250
|
+
node.tail = ParseUtils.getBlankSpaceString(trailingLineBreakQty) + node.tail;
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const validateNodeHead = (element, templatePath) => {
|
|
255
|
+
|
|
256
|
+
if (element.type !== 'text') {
|
|
257
|
+
const trimmedElement = element.value.trim();
|
|
258
|
+
const maskedElement = MaskUtils.maskQuoteContent(trimmedElement);
|
|
259
|
+
|
|
260
|
+
if (maskedElement.endsWith('_')) {
|
|
261
|
+
throw ExceptionUtils.unbalancedQuotesError(
|
|
262
|
+
element.tagType,
|
|
263
|
+
element.lineNumber,
|
|
264
|
+
element.globalPos,
|
|
265
|
+
trimmedElement.length,
|
|
266
|
+
templatePath
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
module.exports.build = build;
|
|
273
|
+
module.exports.parse = parse;
|
package/src/publicApi.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
const IsmlLinter = require('./IsmlLinter');
|
|
2
|
-
const Builder = require('./Builder');
|
|
3
|
-
const ConsoleUtils = require('./util/ConsoleUtils');
|
|
4
|
-
|
|
5
|
-
let linterResult = {};
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
setConfig : json => IsmlLinter.setConfig(json),
|
|
9
|
-
getConfig : () => IsmlLinter.getConfig(),
|
|
10
|
-
parse : (path, content, config) => {
|
|
11
|
-
|
|
12
|
-
if (config) {
|
|
13
|
-
IsmlLinter.setConfig(config);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
linterResult = IsmlLinter.run(path, content);
|
|
17
|
-
return linterResult;
|
|
18
|
-
},
|
|
19
|
-
printResults : () => ConsoleUtils.displayOccurrenceList(linterResult),
|
|
20
|
-
build : path => Builder.run(path),
|
|
21
|
-
|
|
22
|
-
IsmlLinter,
|
|
23
|
-
Builder
|
|
24
|
-
};
|
|
1
|
+
const IsmlLinter = require('./IsmlLinter');
|
|
2
|
+
const Builder = require('./Builder');
|
|
3
|
+
const ConsoleUtils = require('./util/ConsoleUtils');
|
|
4
|
+
|
|
5
|
+
let linterResult = {};
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
setConfig : json => IsmlLinter.setConfig(json),
|
|
9
|
+
getConfig : () => IsmlLinter.getConfig(),
|
|
10
|
+
parse : (path, content, config) => {
|
|
11
|
+
|
|
12
|
+
if (config) {
|
|
13
|
+
IsmlLinter.setConfig(config);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
linterResult = IsmlLinter.run(path, content);
|
|
17
|
+
return linterResult;
|
|
18
|
+
},
|
|
19
|
+
printResults : () => ConsoleUtils.displayOccurrenceList(linterResult),
|
|
20
|
+
build : path => Builder.run(path),
|
|
21
|
+
|
|
22
|
+
IsmlLinter,
|
|
23
|
+
Builder
|
|
24
|
+
};
|