[PATCH] findLink documentation + fixes:

24 views
Skip to first unread message

chocolateboy

unread,
Mar 6, 2014, 3:22:40 PM3/6/14
to dactyl-...@googlegroups.com
# HG changeset patch
# User chocolateboy <choc...@cpan.org>
# Date 1394136350 0
# Node ID a5ac599ddc4b145f38206126b293e14aa7ab19d3
# Parent 20a6198d8780e42a4a21d89d831d7f765c32e747
findLink documentation + fixes:

- document the order in which links are traversed
- fix the use of the rev (reverse) relation
- correctly handle multiple rel/rev values

diff -r 20a6198d8780 -r a5ac599ddc4b common/locale/en-US/buffer.xml
--- a/common/locale/en-US/buffer.xml Thu Mar 06 04:06:33 2014 +1100
+++ b/common/locale/en-US/buffer.xml Thu Mar 06 20:05:50 2014 +0000
@@ -309,9 +309,11 @@
<spec><oa>count</oa>]]</spec>
<description>
<p>
- Follow the last link matching <o>nextpattern</o>. Used,
- for instance, to move to the next page of search
- results.
+ Follow the <oa>count</oa>th link to the next page. Links with
+ pagination metadata are enumerated first (in document order),
+ followed by links matching <o>nextpattern</o> (in reverse
+ document order). Used, for instance, to navigate to the next
+ page of search results.
</p>
</description>
</item>
@@ -322,9 +324,11 @@
<spec><oa>count</oa>[[</spec>
<description>
<p>
- Follow the last link matching <o>previouspattern</o>. Used,
- for instance, to move to the previous page of search
- results.
+ Follow the <oa>count</oa>th link to the previous page. Links with
+ pagination metadata are enumerated first (in document order),
+ followed by links matching <o>previouspattern</o> (in reverse
+ document order). Used, for instance, to navigate to the previous
+ page of search results.
</p>
</description>
</item>
diff -r 20a6198d8780 -r a5ac599ddc4b common/modules/buffer.jsm
--- a/common/modules/buffer.jsm Thu Mar 06 04:06:33 2014 +1100
+++ b/common/modules/buffer.jsm Thu Mar 06 20:05:50 2014 +0000
@@ -447,13 +447,27 @@
},

/**
- * Find the *count*th last link on a page matching one of the given
- * regular expressions, or with a @rel or @rev attribute matching
- * the given relation. Each frame is searched beginning with the
- * last link and progressing to the first, once checking for
- * matching @rel or @rev properties, and then once for each given
- * regular expression. The first match is returned. All frames of
- * the page are searched, beginning with the currently focused.
+ * Find the *count*th link (0-based) on a page matching the supplied *rel*
+ * and *regexps* parameters. All frames in the page are searched, beginning
+ * with the one that's currently focused.
+ *
+ * Candidate links are traversed in the following order:
+ *
+ * 1) all <link> elements (in document order) for which either of the following is true:
+ * a) the element has a @rel attribute which includes the *rel* value
+ * b) the element has a @rev attribute which includes the inverse of the *rel* value
+ * 2) all <a> elements (in document order) for which either of the following is true:
+ * a) the element has a @rel attribute which includes the *rel* value
+ * b) the element has a @rev attribute which includes the inverse of the *rel* value
+ * 3) visible <a> elements (in reverse document order) for which any of the following are true:
+ * a) the element's text content matches a regular expression in *regexps*
+ * b) the element contains a child element with an @alt attribute that matches a
+ * regular expression in *regexps*
+ * c) the element has a @title attribute which matches a regular expression in
+ * *regexps*
+ *
+ * rel matches are case-insensitive. The equivalence of the "prev" and "previous"
+ * rel/rev values is handled automatically.
*
* If follow is true, the link is followed.
*
@@ -464,15 +478,42 @@
* @param {string} path The CSS to use for the search. @optional
*/
findLink: function findLink(rel, regexps, count, follow, path) {
+ // canonicalise the rel for ALIAS and REVERSE lookups
+ rel = rel.toLowerCase();
+
+ const ALIAS = { prev: "prev(?:ious)?", previous: "prev(?:ious)?" },
+ REVERSE = { prev: "next", previous: "next", next: "prev" };
+
let { Hints, dactyl, options } = this.modules;
-
let selector = path || options.get("hinttags").stringDefaultValue;
+ let rev = REVERSE[rel];
+
+ // Match a space-delimited rel/rev value. Note: space delimiters
+ // ([\f\r\n\t ]) are not limited to " ", so we can't use e.g.:
+ // (" " + haystack + " ").contains(" " + needle + " ").
+ //
+ // http://www.w3.org/TR/html401/struct/links.html#adef-rel
+ // http://www.w3.org/TR/html401/struct/links.html#adef-rev
+ // http://www.w3.org/html/wg/drafts/html/master/single-page.html#space-character
+ //
+ // Curry so that the regexps are compiled up front.
+ function containsWord(needle) {
+ let _needle = RegExp("(?:^|\\s)(?:" + (ALIAS[needle] || needle) + ")(?:\\s|$)", "i");
+ return function (haystack) {
+ return _needle.test(haystack);
+ }
+ }
+
+ let containsRel = containsWord(rel);
+ let containsRev = rev ? containsWord(rev) : () => false;

function followFrame(frame) {
function iter(elems) {
- for (let i = 0; i < elems.length; i++)
- if (elems[i].rel.toLowerCase() === rel || elems[i].rev.toLowerCase() === rel)
- yield elems[i];
+ for (let i = 0; i < elems.length; i++) {
+ let elem = elems[i];
+ if (containsRel(elem.rel) || containsRev(elem.rev))
+ yield elem;
+ }
}

let elems = frame.document.getElementsByTagName("link");
Reply all
Reply to author
Forward
0 new messages