mirror of
https://github.com/caddyserver/website.git
synced 2025-04-21 20:46:15 -04:00
docs: Better support for module name collisions
In /docs/modules/, show both modules if module IDs are not globally unique. Show both modules' docs on same page in expandable containers. In /docs/json/, both modules appear in lists in the doc, but disambiguating them isn't implemented yet.
This commit is contained in:
parent
5c3a67692e
commit
e132c5c454
13 changed files with 265 additions and 126 deletions
|
@ -18,9 +18,9 @@
|
|||
<div class="article-container">
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article class="paper paper3">
|
||||
{{markdown $markdownFile.Body}}
|
||||
</article>
|
||||
<div class="paper paper3">
|
||||
<article>{{markdown $markdownFile.Body}}</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</main>
|
||||
|
|
|
@ -15,13 +15,15 @@
|
|||
<div class="article-container">
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article class="paper paper3">
|
||||
<div class="breadcrumbs">
|
||||
<!--Populated by JS-->
|
||||
</div>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
<div class="paper paper3">
|
||||
<article id="json-docs-container">
|
||||
<div class="breadcrumbs">
|
||||
<!--Populated by JS-->
|
||||
</div>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</main>
|
||||
|
|
|
@ -15,27 +15,38 @@
|
|||
<div class="article-container">
|
||||
<div class="paper" id="paper1"></div>
|
||||
<div class="paper" id="paper2"></div>
|
||||
<article id="module-list-container" class="paper paper3">
|
||||
<h1>All Modules</h1>
|
||||
<p>
|
||||
This page lists all registered Caddy modules.
|
||||
</p>
|
||||
<p>
|
||||
We recommend using your browser's "Find in page" feature for quick lookups.
|
||||
</p>
|
||||
<table id="module-list">
|
||||
<tr>
|
||||
<th>Module ID</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<!--Populated by JS-->
|
||||
</table>
|
||||
</article>
|
||||
<article id="module-docs-container" class="paper paper3">
|
||||
<h1 id="module-name"><!--Populated by JS--></h1>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
<div class="paper paper3">
|
||||
<article id="module-list-container">
|
||||
<h1>All Modules</h1>
|
||||
<p>
|
||||
This page lists all registered Caddy modules. Modules are plugins which extend Caddy's <a href="/docs/json/">JSON configuration structure</a>.
|
||||
</p>
|
||||
<p>
|
||||
We recommend using your browser's "Find in page" feature for quick lookups.
|
||||
</p>
|
||||
<table id="module-list">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Module ID</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<!--Populated by JS-->
|
||||
</table>
|
||||
</article>
|
||||
<div id="module-docs-container">
|
||||
<div class="pad"><h1 class="module-name"><!--Populated by JS--></h1></div>
|
||||
<div id="module-multiple-repos">
|
||||
There is more than one module named <b class="module-name"><!--Populated by JS--></b>. Choose one by its repository.
|
||||
</div>
|
||||
<div id="module-template" class="module-repo-container">
|
||||
<div class="module-repo-selector"></div>
|
||||
<article>
|
||||
{{include "/includes/docs-renderbox.html"}}
|
||||
{{include "/includes/docs-details.html"}}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar"></div>
|
||||
</main>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<b>Standard features:</b> ☑️
|
||||
<b>Standard features:</b> <span title="All official Caddy builds come with standard plugins">☑️</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
<div class="nonstandard-notice">
|
||||
<b>This module does not come with Caddy.</b> It can be added by using <b><a href="/docs/build#xcaddy">xcaddy</a></b> or our <b><a href="/download">download page</a></b>. Non-standard modules may be developed by the community and are not officially endorsed or maintained by the Caddy project. The documentation is shown here only as a courtesy.
|
||||
<br><br>
|
||||
<b>Module repository: <a href="javascript:" class="nonstandard-project-link"></a></b>
|
||||
<b>Code repository: <a href="javascript:" class="nonstandard-project-link"></a></b>
|
||||
<br><br>
|
||||
<b>Custom builds:</b> <code class="bash">xcaddy build --with <span class="nonstandard-package-path"></span></code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 id="docs">Description</h2>
|
||||
<div id="top-doc">
|
||||
<div class="top-doc">
|
||||
<!--Populated by JS-->
|
||||
</div>
|
||||
<h2 id="field-list-header">Field List</h2>
|
||||
<dl id="field-list-contents">
|
||||
<h2 class="field-list-header">Field List</h2>
|
||||
<dl class="field-list-contents">
|
||||
<!--Populated by JS-->
|
||||
</dl>
|
|
@ -1 +1 @@
|
|||
<pre><code class="json" id="renderbox"><!--Populated by JS--></code></pre>
|
||||
<pre><code class="json renderbox"><!--Populated by JS--></code></pre>
|
|
@ -6,7 +6,7 @@ article h1 {
|
|||
padding-top: 8%;
|
||||
}
|
||||
|
||||
#renderbox {
|
||||
.renderbox {
|
||||
border-radius: 0;
|
||||
font-size: 20px;
|
||||
line-height: 1.6em;
|
||||
|
|
|
@ -224,6 +224,10 @@ main nav li li a {
|
|||
max-width: 1100px;
|
||||
}
|
||||
|
||||
.pad {
|
||||
padding-top: 8%;
|
||||
}
|
||||
|
||||
article {
|
||||
padding-top: 8%;
|
||||
padding-bottom: 8%;
|
||||
|
@ -238,7 +242,8 @@ width, a few elements should be allowed to
|
|||
extend to the borders of the page
|
||||
*/
|
||||
article > :not(.fullwidth),
|
||||
article > .fullwidth > * {
|
||||
article > .fullwidth > *,
|
||||
.pad {
|
||||
padding-left: 8%;
|
||||
padding-right: 8%;
|
||||
}
|
||||
|
@ -448,13 +453,13 @@ iframe {
|
|||
padding: 10px;
|
||||
color: #886c00;
|
||||
line-height: 1.4em;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nonstandard {
|
||||
color: rgb(214, 145, 16);
|
||||
}
|
||||
|
||||
.standard-flag,
|
||||
.nonstandard-flag {
|
||||
cursor: help;
|
||||
font-size: 8px;
|
||||
|
@ -462,10 +467,25 @@ iframe {
|
|||
padding: 4px 8px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
background-color: rgb(238, 167, 34);
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.standard-flag {
|
||||
background-color: rgb(34, 163, 23);
|
||||
}
|
||||
|
||||
.nonstandard-flag {
|
||||
background-color: rgb(238, 167, 34);
|
||||
}
|
||||
|
||||
.module-repo-differentiator {
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
@ -706,7 +726,8 @@ td code {
|
|||
|
||||
|
||||
#module-docs-container,
|
||||
#module-list-container {
|
||||
#module-list-container,
|
||||
#module-template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -729,7 +750,27 @@ td code {
|
|||
}
|
||||
|
||||
|
||||
#module-multiple-repos {
|
||||
display: none;
|
||||
margin: 25px;
|
||||
}
|
||||
|
||||
.module-repo-selector {
|
||||
font-size: 26px;
|
||||
padding: 25px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #888;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.module-repo-selector:hover {
|
||||
color: #009cda;
|
||||
background: rgb(246, 250, 252);
|
||||
}
|
||||
|
||||
.module-repo-selector-arrow {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// TODO: sanitize all HTML renderings, especially markdown: https://github.com/cure53/DOMPurify
|
||||
|
||||
var pageData = {}, pageDocs = {};
|
||||
|
||||
var $renderbox, $hovercard;
|
||||
var pageDocs = {};
|
||||
var pageData = {};
|
||||
var $hovercard;
|
||||
|
||||
const nonStandardFlag = '<span class="nonstandard-flag" title="This module does not come with official Caddy distributions by default; it needs to be added to custom Caddy builds.">Non-standard</span>';
|
||||
const standardFlag = '<span class="standard-flag" title="This module comes with official Caddy distributions by default.">Standard</span>';
|
||||
|
||||
|
||||
$(function() {
|
||||
$renderbox = $('#renderbox');
|
||||
$hovercard = $('#hovercard');
|
||||
|
||||
var hoverTimeout;
|
||||
|
@ -19,7 +20,7 @@ $(function() {
|
|||
});
|
||||
|
||||
// toggle an object as expanded or collapsed
|
||||
$('#renderbox').on('click', '.toggle-obj', function() {
|
||||
$('body').on('click', '.renderbox .toggle-obj', function() {
|
||||
if ($(this).hasClass('expanded')) {
|
||||
// collapse
|
||||
$(this).html('▸');
|
||||
|
@ -37,7 +38,9 @@ $(function() {
|
|||
clearTimeout(hoverTimeout);
|
||||
|
||||
var pos = $(this).offset();
|
||||
|
||||
var moduleID = $(this).closest('.module-repo-container').data('module-id') || '';
|
||||
var moduleData = pageData[moduleID];
|
||||
|
||||
// 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
|
||||
|
@ -59,10 +62,10 @@ $(function() {
|
|||
if ($(this).hasClass('module')) {
|
||||
// module
|
||||
var $list =$('<div/>');
|
||||
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;
|
||||
if (moduleData.namespaces && moduleData.namespaces[modNamespace]) {
|
||||
for (var i = 0; i < moduleData.namespaces[modNamespace].length; i++) {
|
||||
var modInfo = moduleData.namespaces[modNamespace][i];
|
||||
var href = canTraverse(moduleData) ? '.'+elemPath+'/'+modInfo.name+'/' : './'+modNamespace+'.'+modInfo.name;
|
||||
var content = '<a href="'+href+'" class="module-link"> '+modInfo.name;
|
||||
if (!isStandard(modInfo.package)) {
|
||||
content += nonStandardFlag;
|
||||
|
@ -83,7 +86,7 @@ $(function() {
|
|||
// breadcrumb siblings
|
||||
|
||||
var siblingPath = $(this).data('sibling-path');
|
||||
var bcVal = pageData.breadcrumb[siblingPath];
|
||||
var bcVal = moduleData.breadcrumb[siblingPath];
|
||||
var bcSiblings = [];
|
||||
|
||||
// drill down to the true underlying type
|
||||
|
@ -101,8 +104,8 @@ $(function() {
|
|||
|
||||
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];
|
||||
for (var j = 0; j < moduleData.namespaces[bcVal.module_namespace].length; j++) {
|
||||
var mod = moduleData.namespaces[bcVal.module_namespace][j];
|
||||
bcSiblings.push({name: mod.name, path: siblingPath, isStandard: isStandard(mod.package)})
|
||||
}
|
||||
}
|
||||
|
@ -154,46 +157,58 @@ $(function() {
|
|||
}, '.has-popup');
|
||||
});
|
||||
|
||||
function beginRenderingInto($tpl, moduleID, module) {
|
||||
console.log("RENDERING:", moduleID, module);
|
||||
$tpl.data('module-id', moduleID);
|
||||
pageData[moduleID] = module;
|
||||
|
||||
function beginRendering(json, moduleID) {
|
||||
pageData = json;
|
||||
console.log("PAGE DATA:", pageData);
|
||||
|
||||
// show notice if module is non-standard
|
||||
if (pageData.repo && !isStandard(pageData.structure.type_name)) {
|
||||
$('.nonstandard-project-link').attr('href', pageData.repo).text(pageData.repo);
|
||||
$('.nonstandard-notice').prepend(nonStandardFlag).show();
|
||||
if (module.repo) {
|
||||
if (isStandard(module.structure.type_name)) {
|
||||
$('.nonstandard-notice', $tpl).remove();
|
||||
} else {
|
||||
let { pkg, _ } = splitTypeName(module.structure.type_name);
|
||||
$('.nonstandard-project-link', $tpl).attr('href', module.repo).text(module.repo);
|
||||
$('.nonstandard-package-path', $tpl).text(pkg);
|
||||
$('.nonstandard-notice', $tpl).prepend(nonStandardFlag);
|
||||
}
|
||||
|
||||
var $repoName = $('<span/>').text(stripScheme(module.repo));
|
||||
$('.module-repo-selector', $tpl).html('<span class="module-repo-selector-arrow">▸</span>').append($repoName);
|
||||
}
|
||||
|
||||
// for most types, just render their docs; but for maps or arrays, fall through to underlying type for docs
|
||||
let rawDocs = pageData.structure.doc ?? pageData.structure.elems;
|
||||
let rawDocs = module.structure.doc ?? module.structure.elems;
|
||||
|
||||
$('#top-doc').html(markdown(replaceGoTypeNameWithCaddyModuleName(rawDocs, moduleID)));
|
||||
$('#top-doc').append(makeSubmoduleList("", pageData.structure));
|
||||
$('.top-doc', $tpl).html(markdown(replaceGoTypeNameWithCaddyModuleName(rawDocs, module, moduleID)));
|
||||
$('.top-doc', $tpl).append(makeSubmoduleList(module, "", module.structure));
|
||||
|
||||
renderData(pageData.structure, 0, "", $('<div class="group"/>'));
|
||||
let $group = newGroup();
|
||||
renderData($tpl, module, module.structure, 0, "", $group);
|
||||
$('.renderbox', $tpl).append($group);
|
||||
|
||||
if ($('#field-list-contents').text().trim()) {
|
||||
$('#field-list-header').show();
|
||||
if ($('.field-list-contents', $tpl).text().trim()) {
|
||||
$('.field-list-header', $tpl).show();
|
||||
}
|
||||
|
||||
// if the browser tried to navigate directly to an element
|
||||
// on the page when it loaded, it would have failed since
|
||||
// we hadn't rendered it yet; but now we can scroll to it
|
||||
// directly since rendering has finished
|
||||
if (window.location.hash) {
|
||||
window.location.hash = window.location.hash;
|
||||
}
|
||||
// TODO: see about fixing this for module and JSON docs pages
|
||||
// // if the browser tried to navigate directly to an element
|
||||
// // on the page when it loaded, it would have failed since
|
||||
// // we hadn't rendered it yet; but now we can scroll to it
|
||||
// // directly since rendering has finished
|
||||
// if (window.location.hash.length > 1) {
|
||||
// document.getElementById(window.location.hash.substr(1)).scrollIntoView();
|
||||
// }
|
||||
}
|
||||
|
||||
function renderData(data, nesting, path, $group) {
|
||||
function renderData($tpl, module, data, nesting, path, $group) {
|
||||
switch (data.type) {
|
||||
case "struct":
|
||||
$group.append('{<a href="javascript:" class="toggle-obj expanded" title="Collapse/expand">▾</a>');
|
||||
nesting++;
|
||||
|
||||
var $fieldGroup = $('<div class="group"/>');
|
||||
renderModuleInlineKey(data, nesting, $fieldGroup);
|
||||
var $fieldGroup = newGroup();
|
||||
renderModuleInlineKey($tpl, module, data, nesting, $fieldGroup);
|
||||
$group.append($fieldGroup);
|
||||
if (data.struct_fields) {
|
||||
// TODO: Not sure if sorting the struct fields is a good idea...
|
||||
|
@ -216,19 +231,19 @@ function renderData(data, nesting, path, $group) {
|
|||
|
||||
// render the docs to the page
|
||||
var fieldDoc = markdown(field.doc) || '<p class="explain">There are no docs for this property.</p>';
|
||||
fieldDoc += makeSubmoduleList(fieldPath, field.value);
|
||||
appendToFieldDocs(cleanFieldPath, fieldDoc);
|
||||
fieldDoc += makeSubmoduleList(module, fieldPath, field.value);
|
||||
appendToFieldDocs($tpl, module, cleanFieldPath, fieldDoc);
|
||||
|
||||
// render the field to the JSON box
|
||||
var $fieldGroup = $('<div class="group"/>');
|
||||
var $fieldGroup = newGroup();
|
||||
indent(nesting, $fieldGroup);
|
||||
var keyATag = '<a ';
|
||||
if (canTraverse()) {
|
||||
if (canTraverse(module)) {
|
||||
keyATag += 'href=".'+fieldPath+'/" ';
|
||||
}
|
||||
keyATag += 'data-path="'+fieldPath+'" class="'+linkClass+'">'+field.key+'</a>';
|
||||
$fieldGroup.append('<span class="qu">"</span><span class="key">'+keyATag+'</span><span class="qu">"</span>: ');
|
||||
renderData(field.value, nesting, fieldPath, $fieldGroup);
|
||||
renderData($tpl, module, field.value, nesting, fieldPath, $fieldGroup);
|
||||
if (i < data.struct_fields.length-1) {
|
||||
$fieldGroup.append(',');
|
||||
}
|
||||
|
@ -260,7 +275,7 @@ function renderData(data, nesting, path, $group) {
|
|||
if (data.elems.type == "module_map") {
|
||||
$group.append('{<a href=".'+path+'/" class="module has-popup" data-namespace="'+(data.elems.module_namespace || '')+'" data-path="'+path+'">•••</a>}');
|
||||
} else {
|
||||
renderData(data.elems, nesting, path, $group);
|
||||
renderData($tpl, module, data.elems, nesting, path, $group);
|
||||
}
|
||||
$group.append(']');
|
||||
break;
|
||||
|
@ -268,11 +283,11 @@ function renderData(data, nesting, path, $group) {
|
|||
case "map":
|
||||
$group.append('{\n')
|
||||
nesting++;
|
||||
renderModuleInlineKey(data, nesting, $group);
|
||||
renderModuleInlineKey($tpl, module, data, nesting, $group);
|
||||
indent(nesting, $group);
|
||||
renderData(data.map_keys, nesting, path, $group);
|
||||
renderData($tpl, module, data.map_keys, nesting, path, $group);
|
||||
$group.append(': ');
|
||||
renderData(data.elems, nesting, path, $group);
|
||||
renderData($tpl, module, data.elems, nesting, path, $group);
|
||||
$group.append('\n');
|
||||
nesting--;
|
||||
indent(nesting, $group);
|
||||
|
@ -282,18 +297,16 @@ function renderData(data, nesting, path, $group) {
|
|||
case "module":
|
||||
case "module_map":
|
||||
var aTag = '<a';
|
||||
if (canTraverse()) {
|
||||
if (canTraverse(module)) {
|
||||
aTag += ' href=".'+path+'/"';
|
||||
}
|
||||
aTag += ' class="module has-popup" data-namespace="'+(data.module_namespace || '')+'" data-path="'+path+'">•••</a>';
|
||||
$group.append('{'+aTag+'}');
|
||||
break;
|
||||
}
|
||||
|
||||
$renderbox.append($group);
|
||||
}
|
||||
|
||||
function renderModuleInlineKey(data, nesting, $group) {
|
||||
function renderModuleInlineKey($tpl, module, data, nesting, $group) {
|
||||
if (!data.module_inline_key) {
|
||||
return
|
||||
}
|
||||
|
@ -305,15 +318,15 @@ function renderModuleInlineKey(data, nesting, $group) {
|
|||
}
|
||||
$group.append('\n');
|
||||
|
||||
appendToFieldDocs(data.module_inline_key, $('#hovercard-inline-key').html());
|
||||
appendToFieldDocs($tpl, module, data.module_inline_key, $('#hovercard-inline-key').html());
|
||||
}
|
||||
|
||||
function appendToFieldDocs(cleanFieldPath, fieldDoc) {
|
||||
function appendToFieldDocs($tpl, module, cleanFieldPath, fieldDoc) {
|
||||
var dt = cleanFieldPath;
|
||||
if (canTraverse()) {
|
||||
if (canTraverse(module)) {
|
||||
dt = '<a href="./'+cleanFieldPath+'/">'+dt+'</a>';
|
||||
}
|
||||
$('#field-list-contents').append('<dt class="field-name" id="'+cleanFieldPath+'"><a href="#'+cleanFieldPath+'" class="inline-link">🔗</a>'+dt+'</dt> <dd>'+fieldDoc+'</dd>');
|
||||
$('.field-list-contents', $tpl).append('<dt class="field-name" id="'+cleanFieldPath+'"><a href="#'+cleanFieldPath+'" class="inline-link">🔗</a>'+dt+'</dt> <dd>'+fieldDoc+'</dd>');
|
||||
}
|
||||
|
||||
function indent(nesting, $group) {
|
||||
|
@ -322,7 +335,7 @@ function indent(nesting, $group) {
|
|||
$group.append($span);
|
||||
}
|
||||
|
||||
function makeSubmoduleList(path, value) {
|
||||
function makeSubmoduleList(module, path, value) {
|
||||
while (value.elems) {
|
||||
value = value.elems;
|
||||
}
|
||||
|
@ -330,10 +343,10 @@ function makeSubmoduleList(path, value) {
|
|||
return '';
|
||||
}
|
||||
var submodList = '<ul>';
|
||||
if (pageData.namespaces && pageData.namespaces[value.module_namespace]) {
|
||||
for (var j = 0; j < pageData.namespaces[value.module_namespace].length; j++) {
|
||||
var submod = pageData.namespaces[value.module_namespace][j];
|
||||
var href = canTraverse() ? '.'+path+'/'+submod.name+'/' : './'+value.module_namespace+'.'+submod.name;
|
||||
if (module.namespaces && module.namespaces[value.module_namespace]) {
|
||||
for (var j = 0; j < module.namespaces[value.module_namespace].length; j++) {
|
||||
var submod = module.namespaces[value.module_namespace][j];
|
||||
var href = canTraverse(module) ? '.'+path+'/'+submod.name+'/' : './'+value.module_namespace+'.'+submod.name;
|
||||
var submodLink = '<a href="'+href+'">'+submod.name+'</a>';
|
||||
if (!isStandard(submod.package)) {
|
||||
submodLink += ' '+nonStandardFlag;
|
||||
|
@ -349,18 +362,22 @@ function makeSubmoduleList(path, value) {
|
|||
// includes breadcrumbs; i.e. we are on a page
|
||||
// that can traverse the JSON structure, not
|
||||
// only render part of it in isolation.
|
||||
function canTraverse() {
|
||||
return pageData.breadcrumb != null;
|
||||
function canTraverse(data) {
|
||||
return data.breadcrumb != null;
|
||||
}
|
||||
|
||||
function replaceGoTypeNameWithCaddyModuleName(docs, moduleID) {
|
||||
function newGroup() {
|
||||
return $('<div class="group"/>');
|
||||
}
|
||||
|
||||
function replaceGoTypeNameWithCaddyModuleName(docs, module, moduleID) {
|
||||
if (!docs || !moduleID) return docs;
|
||||
|
||||
// fully qualified type name
|
||||
let fqtn = pageData.structure.type_name;
|
||||
let fqtn = module.structure.type_name;
|
||||
|
||||
// extract just the local type name
|
||||
let typeName = fqtn.substr(fqtn.lastIndexOf('.')+1)
|
||||
let {_, typeName} = splitTypeName(fqtn);
|
||||
|
||||
// replace the type name with the Caddy module ID if it starts the docs.
|
||||
if (docs.indexOf(typeName) === 0) {
|
||||
|
|
|
@ -80,3 +80,17 @@ $(function() {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
function stripScheme(url) {
|
||||
return url.substring(url.indexOf("://")+3);
|
||||
}
|
||||
|
||||
// splitTypeName splits a fully qualified type name into
|
||||
// its package path and type name components, for example:
|
||||
// "github.com/foo/bar.Type" => "github.com/foo/bar" and "Type".
|
||||
function splitTypeName(fqtn) {
|
||||
let lastDotPos = fqtn.lastIndexOf('.');
|
||||
let pkg = fqtn.substr(0, lastDotPos);
|
||||
let typeName = fqtn.substr(lastDotPos+1);
|
||||
return {pkg: pkg, typeName: typeName};
|
||||
}
|
|
@ -25,7 +25,7 @@ $.get("/api/packages").done(function(json) {
|
|||
|
||||
const moduleTemplate =
|
||||
'<div class="module">\n'+
|
||||
' 🔌<a target="_blank" title="View module docs" class="module-link"></a>\n'+
|
||||
' 🔌 <a target="_blank" title="View module docs" class="module-link"></a>\n'+
|
||||
' <span class="module-desc"></span>\n'+
|
||||
'</div>\n';
|
||||
|
||||
|
@ -53,6 +53,7 @@ $.get("/api/packages").done(function(json) {
|
|||
for (var j = 0; j < pkg.modules.length; j++) {
|
||||
var mod = pkg.modules[j];
|
||||
var $mod = $(moduleTemplate);
|
||||
// TODO: if this module name collides with that from another package, add a #hash to the URL to expand the right module's docs automatically
|
||||
$('.module-link', $mod).attr('href', '/docs/modules/'+mod.name).text(mod.name).attr('title', "View module details");
|
||||
$('.module-desc', $mod).text(moduleDocsPreview(mod, 120));
|
||||
$('.package-modules', $pkg).append($mod);
|
||||
|
|
|
@ -9,7 +9,7 @@ setPageTitle();
|
|||
$.get("/api/docs/config"+configPath, function(json) {
|
||||
// wait until the DOM has finished loading before rendering the results
|
||||
$(function() {
|
||||
beginRendering(json.result);
|
||||
beginRenderingInto($('#json-docs-container'), '', json.result);
|
||||
|
||||
// establish the breadcrumb
|
||||
var $bc = $('.breadcrumbs');
|
||||
|
@ -17,9 +17,9 @@ $.get("/api/docs/config"+configPath, function(json) {
|
|||
for (var i = 1; i < pathComponents.length-1; i++) {
|
||||
var bcPath = pathComponents.slice(0, i+1).join('/');
|
||||
var bcSiblingPath = pathComponents.slice(1, i).join('/');
|
||||
|
||||
// prefixing with <span/> is a hack so jQuery treats this as a HTML DOM object
|
||||
$('<span/> › <a href="'+jsonDocsPathPrefix+bcPath.substr(1)+'/" class="breadcrumb has-popup" data-sibling-path="'+bcSiblingPath+'">'+pathComponents[i]+'</a>').appendTo($bc);
|
||||
|
||||
// enclosing with span is a hack so jQuery treats this as a HTML DOM object
|
||||
$('<span> › <a href="'+jsonDocsPathPrefix+bcPath.substr(1)+'/" class="breadcrumb has-popup" data-sibling-path="'+bcSiblingPath+'">'+pathComponents[i]+'</a></span>').appendTo($bc);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -2,40 +2,91 @@ const moduleDocsPathPrefix = "/docs/modules/";
|
|||
|
||||
var moduleID = window.location.pathname.substr(moduleDocsPathPrefix.length);
|
||||
if (moduleID) {
|
||||
// update page title and load the docs for this module
|
||||
// update page title and load the docs for these modules (possibly more than 1 with this ID)
|
||||
document.title = "Module " + moduleID + " - Caddy Documentation";
|
||||
$.get("/api/docs/module/"+moduleID, function(json) {
|
||||
var modules = json.result;
|
||||
|
||||
// wait until the DOM has finished loading before rendering the results
|
||||
$(function() {
|
||||
$('#module-docs-container').show();
|
||||
$('h1').text("Module "+moduleID);
|
||||
beginRendering(json.result, moduleID);
|
||||
$('.module-name').text("Module "+moduleID);
|
||||
modules.forEach((module) => {
|
||||
$tpl = $('#module-template').clone().attr('id', stripScheme(module.repo));
|
||||
if (modules.length > 1) {
|
||||
$('article', $tpl).hide();
|
||||
}
|
||||
beginRenderingInto($tpl, moduleID, module);
|
||||
$('#module-docs-container').append($tpl);
|
||||
});
|
||||
if (modules.length > 1) {
|
||||
$('#module-multiple-repos .module-name').text(moduleID);
|
||||
$('#module-multiple-repos').show();
|
||||
} else {
|
||||
$('.module-repo-selector').hide();
|
||||
}
|
||||
|
||||
// if a specific repo's module is wanted, expand and scroll to it
|
||||
if (window.location.hash.length > 1) {
|
||||
// TODO: weird bug in jQuery(??) that it can't select IDs with slashes in them, so we use vanilla JS
|
||||
var container = document.getElementById(window.location.hash.substr(1));
|
||||
$('.module-repo-selector', container).click();
|
||||
container.scrollIntoView();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(function() {
|
||||
$('body').on('click', '.module-repo-selector', function() {
|
||||
if ($(this).hasClass('expanded')) {
|
||||
// collapse
|
||||
$('.module-repo-selector-arrow', this).html('▸');
|
||||
} else {
|
||||
// expand
|
||||
$('.module-repo-selector-arrow', this).html('▾');
|
||||
}
|
||||
$(this).toggleClass('expanded');
|
||||
$(this).next('article').toggle();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// populate the module list
|
||||
$.get("/api/modules", function(json) {
|
||||
var moduleList = json.result;
|
||||
|
||||
console.log("MODULE LIST:", moduleList);
|
||||
|
||||
// wait until the DOM has finished loading before rendering the results
|
||||
$(function() {
|
||||
$('#module-list-container').show();
|
||||
$table = $('#module-list');
|
||||
for (modID in moduleList) {
|
||||
var val = moduleList[modID];
|
||||
var infos = moduleList[modID];
|
||||
|
||||
// refine a short preview of the module's docs
|
||||
let shortDoc = truncate(val.doc, 200);
|
||||
if (shortDoc && shortDoc.indexOf(modID) === 0) {
|
||||
shortDoc = shortDoc.substr(modID.length).trim();
|
||||
}
|
||||
|
||||
var standard = isStandard(val.type_name);
|
||||
var $tr = $('<tr/>');
|
||||
$tr.append('<td><a href="./'+modID+'" class="module-link">'+modID+'</a>'+(standard ? '' : ' '+nonStandardFlag)+'</td>');
|
||||
$tr.append($('<td/>').text(shortDoc));
|
||||
$table.append($tr);
|
||||
infos.forEach((info) => {
|
||||
// refine a short preview of the module's docs
|
||||
let shortDoc = truncate(info.docs, 200);
|
||||
if (shortDoc && shortDoc.indexOf(modID) === 0) {
|
||||
shortDoc = shortDoc.substr(modID.length).trim();
|
||||
}
|
||||
|
||||
let modLink = "./"+modID;
|
||||
if (infos.length > 1) {
|
||||
modLink += "#"+stripScheme(info.repo);
|
||||
}
|
||||
|
||||
var standard = isStandard(info.package);
|
||||
var $tr = $('<tr/>');
|
||||
$tr.append('<td>'+(standard ? standardFlag : nonStandardFlag)+'</td>');
|
||||
var $tdLink = $('<td><a href="'+modLink+'" class="module-link">'+modID+'</a></td>');
|
||||
if (infos.length > 1) {
|
||||
$tdLink.append($('<div class="module-repo-differentiator">').text('('+stripScheme(info.repo)+')'));
|
||||
}
|
||||
$tr.append($tdLink);
|
||||
$tr.append($('<td/>').text(shortDoc));
|
||||
$table.append($tr);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue