Skip to content

Commit f20e2bf

Browse files
committed
reduce multilevel property reference
- this.options to options - move htmlEntity flag to build time
1 parent 69da9ba commit f20e2bf

File tree

1 file changed

+60
-60
lines changed

1 file changed

+60
-60
lines changed

src/xmlparser/OrderedObjParser.js

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -161,28 +161,29 @@ function addExternalEntities(externalEntities) {
161161
* @param {boolean} escapeEntities
162162
*/
163163
function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
164+
const options = this.options;
164165
if (val !== undefined) {
165-
if (this.options.trimValues && !dontTrim) {
166+
if (options.trimValues && !dontTrim) {
166167
val = val.trim();
167168
}
168169
if (val.length > 0) {
169170
if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);
170171

171172
// Pass jPath string or matcher based on options.jPath setting
172-
const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
173-
const newval = this.options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);
173+
const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;
174+
const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);
174175
if (newval === null || newval === undefined) {
175176
//don't parse
176177
return val;
177178
} else if (typeof newval !== typeof val || newval !== val) {
178179
//overwrite
179180
return newval;
180-
} else if (this.options.trimValues) {
181-
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
181+
} else if (options.trimValues) {
182+
return parseValue(val, options.parseTagValue, options.numberParseOptions);
182183
} else {
183184
const trimmedVal = val.trim();
184185
if (trimmedVal === val) {
185-
return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
186+
return parseValue(val, options.parseTagValue, options.numberParseOptions);
186187
} else {
187188
return val;
188189
}
@@ -210,7 +211,8 @@ function resolveNameSpace(tagname) {
210211
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
211212

212213
function buildAttributesMap(attrStr, jPath, tagName) {
213-
if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') {
214+
const options = this.options;
215+
if (options.ignoreAttributes !== true && typeof attrStr === 'string') {
214216
// attrStr = attrStr.replace(/\r?\n/g, ' ');
215217
//attrStr = attrStr || attrStr.trim();
216218

@@ -230,7 +232,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
230232

231233
if (attrName.length && oldVal !== undefined) {
232234
let val = oldVal;
233-
if (this.options.trimValues) val = val.trim();
235+
if (options.trimValues) val = val.trim();
234236
val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);
235237
processedVals[i] = val;
236238

@@ -245,7 +247,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
245247
}
246248

247249
// Hoist toString() once — path doesn't change during attribute processing
248-
const jPathStr = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
250+
const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;
249251

250252
// Second pass: apply processors, build final attrs
251253
let hasAttrs = false;
@@ -254,28 +256,28 @@ function buildAttributesMap(attrStr, jPath, tagName) {
254256

255257
if (this.ignoreAttributesFn(attrName, jPathStr)) continue;
256258

257-
let aName = this.options.attributeNamePrefix + attrName;
259+
let aName = options.attributeNamePrefix + attrName;
258260

259261
if (attrName.length) {
260-
if (this.options.transformAttributeName) {
261-
aName = this.options.transformAttributeName(aName);
262+
if (options.transformAttributeName) {
263+
aName = options.transformAttributeName(aName);
262264
}
263-
aName = sanitizeName(aName, this.options);
265+
aName = sanitizeName(aName, options);
264266

265267
if (matches[i][4] !== undefined) {
266268
// Reuse already-processed value — no double entity replacement
267269
const oldVal = processedVals[i];
268270

269-
const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPathStr);
271+
const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);
270272
if (newVal === null || newVal === undefined) {
271273
attrs[aName] = oldVal;
272274
} else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {
273275
attrs[aName] = newVal;
274276
} else {
275-
attrs[aName] = parseValue(oldVal, this.options.parseAttributeValue, this.options.numberParseOptions);
277+
attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);
276278
}
277279
hasAttrs = true;
278-
} else if (this.options.allowBooleanAttributes) {
280+
} else if (options.allowBooleanAttributes) {
279281
attrs[aName] = true;
280282
hasAttrs = true;
281283
}
@@ -284,9 +286,9 @@ function buildAttributesMap(attrStr, jPath, tagName) {
284286

285287
if (!hasAttrs) return;
286288

287-
if (this.options.attributesGroupName) {
289+
if (options.attributesGroupName) {
288290
const attrCollection = {};
289-
attrCollection[this.options.attributesGroupName] = attrs;
291+
attrCollection[options.attributesGroupName] = attrs;
290292
return attrCollection;
291293
}
292294
return attrs;
@@ -306,9 +308,9 @@ const parseXml = function (xmlData) {
306308
this.currentExpandedLength = 0;
307309
this.docTypeEntitiesKeys = [];
308310
this.lastEntitiesKeys = Object.keys(this.lastEntities);
309-
this.htmlEntitiesKeys = Object.keys(this.htmlEntities);
310-
311-
const docTypeReader = new DocTypeReader(this.options.processEntities);
311+
this.htmlEntitiesKeys = this.options.htmlEntities ? Object.keys(this.htmlEntities) : [];
312+
const options = this.options;
313+
const docTypeReader = new DocTypeReader(options.processEntities);
312314
const xmlLen = xmlData.length;
313315
for (let i = 0; i < xmlLen; i++) {//for each char in XML data
314316
const ch = xmlData[i];
@@ -320,25 +322,25 @@ const parseXml = function (xmlData) {
320322
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.")
321323
let tagName = xmlData.substring(i + 2, closeIndex).trim();
322324

323-
if (this.options.removeNSPrefix) {
325+
if (options.removeNSPrefix) {
324326
const colonIndex = tagName.indexOf(":");
325327
if (colonIndex !== -1) {
326328
tagName = tagName.substr(colonIndex + 1);
327329
}
328330
}
329331

330-
tagName = transformTagName(this.options.transformTagName, tagName, "", this.options).tagName;
332+
tagName = transformTagName(options.transformTagName, tagName, "", options).tagName;
331333

332334
if (currentNode) {
333335
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
334336
}
335337

336338
//check if last tag of nested tag was unpaired tag
337339
const lastTagName = this.matcher.getCurrentTag();
338-
if (tagName && this.options.unpairedTagsSet.has(tagName)) {
340+
if (tagName && options.unpairedTagsSet.has(tagName)) {
339341
throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
340342
}
341-
if (lastTagName && this.options.unpairedTagsSet.has(lastTagName)) {
343+
if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {
342344
// Pop the unpaired tag
343345
this.matcher.pop();
344346
this.tagsNodeStack.pop();
@@ -356,12 +358,12 @@ const parseXml = function (xmlData) {
356358
if (!tagData) throw new Error("Pi Tag is not closed.");
357359

358360
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
359-
if ((this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags) {
361+
if ((options.ignoreDeclaration && tagData.tagName === "?xml") || options.ignorePiTags) {
360362
//do nothing
361363
} else {
362364

363365
const childNode = new xmlNode(tagData.tagName);
364-
childNode.add(this.options.textNodeName, "");
366+
childNode.add(options.textNodeName, "");
365367

366368
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
367369
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
@@ -375,12 +377,12 @@ const parseXml = function (xmlData) {
375377
&& xmlData.charCodeAt(i + 2) === 45
376378
&& xmlData.charCodeAt(i + 3) === 45) { //'!--'
377379
const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.")
378-
if (this.options.commentPropName) {
380+
if (options.commentPropName) {
379381
const comment = xmlData.substring(i + 4, endIndex - 2);
380382

381383
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
382384

383-
currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
385+
currentNode.add(options.commentPropName, [{ [options.textNodeName]: comment }]);
384386
}
385387
i = endIndex;
386388
} else if (c1 === 33
@@ -400,15 +402,15 @@ const parseXml = function (xmlData) {
400402
if (val == undefined) val = "";
401403

402404
//cdata should be set even if it is 0 length string
403-
if (this.options.cdataPropName) {
404-
currentNode.add(this.options.cdataPropName, [{ [this.options.textNodeName]: tagExp }]);
405+
if (options.cdataPropName) {
406+
currentNode.add(options.cdataPropName, [{ [options.textNodeName]: tagExp }]);
405407
} else {
406-
currentNode.add(this.options.textNodeName, val);
408+
currentNode.add(options.textNodeName, val);
407409
}
408410

409411
i = closeIndex + 2;
410412
} else {//Opening tag
411-
let result = readTagExp(xmlData, i, this.options.removeNSPrefix);
413+
let result = readTagExp(xmlData, i, options.removeNSPrefix);
412414

413415
// Safety check: readTagExp can return undefined
414416
if (!result) {
@@ -423,13 +425,13 @@ const parseXml = function (xmlData) {
423425
let attrExpPresent = result.attrExpPresent;
424426
let closeIndex = result.closeIndex;
425427

426-
({ tagName, tagExp } = transformTagName(this.options.transformTagName, tagName, tagExp, this.options));
428+
({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
427429

428-
if (this.options.strictReservedNames &&
429-
(tagName === this.options.commentPropName
430-
|| tagName === this.options.cdataPropName
431-
|| tagName === this.options.textNodeName
432-
|| tagName === this.options.attributesGroupName
430+
if (options.strictReservedNames &&
431+
(tagName === options.commentPropName
432+
|| tagName === options.cdataPropName
433+
|| tagName === options.textNodeName
434+
|| tagName === options.attributesGroupName
433435
)) {
434436
throw new Error(`Invalid tag name: ${tagName}`);
435437
}
@@ -444,7 +446,7 @@ const parseXml = function (xmlData) {
444446

445447
//check if last tag was unpaired tag
446448
const lastTag = currentNode;
447-
if (lastTag && this.options.unpairedTagsSet.has(lastTag.tagname)) {
449+
if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {
448450
currentNode = this.tagsNodeStack.pop();
449451
this.matcher.pop();
450452
}
@@ -486,7 +488,7 @@ const parseXml = function (xmlData) {
486488

487489
if (prefixedAttrs) {
488490
// Extract raw attributes (without prefix) for our use
489-
rawAttrs = extractRawAttributes(prefixedAttrs, this.options);
491+
rawAttrs = extractRawAttributes(prefixedAttrs, options);
490492
}
491493
}
492494

@@ -504,7 +506,7 @@ const parseXml = function (xmlData) {
504506
i = result.closeIndex;
505507
}
506508
//unpaired tag
507-
else if (this.options.unpairedTagsSet.has(tagName)) {
509+
else if (options.unpairedTagsSet.has(tagName)) {
508510
i = result.closeIndex;
509511
}
510512
//normal tag
@@ -523,7 +525,7 @@ const parseXml = function (xmlData) {
523525
}
524526

525527
// For stop nodes, store raw content as-is without any processing
526-
childNode.add(this.options.textNodeName, tagContent);
528+
childNode.add(options.textNodeName, tagContent);
527529

528530
this.matcher.pop(); // Pop the stop node tag
529531
this.isCurrentNodeStopNode = false; // Reset flag
@@ -532,7 +534,7 @@ const parseXml = function (xmlData) {
532534
} else {
533535
//selfClosing tag
534536
if (isSelfClosing) {
535-
({ tagName, tagExp } = transformTagName(this.options.transformTagName, tagName, tagExp, this.options));
537+
({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
536538

537539
const childNode = new xmlNode(tagName);
538540
if (prefixedAttrs) {
@@ -542,7 +544,7 @@ const parseXml = function (xmlData) {
542544
this.matcher.pop(); // Pop self-closing tag
543545
this.isCurrentNodeStopNode = false; // Reset flag
544546
}
545-
else if (this.options.unpairedTagsSet.has(tagName)) {//unpaired tag
547+
else if (options.unpairedTagsSet.has(tagName)) {//unpaired tag
546548
const childNode = new xmlNode(tagName);
547549
if (prefixedAttrs) {
548550
childNode[":@"] = prefixedAttrs;
@@ -557,7 +559,7 @@ const parseXml = function (xmlData) {
557559
//opening tag
558560
else {
559561
const childNode = new xmlNode(tagName);
560-
if (this.tagsNodeStack.length > this.options.maxNestedTags) {
562+
if (this.tagsNodeStack.length > options.maxNestedTags) {
561563
throw new Error("Maximum nested tags exceeded");
562564
}
563565
this.tagsNodeStack.push(currentNode);
@@ -680,22 +682,20 @@ function replaceEntitiesValue(val, tagName, jPath) {
680682
if (val.indexOf('&') === -1) return val;
681683

682684
// Replace HTML entities if enabled
683-
if (this.options.htmlEntities) {
684-
for (const entityName of this.htmlEntitiesKeys) {
685-
const entity = this.htmlEntities[entityName];
686-
const matches = val.match(entity.regex);
687-
if (matches) {
688-
//console.log(matches);
689-
this.entityExpansionCount += matches.length;
690-
if (entityConfig.maxTotalExpansions &&
691-
this.entityExpansionCount > entityConfig.maxTotalExpansions) {
692-
throw new Error(
693-
`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
694-
);
695-
}
685+
for (const entityName of this.htmlEntitiesKeys) {
686+
const entity = this.htmlEntities[entityName];
687+
const matches = val.match(entity.regex);
688+
if (matches) {
689+
//console.log(matches);
690+
this.entityExpansionCount += matches.length;
691+
if (entityConfig.maxTotalExpansions &&
692+
this.entityExpansionCount > entityConfig.maxTotalExpansions) {
693+
throw new Error(
694+
`Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
695+
);
696696
}
697-
val = val.replace(entity.regex, entity.val);
698697
}
698+
val = val.replace(entity.regex, entity.val);
699699
}
700700

701701
// Replace ampersand entity last

0 commit comments

Comments
 (0)