Add the ability to specify a README and make that the initial first page for the docs browser.

main
Zed A. Shaw 2 years ago
parent 14b7337949
commit 323ae3dc2a
  1. 27
      README.md
  2. 55
      admin/pages/DocsBrowser.svelte
  3. 25
      client/api.js
  4. 7
      commands/codedoc.js
  5. 2
      lib/builderator.js

@ -1,8 +1,6 @@
16. Then continue studying anything you find interesting and trying to change the existing pages.
This should give you a quick crash course in how the framework operates while I work on better documentation and instructions.# bandolier-template
# Introduction
The Bandolier (aka `bando`) is an educational web framework featured in the Learn JavaScript the Hard Way course. The Bandolier contains all of the features a full stack developer would need to learn, but with smaller easier to understand implementations that are fully visible in the project. It includes implementations of:
The Bandolier (aka `bando`) is an educational web framework featured in the [Learn JavaScript the Hard Way](https://learnjsthehardway.com) course. The Bandolier contains all of the features a full stack developer would need to learn, but with smaller easier to understand implementations that are fully visible in the project. It includes implementations of:
* JSON APIs backends.
* Multi-page and Single-page web UIs.
@ -17,7 +15,8 @@ The Bandolier (aka `bando`) is an educational web framework featured in the Lear
* Helpful video processing in JavaScript.
* Template generators to get started with code.
* Full but simple database administrator in the browser.
* Basic Discord integration.
* Basic [Discord](https://discord.com) integration.
* Custom documentation generation for APIs using [acorn](https://github.com/acornjs/acorn).
* Includes common things you need like [lucide](lucide.dev) icons, Email DNS testing, web log analysis, in an easy to extend administrator tool.
* All implemented in reasonably sized pieces of code you can study on your own.
@ -31,7 +30,7 @@ This is the template project that's checked out and configured when you run the
First, install the [ljsthw-bandolier](https://git.learnjsthehardway.com/learn-javascript-the-hard-way/ljsthw-bandolier#ljsthw-bandolier):
```
```shell
npm install git+https://git.learnjsthehardway.com/learn-javascript-the-hard-way/ljsthw-bandolier.git
```
@ -39,7 +38,7 @@ That will create a command you'll use to manage installs and updates of the [Ban
You should now be able to do this:
```
```shell
npx bando-up --version
npx bando-up --help
```
@ -48,7 +47,7 @@ If you can't then refer to the documentation for `ljsthw-bandolier`, _especially
If you can run the `npx bando-up` command then use it to create your first project:
```
```shell
npx bando-up create my-project
```
@ -58,7 +57,7 @@ This will checkout the [Bandolier Template](https://git.learnjsthehardway.com/le
If you checked out your first project into `my-project` then do this:
```
```shell
cd my-project
npm install
```
@ -67,13 +66,13 @@ That will move you into the project directory and install all of the required so
Once `npm install` finishes you can configure the application:
```
```shell
npm run knex migrate:latest
```
This will setup your database, and then you can finally do the initialize command to finish the setup:
```
```shell
node bando.js init
```
@ -81,7 +80,7 @@ This will configure some items, rerun the migrations just in case, and copy any
Open another Terminal window and start the app in `DANGER_ADMIN` mode:
```
```shell
npm run DANGER_ADMIN
```
@ -97,7 +96,7 @@ The final test is switch back to the browser and refresh the page to see that yo
In theory you shouldn't need playwright to download browsers, so just tell it not to.
```
```shell
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install
```
@ -107,7 +106,7 @@ This isn't as needed on Linux as OSX, because the Playwright project forces peop
If this doesn't work then this might https://github.com/nodejs/node-gyp/blob/main/docs/Updating-npm-bundled-node-gyp.md which says that npm updates don't update the node-gyp it uses internally. Depending on your version you will have to run different commands, but this works for 7,8, and 9 versions:
```
```shell
npm explore npm/node_modules/@npmcli/run-script -g -- npm_config_global=false npm install node-gyp@latest
```

@ -9,14 +9,15 @@
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"
"_BUG_": "bug",
"_TODO_": "clipboard-check",
"_WARNING_": "alert-triangle",
"_FOOTGUN_": "bomb",
"_DEPRECATED_": "axe"
}
const jump = (id) => {
@ -29,12 +30,15 @@
}
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");
@ -42,6 +46,22 @@
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": "{}",
@ -51,11 +71,16 @@
}
onMount(async () => {
await load_readme();
await load_index();
});
$: if(params.wild && params.wild !== url) {
load_docs(params.wild);
$: if(params.wild) {
load_docs(params.wild)
url = url; // the most irritating thing about Svelte
} else {
load_readme();
url = url;
}
</script>
@ -85,6 +110,10 @@
max-width: calc(100vw - 300px);
}
right > div {
padding: 0.5rem;
}
export {
border-top: 1px solid var(--value5);
padding: 0.5rem;
@ -175,8 +204,9 @@
<Layout footer={ false} header={ false } centered={ true } fullscreen={ true }>
<sidebar>
<top><h4><a href="/" use:link><Icon name="chevrons-up" /> Docs</a></h4></top>
<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}
@ -184,7 +214,13 @@
</sidebar>
<right>
{#if docs_data}
{#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 }
@ -206,7 +242,6 @@
{#if docs_data.comment}
{@html docs_data.comment}
{/if}
</module-header>
{#each docs_data.exports as exp}

@ -330,6 +330,29 @@ export const raw = async (url, method, body, unauthed_action) => {
}
}
/*
Used for fetching basic resources, not JSON data from the API. Uses the
same return signature as `raw()` but doesn't attempt a JSON conversion,
and only does a "GET" request. It returns the result of `res.blob()`
so you can convert it to a string or JSON as you need, or leave it if
it's a binary file.
+ `url string` -- URL to get.
+ ___return___ `Array[status, Blob|{}]` -- Returns a Blob or when status is 500 a `{"message": "Error message"}`.
*/
export const blob = async (url) => {
let data;
try {
let res = await fetch(url, fetch_opts);
data = await res.blob();
return [res.status, data];
} catch(error) {
log.error(error, "Failed to parse reply body as JSON. Text is:", data, "error", error, "URL", url);
return [500, {"message": "Exception processing request. See log.debug."}];
}
}
/*
The GET method request. To keep things consistent with the
other requests this accepts a `data` parameter, but it URL
@ -439,5 +462,5 @@ export const schema = async (table) => {
export default {
post, get, put, del, mock, options, fetch_opts,
logout_user, validate, can_submit, clean_form, schema
logout_user, validate, can_submit, clean_form, schema, blob
}

@ -15,7 +15,8 @@ export const description = "Describe your command here."
// your command uses the npm package commander's options format
export const options = [
["--quiet", "Don't output the stats at the end."]
["--quiet", "Don't output the stats at the end."],
["--readme", "README file to use as the initial page", "README.md"]
]
// example of a positional argument, it's the 1st argument to main
@ -329,6 +330,10 @@ export const main = async (source_globs, opts) => {
const index_name = path.join(opts.output, "index.json");
fs.writeFileSync(index_name, dump(index));
// render the README.md to the initial docs
const readme_name = path.join(opts.output, "index.html");
const md_out = RENDERER.render(fs.readFileSync(opts.readme).toString());
fs.writeFileSync(readme_name, md_out);
const percent = Math.floor(100 * STATS.docs / STATS.total);

@ -11,7 +11,7 @@ import Path from "path";
import { execSync } from "child_process";
/*
Fixes some common problems with `fast-glob` on windows. I removes
Fixes some common problems with `fast-glob` on windows. It removes
leading "C:\" from paths and replaces all of the `\\` with `/`.
__BUG__: This obviously won't work if you're on a different drive than C:.

Loading…
Cancel
Save