aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesús <heckyel@hyperbola.info>2019-09-21 12:03:39 -0500
committerJesús <heckyel@hyperbola.info>2019-09-21 12:03:39 -0500
commit648066ec2b431a23bf0134b701db3914abaf752b (patch)
treeaeedd94cf503655ef3ef00e80d8f6c7a45429995
parent6f300357e247ce0645acdff25d2f0b1c056d3ae1 (diff)
downloadematrix-648066ec2b431a23bf0134b701db3914abaf752b.tar.lz
ematrix-648066ec2b431a23bf0134b701db3914abaf752b.tar.xz
ematrix-648066ec2b431a23bf0134b701db3914abaf752b.zip
Improvement to the i18n mechanism for dashboard pages
-rw-r--r--js/i18n.js112
1 files changed, 64 insertions, 48 deletions
diff --git a/js/i18n.js b/js/i18n.js
index 1f1dbb7..da7d469 100644
--- a/js/i18n.js
+++ b/js/i18n.js
@@ -21,53 +21,62 @@
uMatrix Home: https://github.com/gorhill/uMatrix
*/
-/* global vAPI, uDom */
-
'use strict';
-/******************************************************************************/
-
// This file should always be included at the end of the `body` tag, so as
// to ensure all i18n targets are already loaded.
(function() {
-
- /******************************************************************************/
-
// https://github.com/gorhill/uBlock/issues/2084
- // Anything else than <a>, <b>, <code>, <em>, <i>, <input>, and <span> will
- // be rendered as plain text.
- // For <input>, only the type attribute is allowed.
- // For <a>, only href attribute must be present, and it MUST starts with
- // `https://`, and includes no single- or double-quotes.
- // No HTML entities are allowed, there is code to handle existing HTML
- // entities already present in translation files until they are all gone.
-
- var reSafeTags = /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/,
- reSafeInput = /^([\s\S]*?)<(input type="[^"]+")>(.*?)([\s\S]*)$/,
- reInput = /^input type=(['"])([a-z]+)\1$/,
- reSafeLink = /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/,
- reLink = /^a href=(['"])(https?:\/\/[^'"]+)\1$/;
+ // Anything else than <a>, <b>, <code>, <em>, <i>, <input>, and
+ // <span> will be rendered as plain text. For <input>, only the
+ // type attribute is allowed. For <a>, only href attribute must
+ // be present, and it MUST starts with `https://`, and includes no
+ // single- or double-quotes. No HTML entities are allowed, there
+ // is code to handle existing HTML entities already present in
+ // translation files until they are all gone.
+ //
+ // ηMatrix:
+ // We're not going to remove anything, but rather going to make
+ // full use of HTML tags and HTML entities in translations. Of
+ // course, this check for safe tags is going to stay and will be
+ // used to check the source text. The above comment is kept just
+ // in case.
+
+ let reSafeTags =
+ /^([\s\S]*?)<(b|blockquote|code|em|i|kbd|span|sup)>(.+?)<\/\2>([\s\S]*)$/;
+ let reSafeInput = /^([\s\S]*?)<(input type="[^"]+")>(.*?)([\s\S]*)$/;
+ let reInput = /^input type=(['"])([a-z]+)\1$/;
+ let reSafeLink =
+ /^([\s\S]*?)<(a href=['"]https?:\/\/[^'" <>]+['"])>(.+?)<\/a>([\s\S]*)$/;
+ let reLink = /^a href=(['"])(https?:\/\/[^'"]+)\1$/;
var safeTextToTagNode = function(text) {
- var matches, node;
- if ( text.lastIndexOf('a ', 0) === 0 ) {
+ let matches;
+ let node;
+
+ if (text.lastIndexOf('a ', 0) === 0) {
matches = reLink.exec(text);
- if ( matches === null ) { return null; }
+ if (matches === null) {
+ return null;
+ }
node = document.createElement('a');
node.setAttribute('href', matches[2]);
return node;
}
- if ( text.lastIndexOf('input ', 0) === 0 ) {
+ if (text.lastIndexOf('input ', 0) === 0) {
matches = reInput.exec(text);
- if ( matches === null ) { return null; }
+ if (matches === null) {
+ return null;
+ }
node = document.createElement('input');
node.setAttribute('type', matches[2]);
return node;
}
- // Firefox extension validator warns if using a variable as argument for
- // document.createElement().
- switch ( text ) {
+ // Firefox extension validator warns if using a variable as
+ // argument for document.createElement().
+ // ηMatrix: is it important for us?
+ switch (text) {
case 'b':
return document.createElement('b');
case 'blockquote':
@@ -90,46 +99,53 @@
};
var safeTextToTextNode = function(text) {
- // TODO: remove once no more HTML entities in translation files.
- if ( text.indexOf('&') !== -1 ) {
- text = text.replace(/&ldquo;/g, '“')
+ if (text.indexOf('&') !== -1) {
+ text = text
+ .replace(/&ldquo;/g, '“')
.replace(/&rdquo;/g, '”')
.replace(/&lsquo;/g, '‘')
- .replace(/&rsquo;/g, '’');
+ .replace(/&rsquo;/g, '’')
+ .replace(/&lt;/g, '<')
+ .replace(/&gt;/g, '>');
}
return document.createTextNode(text);
};
var safeTextToDOM = function(text, parent) {
- if ( text === '' ) { return; }
- // Fast path (most common).
- if ( text.indexOf('<') === -1 ) {
+ if (text === '') {
+ return;
+ }
+
+ if (text.indexOf('<') === -1) {
return parent.appendChild(safeTextToTextNode(text));
}
- // Slow path.
- // `<p>` no longer allowed. Code below can be remove once all <p>'s are
- // gone from translation files.
- text = text.replace(/^<p>|<\/p>/g, '')
+
+ // Using the raw <p> element is not allowed for security reason,
+ // but it's good for formatting content, so here it's substituted
+ // for a safer equivalent (for the extension.)
+ text = text
+ .replace(/^<p>|<\/p>/g, '')
.replace(/<p>/g, '\n\n');
- // Parse allowed HTML tags.
- var matches,
- matches1 = reSafeTags.exec(text),
- matches2 = reSafeLink.exec(text);
- if ( matches1 !== null && matches2 !== null ) {
+
+ let matches;
+ let matches1 = reSafeTags.exec(text);
+ let matches2 = reSafeLink.exec(text);
+ if (matches1 !== null && matches2 !== null) {
matches = matches1.index < matches2.index ? matches1 : matches2;
- } else if ( matches1 !== null ) {
+ } else if (matches1 !== null) {
matches = matches1;
- } else if ( matches2 !== null ) {
+ } else if (matches2 !== null) {
matches = matches2;
} else {
matches = reSafeInput.exec(text);
}
- if ( matches === null ) {
+ if (matches === null) {
parent.appendChild(safeTextToTextNode(text));
return;
}
+
safeTextToDOM(matches[1], parent);
- var node = safeTextToTagNode(matches[2]) || parent;
+ let node = safeTextToTagNode(matches[2]) || parent;
safeTextToDOM(matches[3], node);
parent.appendChild(node);
safeTextToDOM(matches[4], parent);