@awesome-fe/translate
Version:
Translation utils
350 lines • 10.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultSelectors = exports.DomTableRowElement = exports.DomTableCellElement = exports.DomTableElement = exports.DomText = exports.DomElement = exports.DomDocumentType = exports.DomDocumentFragment = exports.DomDocument = exports.DomComment = exports.DomParentNode = exports.DomChildNode = exports.DomAttr = exports.DomNode = void 0;
const parse5_1 = require("parse5");
const dom_tree_adapter_1 = require("./dom-tree-adapter");
class DomNode {
static treeAdapter = dom_tree_adapter_1.DomTreeAdapter.create();
nodeName;
parentNode;
childNodes = [];
get index() {
if (!(this instanceof DomChildNode)) {
return -1;
}
return this.parentNode?.childNodes.indexOf(this);
}
get indexOfElement() {
if (!(this instanceof DomElement)) {
return -1;
}
return this.parentNode?.children.indexOf(this);
}
get firstChild() {
return this.childNodes?.[0];
}
get lastChild() {
return this.childNodes?.[this.childNodes.length - 1];
}
get children() {
return this.childNodes?.filter(child => child instanceof DomElement);
}
get firstElementChild() {
return this.children?.[0];
}
get lastElementChild() {
return this.children?.[this.children.length - 1];
}
get textContent() {
let result = '';
if (this instanceof DomText) {
result += this.value;
}
else if (this instanceof DomParentNode) {
result += this.childNodes.map(it => it.textContent).join('');
}
return result;
}
set textContent(value) {
this.childNodes = [new DomText(value)];
}
get parentElement() {
let parent = this.parentNode;
while (parent) {
if (parent instanceof DomElement) {
return parent;
}
parent = parent.parentNode;
}
}
get previousElementSibling() {
let node = this.previousSibling();
while (node) {
if (node instanceof DomElement) {
return node;
}
node = node.previousSibling();
}
}
get nextElementSibling() {
let node = this.nextSibling();
while (node) {
if (node instanceof DomElement) {
return node;
}
node = node.nextSibling();
}
}
previousSibling() {
if (this.index === -1) {
return;
}
return this.parentNode?.childNodes[this.index - 1];
}
nextSibling() {
if (this.index === -1) {
return;
}
return this.parentNode?.childNodes[this.index + 1];
}
queryAncestor(selector) {
return this.parentElement && (selector(this.parentElement) || this.parentElement.queryAncestor(selector));
}
appendChild(child) {
if (this instanceof DomParentNode) {
child.parentNode = this;
this.childNodes.push(child);
}
return child;
}
insertBefore(newNode, referenceNode) {
newNode.remove();
this.childNodes.splice(referenceNode.index, 0, newNode);
return newNode;
}
insertAfter(newNode, referenceNode) {
newNode.remove();
this.childNodes.splice(referenceNode.index + 1, 0, newNode);
return newNode;
}
}
exports.DomNode = DomNode;
class DomAttr {
name;
value;
}
exports.DomAttr = DomAttr;
class DomChildNode extends DomNode {
remove() {
if (!this.parentNode) {
return;
}
this.parentNode.childNodes.splice(this.index, 1);
}
}
exports.DomChildNode = DomChildNode;
class DomParentNode extends DomChildNode {
get children() {
return this.childNodes.filter(it => it instanceof DomElement);
}
prepend(node) {
this.childNodes.unshift(node);
}
querySelectorAll(selector) {
const result = [];
for (const child of this.children) {
if (selector(child)) {
result.push(child);
}
result.push(...child.querySelectorAll(selector));
}
return result;
}
querySelector(selector) {
for (const child of this.children) {
if (selector(child)) {
return child;
}
const subNode = child.querySelector(selector);
if (subNode) {
return subNode;
}
}
}
mergeTextNodes() {
let text = '';
for (let i = this.childNodes.length - 1; i >= 0; i--) {
const node = this.childNodes[i];
if (node instanceof DomText) {
text = node.value + text;
if (!(node.previousSibling() instanceof DomText)) {
node.value = text;
text = '';
}
else {
node.remove();
}
}
if (node instanceof DomParentNode) {
node.mergeTextNodes();
}
}
}
}
exports.DomParentNode = DomParentNode;
class DomComment extends DomChildNode {
data;
nodeName = '#comment';
constructor(data) {
super();
this.data = data;
}
}
exports.DomComment = DomComment;
class DomDocument extends DomParentNode {
nodeName = '#document';
mode;
get head() {
return this.querySelector(it => it.isTagOf('head'));
}
get body() {
return this.querySelector(it => it.isTagOf('body'));
}
get title() {
return this.titleElement?.textContent;
}
set title(value) {
const element = this.titleElement || this.head.appendChild(new DomElement('title'));
element.textContent = value ?? '';
}
get titleElement() {
const element = this.querySelector(it => it.isTagOf('title'));
if (element) {
return element;
}
}
toHtml() {
return (0, parse5_1.serialize)(this, { treeAdapter: DomNode.treeAdapter });
}
toFragment() {
// 如果是文档片段,则只序列化 body
return (0, parse5_1.serialize)(this.body, { treeAdapter: DomNode.treeAdapter });
}
isFragment() {
// 目前看来,片段和非片段的主要差别是 mode 为 'quirks',并且head 中没有任何东西
return this.mode === 'quirks' && this.head.childNodes.length === 0;
}
static parse(content) {
return (0, parse5_1.parse)(content, { treeAdapter: DomNode.treeAdapter });
}
}
exports.DomDocument = DomDocument;
class DomDocumentFragment extends DomParentNode {
nodeName = '#document-fragment';
toHtml() {
return (0, parse5_1.serialize)(this, { treeAdapter: DomNode.treeAdapter });
}
static parse(content) {
return (0, parse5_1.parseFragment)(content, { treeAdapter: DomNode.treeAdapter });
}
}
exports.DomDocumentFragment = DomDocumentFragment;
class DomDocumentType extends DomChildNode {
name;
publicId;
systemId;
nodeName = '#documentType';
constructor(name, publicId, systemId) {
super();
this.name = name;
this.publicId = publicId;
this.systemId = systemId;
}
}
exports.DomDocumentType = DomDocumentType;
function isSameName(name1, name2) {
return name1?.localeCompare(name2) === 0;
}
class DomElement extends DomParentNode {
tagName;
attrs;
namespaceURI;
constructor(tagName, attrs = [], namespaceURI = 'http://www.w3.org/1999/xhtml') {
super();
this.tagName = tagName;
this.attrs = attrs;
this.namespaceURI = namespaceURI;
this.nodeName = tagName;
}
get innerHTML() {
return (0, parse5_1.serialize)(this, { treeAdapter: DomNode.treeAdapter });
}
set innerHTML(html) {
const fragment = (0, parse5_1.parseFragment)(html, { treeAdapter: DomNode.treeAdapter });
this.childNodes = fragment.childNodes;
}
get outerHTML() {
const node = new DomElement('div');
node.childNodes = [this];
return node.innerHTML;
}
get className() {
return this.getAttributeNode('class')?.value;
}
get templateContent() {
let parent = this.parentNode;
while (parent) {
if (parent instanceof DomDocumentFragment) {
return parent;
}
parent = parent.parentNode;
}
}
getAttributeNode(name) {
return this.attrs.find(it => isSameName(it.name, name));
}
getAttribute(name) {
return this.getAttributeNode(name)?.value;
}
hasAttribute(name) {
return !!this.getAttributeNode(name);
}
setAttribute(name, value) {
const attr = this.getAttributeNode(name);
if (!attr) {
this.attrs.push({ name, value });
}
else {
attr.value = value;
}
}
getAttributes() {
return this.attrs;
}
setAttributes(...domAttrs) {
this.attrs.push(...domAttrs);
}
removeAttribute(name) {
const index = this.attrs.findIndex(it => isSameName(it.name, name));
if (index !== -1) {
this.attrs.splice(index, 1);
}
}
isSameTag(element) {
return this.isTagOf(element.tagName);
}
isTagOf(...names) {
return !!names.find(name => isSameName(this.tagName, name));
}
hasClass(...classNames) {
const classes = this.getAttribute('class')?.split(' ');
return classNames.some(it => classes?.includes(it));
}
}
exports.DomElement = DomElement;
class DomText extends DomChildNode {
value;
nodeName = '#text';
constructor(value) {
super();
this.value = value;
}
}
exports.DomText = DomText;
class DomTableElement extends DomElement {
}
exports.DomTableElement = DomTableElement;
class DomTableCellElement extends DomElement {
}
exports.DomTableCellElement = DomTableCellElement;
class DomTableRowElement extends DomElement {
get cells() {
return this.children.filter(it => it.isTagOf('td') || it.isTagOf('th'));
}
}
exports.DomTableRowElement = DomTableRowElement;
const elementSelectors = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 't', 'nt-wrapper']
.map(it => (node) => node.isTagOf(it));
const attributeSelector = (node) => node.hasAttribute('ng-should-translate');
exports.defaultSelectors = [...elementSelectors, attributeSelector];
//# sourceMappingURL=dom-models.js.map