Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unifying attributes with other child nodes. #84

Merged
merged 10 commits into from
Jan 29, 2024
2 changes: 1 addition & 1 deletion src/dom/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { XDocument } from "./xdocument";
import { XNode } from './xnode';

// Wrapper around DOM methods so we can condense their invocations.
export function domGetAttributeValue(node: any, name: string) {
export function domGetAttributeValue(node: XNode, name: string) {
return node.getAttributeValue(name);
}

Expand Down
5 changes: 3 additions & 2 deletions src/dom/xdocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ export class XDocument extends XNode {
this.documentElement = null;
}

clear() {
// TODO: Do we still need this?
/* clear() {
XNode.recycle(this.documentElement);
this.documentElement = null;
}
} */

appendChild(node: any) {
super.appendChild(node);
Expand Down
44 changes: 30 additions & 14 deletions src/dom/xml-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @param disallowBrowserSpecificOptimization A boolean, to avoid browser optimization.
* @returns The XML value as a string.
*/
export function xmlValue(node: any, disallowBrowserSpecificOptimization: boolean = false): string {
export function xmlValue(node: XNode | any, disallowBrowserSpecificOptimization: boolean = false): string {
if (!node) {
return '';
}
Expand All @@ -42,25 +42,28 @@
case DOM_DOCUMENT_NODE:
case DOM_DOCUMENT_FRAGMENT_NODE:
if (!disallowBrowserSpecificOptimization) {
// IE, Safari, Opera, and friends
// Only returns something if node has either `innerText` or `textContent` (not an XNode).
// IE, Safari, Opera, and friends (`innerText`)
const innerText = node.innerText;
if (innerText != undefined) {
return innerText;
}
// Firefox
// Firefox (`textContent`)
const textContent = node.textContent;
if (textContent != undefined) {
return textContent;
}
}

if (node.transformedChildNodes.length > 0) {
for (let i = 0; i < node.transformedChildNodes.length; ++i) {
ret += xmlValue(node.transformedChildNodes[i]);
const transformedTextNodes = node.transformedChildNodes.filter((n: XNode) => n.nodeType !== DOM_ATTRIBUTE_NODE);
for (let i = 0; i < transformedTextNodes.length; ++i) {
ret += xmlValue(transformedTextNodes[i]);
}
} else {
for (let i = 0; i < node.childNodes.length; ++i) {
ret += xmlValue(node.childNodes[i]);
const textNodes = node.childNodes.filter((n: XNode) => n.nodeType !== DOM_ATTRIBUTE_NODE);
for (let i = 0; i < textNodes.length; ++i) {
ret += xmlValue(textNodes[i]);
}
}

Expand Down Expand Up @@ -96,7 +99,7 @@
return textContent;
}
}
// pobrecito!

const len = node.transformedChildNodes.length;
for (let i = 0; i < len; ++i) {
ret += xmlValue(node.transformedChildNodes[i]);
Expand Down Expand Up @@ -137,10 +140,15 @@
buffer.push(`<!--${node.nodeValue}-->`);
} else if (node.nodeType == DOM_ELEMENT_NODE) {
buffer.push(`<${xmlFullNodeName(node)}`);
for (let i = 0; i < node.attributes.length; ++i) {
const a = node.attributes[i];
if (a && a.nodeName && a.nodeValue) {
buffer.push(` ${xmlFullNodeName(a)}="${xmlEscapeAttr(a.nodeValue)}"`);

for (let i = 0; i < node.childNodes.length; ++i) {
const childNode = node.childNodes[i];
if (!childNode || childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
continue;
}

if (childNode.nodeName && childNode.nodeValue) {
buffer.push(` ${xmlFullNodeName(childNode)}="${xmlEscapeAttr(childNode.nodeValue)}"`);
}
}

Expand Down Expand Up @@ -233,7 +241,11 @@
function xmlElementLogicTrivial(node: XNode, buffer: string[], options: XmlOutputOptions) {
buffer.push(`<${xmlFullNodeName(node)}`);

const attributes = node.transformedAttributes || node.attributes;
let attributes = node.transformedChildNodes.filter(n => n.nodeType === DOM_ATTRIBUTE_NODE);
if (attributes.length === 0) {
attributes = node.childNodes.filter(n => n.nodeType === DOM_ATTRIBUTE_NODE);
}

for (let i = 0; i < attributes.length; ++i) {
const attribute = attributes[i];
if (!attribute) {
Expand All @@ -245,7 +257,11 @@
}
}

let childNodes = node.transformedChildNodes.length > 0 ? node.transformedChildNodes : node.childNodes;
let childNodes = node.transformedChildNodes.filter(n => n.nodeType !== DOM_ATTRIBUTE_NODE);
if (childNodes.length === 0) {
childNodes = node.childNodes.filter(n => n.nodeType !== DOM_ATTRIBUTE_NODE);

Check warning on line 262 in src/dom/xml-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 262 in src/dom/xml-functions.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
}

childNodes = childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
if (childNodes.length === 0) {
if (options.outputMethod === 'html' && ['hr', 'link', 'meta'].includes(node.nodeName)) {
Expand Down
32 changes: 21 additions & 11 deletions src/dom/xml-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
XML11_VERSION_INFO
} from './xmltoken';
import { XNode } from './xnode';
import { DOM_ATTRIBUTE_NODE } from '../constants';

/**
* Original author: Steffen Meschkat <[email protected]> (the `xmlParse` function,
Expand Down Expand Up @@ -67,12 +68,17 @@
};
let n = node;
while (n !== null) {
for (let i = 0; i < n.attributes.length; i++) {
if (n.attributes[i].nodeName.startsWith('xmlns:')) {
const prefix = n.attributes[i].nodeName.split(':')[1];
if (!(prefix in map)) map[prefix] = n.attributes[i].nodeValue;
} else if (n.attributes[i].nodeName == 'xmlns') {
if (!('' in map)) map[''] = n.attributes[i].nodeValue || null;
for (let i = 0; i < n.childNodes.length; i++) {
const childNode = n.childNodes[i];
if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
continue;
}

if (childNode.nodeName.startsWith('xmlns:')) {
const prefix = childNode.nodeName.split(':')[1];
if (!(prefix in map)) map[prefix] = childNode.nodeValue;
} else if (childNode.nodeName == 'xmlns') {
if (!('' in map)) map[''] = childNode.nodeValue || null;

Check warning on line 81 in src/dom/xml-parser.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
}
}
n = n.parentNode;
Expand Down Expand Up @@ -230,39 +236,43 @@
parent = stack[stack.length - 1];
} else if (text.charAt(0) === '?') {
// Ignore XML declaration and processing instructions
} else if (text.charAt(0) === '!') {
// Ignore comments
// console.log(`Ignored ${text}`);
} else {
const empty = text.match(this.regexEmpty);
const tagname = regexTagname.exec(text)[1];
let node = domCreateElement(xmlDocument, tagname);

let attribute;
while ((attribute = regexAttribute.exec(text))) {
const val = he.decode(attribute[5] || attribute[7] || '');
domSetAttribute(node, attribute[1], val);
}

node.siblingPosition = parent.childNodes.length;
domAppendChild(parent, node);
if (!empty) {
parent = node;
stack.push(node);
}

const namespaceMap = this.namespaceMapAt(node);
if (node.prefix !== null) {
if (node.prefix in namespaceMap) node.namespaceUri = namespaceMap[node.prefix];
// else, prefix is undefined. do anything?
} else {
if ('' in namespaceMap) node.namespaceUri = namespaceMap[''];
}
for (let i = 0; i < node.attributes.length; ++i) {
if (node.attributes[i].prefix !== null) {
if (node.attributes[i].prefix in namespaceMap) {
node.attributes[i].namespaceUri = namespaceMap[node.attributes[i].prefix];
}

for (let i = 0; i < node.childNodes.length; ++i) {
const childNode = node.childNodes[i];
if (childNode.nodeType !== DOM_ATTRIBUTE_NODE) {
continue;

Check warning on line 271 in src/dom/xml-parser.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
}

Check warning on line 272 in src/dom/xml-parser.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

if (childNode.prefix !== null && childNode.prefix in namespaceMap) {
childNode.namespaceUri = namespaceMap[childNode.prefix];
// else, prefix undefined.
}
// elements with no prefix always have no namespace, so do nothing here.
Expand Down
Loading
Loading