Greasemonkey: move GM_* template into seperate file.

Also ported it to jinja rather than str.format().

Also ran the js through jslint and fixed up a few very minor things.
This commit is contained in:
Jimmy 2017-10-04 22:39:32 +13:00
parent c1b912f567
commit fd5d44182b
4 changed files with 128 additions and 116 deletions

View File

@ -29,7 +29,7 @@ import glob
import attr
from PyQt5.QtCore import pyqtSignal, QObject
from qutebrowser.utils import log, standarddir
from qutebrowser.utils import log, standarddir, jinja
from qutebrowser.commands import cmdutils
@ -41,115 +41,6 @@ def _scripts_dir():
class GreasemonkeyScript:
"""Container class for userscripts, parses metadata blocks."""
GM_BOOTSTRAP_TEMPLATE = r"""var _qute_script_id = "__gm_{scriptName}";
function GM_log(text) {{
console.log(text);
}}
GM_info = (function() {{
return {{
'script': {scriptInfo},
'scriptMetaStr': {scriptMeta},
'scriptWillUpdate': false,
'version': '0.0.1',
'scriptHandler': 'Tampermonkey' //so scripts don't expect exportFunction
}};
}}());
function GM_setValue(key, value) {{
if (localStorage !== null &&
typeof key === "string" &&
(typeof value === "string" ||
typeof value === "number" ||
typeof value == "boolean")) {{
localStorage.setItem(_qute_script_id + key, value);
}}
}}
function GM_getValue(key, default_) {{
if (localStorage !== null && typeof key === "string") {{
return localStorage.getItem(_qute_script_id + key) || default_;
}}
}}
function GM_deleteValue(key) {{
if (localStorage !== null && typeof key === "string") {{
localStorage.removeItem(_qute_script_id + key);
}}
}}
function GM_listValues() {{
var i;
var keys = [];
for (i = 0; i < localStorage.length; ++i) {{
if (localStorage.key(i).startsWith(_qute_script_id)) {{
keys.push(localStorage.key(i));
}}
}}
return keys;
}}
function GM_openInTab(url) {{
window.open(url);
}}
// Almost verbatim copy from Eric
function GM_xmlhttpRequest(/* object */ details) {{
details.method = details.method.toUpperCase() || "GET";
if(!details.url) {{
throw("GM_xmlhttpRequest requires an URL.");
}}
// build XMLHttpRequest object
var oXhr = new XMLHttpRequest;
// run it
if("onreadystatechange" in details)
oXhr.onreadystatechange = function() {{
details.onreadystatechange(oXhr)
}};
if("onload" in details)
oXhr.onload = function() {{ details.onload(oXhr) }};
if("onerror" in details)
oXhr.onerror = function() {{ details.onerror(oXhr) }};
oXhr.open(details.method, details.url, true);
if("headers" in details)
for(var header in details.headers)
oXhr.setRequestHeader(header, details.headers[header]);
if("data" in details)
oXhr.send(details.data);
else
oXhr.send();
}}
function GM_addStyle(/* String */ styles) {{
var head = document.getElementsByTagName("head")[0];
if (head === undefined) {{
document.onreadystatechange = function() {{
if (document.readyState == "interactive") {{
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text/css");
oStyle.appendChild(document.createTextNode(styles));
document.getElementsByTagName("head")[0].appendChild(oStyle);
}}
}}
}}
else {{
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text/css");
oStyle.appendChild(document.createTextNode(styles));
head.appendChild(oStyle);
}}
}}
unsafeWindow = window;
"""
def __init__(self, properties, code):
self._code = code
self.includes = []
@ -200,12 +91,12 @@ unsafeWindow = window;
browser's debugger/inspector will not match up to the line
numbers in the source script directly.
"""
gm_bootstrap = self.GM_BOOTSTRAP_TEMPLATE.format(
scriptName=self.name,
scriptInfo=self._meta_json(),
scriptMeta=self.script_meta)
return '\n'.join(
["(function(){", gm_bootstrap, self._code, "})();"])
return jinja.js_environment.get_template(
'greasemonkey_wrapper.js').render(
scriptName=self.name,
scriptInfo=self._meta_json(),
scriptMeta=self.script_meta,
scriptSource=self._code)
def _meta_json(self):
return json.dumps({

View File

@ -1,2 +1,4 @@
# Upstream Mozilla's code
pac_utils.js
# Actually a jinja template so eslint chokes on the {{}} syntax.
greasemonkey_wrapper.js

View File

@ -0,0 +1,118 @@
(function () {
var _qute_script_id = "__gm_{{ scriptName }}";
function GM_log(text) {
console.log(text);
}
var GM_info = (function () {
return {
'script': {{ scriptInfo }},
'scriptMetaStr': {{ scriptMeta }},
'scriptWillUpdate': false,
'version': '0.0.1',
'scriptHandler': 'Tampermonkey' // so scripts don't expect exportFunction
};
}());
function GM_setValue(key, value) {
if (localStorage !== null &&
typeof key === "string" &&
(typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean")) {
localStorage.setItem(_qute_script_id + key, value);
}
}
function GM_getValue(key, default_) {
if (localStorage !== null && typeof key === "string") {
return localStorage.getItem(_qute_script_id + key) || default_;
}
}
function GM_deleteValue(key) {
if (localStorage !== null && typeof key === "string") {
localStorage.removeItem(_qute_script_id + key);
}
}
function GM_listValues() {
var i, keys = [];
for (i = 0; i < localStorage.length; i = i + 1) {
if (localStorage.key(i).startsWith(_qute_script_id)) {
keys.push(localStorage.key(i));
}
}
return keys;
}
function GM_openInTab(url) {
window.open(url);
}
// Almost verbatim copy from Eric
function GM_xmlhttpRequest(/* object */ details) {
details.method = details.method.toUpperCase() || "GET";
if (!details.url) {
throw ("GM_xmlhttpRequest requires an URL.");
}
// build XMLHttpRequest object
var oXhr = new XMLHttpRequest();
// run it
if ("onreadystatechange" in details) {
oXhr.onreadystatechange = function () {
details.onreadystatechange(oXhr);
};
}
if ("onload" in details) {
oXhr.onload = function () { details.onload(oXhr) };
}
if ("onerror" in details) {
oXhr.onerror = function () { details.onerror(oXhr) };
}
oXhr.open(details.method, details.url, true);
if ("headers" in details) {
for (var header in details.headers) {
oXhr.setRequestHeader(header, details.headers[header]);
}
}
if ("data" in details) {
oXhr.send(details.data);
} else {
oXhr.send();
}
}
function GM_addStyle(/* String */ styles) {
var head = document.getElementsByTagName("head")[0];
if (head === undefined) {
document.onreadystatechange = function () {
if (document.readyState == "interactive") {
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text/css");
oStyle.appendChild(document.createTextNode(styles));
document.getElementsByTagName("head")[0].appendChild(oStyle);
}
}
}
else {
var oStyle = document.createElement("style");
oStyle.setAttribute("type", "text/css");
oStyle.appendChild(document.createTextNode(styles));
head.appendChild(oStyle);
}
}
unsafeWindow = window;
//====== The actual user script source ======//
{{ scriptSource }}
//====== End User Script ======//
})();

View File

@ -136,3 +136,4 @@ def render(template, **kwargs):
environment = Environment()
js_environment = jinja2.Environment(loader=Loader('javascript'))