UNPKG

domtranslator

Version:
103 lines (101 loc) 3.47 kB
import { getNodeImportanceScore } from './utils/nodes'; /** * Manages translation state of DOM nodes. * * Class is purposed for translate primitive nodes. * It manages only node values itself, with no recursive processing nested nodes. */ export class NodesTranslator { translateCallback; idCounter = 0; nodeStorage = new WeakMap(); config; constructor(translateCallback, { nodeImportanceScore = getNodeImportanceScore } = {}) { this.translateCallback = translateCallback; this.config = { nodeImportanceScore, }; } has(node) { return this.nodeStorage.has(node); } getState(node) { const nodeData = this.nodeStorage.get(node); if (!nodeData) return null; const { originalText } = nodeData; return { originalText }; } /** * Translates nodes that contain text (e.g., Text, Attr) * After translation calls the callback with the translated node */ translate = (node, callback) => { if (this.has(node)) throw new Error('This node has already been translated'); if (node.nodeType !== Node.ATTRIBUTE_NODE && node.nodeType !== Node.TEXT_NODE) { throw new Error('Cannot translate node: only Text and Attr nodes are supported'); } // Skip empty text if (node.nodeValue === null || node.nodeValue.trim().length == 0) return; this.nodeStorage.set(node, { id: this.idCounter++, updateId: 1, originalText: null, importanceScore: this.config.nodeImportanceScore(node), }); this.translateNodeContent(node, callback); }; /** * Restores the original node text */ restore(node) { const nodeData = this.nodeStorage.get(node); if (!nodeData) return; if (nodeData.originalText !== null) { node.nodeValue = nodeData.originalText; } this.nodeStorage.delete(node); } /** * Translates node after it has been modified * After translation calls the callback with the translated node */ update(node, callback) { const nodeData = this.nodeStorage.get(node); if (!nodeData) throw new Error('Node cannot be updated because it was never translated'); nodeData.updateId++; this.translateNodeContent(node, callback); } /** * Call only for new and updated nodes */ translateNodeContent(node, callback) { const nodeData = this.nodeStorage.get(node); if (!nodeData) { throw new Error('Node is not register'); } if (node.nodeValue === null) return; const nodeId = nodeData.id; const nodeContext = nodeData.updateId; return this.translateCallback(node.nodeValue, nodeData.importanceScore).then((text) => { const actualNodeData = this.nodeStorage.get(node); if (!actualNodeData || nodeId !== actualNodeData.id) { return; } if (nodeContext !== actualNodeData.updateId) { return; } actualNodeData.originalText = node.nodeValue !== null ? node.nodeValue : ''; node.nodeValue = text; if (callback) callback(node); }); } } //# sourceMappingURL=sourcemaps/NodesTranslator.js.map