bkyk8rc3zvpnsf5inmcqq4n3k98cv6hj-my-site-hyper-literate-git.test.suzanne.soy-0.0.1

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

manual-racket.js (8947B)


      1 /* For the Racket manual style */
      2 
      3 AddOnLoad(function() {
      4     /* Look for header elements that have x-source-module and x-part tag.
      5        For those elements, add a hidden element that explains how to
      6        link to the section, and set the element's onclick() to display
      7        the explanation. */
      8     var tag_names = ["h1", "h2", "h3", "h4", "h5"];
      9     for (var j = 0; j < tag_names.length; j++) {
     10         elems = document.getElementsByTagName(tag_names[j]);
     11         for (var i = 0; i < elems.length; i++) {
     12             var elem = elems.item(i);
     13             AddPartTitleOnClick(elem);
     14         }
     15     }
     16 })
     17 
     18 // cache of source urls
     19 var cache = {};
     20 
     21 function ParseSource(source, mod_path, single_collection) {
     22 
     23     var source_url = new URL(source);
     24 
     25     if (source_url.protocol == "github:") {
     26         // browser URL parser only works with http(s) URLs
     27         source_url = new URL("https" + source.substring(6));
     28         var host = source_url.host;
     29         var url_path = source_url.pathname.substring(1).split("/");
     30         if (!(url_path.length >= 2)) return null;
     31         var user = url_path.shift();
     32         var repo = url_path.shift();
     33         var branch = url_path.shift();
     34         var source_path = url_path.join("/");
     35     }
     36     else if (("https:" == source_url.protocol) || ("git:" == source_url.protocol)) {
     37         // browser URL parser only works with http(s) URLs
     38         if ("git:" == source_url.protocol)
     39             source_url = new URL("https" + source.substring(3));
     40 
     41         var host = source_url.host;
     42         var source_path = source_url.searchParams.get("path");
     43         var branch = (source_url.hash || "#master").substring(1);
     44         var url_path = source_url.pathname.substring(1).split("/");
     45         if (url_path.length < 2) throw [source_url.pathname, url_path];
     46         var user = url_path.shift();
     47         var repo = url_path.shift();
     48         var mtch = repo.match(/(.*)\.git$/);
     49         if (mtch) repo = mtch[1];
     50 
     51     }
     52     else return null;
     53 
     54     var mod_path_re = /^\(lib "(.+)"\)$/;
     55 
     56     var mod_path_elems = mod_path && mod_path.match(mod_path_re)[1].split("/");
     57 
     58     if (!user || !repo || !mod_path_elems)
     59         return null;
     60     if (single_collection)
     61         mod_path_elems.shift();
     62 
     63     var file_path = mod_path_elems.join("/");
     64 
     65 
     66     if (source_path) {
     67         file_path = source_path + "/" + file_path;
     68     }
     69 
     70     return { user: user,
     71              repo: repo,
     72              file_path: file_path,
     73              branch: branch,
     74              host: host };
     75 }
     76 
     77 function AddSourceElement(pkg_url, info) {
     78     info.appendChild(document.createTextNode("Document source "));
     79     var url_line = document.createElement("div");
     80     var a = document.createElement("a");
     81     a.href = pkg_url;
     82     a.style.whiteSpace = "nowrap";
     83     a.appendChild(document.createTextNode(pkg_url));
     84     addSpan(url_line, "\xA0", "RktRdr");
     85     url_line.appendChild(a);
     86     info.appendChild(url_line);
     87 }
     88 
     89 var prefixes = { "github.com": "tree",
     90                  "gitlab.com": "-/blob" };
     91 
     92 
     93 function AddSourceUrl(source, mod_path, collection, info) {
     94     // multi is encoded as an array, empty as false
     95     single_collection = (typeof collection === "string");
     96 
     97     var parsed = source && mod_path && ParseSource(source, mod_path, single_collection);
     98 
     99     if (!parsed) return;
    100 
    101     prefix = prefixes.hasOwnProperty(parsed.host) && prefixes[parsed.host];
    102     if (!prefix) return;
    103 
    104     var correct_url = "https://" + [parsed.host, parsed.user, parsed.repo, prefix, parsed.branch, parsed.file_path].join("/");
    105 
    106     if (info) AddSourceElement(correct_url, info);
    107 }
    108 
    109 function addSpan(dest, str, cn) {
    110     var s = document.createElement("span");
    111     s.className = cn;
    112     s.style.whiteSpace = "nowrap";
    113     s.appendChild(document.createTextNode(str));
    114     dest.appendChild(s);
    115 }
    116 
    117 
    118 // test cases
    119 if (false) {
    120     console.log(ParseSource("git://gitlab.com/benn/foo?path=xxx",
    121                             '(lib "asn1/scribblings/asn1.scrbl")',
    122                             false))
    123     console.log(ParseSource("github://github.com/carl-eastlund/mischief/master",
    124                             '(lib "asn1/scribblings/asn1.scrbl")',
    125                             false))
    126     console.log(ParseSource("github://github.com/carl-eastlund/mischief/stable/dir",
    127                             '(lib "asn1/scribblings/asn1.scrbl")',
    128                             false))
    129 
    130     console.log(ParseSource("git://github.com/racket/racket/?path=pkgs/racket-doc",
    131                             '(lib "asn1/scribblings/asn1.scrbl")',
    132                             false));
    133 
    134     console.log(ParseSource("git://github.com/rmculpepper/asn1.git?path=asn1-doc",
    135                             '(lib "asn1/scribblings/asn1.scrbl")',
    136                             true));
    137     console.log(ParseSource("git://github.com/rmculpepper/asn1",
    138                             '(lib "asn1/scribblings/asn1.scrbl")',
    139                             true));
    140     console.log(ParseSource("git://github.com/rmculpepper/asn1",
    141                             '(lib "asn1/scribblings/asn1.scrbl")',
    142                             false));
    143 }
    144 
    145 function AddPartTitleOnClick(elem) {
    146     var mod_path = elem.getAttribute("x-source-module");
    147     var tag = elem.getAttribute("x-part-tag");
    148     var source_pkg = elem.getAttribute("x-source-pkg");
    149 
    150     // create here to share
    151     var info = document.createElement("div");
    152 
    153 
    154     // tag is not needed, but this way we can add the element in only one place
    155     // avoid failing on browser that don't have `fetch`
    156     if (mod_path && source_pkg && tag && window.fetch) {
    157 
    158         var cached = cache[mod_path]
    159         if (cached) {
    160             AddSourceElement(cached[0], mod_path, cached[1], info);
    161         }
    162         else {
    163             fetch("https://pkgs.racket-lang.org/pkg/" + source_pkg + ".json")
    164                 .then(function (response) { return response.json(); })
    165                 .then(function (data) {
    166                     var vers = data["versions"] || {};
    167                     var def = vers["default"] || {};
    168                     var source = def["source"] || undefined;
    169                     var collection = data["collection"];
    170                     if (source) {
    171                         cache[mod_path] = [source, collection];
    172                         AddSourceUrl(source, mod_path, collection, info);
    173                     }
    174                 });
    175         }
    176     }
    177 
    178     if (mod_path && tag) {
    179         // Might not be present:
    180         var prefixes = elem.getAttribute("x-part-prefixes");
    181 
    182         info.className = "RPartExplain";
    183 
    184         /* The "top" tag refers to a whole document: */
    185         var is_top = (tag == "\"top\"");
    186         info.appendChild(document.createTextNode("Link to this "
    187                                                  + (is_top ? "document" : "section")
    188                                                  + " with "));
    189 
    190         /* Break `secref` into two lines if the module path and tag
    191            are long enough: */
    192         var is_long = (is_top ? false : ((mod_path.length
    193                                           + tag.length
    194                                           + (prefixes ? (16 + prefixes.length) : 0))
    195                                          > 60));
    196 
    197         var line1 = document.createElement("div");
    198         var line1x = ((is_long && prefixes) ? document.createElement("div") : line1);
    199         var line2 = (is_long ? document.createElement("div") : line1);
    200 
    201         /* Construct a `secref` call with suitable syntax coloring: */
    202         addSpan(line1, "\xA0@", "RktRdr");
    203         addSpan(line1, (is_top ? "other-doc" : "secref"), "RktSym");
    204         addSpan(line1, "[", "RktPn");
    205         if (!is_top)
    206             addSpan(line1, tag, "RktVal");
    207         if (is_long) {
    208             /* indent additional lines: */
    209             if (prefixes)
    210                 addSpan(line1x, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
    211             addSpan(line2, "\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0", "RktPn");
    212         }
    213         if (prefixes) {
    214             addSpan(line1x, " #:tag-prefixes ", "RktPn");
    215             addSpan(line1x, "'", "RktVal");
    216             addSpan(line1x, prefixes, "RktVal");
    217         }
    218         if (!is_top)
    219             addSpan(line2, " #:doc ", "RktPn");
    220         addSpan(line2, "'", "RktVal");
    221         addSpan(line2, mod_path, "RktVal");
    222         addSpan(line2, "]", "RktPn");
    223 
    224         info.appendChild(line1);
    225         if (is_long)
    226             info.appendChild(line1x);
    227         if (is_long)
    228             info.appendChild(line2);
    229 
    230         info.style.display = "none";
    231 
    232         /* Add the new element afterthe header: */
    233         var n = elem.nextSibling;
    234         if (n)
    235             elem.parentNode.insertBefore(info, n);
    236         else
    237             elem.parentNode.appendChild(info);
    238 
    239         /* Clicking the header shows the explanation element: */
    240         elem.onclick = function () {
    241             if (info.style.display == "none")
    242                 info.style.display = "block";
    243             else
    244                 info.style.display = "none";
    245         }
    246     }
    247 }