UNPKG

locize

Version:

This package adds the incontext editor to your i18next setup.

104 lines (99 loc) 3.58 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var i18nextSubliminal = require('i18next-subliminal'); var postMessage = require('./postMessage.js'); var store = require('../store.js'); var DANGEROUS_ATTR_NAMES = /^(on\w+|style)$/i; var URL_ATTR_NAMES = /^(href|src|action|formaction|xlink:href)$/i; var DANGEROUS_URL_SCHEMES = /^\s*(javascript|data|vbscript|file)\s*:/i; function isSafeAttributeWrite(attr, value) { if (typeof attr !== 'string') return false; if (DANGEROUS_ATTR_NAMES.test(attr)) return false; if (URL_ATTR_NAMES.test(attr) && typeof value === 'string' && DANGEROUS_URL_SCHEMES.test(value)) return false; return true; } function sanitizeTranslationHtml(html) { if (typeof html !== 'string') return html; if (typeof DOMParser === 'undefined') return html; try { var doc = new DOMParser().parseFromString("<body>".concat(html, "</body>"), 'text/html'); var disallowedTags = ['SCRIPT', 'IFRAME', 'OBJECT', 'EMBED', 'LINK', 'META', 'BASE', 'STYLE']; disallowedTags.forEach(function (tag) { doc.body.querySelectorAll(tag.toLowerCase()).forEach(function (n) { return n.remove(); }); }); doc.body.querySelectorAll('*').forEach(function (n) { var attrs = Array.from(n.attributes); attrs.forEach(function (a) { var name = a.name; var val = a.value; if (/^on/i.test(name)) { n.removeAttribute(name); return; } if (URL_ATTR_NAMES.test(name) && DANGEROUS_URL_SCHEMES.test(val)) { n.removeAttribute(name); } }); }); return doc.body.innerHTML; } catch (e) { return html; } } function setValueOnNode(meta, value) { var item = store.store.get(meta.eleUniqueID); if (!item || !item.keys[meta.textType]) return; var txtWithHiddenMeta = item.subliminal ? i18nextSubliminal.wrap(value, item.subliminal) : value; if (meta.textType === 'text') { item.node.textContent = txtWithHiddenMeta; } else if (meta.textType.indexOf('attr:') === 0) { var attr = meta.textType.replace('attr:', ''); if (!isSafeAttributeWrite(attr, txtWithHiddenMeta)) return; item.node.setAttribute(attr, txtWithHiddenMeta); } else if (meta.textType === 'html') { var id = "".concat(meta.textType, "-").concat(meta.children); if (!item.originalChildNodes) { var clones = []; item.node.childNodes.forEach(function (c) { clones.push(c); }); item.originalChildNodes = clones; } var sanitisedHtml = sanitizeTranslationHtml(txtWithHiddenMeta); if (item.children[id].length === item.node.childNodes.length) { item.node.innerHTML = sanitisedHtml; } else { var children = item.children[id]; var first = children[0].child; var dummy = document.createElement('div'); dummy.innerHTML = sanitisedHtml; var nodes = []; dummy.childNodes.forEach(function (c) { nodes.push(c); }); nodes.forEach(function (c) { try { item.node.insertBefore(c, first); } catch (error) { item.node.appendChild(c); } }); children.forEach(function (replaceable) { if (item.node.contains(replaceable.child)) { item.node.removeChild(replaceable.child); } }); } } } function handler(payload) { var meta = payload.meta, value = payload.value; if (meta && value !== undefined) { setValueOnNode(meta, value); } } postMessage.api.addHandler('editKey', handler); exports.setValueOnNode = setValueOnNode;