mirror of
https://github.com/caddyserver/website.git
synced 2025-04-21 12:36:16 -04:00
New download page, better JSON/module docs
This commit is contained in:
parent
09c3a73299
commit
5c3a67692e
8 changed files with 277 additions and 217 deletions
|
@ -51,12 +51,18 @@
|
||||||
<option value="windows-amd64">Windows amd64</option>
|
<option value="windows-amd64">Windows amd64</option>
|
||||||
<option value="windows-arm-6">Windows arm 6</option>
|
<option value="windows-arm-6">Windows arm 6</option>
|
||||||
<option value="windows-arm-7">Windows arm 7</option>
|
<option value="windows-arm-7">Windows arm 7</option>
|
||||||
|
<!-- <option value="windows-arm64">Windows arm64</option> TODO: Go 1.17 - https://github.com/golang/go/issues/36439 -->
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<b>Additional packages:</b> <span id="package-count">0</span>
|
<b>Standard features:</b> ☑️
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<b>Extra features:</b> <span id="package-count">0</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -64,24 +70,17 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="packages-explanation">
|
<input type="search" id="filter" placeholder="Filter packages and modules...">
|
||||||
Always comes with all standard <a href="/docs/modules">Caddy modules</a>.
|
|
||||||
<br><br>
|
<div class="text-center">
|
||||||
Optionally select additional packages to include in your build: <span class="warning">⚠️ Only choose plugins you need and trust</span>
|
<span class="warning">⚠️ Only choose plugins you need and trust</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-container">
|
<div id="optional-packages">
|
||||||
<table id="optional-packages">
|
<!-- Populated by JavaScript -->
|
||||||
<tr>
|
|
||||||
<th>Package</th>
|
|
||||||
<th class="text-center">Version</th>
|
|
||||||
<th>Modules</th>
|
|
||||||
</tr>
|
|
||||||
<!-- Populated by JS -->
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{include "/includes/footer.html"}}
|
{{include "/includes/footer.html"}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -720,7 +720,7 @@ td code {
|
||||||
|
|
||||||
#module-list td:first-child {
|
#module-list td:first-child {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
max-width: 300px;
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#module-list .module-link {
|
#module-list .module-link {
|
||||||
|
|
|
@ -28,27 +28,43 @@ body {
|
||||||
|
|
||||||
#download {
|
#download {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 16px;
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.packages-explanation {
|
#filter {
|
||||||
margin: 20px auto;
|
margin-top: 1em;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px;
|
||||||
|
font-size: 24px;
|
||||||
|
text-align: center;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filter.found {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
#filter.not-found {
|
||||||
|
color: #cc0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
margin-left: 1em;
|
margin-top: 20px;
|
||||||
font-size: 12px;
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 2px 15px;
|
padding: 5px 15px;
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
border: 2px solid rgb(255, 201, 0);
|
color: rgb(255, 208, 0);
|
||||||
color: rgb(206, 151, 0);
|
background: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:disabled,
|
input:disabled,
|
||||||
select:disabled,
|
select:disabled,
|
||||||
#optional-packages.disabled .optpkg label {
|
#optional-packages.disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,133 +145,93 @@ select:disabled,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.table-container {
|
|
||||||
overflow-x: auto;
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
|
|
||||||
border-top-left-radius: 8px;
|
|
||||||
border-top-right-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages {
|
#optional-packages {
|
||||||
width: 100%;
|
margin-top: 2em;
|
||||||
border-spacing: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #optional-packages tr {
|
.package {
|
||||||
height: 1px;
|
|
||||||
} */
|
|
||||||
|
|
||||||
#optional-packages th,
|
|
||||||
#optional-packages td {
|
|
||||||
border-bottom: 1px solid #dfeaf0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages th:first-child { border-top-left-radius: 8px; }
|
|
||||||
#optional-packages th:last-child { border-top-right-radius: 8px; }
|
|
||||||
|
|
||||||
#optional-packages th {
|
|
||||||
background: #dfe8ec;
|
|
||||||
text-align: left;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
color: #54676f;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
border-color: #90a2ac;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages th:first-child {
|
|
||||||
padding-left: 4.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages td {
|
|
||||||
background: #fff;
|
|
||||||
height: 1px; /* TODO: works on Chrome, but not Firefox */
|
|
||||||
/* height: 100%; TODO: works on Firefox, but not Chrome */
|
|
||||||
/* TODO:
|
|
||||||
see https://stackoverflow.com/a/34781198/1048862
|
|
||||||
(could also do tr with height: 1px which gets ignored,
|
|
||||||
then td with height: inherit; but this effectively the
|
|
||||||
same as just doing a td with height: 1px.)
|
|
||||||
I don't like how either Firefox or Chrome handle this
|
|
||||||
styling (setting the height of the parent shouldn't be
|
|
||||||
required at all, the browser is rendering a height
|
|
||||||
regardless!) but I think I lean toward Firefox's as
|
|
||||||
being more correct; the hack in Firefox is setting a
|
|
||||||
flexible 100% height on the parent, rather than the hack
|
|
||||||
in Chrome which is setting a height that is too small
|
|
||||||
and stretched or ignored anyway.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages th,
|
|
||||||
#optional-packages .optpkg td:first-child label,
|
|
||||||
#optional-packages td:not(:first-child) {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages .optpkg-name {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages .optpkg input[type=checkbox] {
|
|
||||||
transform: scale(1.5);
|
|
||||||
cursor: pointer;
|
|
||||||
margin-right: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#optional-packages .optpkg label {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
padding: 2em;
|
||||||
height: 100%;
|
background: rgba(255, 255, 255, .4);
|
||||||
line-height: 1em;
|
border: 10px solid transparent;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 200ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages:not(.disabled) .optpkg label:hover {
|
.package:hover {
|
||||||
background: linear-gradient(90deg, rgba(242,248,253,1) 75%, rgba(242,248,253,0) 100%);
|
transform: scale(1.02);
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 2px 20px -2px rgba(0, 0, 0, .05);
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg.selected td {
|
.package.selected {
|
||||||
background-color: #f2f8fd;
|
border-color: rgb(25, 97, 192);
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg input[type=text] {
|
.package-icon {
|
||||||
font-size: 12px;
|
font-size: 48px;
|
||||||
padding: 6px;
|
margin-right: 20px;
|
||||||
outline: none;
|
}
|
||||||
|
|
||||||
|
.package-data {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-meta {
|
||||||
|
float: right;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-downloads {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-version-input {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid #ccc;
|
max-width: 75px;
|
||||||
border-radius: 4px;
|
padding: 4px;
|
||||||
|
margin-left: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg input[type=text]::placeholder {
|
.package-link {
|
||||||
font-style: italic;
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: inherit;
|
||||||
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg-no-modules {
|
.package-host {
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-modules {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-no-modules {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg-module {
|
.module {
|
||||||
margin-top: .5em;
|
margin: 10px 0;
|
||||||
margin-bottom: .5em;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg-module .module-name {
|
.module-link {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-family: 'PT Mono', monospace;
|
font-family: 'PT Mono', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optional-packages .optpkg-module .module-description {
|
.module-desc {
|
||||||
color: #444;
|
|
||||||
margin-left: 1em;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,6 +240,9 @@ select:disabled,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.swal-custom-content {
|
.swal-custom-content {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,20 +14,23 @@ function isStandard(packagePath) {
|
||||||
return packagePath.startsWith(caddyImportPath);
|
return packagePath.startsWith(caddyImportPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function substrBeforeLastDot(s) {
|
function truncate(str, maxLen) {
|
||||||
return s.substr(0, s.lastIndexOf('.'))
|
|
||||||
}
|
|
||||||
|
|
||||||
function substrAfterLastDot(s) {
|
|
||||||
return s.substr(s.lastIndexOf('.'))
|
|
||||||
}
|
|
||||||
|
|
||||||
function truncate(str, len) {
|
|
||||||
if (!str) return "";
|
if (!str) return "";
|
||||||
var startLen = str.length;
|
str = str.trim();
|
||||||
str = str.substring(0, len);
|
let firstPeriod = str.match(/\.(\s|$)/); // first dot not in the middle of a word, or at end of string
|
||||||
if (startLen > len) {
|
let terminate = firstPeriod ? firstPeriod.index+1 : str.length;
|
||||||
str += "...";
|
str = str.substring(0, terminate);
|
||||||
|
if (str.length <= maxLen) {
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
return str;
|
return str+"...";
|
||||||
|
}
|
||||||
|
|
||||||
|
function moduleDocsPreview(mod, maxLen) {
|
||||||
|
if (!mod || !mod.docs) return "";
|
||||||
|
let short = truncate(mod.docs, maxLen);
|
||||||
|
if (short.indexOf(mod.name) === 0) {
|
||||||
|
short = short.substr(mod.name.length).trim();
|
||||||
|
}
|
||||||
|
return short;
|
||||||
}
|
}
|
|
@ -155,29 +155,23 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function beginRendering(json) {
|
function beginRendering(json, moduleID) {
|
||||||
pageData = json;
|
pageData = json;
|
||||||
console.log("DATA:", pageData);
|
console.log("PAGE DATA:", pageData);
|
||||||
|
|
||||||
// show notice if module is non-standard
|
// show notice if module is non-standard
|
||||||
if (pageData.structure.type_name && !isStandard(pageData.structure.type_name)) {
|
if (pageData.repo && !isStandard(pageData.structure.type_name)) {
|
||||||
var projectHref = 'https://'+pageData.structure.type_name;
|
$('.nonstandard-project-link').attr('href', pageData.repo).text(pageData.repo);
|
||||||
projectHref = substrBeforeLastDot(projectHref);
|
|
||||||
$('.nonstandard-project-link').attr('href', projectHref).text(projectHref);
|
|
||||||
$('.nonstandard-notice').prepend(nonStandardFlag).show();
|
$('.nonstandard-notice').prepend(nonStandardFlag).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageData.structure.doc) {
|
// for most types, just render their docs; but for maps or arrays, fall through to underlying type for docs
|
||||||
// for most types, just render their docs
|
let rawDocs = pageData.structure.doc ?? pageData.structure.elems;
|
||||||
$('#top-doc').html(markdown(pageData.structure.doc));
|
|
||||||
} else if (pageData.structure.elems) {
|
$('#top-doc').html(markdown(replaceGoTypeNameWithCaddyModuleName(rawDocs, moduleID)));
|
||||||
// for maps or arrays, fall through to the underlying type
|
|
||||||
$('#top-doc').html(markdown(pageData.structure.elems.doc));
|
|
||||||
}
|
|
||||||
$('#top-doc').append(makeSubmoduleList("", pageData.structure));
|
$('#top-doc').append(makeSubmoduleList("", pageData.structure));
|
||||||
|
|
||||||
renderData(pageData.structure, 0, "", $('<div class="group"/>'));
|
renderData(pageData.structure, 0, "", $('<div class="group"/>'));
|
||||||
console.log("DOCS:", pageDocs);
|
|
||||||
|
|
||||||
if ($('#field-list-contents').text().trim()) {
|
if ($('#field-list-contents').text().trim()) {
|
||||||
$('#field-list-header').show();
|
$('#field-list-header').show();
|
||||||
|
@ -359,6 +353,23 @@ function canTraverse() {
|
||||||
return pageData.breadcrumb != null;
|
return pageData.breadcrumb != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replaceGoTypeNameWithCaddyModuleName(docs, moduleID) {
|
||||||
|
if (!docs || !moduleID) return docs;
|
||||||
|
|
||||||
|
// fully qualified type name
|
||||||
|
let fqtn = pageData.structure.type_name;
|
||||||
|
|
||||||
|
// extract just the local type name
|
||||||
|
let typeName = fqtn.substr(fqtn.lastIndexOf('.')+1)
|
||||||
|
|
||||||
|
// replace the type name with the Caddy module ID if it starts the docs.
|
||||||
|
if (docs.indexOf(typeName) === 0) {
|
||||||
|
docs = moduleID + docs.substr(typeName.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
||||||
function markdown(input) {
|
function markdown(input) {
|
||||||
if (!input) {
|
if (!input) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -1,72 +1,68 @@
|
||||||
// download package list as soon as possible
|
// download package list as soon as possible
|
||||||
$.get("/api/packages").done(function(json) {
|
$.get("/api/packages").done(function(json) {
|
||||||
|
// sort package list by most popular, seems to make sense for convenience
|
||||||
var packageList = json.result;
|
var packageList = json.result;
|
||||||
const preselectedPackage = new URL(window.location.href).searchParams.getAll("package") ;
|
packageList.sort((a, b) => {
|
||||||
|
return b.downloads > a.downloads ? 1 : -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
const preselectedPackage = new URL(window.location.href).searchParams.getAll("package");
|
||||||
|
|
||||||
// wait until the DOM has finished loading before rendering the results
|
// wait until the DOM has finished loading before rendering the results
|
||||||
$(function() {
|
$(function() {
|
||||||
const optpkgTemplate =
|
const packageTemplate =
|
||||||
'<tr class="optpkg">'+
|
'<div class="package">\n'+
|
||||||
' <td><label><input type="checkbox" class="optpkg-check"><span class="optpkg-name"></span></label></td>'+
|
' <div class="package-icon">📦</div>\n'+
|
||||||
' <td class="text-center"><input type="text" name="version" placeholder="latest" title="Package version" size="5"></td>'+
|
' <div class="package-data">\n'+
|
||||||
' <td class="optpkg-modules"></td>'+
|
' <div class="package-meta">\n'+
|
||||||
'</tr>';
|
' <b>downloads:</b> <span class="package-downloads"></span>\n'+
|
||||||
|
' <b>version:</b> <input type="text" class="package-version-input" name="version" placeholder="latest" title="Any version string recognized by `go get` can be used">\n'+
|
||||||
|
' </div>\n'+
|
||||||
|
' <a target="_blank" title="View package repo" class="package-link"></a>\n'+
|
||||||
|
' <div class="package-modules"></div>\n'+
|
||||||
|
' </div>\n'+
|
||||||
|
'</div>\n'
|
||||||
|
|
||||||
|
const moduleTemplate =
|
||||||
|
'<div class="module">\n'+
|
||||||
|
' 🔌<a target="_blank" title="View module docs" class="module-link"></a>\n'+
|
||||||
|
' <span class="module-desc"></span>\n'+
|
||||||
|
'</div>\n';
|
||||||
|
|
||||||
const optpkgModuleTemplate =
|
|
||||||
'<div class="optpkg-module">'+
|
|
||||||
' <a class="module-name" title="View docs"></a>'+
|
|
||||||
' <span class="module-description"></span>'+
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
for (var i = 0; i < packageList.length; i++) {
|
for (var i = 0; i < packageList.length; i++) {
|
||||||
var pkg = packageList[i];
|
var pkg = packageList[i];
|
||||||
if (isStandard(pkg.path)) {
|
|
||||||
// not necessary to show, since these packages
|
|
||||||
// come with standard distribution
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $optpkg = $(optpkgTemplate);
|
var $pkg = $(packageTemplate);
|
||||||
$('.optpkg-name', $optpkg).text(pkg.path);
|
|
||||||
|
let { provider, path } = splitVCSProvider(pkg.path);
|
||||||
|
if (provider) {
|
||||||
|
var $pkgHost = $('<span class="package-host"/>').text(provider);
|
||||||
|
$('.package-link', $pkg).html($pkgHost).append('<br/>');
|
||||||
|
}
|
||||||
|
$pkgName = $('<span class="package-name"/>').text(path);
|
||||||
|
|
||||||
|
$('.package-link', $pkg).append($pkgName);
|
||||||
|
$('.package-link', $pkg).prop('href', pkg.repo);
|
||||||
|
$('.package-downloads', $pkg).text(pkg.downloads);
|
||||||
if (preselectedPackage.includes(pkg.path)) {
|
if (preselectedPackage.includes(pkg.path)) {
|
||||||
$('.optpkg-check', $optpkg).prop("checked", true);
|
$($pkg).addClass("selected");
|
||||||
$('.optpkg-check', $optpkg).closest('.optpkg').toggleClass("selected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.optpkg-check', $optpkg).change({pkg: pkg}, (event) => {
|
|
||||||
const element = $(event.currentTarget);
|
|
||||||
let newUrl = new URL(window.location.href);
|
|
||||||
let currentSelected = newUrl.searchParams.getAll("package") ;
|
|
||||||
newUrl.searchParams.delete("package");
|
|
||||||
const pkgPath = event.data.pkg.path;
|
|
||||||
if (element.is(':checked')) {
|
|
||||||
if (!currentSelected.includes(pkgPath)) {
|
|
||||||
currentSelected = [...currentSelected, pkgPath];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const position = currentSelected.indexOf(pkgPath);
|
|
||||||
if (position >= 0) {
|
|
||||||
currentSelected.splice(position, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentSelected.forEach( (selected) => newUrl.searchParams.append("package", selected));
|
|
||||||
history.replaceState({}, "Download Caddy", newUrl.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pkg.modules && pkg.modules.length > 0) {
|
if (pkg.modules && pkg.modules.length > 0) {
|
||||||
for (var j = 0; j < pkg.modules.length; j++) {
|
for (var j = 0; j < pkg.modules.length; j++) {
|
||||||
var mod = pkg.modules[j];
|
var mod = pkg.modules[j];
|
||||||
var $mod = $(optpkgModuleTemplate);
|
var $mod = $(moduleTemplate);
|
||||||
$('.module-name', $mod).attr('href', '/docs/modules/'+mod.name).text(mod.name);
|
$('.module-link', $mod).attr('href', '/docs/modules/'+mod.name).text(mod.name).attr('title', "View module details");
|
||||||
$('.module-description', $mod).text(truncate(mod.docs, 120));
|
$('.module-desc', $mod).text(moduleDocsPreview(mod, 120));
|
||||||
$('.optpkg-modules', $optpkg).append($mod);
|
$('.package-modules', $pkg).append($mod);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$('.optpkg-modules', $optpkg)
|
$('.package-modules', $pkg)
|
||||||
.addClass("optpkg-no-modules")
|
.addClass("package-no-modules")
|
||||||
.text('This package does not add any modules. Either it is another kind of plugin (such as a config adapter) or this listing is in error.');
|
.text('This package does not add any modules to the JSON config structure. Either it is another kind of plugin (such as a config adapter) or this listing is in error.');
|
||||||
}
|
}
|
||||||
$('#optional-packages').append($optpkg);
|
$('#optional-packages').append($pkg);
|
||||||
}
|
}
|
||||||
updatePage();
|
updatePage();
|
||||||
});
|
});
|
||||||
|
@ -86,19 +82,71 @@ $(function() {
|
||||||
|
|
||||||
downloadButtonHtml = $('#download').html();
|
downloadButtonHtml = $('#download').html();
|
||||||
|
|
||||||
// update the page, including the download link, when form fields change
|
$('#filter').on('search keyup', function(event) {
|
||||||
$('#optional-packages').on('change', 'input[type=checkbox]', function() {
|
var count = 0;
|
||||||
$(this).closest('.optpkg').toggleClass('selected');
|
var q = $(this).val().trim().toLowerCase();
|
||||||
updatePage();
|
|
||||||
});
|
$('.package').each(function() {
|
||||||
$('#optional-packages').on('change keyup', 'input[name=version]', function() {
|
if (!q) {
|
||||||
updatePage();
|
// filter is cleared; show all
|
||||||
|
this.style.display = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var corpus = $(this).find('.package-link, .module-link, .module-desc').text().trim().toLowerCase();
|
||||||
|
|
||||||
|
if (corpus.indexOf(q) === -1) {
|
||||||
|
this.style.display = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.style.display = '';
|
||||||
|
count++;
|
||||||
|
});
|
||||||
|
|
||||||
|
// update color of search input based on results
|
||||||
|
if (q) {
|
||||||
|
if (count > 0) {
|
||||||
|
$('#filter').addClass('found').removeClass('not-found');
|
||||||
|
} else {
|
||||||
|
$('#filter').addClass('not-found').removeClass('found');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('#filter').removeClass('found not-found');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#platform').change(function() {
|
$('#platform').change(function() {
|
||||||
updatePage();
|
updatePage();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#download').click(function(event) {
|
$('#optional-packages').on('click', '.package', function() {
|
||||||
|
$(this).toggleClass('selected');
|
||||||
|
updatePage();
|
||||||
|
|
||||||
|
let newUrl = new URL(window.location.href);
|
||||||
|
let currentSelected = newUrl.searchParams.getAll("package") ;
|
||||||
|
newUrl.searchParams.delete("package");
|
||||||
|
const pkgPath = $('.package-link', $(this)).text().trim();
|
||||||
|
if ($(this).hasClass('selected')) {
|
||||||
|
if (!currentSelected.includes(pkgPath)) {
|
||||||
|
currentSelected = [...currentSelected, pkgPath];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const position = currentSelected.indexOf(pkgPath);
|
||||||
|
if (position >= 0) {
|
||||||
|
currentSelected.splice(position, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentSelected.forEach( (selected) => newUrl.searchParams.append("package", selected));
|
||||||
|
history.replaceState({}, document.title, newUrl.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
// when a link within a package listing is clicked, only operate the link (don't select the package)
|
||||||
|
$('#optional-packages').on('click', '.package-link, .module-link, .package-version-input', function(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#download').click(function() {
|
||||||
if ($(this).hasClass('disabled')) {
|
if ($(this).hasClass('disabled')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +228,7 @@ function getDownloadLink() {
|
||||||
// get plugins and their versions
|
// get plugins and their versions
|
||||||
$('#optional-packages .selected').each(function() {
|
$('#optional-packages .selected').each(function() {
|
||||||
// get package path
|
// get package path
|
||||||
var p = $('.optpkg-name', this).text().trim();
|
var p = $('.package-link', this).text().trim();
|
||||||
|
|
||||||
// get package version, if user specified one
|
// get package version, if user specified one
|
||||||
var ver = $('input[name=version]', this).val().trim();
|
var ver = $('input[name=version]', this).val().trim();
|
||||||
|
@ -216,7 +264,7 @@ function handleBuildError(jqxhr, status, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePage() {
|
function updatePage() {
|
||||||
$('#package-count').text($('.optpkg.selected').length);
|
$('#package-count').text($('.package.selected').length);
|
||||||
$('#download').attr('href', getDownloadLink());
|
$('#download').attr('href', getDownloadLink());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,4 +292,17 @@ function enableFields() {
|
||||||
window.onbeforeunload = null;
|
window.onbeforeunload = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function splitVCSProvider(pkgPath) {
|
||||||
|
var providers = ["github.com/", "bitbucket.org/"];
|
||||||
|
for (var i = 0; i < providers.length; i++) {
|
||||||
|
if (pkgPath.toLowerCase().indexOf(providers[i]) == 0) {
|
||||||
|
return {
|
||||||
|
provider: providers[i],
|
||||||
|
path: pkgPath.slice(providers[i].length)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {provider: "", path: pkgPath};
|
||||||
|
}
|
||||||
|
|
||||||
var downloadButtonHtml; // to restore button to its original contents
|
var downloadButtonHtml; // to restore button to its original contents
|
||||||
|
|
|
@ -9,7 +9,7 @@ if (moduleID) {
|
||||||
$(function() {
|
$(function() {
|
||||||
$('#module-docs-container').show();
|
$('#module-docs-container').show();
|
||||||
$('h1').text("Module "+moduleID);
|
$('h1').text("Module "+moduleID);
|
||||||
beginRendering(json.result);
|
beginRendering(json.result, moduleID);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,10 +23,17 @@ if (moduleID) {
|
||||||
$table = $('#module-list');
|
$table = $('#module-list');
|
||||||
for (modID in moduleList) {
|
for (modID in moduleList) {
|
||||||
var val = moduleList[modID];
|
var val = 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 standard = isStandard(val.type_name);
|
||||||
var $tr = $('<tr/>');
|
var $tr = $('<tr/>');
|
||||||
$tr.append('<td><a href="./'+modID+'" class="module-link">'+modID+'</a>'+(standard ? '' : ' '+nonStandardFlag)+'</td>');
|
$tr.append('<td><a href="./'+modID+'" class="module-link">'+modID+'</a>'+(standard ? '' : ' '+nonStandardFlag)+'</td>');
|
||||||
$tr.append('<td>'+markdown(truncate(val.doc, 200))+'</td>');
|
$tr.append($('<td/>').text(shortDoc));
|
||||||
$table.append($tr);
|
$table.append($tr);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue