This is the template project that's checked out and configured when you run the bando-up command from ljsthw-bandolier. This is where the code really lives.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bandolier-template/admin/pages/DocsBrowser.svelte

312 lines
7.6 KiB

<script>
import { link } from 'svelte-spa-router';
import { onMount } from 'svelte';
import Layout from '$/client/Layout.svelte';
import Icon from '$/client/components/Icon.svelte';
import Code from "$/client/components/Code.svelte";
import api from "$/client/api.js";
let index = {};
let docs_data;
let url;
let readme_docs;
export let params;
const caps_to_icon = {
"_BUG_": "bug",
"_TODO_": "clipboard-check",
"_WARNING_": "alert-triangle",
"_FOOTGUN_": "bomb",
"_DEPRECATED_": "axe"
}
const jump = (id) => {
let node = document.getElementById(id);
if(node) node.scrollIntoView();
}
const jump_top = () => {
jump("top-scroll");
}
const load_docs = async (to_load) => {
// only load if the URL changed
if(to_load !== url) {
const [status, data] = await api.get(`/docs/api/${to_load}.json`);
docs_data = status === 200 ? data : {};
url = to_load;
jump_top();
}
}
const load_index = async () => {
const [status, data] = await api.get("/docs/api/index.json");
index = status === 200 ? data : {};
}
const load_readme = async () => {
if(!readme_docs) {
console.log("LOAD README");
const [status, data] = await api.blob("/docs/api/index.html");
if(status === 200) {
readme_docs = await data.text();
} else {
readme_docs = `<callout class="error">ERROR LOADING README: ${status}</callout>`
}
}
url = "/docs/";
console.log("URL", url, "README", readme_docs !== undefined, "PARAMS", params);
}
const type_to_syntax = {
"callexpression": "()",
"objectexpression": "{}",
"function": "()",
"class": "{}",
"method": "()"
}
onMount(async () => {
await load_readme();
await load_index();
});
$: if(params.wild) {
load_docs(params.wild)
url = url; // the most irritating thing about Svelte
} else {
load_readme();
url = url;
}
</script>
<style>
sidebar {
max-width: 300px;
min-height: 100vh;
height: 100vh;
max-height: 100vh;
margin: unset;
}
sidebar items {
overflow-y: auto;
}
right {
display: flex;
flex-direction: column;
min-height: 100vh;
height: 100vh;
max-height: 100vh;
overflow-y: auto;
width: calc(100vw - 300px);
min-width: calc(100vw - 300px);
max-width: calc(100vw - 300px);
}
right > div {
padding: 0.5rem;
}
export {
border-top: 1px solid var(--value5);
padding: 0.5rem;
}
export.member {
padding-left: 1.5rem;
}
export.class-def {
background-color: var(--value7);
}
export > heading {
display: flex;
flex-direction: column;
width: 100%;
margin-bottom: 1rem;
}
export > heading h4,
export > heading h2,
export > heading h1
{
margin-top: 0.5rem;
font-family: var(--font-family);
font-weight: 600;
}
export > heading meta-data {
display: grid;
gap: 0.5rem;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto;
}
export > info {
display: block;
padding-top: 0.5rem;
}
export > info commment {
display: block;
}
/* FOOTGUN: https://github.com/sveltejs/svelte/issues/2967
When you @html in Svelte it can't apply any styles from here.
You have to scope the a tag style inside module-header, BUT,
set it to global so Svelte will apply it to the whole doc,
not its special class.
*/
module-header :global(a) {
color: var(--color-text-inverted);
}
module-header {
display: block;
padding: 0.5rem;
background-color: var(--color-bg-inverted);
color: var(--color-text-inverted);
}
module-header :global(h2),
module-header :global(h3),
module-header :global(h4) {
margin-top: 3rem;
}
toc {
display: grid;
grid-template-columns: repeat(5, 1fr);
background-color: var(--value3);
color: var(--value9);
}
toc span {
border: 1px solid black;
padding: 0.5rem;
text-align: center;
}
.no-doc {
background-color: var(--color-error);
}
</style>
<Layout footer={ false} header={ false } centered={ true } fullscreen={ true }>
<sidebar>
<top><h4><a href="/" use:link><Icon name="chevrons-up" />API Docs</a></h4></top>
<items>
<a class:active={ url === "/docs/" } href="/docs/" use:link>README</a>
{#each Object.keys(index) as item}
<a class:active={ item === url } href="/docs/{item}" use:link>{item}</a>
{/each}
</items>
</sidebar>
<right>
{#if url === "/docs/"}
<div id="top-scroll">
{#if readme_docs}
{@html readme_docs}
{/if}
</div>
{:else if docs_data}
<toc id="top-scroll">
{#each docs_data.exports as exp}
<span class:no-doc={ !exp.comment } on:click={ () => jump(exp.slug) }>{ exp.name }
{#each exp.caps as cap_word}<Icon name={ caps_to_icon[cap_word] } size="24" light={ true }/>{/each}
</span>
{#if exp.isa == "class"}
{#each exp.methods as member}
<span class:no-doc={ !member.comment } on:click={ () => jump(member.slug) }>.{ member.name }
{#each member.caps as cap_word}<Icon name={ caps_to_icon[cap_word] } size="24" light={ true } />{/each}
</span>
{/each}
{/if}
{/each}
</toc>
<module-header>
<h1>{ url }</h1>
{#if docs_data.comment}
{@html docs_data.comment}
{/if}
</module-header>
{#each docs_data.exports as exp}
{#if exp.isa === "class"}
<export class="class-def">
<heading>
<h2 on:click={ () => jump_top() } id={ exp.slug }>class { exp.name }</h2>
<Code content={ exp.code } language="javascript" />
</heading>
<comment>
{#if exp.comment}
{@html exp.comment}
{/if}
</comment>
</export>
{#each exp.methods as member}
<export class="member">
<heading>
<h4 id={ member.slug } on:click={ () => jump(exp.slug) }>.{member.name}{ type_to_syntax[member.isa] || "" }
</h4>
<meta-data>
{docs_data.source}:{ member.line_start }
<em>{ member.isa } of { exp.name }</em>
{#if member.static}<b>static</b>{/if}
{#if member.async}<b>async</b>{/if}
{#if member.generator}<b>generator</b>{/if}
</meta-data>
</heading>
<info>
{#if member.comment}
<comment>
{ @html member.comment }
</comment>
{/if}
<Code content={ member.code } language="javascript" />
</info>
</export>
{/each}
{:else}
<export>
<heading>
<h4 on:click={ () => jump_top() }
id={ exp.slug }>{exp.name}{ type_to_syntax[exp.isa] || "" }
</h4>
<meta-data>
{docs_data.source}:{ exp.line_start }
<em>{ exp.isa }</em>
{#if exp.static}<b>static</b>{/if}
{#if exp.async}<b>async</b>{/if}
{#if exp.generator}<b>generator</b>{/if}
</meta-data>
</heading>
<info>
{#if exp.comment}
<comment>
{@html exp.comment}
</comment>
{/if}
<Code content={ exp.code } language="javascript" />
</info>
</export>
{/if}
{/each}
{/if}
</right>
</Layout>