mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 17:57:58 +01:00
XPath validators for 'extendhinttags', 'nextpattern', 'prevpattern'.
This commit is contained in:
@@ -1639,11 +1639,13 @@ const Buffer = Module("buffer", {
|
||||
options: function () {
|
||||
options.add(["nextpattern"],
|
||||
"Patterns to use when guessing the 'next' page in a document sequence",
|
||||
"stringlist", UTF8("\\bnext\\b,^>$,^(>>|»)$,^(>|»),(>|»)$,\\bmore\\b"));
|
||||
"stringlist", UTF8("\\bnext\\b,^>$,^(>>|»)$,^(>|»),(>|»)$,\\bmore\\b"),
|
||||
{ validator: Option.validateXPath });
|
||||
|
||||
options.add(["previouspattern"],
|
||||
"Patterns to use when guessing the 'previous' page in a document sequence",
|
||||
"stringlist", UTF8("\\bprev|previous\\b,^<$,^(<<|«)$,^(<|«),(<|«)$"));
|
||||
"stringlist", UTF8("\\bprev|previous\\b,^<$,^(<<|«)$,^(<|«),(<|«)$"),
|
||||
{ validator: Option.validateXPath });
|
||||
|
||||
options.add(["pageinfo", "pa"],
|
||||
"Desired info in the :pageinfo output",
|
||||
|
||||
@@ -770,7 +770,7 @@ const CommandLine = Module("commandline", {
|
||||
// FIXME: <Esc> should trigger "cancel" event
|
||||
if (events.isAcceptKey(key)) {
|
||||
let mode = this._currentExtendedMode; // save it here, as modes.pop() resets it
|
||||
this._keepCommand = !userContext.hidden_option_command_afterimage;
|
||||
this._keepCommand = userContext.hidden_option_command_afterimage;
|
||||
this._currentExtendedMode = null; // Don't let modes.pop trigger "cancel"
|
||||
modes.pop();
|
||||
commandline.triggerCallback("submit", mode, command);
|
||||
|
||||
@@ -1053,25 +1053,15 @@ const Hints = Module("hints", {
|
||||
util.makeXPath(["input[not(@type='hidden')]", "a", "area", "iframe", "textarea", "button", "select",
|
||||
"*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @role='link']"]);
|
||||
|
||||
function checkXPath(val) {
|
||||
try {
|
||||
util.evaluateXPath(val, document.implementation.createDocument("", "", null));
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
options.add(["extendedhinttags", "eht"],
|
||||
"XPath string of hintable elements activated by ';'",
|
||||
"regexmap", "[iI]:" + Option.quote(util.makeXPath(["img"])),
|
||||
{ validator: checkXPath });
|
||||
{ validator: Option.validateXPath });
|
||||
|
||||
options.add(["hinttags", "ht"],
|
||||
"XPath string of hintable elements activated by 'f' and 'F'",
|
||||
"string", DEFAULT_HINTTAGS,
|
||||
{ validator: checkXPath });
|
||||
{ validator: Option.validateXPath });
|
||||
|
||||
options.add(["hintkeys", "hk"],
|
||||
"The keys used to label and select hints",
|
||||
|
||||
@@ -48,6 +48,9 @@ const Option = Class("Option", {
|
||||
if (this.type in Option.joinValues)
|
||||
this.joinValues = Option.joinValues[this.type];
|
||||
|
||||
if (this.type in Option.testValues)
|
||||
this.testValues = Option.testValues[this.type];
|
||||
|
||||
this._op = Option.ops[this.type];
|
||||
|
||||
if (arguments.length > 3) {
|
||||
@@ -325,6 +328,8 @@ const Option = Class("Option", {
|
||||
*/
|
||||
setter: null,
|
||||
|
||||
testValues: function (values, validator) validator(values),
|
||||
|
||||
/**
|
||||
* @property {function} The function called to validate the option's value
|
||||
* when set.
|
||||
@@ -383,7 +388,7 @@ const Option = Class("Option", {
|
||||
return re;
|
||||
},
|
||||
unparseRegex: function (re) re.bang + Option.quote(re.source.replace(/\\(.)/g, function (m, n1) n1 == "/" ? n1 : m), /^!|:/) +
|
||||
(typeof re.result == "string" ? ":" + Option.quote(re.result) : ""),
|
||||
(typeof re.result === "string" ? ":" + Option.quote(re.result) : ""),
|
||||
|
||||
getKey: {
|
||||
stringlist: function (k) this.values.indexOf(k) >= 0,
|
||||
@@ -427,6 +432,12 @@ const Option = Class("Option", {
|
||||
})
|
||||
},
|
||||
|
||||
testValues: {
|
||||
regexmap: function (vals, validator) vals.every(function (re) validator(re.result)),
|
||||
stringlist: function (vals, validator) vals.every(validator, this),
|
||||
stringmap: function (vals, validator) array(values(vals)).every(validator, this)
|
||||
},
|
||||
|
||||
dequote: function (value) {
|
||||
let arg;
|
||||
[, arg, Option._quote] = Commands.parseArg(String(value), "");
|
||||
@@ -556,6 +567,12 @@ const Option = Class("Option", {
|
||||
if (this.type == "regexmap")
|
||||
return Array.concat(values).every(function (re) res.some(function (item) item[0] == re.result));
|
||||
return Array.concat(values).every(function (value) res.some(function (item) item[0] == value));
|
||||
},
|
||||
|
||||
validateXPath: function (values) {
|
||||
let evaluator = XPathEvaluator();
|
||||
return this.testValues(values,
|
||||
function (value) evaluator.createExpression(value, util.evaluateXPath.resolver));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -275,34 +275,36 @@ const Util = Module("Util", {
|
||||
* @param {boolean} asIterator Whether to return the results as an
|
||||
* XPath iterator.
|
||||
*/
|
||||
evaluateXPath: function (expression, doc, elem, asIterator) {
|
||||
if (!doc)
|
||||
doc = util.activeWindow.content.document;
|
||||
if (!elem)
|
||||
elem = doc;
|
||||
if (isArray(expression))
|
||||
expression = util.makeXPath(expression);
|
||||
evaluateXPath: (function () {
|
||||
function evaluateXPath(expression, doc, elem, asIterator) {
|
||||
if (!doc)
|
||||
doc = util.activeWindow.content.document;
|
||||
if (!elem)
|
||||
elem = doc;
|
||||
if (isArray(expression))
|
||||
expression = util.makeXPath(expression);
|
||||
|
||||
let result = doc.evaluate(expression, elem,
|
||||
function lookupNamespaceURI(prefix) {
|
||||
return {
|
||||
xul: XUL.uri,
|
||||
xhtml: XHTML.uri,
|
||||
xhtml2: "http://www.w3.org/2002/06/xhtml2",
|
||||
dactyl: NS.uri
|
||||
}[prefix] || null;
|
||||
},
|
||||
asIterator ? Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE : Ci.nsIDOMXPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
|
||||
null
|
||||
);
|
||||
let result = doc.evaluate(expression, elem,
|
||||
evaluateXPath.resolver,
|
||||
asIterator ? Ci.nsIDOMXPathResult.ORDERED_NODE_ITERATOR_TYPE : Ci.nsIDOMXPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
|
||||
null
|
||||
);
|
||||
|
||||
return Object.create(result, {
|
||||
__iterator__: {
|
||||
value: asIterator ? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
|
||||
: function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
|
||||
}
|
||||
});
|
||||
},
|
||||
return Object.create(result, {
|
||||
__iterator__: {
|
||||
value: asIterator ? function () { let elem; while ((elem = this.iterateNext())) yield elem; }
|
||||
: function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }
|
||||
}
|
||||
});
|
||||
}
|
||||
evaluateXPath.resolver = function lookupNamespaceURI(prefix) ({
|
||||
xul: XUL.uri,
|
||||
xhtml: XHTML.uri,
|
||||
xhtml2: "http://www.w3.org/2002/06/xhtml2",
|
||||
dactyl: NS.uri
|
||||
}[prefix] || null);
|
||||
return evaluateXPath;
|
||||
})(),
|
||||
|
||||
extend: function extend(dest) {
|
||||
Array.slice(arguments, 1).filter(util.identity).forEach(function (src) {
|
||||
|
||||
Reference in New Issue
Block a user