possibly_valid_url: allow spaces after first '/'
[conkeror/arlinius.git] / modules / follow-relationship.js
blobfc7e828b76f0e0cd37af9ab378602144e990e7e7
1 /**
2  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2012 John Foerch
4  *
5  * Portions of this file were derived from Vimperator,
6  * (C) Copyright 2007 Doug Kearns
7  * (C) Copyright 2007-2008 Martin Stubenschrott.
8  *
9  * Use, modification, and distribution are subject to the terms specified in the
10  * COPYING file.
11 **/
13 require("element.js");
15 const RELATIONSHIP_NEXT = 0;
16 const RELATIONSHIP_PREVIOUS = 1;
18 var browser_relationship_rel_regexp = ["next", "prev|previous"];
19 var browser_relationship_rev_regexp = ["prev|previous", "next"];
21 define_variable("browser_relationship_patterns", {},
22     "Patterns used by `follow-next' and `follow-previous'. "+
23     "User value may be overridden for specific websites by "+
24     "page-modes.");
26 browser_relationship_patterns[RELATIONSHIP_NEXT] =
27     [/^next$/i,
28      new RegExp("^>$","i"),
29      new RegExp("^(>>|»)$","i"),
30      new RegExp("^(>|»)","i"),
31      new RegExp("(>|»)$","i"),
32      new RegExp("\\bnext","i")
33     ];
35 browser_relationship_patterns[RELATIONSHIP_PREVIOUS] =
36     [/^(prev|previous)$/i,
37      new RegExp("^<$","i"),
38      new RegExp("^(<<|«)$","i"),
39      new RegExp("^(<|«)","i"),
40      new RegExp("(<|«)$","i"),
41      new RegExp("\\bprev|previous\\b","i")
42     ];
44 function document_get_element_by_relationship (doc, patterns, relationship) {
45     patterns = patterns[relationship];
46     var rel_name = new RegExp(browser_relationship_rel_regexp[relationship], "i");
47     var rev_name = new RegExp(browser_relationship_rev_regexp[relationship], "i");
49     var elems = doc.getElementsByTagName("link");
50     // links have higher priority than anchors
51     for (var i = 0, n = elems.length; i < n; i++) {
52         if (rel_name.test(elems[i].rel) || rev_name.test(elems[i].rev))
53             return elems[i];
54     }
56     // no links? look for anchors
57     elems = doc.getElementsByTagName("a");
58     for (i = 0, n = elems.length; i < n; i++) {
59         if (rel_name.test(elems[i].rel) || rev_name.test(elems[i].rev))
60             return elems[i];
61     }
63     for (var j = 0, p = patterns.length; j < p; ++j) {
64         var pattern = patterns[j];
65         if (pattern instanceof Function) {
66             var elem = pattern(doc);
67             if (elem)
68                 return elem;
69         } else {
70             for (i = 0, n = elems.length; i < n; i++) { // loop through list of anchors again
71                 if (pattern.test(elems[i].textContent))
72                     return elems[i];
73                 // images with alt text being href
74                 var children = elems[i].childNodes;
75                 for (var k = 0, c = children.length; k < c; k++) {
76                     if (children[k].alt && pattern.test(children[k].alt))
77                         return elems[i];
78                 }
79             }
80         }
81     }
82     return null;
85 define_browser_object_class("relationship-next", null,
86     function (I, prompt) {
87         var doc = I.buffer.document;
88         for (let frame in frame_iterator(I.buffer.top_frame, I.buffer.focused_frame)) {
89             let elem = document_get_element_by_relationship(
90                 frame.document,
91                 I.local.browser_relationship_patterns,
92                 RELATIONSHIP_NEXT);
93             if (elem)
94                 yield co_return(elem);
95         }
96         throw interactive_error("No \"next\" link found.");
97     });
99 define_browser_object_class("relationship-previous", null,
100     function (I, prompt) {
101         var doc = I.buffer.document;
102         for (let frame in frame_iterator(I.buffer.top_frame, I.buffer.focused_frame)) {
103             let elem = document_get_element_by_relationship(
104                 frame.document,
105                 I.local.browser_relationship_patterns,
106                 RELATIONSHIP_PREVIOUS);
107             if (elem)
108                 yield co_return(elem);
109         }
110         throw interactive_error("No \"previous\" link found.");
111     });
113 provide("follow-relationship");