own page load microopt: reduce blocking on i18n
* localStorage cache is faster than chrome.i18n.get * TreeWalker is faster than tHTML for removing extraneous whitespace * simple for() is faster than for-of with [...iterable]
This commit is contained in:
parent
4eae87e606
commit
b3b1d4a628
|
@ -37,6 +37,18 @@ function webNavigationListener(method, data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset i18n cache on language change
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const {browserUIlanguage} = tryJSONparse(localStorage.L10N) || {};
|
||||||
|
const UIlang = chrome.i18n.getUILanguage();
|
||||||
|
if (browserUIlanguage != UIlang) {
|
||||||
|
localStorage.L10N = JSON.stringify({
|
||||||
|
browserUIlanguage: UIlang,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// messaging
|
// messaging
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
||||||
|
|
|
@ -5,10 +5,14 @@ tDocLoader();
|
||||||
|
|
||||||
|
|
||||||
function t(key, params) {
|
function t(key, params) {
|
||||||
const s = chrome.i18n.getMessage(key, params);
|
const cache = !params && t.cache[key];
|
||||||
|
const s = cache || chrome.i18n.getMessage(key, params);
|
||||||
if (s == '') {
|
if (s == '') {
|
||||||
throw `Missing string "${key}"`;
|
throw `Missing string "${key}"`;
|
||||||
}
|
}
|
||||||
|
if (!params && !cache) {
|
||||||
|
t.cache[key] = s;
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,24 +39,38 @@ function tHTML(html) {
|
||||||
|
|
||||||
|
|
||||||
function tNodeList(nodes) {
|
function tNodeList(nodes) {
|
||||||
for (const node of [...nodes]) {
|
const PREFIX = 'i18n-';
|
||||||
|
for (let n = nodes.length; --n >= 0;) {
|
||||||
|
const node = nodes[n];
|
||||||
// skip non-ELEMENT_NODE
|
// skip non-ELEMENT_NODE
|
||||||
if (node.nodeType != 1) {
|
if (node.nodeType != 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (node.localName == 'template') {
|
if (node.localName == 'template') {
|
||||||
|
const elements = node.content.querySelectorAll('*');
|
||||||
|
tNodeList(elements);
|
||||||
|
template[node.dataset.id] = elements[0];
|
||||||
// compress inter-tag whitespace to reduce number of DOM nodes by 25%
|
// compress inter-tag whitespace to reduce number of DOM nodes by 25%
|
||||||
template[node.dataset.id] = tHTML(node.innerHTML);
|
const walker = document.createTreeWalker(elements[0], NodeFilter.SHOW_TEXT);
|
||||||
|
const toRemove = [];
|
||||||
|
while (walker.nextNode()) {
|
||||||
|
const textNode = walker.currentNode;
|
||||||
|
if (!textNode.nodeValue.trim()) {
|
||||||
|
toRemove.push(textNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toRemove.forEach(el => el.remove());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const attr of [...node.attributes]) {
|
for (let a = node.attributes.length; --a >= 0;) {
|
||||||
let name = attr.nodeName;
|
const attr = node.attributes[a];
|
||||||
if (name.indexOf('i18n-') != 0) {
|
const name = attr.nodeName;
|
||||||
|
if (!name.startsWith(PREFIX)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
name = name.substr(5); // 'i18n-'.length
|
const type = name.substr(PREFIX.length);
|
||||||
const value = t(attr.value);
|
const value = t(attr.value);
|
||||||
switch (name) {
|
switch (type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
node.insertBefore(document.createTextNode(value), node.firstChild);
|
node.insertBefore(document.createTextNode(value), node.firstChild);
|
||||||
break;
|
break;
|
||||||
|
@ -63,15 +81,17 @@ function tNodeList(nodes) {
|
||||||
node.insertAdjacentHTML('afterbegin', value);
|
node.insertAdjacentHTML('afterbegin', value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
node.setAttribute(name, value);
|
node.setAttribute(type, value);
|
||||||
}
|
}
|
||||||
node.removeAttribute(attr.nodeName);
|
node.removeAttribute(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function tDocLoader() {
|
function tDocLoader() {
|
||||||
|
t.cache = tryJSONparse(localStorage.L10N) || {};
|
||||||
|
const cacheLength = Object.keys(t.cache).length;
|
||||||
// localize HEAD
|
// localize HEAD
|
||||||
tNodeList(document.getElementsByTagName('*'));
|
tNodeList(document.getElementsByTagName('*'));
|
||||||
|
|
||||||
|
@ -85,6 +105,9 @@ function tDocLoader() {
|
||||||
const onLoad = () => {
|
const onLoad = () => {
|
||||||
tDocLoader.stop();
|
tDocLoader.stop();
|
||||||
process(observer.takeRecords());
|
process(observer.takeRecords());
|
||||||
|
if (cacheLength != Object.keys(t.cache).length) {
|
||||||
|
localStorage.L10N = JSON.stringify(t.cache);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
tDocLoader.start = () => {
|
tDocLoader.start = () => {
|
||||||
observer.observe(document, {subtree: true, childList: true});
|
observer.observe(document, {subtree: true, childList: true});
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
<title i18n-text-append="optionsHeading">Stylus </title>
|
<title i18n-text-append="optionsHeading">Stylus </title>
|
||||||
<link rel="stylesheet" href="index.css">
|
<link rel="stylesheet" href="index.css">
|
||||||
<script src="/dom.js"></script>
|
<script src="/dom.js"></script>
|
||||||
<script src="/localization.js"></script>
|
|
||||||
<script src="/messaging.js"></script>
|
<script src="/messaging.js"></script>
|
||||||
|
<script src="/localization.js"></script>
|
||||||
<script src="/prefs.js"></script>
|
<script src="/prefs.js"></script>
|
||||||
<script src="/apply.js"></script>
|
<script src="/apply.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="dom.js"></script>
|
<script src="dom.js"></script>
|
||||||
<script src="localization.js"></script>
|
|
||||||
<script src="messaging.js"></script>
|
<script src="messaging.js"></script>
|
||||||
|
<script src="localization.js"></script>
|
||||||
<script src="prefs.js"></script>
|
<script src="prefs.js"></script>
|
||||||
<script src="apply.js"></script>
|
<script src="apply.js"></script>
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user