You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.0 KiB
214 lines
7.0 KiB
import { html } from 'parse5'; |
|
import { Element, Document, ProcessingInstruction, Comment, Text, isDirective, isText, isComment, isTag, } from 'domhandler'; |
|
function createTextNode(value) { |
|
return new Text(value); |
|
} |
|
function enquoteDoctypeId(id) { |
|
const quote = id.includes('"') ? "'" : '"'; |
|
return quote + id + quote; |
|
} |
|
/** @internal */ |
|
export function serializeDoctypeContent(name, publicId, systemId) { |
|
let str = '!DOCTYPE '; |
|
if (name) { |
|
str += name; |
|
} |
|
if (publicId) { |
|
str += ` PUBLIC ${enquoteDoctypeId(publicId)}`; |
|
} |
|
else if (systemId) { |
|
str += ' SYSTEM'; |
|
} |
|
if (systemId) { |
|
str += ` ${enquoteDoctypeId(systemId)}`; |
|
} |
|
return str; |
|
} |
|
export const adapter = { |
|
// Re-exports from domhandler |
|
isCommentNode: isComment, |
|
isElementNode: isTag, |
|
isTextNode: isText, |
|
//Node construction |
|
createDocument() { |
|
const node = new Document([]); |
|
node['x-mode'] = html.DOCUMENT_MODE.NO_QUIRKS; |
|
return node; |
|
}, |
|
createDocumentFragment() { |
|
return new Document([]); |
|
}, |
|
createElement(tagName, namespaceURI, attrs) { |
|
const attribs = Object.create(null); |
|
const attribsNamespace = Object.create(null); |
|
const attribsPrefix = Object.create(null); |
|
for (let i = 0; i < attrs.length; i++) { |
|
const attrName = attrs[i].name; |
|
attribs[attrName] = attrs[i].value; |
|
attribsNamespace[attrName] = attrs[i].namespace; |
|
attribsPrefix[attrName] = attrs[i].prefix; |
|
} |
|
const node = new Element(tagName, attribs, []); |
|
node.namespace = namespaceURI; |
|
node['x-attribsNamespace'] = attribsNamespace; |
|
node['x-attribsPrefix'] = attribsPrefix; |
|
return node; |
|
}, |
|
createCommentNode(data) { |
|
return new Comment(data); |
|
}, |
|
//Tree mutation |
|
appendChild(parentNode, newNode) { |
|
const prev = parentNode.children[parentNode.children.length - 1]; |
|
if (prev) { |
|
prev.next = newNode; |
|
newNode.prev = prev; |
|
} |
|
parentNode.children.push(newNode); |
|
newNode.parent = parentNode; |
|
}, |
|
insertBefore(parentNode, newNode, referenceNode) { |
|
const insertionIdx = parentNode.children.indexOf(referenceNode); |
|
const { prev } = referenceNode; |
|
if (prev) { |
|
prev.next = newNode; |
|
newNode.prev = prev; |
|
} |
|
referenceNode.prev = newNode; |
|
newNode.next = referenceNode; |
|
parentNode.children.splice(insertionIdx, 0, newNode); |
|
newNode.parent = parentNode; |
|
}, |
|
setTemplateContent(templateElement, contentElement) { |
|
adapter.appendChild(templateElement, contentElement); |
|
}, |
|
getTemplateContent(templateElement) { |
|
return templateElement.children[0]; |
|
}, |
|
setDocumentType(document, name, publicId, systemId) { |
|
const data = serializeDoctypeContent(name, publicId, systemId); |
|
let doctypeNode = document.children.find((node) => isDirective(node) && node.name === '!doctype'); |
|
if (doctypeNode) { |
|
doctypeNode.data = data !== null && data !== void 0 ? data : null; |
|
} |
|
else { |
|
doctypeNode = new ProcessingInstruction('!doctype', data); |
|
adapter.appendChild(document, doctypeNode); |
|
} |
|
doctypeNode['x-name'] = name !== null && name !== void 0 ? name : undefined; |
|
doctypeNode['x-publicId'] = publicId !== null && publicId !== void 0 ? publicId : undefined; |
|
doctypeNode['x-systemId'] = systemId !== null && systemId !== void 0 ? systemId : undefined; |
|
}, |
|
setDocumentMode(document, mode) { |
|
document['x-mode'] = mode; |
|
}, |
|
getDocumentMode(document) { |
|
return document['x-mode']; |
|
}, |
|
detachNode(node) { |
|
if (node.parent) { |
|
const idx = node.parent.children.indexOf(node); |
|
const { prev, next } = node; |
|
node.prev = null; |
|
node.next = null; |
|
if (prev) { |
|
prev.next = next; |
|
} |
|
if (next) { |
|
next.prev = prev; |
|
} |
|
node.parent.children.splice(idx, 1); |
|
node.parent = null; |
|
} |
|
}, |
|
insertText(parentNode, text) { |
|
const lastChild = parentNode.children[parentNode.children.length - 1]; |
|
if (lastChild && isText(lastChild)) { |
|
lastChild.data += text; |
|
} |
|
else { |
|
adapter.appendChild(parentNode, createTextNode(text)); |
|
} |
|
}, |
|
insertTextBefore(parentNode, text, referenceNode) { |
|
const prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1]; |
|
if (prevNode && isText(prevNode)) { |
|
prevNode.data += text; |
|
} |
|
else { |
|
adapter.insertBefore(parentNode, createTextNode(text), referenceNode); |
|
} |
|
}, |
|
adoptAttributes(recipient, attrs) { |
|
for (let i = 0; i < attrs.length; i++) { |
|
const attrName = attrs[i].name; |
|
if (typeof recipient.attribs[attrName] === 'undefined') { |
|
recipient.attribs[attrName] = attrs[i].value; |
|
recipient['x-attribsNamespace'][attrName] = attrs[i].namespace; |
|
recipient['x-attribsPrefix'][attrName] = attrs[i].prefix; |
|
} |
|
} |
|
}, |
|
//Tree traversing |
|
getFirstChild(node) { |
|
return node.children[0]; |
|
}, |
|
getChildNodes(node) { |
|
return node.children; |
|
}, |
|
getParentNode(node) { |
|
return node.parent; |
|
}, |
|
getAttrList(element) { |
|
return element.attributes; |
|
}, |
|
//Node data |
|
getTagName(element) { |
|
return element.name; |
|
}, |
|
getNamespaceURI(element) { |
|
return element.namespace; |
|
}, |
|
getTextNodeContent(textNode) { |
|
return textNode.data; |
|
}, |
|
getCommentNodeContent(commentNode) { |
|
return commentNode.data; |
|
}, |
|
getDocumentTypeNodeName(doctypeNode) { |
|
var _a; |
|
return (_a = doctypeNode['x-name']) !== null && _a !== void 0 ? _a : ''; |
|
}, |
|
getDocumentTypeNodePublicId(doctypeNode) { |
|
var _a; |
|
return (_a = doctypeNode['x-publicId']) !== null && _a !== void 0 ? _a : ''; |
|
}, |
|
getDocumentTypeNodeSystemId(doctypeNode) { |
|
var _a; |
|
return (_a = doctypeNode['x-systemId']) !== null && _a !== void 0 ? _a : ''; |
|
}, |
|
//Node types |
|
isDocumentTypeNode(node) { |
|
return isDirective(node) && node.name === '!doctype'; |
|
}, |
|
// Source code location |
|
setNodeSourceCodeLocation(node, location) { |
|
if (location) { |
|
node.startIndex = location.startOffset; |
|
node.endIndex = location.endOffset; |
|
} |
|
node.sourceCodeLocation = location; |
|
}, |
|
getNodeSourceCodeLocation(node) { |
|
return node.sourceCodeLocation; |
|
}, |
|
updateNodeSourceCodeLocation(node, endLocation) { |
|
if (endLocation.endOffset != null) |
|
node.endIndex = endLocation.endOffset; |
|
node.sourceCodeLocation = { |
|
...node.sourceCodeLocation, |
|
...endLocation, |
|
}; |
|
}, |
|
}; |
|
//# sourceMappingURL=index.js.map
|