Skip to content

Commit

Permalink
Add mappable documentation pathnames (#11)
Browse files Browse the repository at this point in the history
* implement mappable names

- export `walkChildren` from `"#/lib/docs/nodes.ts"` after sorting deterministically.
- drop support for `/playgrounds` playgrounds, switch to exclusively `/p` playgrounds.

* update playgrounds documentation
  • Loading branch information
EthanThatOneKid authored Mar 28, 2024
1 parent fcc59b7 commit 5e7f4e9
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 23 deletions.
8 changes: 4 additions & 4 deletions docs/02_playgrounds/00_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ title: Playgrounds
# Playgrounds

You may encounter text editors across this site with a "Play" button. These are
playgrounds. Playgrounds enable visitors to quickly edit and run jsonx code in
the browser.
playgrounds. Playgrounds are an interactive and fun tool enabling visitors to
quickly edit and run jsonx code in the browser.

- [Create a new playground↩](/playgrounds)
- [Playgrounds manual↩](/02_playgrounds/02_manual)
- [Create a new playground↩](/p)
- [Playgrounds manual↩](/playgrounds/manual)
2 changes: 1 addition & 1 deletion docs/03_jsx/00_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ title: JSX
>
> JSX definition coming soon.
[Learn why jsonx uses JS](/03_jsx/01_theory.md).
[Learn why jsonx uses JS](/jsx/theory.md).

## Why does jsonx use JSX?

Expand Down
4 changes: 2 additions & 2 deletions docs/04_examples/00_index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Examples
---
---

# Examples

Expand All @@ -10,4 +10,4 @@ title: Examples
Learn how to use jsonx in practical situations.

- [Hello world↩](/04_examples/01_hello)
- [Hello world↩](/examples/hello)
4 changes: 2 additions & 2 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as $api_meta from "./routes/api/meta.ts";
import * as $api_playgrounds_id_ from "./routes/api/playgrounds/[id].ts";
import * as $api_playgrounds_index from "./routes/api/playgrounds/index.ts";
import * as $index from "./routes/index.ts";
import * as $playgrounds_id_ from "./routes/playgrounds/[id].tsx";
import * as $p_id_ from "./routes/p/[[id]].tsx";

import { type Manifest } from "$fresh/server.ts";

Expand All @@ -24,7 +24,7 @@ const manifest = {
"./routes/api/playgrounds/[id].ts": $api_playgrounds_id_,
"./routes/api/playgrounds/index.ts": $api_playgrounds_index,
"./routes/index.ts": $index,
"./routes/playgrounds/[id].tsx": $playgrounds_id_,
"./routes/p/[[id]].tsx": $p_id_,
},
islands: {},
baseUrl: import.meta.url,
Expand Down
39 changes: 34 additions & 5 deletions lib/docs/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import type { FSItem } from "./items.ts";
import type { Node } from "./nodes.ts";
import { sortChildren } from "./nodes.ts";
import { renderMd } from "./md.ts";
import { walkChildren } from "#/lib/docs/nodes.ts";

/**
* RenderFSItemsOptions represents the options for rendering file-based items.
*/
export interface ReadFSItemsOptions {
root: string | URL;
isIndex?: (suffix: string, override?: string) => boolean;
mapName?: (name: string[]) => string[];
}

/**
Expand Down Expand Up @@ -94,8 +96,9 @@ export async function readFSItems(
}

// Read the file-based items.
const items: FSItem[] = [];
const contents = new Map<string, Content>();
let id = 0;
const contentsByID = new Map<number, Content>();
const items: (FSItem & { id: number })[] = [];
const walkIt = walk(
options.root,
{ exts: [".md"], includeDirs: false },
Expand Down Expand Up @@ -124,14 +127,40 @@ export async function readFSItems(

// Store the item contents.
const { body, toc } = renderMd(md);
contents.set(
name.join(NAME_SEPARATOR),
contentsByID.set(
id,
{ md, body, title, toc, playground },
);

// Store the item in the items array.
const item = { name, title, href };
const item = { id, name, title, href };
items.push(item);
id++;
}

// Construct recursive nodes from items.
const nodes = toNodes(items);

// Map the item names and nodes in place.
if (options.mapName) {
for (const item of items) {
item.name = options.mapName(item.name);
}

walkChildren(nodes, (node) => {
node.name = options.mapName!(node.name);
});
}

// Copy contents to the contents map with the mapped name.
const contents = new Map<string, Content>();
for (const [id, content] of contentsByID) {
const item = items.find((item) => item.id === id);
if (!item) {
throw new Error(`Item not found for content ID: ${id}`);
}

contents.set(item.name.join(NAME_SEPARATOR), content);
}

// Return items relative to the root.
Expand Down
22 changes: 19 additions & 3 deletions lib/docs/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,24 @@ export function sortChildren<T>(
node: Node<T>,
fn: (a: Node<T>, b: Node<T>) => number,
): void {
if (node.children !== undefined) {
node.children.sort(fn);
node.children.forEach((child) => sortChildren(child, fn));
return walkChildren(node.children ?? [], (node) => {
if (node.children !== undefined) {
node.children.sort(fn);
}
});
}

/**
* walkChildren walks the children of a node recursively.
*/
export function walkChildren<T>(
children: Node<T>[],
fn: (node: Node<T>) => void,
): void {
for (const child of children) {
fn(child);
if (child.children !== undefined) {
walkChildren(child.children, fn);
}
}
}
2 changes: 2 additions & 0 deletions lib/resources/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ import { readFSItems } from "#/lib/docs/mod_server.ts";
export const { items, contents, nodes } = await readFSItems({
root: "./docs",
isIndex: (suffix) => suffix.startsWith("00_"),
mapName: (name) =>
name.map((part) => part.replace(/^\d{2}_/, "").replace(/_/g, "-")),
});
7 changes: 1 addition & 6 deletions routes/playgrounds/[id].tsx → routes/p/[[id]].tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import type { FreshContext, RouteConfig } from "$fresh/server.ts";
import type { FreshContext } from "$fresh/server.ts";
import { Head } from "$fresh/runtime.ts";
import { getMeta } from "#/lib/meta/meta.ts";
import { getPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
import { kv } from "#/lib/resources/kv.ts";
import { defaultExample } from "#/lib/resources/examples.ts";
import PlaygroundAside from "#/components/playground_aside.tsx";
import Playground from "#/components/playground/playground.tsx";
import { parse } from "$std/path/parse.ts";
import { parsePlaygroundExampleExpression } from "#/lib/playgrounds/expressions/mod.ts";
import { readExample } from "#/lib/examples/mod.ts";

export const config: RouteConfig = {
routeOverride: "/(p|playgrounds){/:id}?",
};

export default async function PlaygroundHandler(
_request: Request,
ctx: FreshContext,
Expand Down

0 comments on commit 5e7f4e9

Please sign in to comment.