'use strict';

/**
 * Node attributes that define how node content will be localized.
 *
 * There're following supported attributes:
 *  - i18n: replace value of `innerHTML` property by localized text;
 *  - i18n-title: replace value of `title` attribute by localized text;
 *  - i18n-placeholder: replace value of `placeholder` attribute by localized text.
 *
 * @type {Array}
 */
const I18N_ATTRS = ['i18n', 'i18n-title', 'i18n-placeholder'];

$(() => {
	localizePage();

	/**
	 * Localize all nodes.
	 */
	function localizePage() {
		// Localize static nodes
		for (let attr of I18N_ATTRS) {
			let nodes = $(`[${attr}]`).toArray();
			localizeNodes(nodes);
		}

		// Localize dynamic nodes
		new MutationObserver((mutations) => {
			for (let mutation of mutations) {
				for (let node of mutation.addedNodes) {
					localizeNode(node);
					for (let attr of I18N_ATTRS) {
						let nodes = $(node).find(`[${attr}]`).toArray();
						localizeNodes(nodes);
					}
				}
			}
		}).observe(document.body, {
			childList: true,
			subtree: true,
		});
	}

	/**
	 * Localize given array of nodes.
	 * @param  {Array} nodes Array of nodes to be localized
	 */
	function localizeNodes(nodes) {
		nodes.forEach(localizeNode);
	}

	/**
	 * Localize given node.
	 * @param  {Object} node Node element
	 */
	function localizeNode(node) {
		if (!(node instanceof Element)) {
			return;
		}

		for (let attr of I18N_ATTRS) {
			if (!node.hasAttribute(attr)) {
				continue;
			}

			let tag = node.getAttribute(attr);
			let text = chrome.i18n.getMessage(tag) || tag;

			switch (attr) {
				case 'i18n':
					node.innerHTML = text;
					break;

				case 'i18n-title':
					node.setAttribute('title', text);
					break;

				case 'i18n-placeholder':
					node.setAttribute('placeholder', text);
					break;
			}
		}
	}
});

@@ -156,25 +156,27 @@
 lue of %60
-innerHTML
+textContent
 %60 proper
@@ -451,16 +451,53 @@
 () =%3E %7B%0A
+%09const domParser = new DOMParser();%0A%0A
 %09localiz
@@ -1636,22 +1636,267 @@
 %09%09%09%09
-node.innerHTML
+if (hasHtmlTags(text)) %7B%0A%09%09%09%09%09%09let nodes = makeNodes(text);%0A%09%09%09%09%09%09if (nodes) %7B%0A%09%09%09%09%09%09%09nodes.forEach((n) =%3E %7B%0A%09%09%09%09%09%09%09%09node.appendChild(n);%0A%09%09%09%09%09%09%09%7D);%0A%09%09%09%09%09%09%7D else %7B%0A%09%09%09%09%09%09%09// Fallback%0A%09%09%09%09%09%09%09node.textContent = text;%0A%09%09%09%09%09%09%7D%0A%09%09%09%09%09%7D else %7B%0A%09%09%09%09%09%09node.textContent
  = t
@@ -1896,24 +1896,31 @@
 ent = text;%0A
+%09%09%09%09%09%7D%0A
 %09%09%09%09%09break;%0A
@@ -2092,13 +2092,673 @@
 %7D%0A%09%09%7D%0A%09%7D
+%0A%0A%09/**%0A%09 * Create array of nodes which can be applied to node to be translated.%0A%09 * @param  %7BString%7D rawHtml String contains HTML code%0A%09 * @return %7BArray%7D Array of nodes from given text%0A%09 */%0A%09function makeNodes(rawHtml) %7B%0A%09%09let html = %60%3Cdiv%3E$%7BrawHtml%7D%3C/div%3E%60;%0A%0A%09%09let body = domParser.parseFromString(html, 'text/html').body;%0A%09%09return %5B...body.firstChild.childNodes%5D.filter((a) =%3E %7B%0A%09%09%09return a.nodeType === a.TEXT_NODE %7C%7C a.tagName === 'A';%0A%09%09%7D);%0A%09%7D%0A%0A%09/**%0A%09 * Check if given text contains HTML tags%0A%09 * @param  %7BString%7D text String supposed to have HTML tags%0A%09 * @return %7BBoolean%7D Check result%0A%09 */%0A%09function hasHtmlTags(text) %7B%0A%09%09return /%3C.+?%3E/.test(text);%0A%09%7D
 %0A%7D);%0A

Allow only `a` tag in translated strings