From ca8197d48349d81c55db8cdef607cfc64cd51d1e Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Sat, 21 Mar 2020 21:03:29 -0600 Subject: [PATCH] docs: Add SPA page for listing modules by their ID --- Caddyfile | 8 +- README.md | 4 +- src/docs/json/index.html | 31 +-- src/docs/modules/index.html | 54 +++++ src/includes/docs-details.html | 7 + src/includes/docs-hovercard.html | 14 ++ src/includes/docs-nav.html | 1 + src/includes/docs-renderbox.html | 1 + src/resources/css/docs.css | 52 ++++- src/resources/js/docs-api.js | 345 +++++++++++++++++++++++++++++ src/resources/js/docs-json.js | 359 ------------------------------- src/resources/js/docs.js | 4 + src/resources/js/json-docs.js | 46 ++++ src/resources/js/module-docs.js | 31 +++ 14 files changed, 565 insertions(+), 392 deletions(-) create mode 100644 src/docs/modules/index.html create mode 100644 src/includes/docs-details.html create mode 100644 src/includes/docs-hovercard.html create mode 100644 src/includes/docs-renderbox.html create mode 100644 src/resources/js/docs-api.js delete mode 100644 src/resources/js/docs-json.js create mode 100644 src/resources/js/json-docs.js create mode 100644 src/resources/js/module-docs.js diff --git a/Caddyfile b/Caddyfile index 9fa1df9..58fbec9 100644 --- a/Caddyfile +++ b/Caddyfile @@ -5,8 +5,10 @@ root * src file_server templates -redir /docs/json /docs/json/ -rewrite /docs/json/* /docs/json/index.html -rewrite /docs/* /docs/index.html +redir /docs/json /docs/json/ +redir /docs/modules /docs/modules/ +rewrite /docs/json/* /docs/json/index.html +rewrite /docs/modules/* /docs/modules/index.html +rewrite /docs/* /docs/index.html reverse_proxy /api/* localhost:4444 diff --git a/README.md b/README.md index cc2e741..088718e 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,8 @@ This is the source of the Caddy website, [caddyserver.com](https://caddyserver.c 2. `cd website` 3. `caddy run` -Your first time, you may be prompted for a password. This is so Caddy can serve the site over local HTTPS. +Your first time, you may be prompted for a password. This is so Caddy can serve the site over local HTTPS. If you can't bind to low ports, change [the address at the top of the Caddyfile](https://github.com/caddyserver/website/blob/master/Caddyfile#L1), for example `localhost:2015`. -You can then load [https://localhost](https://localhost) in your browser. +You can then load [https://localhost](https://localhost) (or whatever address you configured) in your browser. diff --git a/src/docs/json/index.html b/src/docs/json/index.html index 0bdce92..6b3951b 100644 --- a/src/docs/json/index.html +++ b/src/docs/json/index.html @@ -1,11 +1,12 @@ - JSON Structure - Caddy Documentation + JSON Config Structure - Caddy Documentation {{include "/includes/docs-head.html"}} - + + {{include "/includes/docs-header.html"}} @@ -16,36 +17,16 @@ -
+ {{include "/includes/docs-renderbox.html"}}
-

- -

-

Field List

-
- -
+ {{include "/includes/docs-details.html"}}
- -
-
-
-

- Fulfilled by modules in namespace: -

-
-
-
-

This property is required because it specifies the module name.

-
-
- -
+ {{include "/includes/docs-hovercard.html"}} {{include "/includes/footer.html"}} diff --git a/src/docs/modules/index.html b/src/docs/modules/index.html new file mode 100644 index 0000000..cb6bc5e --- /dev/null +++ b/src/docs/modules/index.html @@ -0,0 +1,54 @@ + + + + Modules - Caddy Documentation + {{include "/includes/docs-head.html"}} + + + + + + + {{include "/includes/docs-header.html"}} +
+ {{include "/includes/docs-nav.html"}} +
+ +
+
+

All Modules

+

+ This page lists all registered Caddy modules. +

+

+ We recommend using your browser's "Find in page" feature for quick lookups. +

+ + + + + + +
Module IDDescription
+
+
+ +
+
+

+
+ {{include "/includes/docs-renderbox.html"}} +
+ {{include "/includes/docs-details.html"}} +
+
+ +
+ +
+ + {{include "/includes/docs-hovercard.html"}} + + {{include "/includes/footer.html"}} + + diff --git a/src/includes/docs-details.html b/src/includes/docs-details.html new file mode 100644 index 0000000..831136e --- /dev/null +++ b/src/includes/docs-details.html @@ -0,0 +1,7 @@ +

+ +

+

Field List

+
+ +
\ No newline at end of file diff --git a/src/includes/docs-hovercard.html b/src/includes/docs-hovercard.html new file mode 100644 index 0000000..0f5792f --- /dev/null +++ b/src/includes/docs-hovercard.html @@ -0,0 +1,14 @@ +
+
+
+

+ Fulfilled by modules in namespace: +

+
+
+
+

This property is required because it specifies the module name.

+
+
+ +
\ No newline at end of file diff --git a/src/includes/docs-nav.html b/src/includes/docs-nav.html index 3eb79ed..04543d5 100644 --- a/src/includes/docs-nav.html +++ b/src/includes/docs-nav.html @@ -30,6 +30,7 @@
  • Global options
  • +
  • Modules
  • JSON Config Structure
  • Automatic HTTPS
  • diff --git a/src/includes/docs-renderbox.html b/src/includes/docs-renderbox.html new file mode 100644 index 0000000..a778960 --- /dev/null +++ b/src/includes/docs-renderbox.html @@ -0,0 +1 @@ +
    \ No newline at end of file diff --git a/src/resources/css/docs.css b/src/resources/css/docs.css index 99701ff..844f7c9 100644 --- a/src/resources/css/docs.css +++ b/src/resources/css/docs.css @@ -198,7 +198,7 @@ article li { h1 { font-size: 80px; color: #196165; - margin-bottom: 25px; + margin-bottom: 50px; } h2 { @@ -352,12 +352,13 @@ main > .sidebar:not(:last-child) { .json .str { color: #2f8598; } .json .num { color: #038a3f; } .json .bool { color: #9b5e14; } -.json .key a:not(:hover) { color: inherit; } +.json .key a:not([href]) { color: #222; } .json a { text-decoration: none; font-weight: bold; } -.json .has-popup { border-bottom: 1px dashed #1c82dc; } +.json .has-popup { border-bottom: 1px dashed #222; } +.json a[href].has-popup { border-bottom-color: #1c82dc; } .json .has-popup.module { border-bottom: none; } @@ -567,6 +568,51 @@ td code { font-size: 14px; word-wrap: break-word; } + + + + + + +#module-docs-container, +#module-list-container { + display: none; +} + +#module-list { + margin-top: 50px; +} + +#module-list td:first-child { + word-wrap: break-word; + max-width: 300px; +} + +#module-list .module-link { + font-weight: bold; + font-size: 20px; +} + + + + + + + + + + + + + + + + + + + + + @media (max-width: 1400px) { article aside { diff --git a/src/resources/js/docs-api.js b/src/resources/js/docs-api.js new file mode 100644 index 0000000..a05b7dd --- /dev/null +++ b/src/resources/js/docs-api.js @@ -0,0 +1,345 @@ +// TODO: sanitize all HTML renderings, especially markdown: https://github.com/cure53/DOMPurify + +var pageData = {}, pageDocs = {}; + +var $renderbox, $hovercard; + +$(function() { + $renderbox = $('#renderbox'); + $hovercard = $('#hovercard'); + + var hoverTimeout; + $hovercard.hover(function() { + clearTimeout(hoverTimeout); + }, function() { + clearTimeout(hoverTimeout); + $hovercard.removeClass('popup'); + }); + + // toggle an object as expanded or collapsed + $('#renderbox').on('click', '.toggle-obj', function() { + if ($(this).hasClass('expanded')) { + // collapse + $(this).html('▸'); + } else { + // expand + $(this).html('▾'); + } + $(this).nextUntil('.end-obj').toggleClass('collapsed'); + $(this).toggleClass('expanded'); + }); + + $('body').on({ + mouseenter: function() { + // don't allow hoverbox to close anymore, we're re-opening it + clearTimeout(hoverTimeout); + + var pos = $(this).position(); + + // there is a gap between the hoverbox and the link that originated it; + // there may be a different link in this gap; if the hover box is visible, + // then we should ignore the hover on this link to allow cursor to visit + // the hoverbox if that is where it is going; this makes it possible to + // visit the hoverbox while it is over a list of links that are tightly + // stacked vertically; if user wants to visit hoverbox for link in this + // gap, they can just move the cursor slow enough to fire the timeout + if ($hovercard.is(':visible') && $hovercard.position().top - 10 < pos.top) { + return; + } + + // fill out hovercard + + var elemPath = $(this).data('path'); + var modNamespace = $(this).data('namespace'); + + $('.hovercard-elem').hide(); + + if ($(this).hasClass('module')) { + // module + var $list =$('
    '); + if (pageData.namespaces && pageData.namespaces[modNamespace]) { + for (var i = 0; i < pageData.namespaces[modNamespace].length; i++) { + var modInfo = pageData.namespaces[modNamespace][i]; + var href = canTraverse() ? '.'+elemPath+'/'+modInfo.name+'/' : './'+modNamespace+'.'+modInfo.name; + $list.append(''+modInfo.name+''+truncate(modInfo.docs, 115)+''); + } + } + $('#hovercard-module-list').html($list); + $('#hovercard-namespace').text(modNamespace) + $('#hovercard-module').show(); + + } else if ($(this).hasClass('module-inline-key')) { + // inline key + $('#hovercard-inline-key').show(); + + } else if ($(this).hasClass('breadcrumb')) { + // breadcrumb siblings + + var siblingPath = $(this).data('sibling-path'); + var bcVal = pageData.breadcrumb[siblingPath]; + var bcSiblings = []; + + // drill down to the true underlying type + while (bcVal.elems) { + bcVal = bcVal.elems; + } + + switch (bcVal.type) { + case "struct": + for (var j = 0; j < bcVal.struct_fields.length; j++) { + var sf = bcVal.struct_fields[j]; + bcSiblings.push({name: sf.key, path: siblingPath}) + } + break; + + case "module": + case "module_map": + for (var j = 0; j < pageData.namespaces[bcVal.module_namespace].length; j++) { + var mod = pageData.namespaces[bcVal.module_namespace][j]; + bcSiblings.push({name: mod.name, path: siblingPath}) + } + } + + var $siblings = $('