From 8b7505dc2f11fb0bb12de5d911273034ecef5ca5 Mon Sep 17 00:00:00 2001 From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com> Date: Wed, 27 Mar 2024 00:13:43 -0700 Subject: [PATCH] Render markdown as documentation pages (#6) * add overview docs content * toc wip * move nav to components dir * wip * wip * wip * wip * wip * wip * wip * wip * file `server/docs/docs.ts` is coming together * abstract global styles to static file `global.css` * add `toPath` * add `components\doc\expression.ts` * Update deno.jsonc * wip * drawer wip ```js // Note: I do not want to have to build an entire drawer component // just to show the playground on documentation pages. For now, // it is much easier to just place the playground at the bottom of // the documentation page. I will revisit this later when I have // more time to work on it. ``` * add playground to doc component * import shared code in 2 route files * Delete drawer.tsx * navigation looks good! Consistent code highlighting is an ongoing challenge. Found . * add alias `p` for route `playgrounds` Reference: . * add footer (w/ css grid) * replace gfm with markdown-it * Update fs.ts * fix toc component * fix hljs * use markdown-it toc in cousin element * add 'copy code to clipboard' button to code blocks Source: * Create 00_index.md * wip - add overridable names. - update `docs/02_playgrounds/00_index.md` documentation file. - add `` to `routes/playgrounds/[id].tsx` route file. - create `components/playground_aside.tsx` component file. * wip - create dedicated md.css for documentation pages. - update documentation. - support default and example playgrounds. * update documentation --- client/components/playground/scripts.tsx | 23 --- client/nav.tsx | 28 --- client/playgrounds.ts | 13 -- components/doc/doc.tsx | 37 ++++ components/doc/doc_content.tsx | 63 ++++++ components/foot.tsx | 19 ++ components/hljs.tsx | 13 ++ components/nav.tsx | 43 ++++ .../playground/playground.tsx | 6 +- components/playground/scripts.tsx | 22 +++ components/playground_aside.tsx | 25 +++ components/toc.tsx | 29 +++ deno.jsonc | 9 + docs/00_index.md | 8 + docs/01_getting_started/00_index.md | 81 ++++++++ docs/02_playgrounds/00_index.md | 12 ++ docs/02_playgrounds/01_new.md | 4 + docs/02_playgrounds/02_handbook.md | 60 ++++++ docs/03_jsx/00_index.md | 29 +++ docs/03_jsx/01_theory.md | 15 ++ docs/04_examples/00_index.md | 13 ++ docs/04_examples/01_hello.md | 10 + docs/98_api_docs.md | 4 + docs/99_github.md | 4 + {server/examples => examples}/01_animals.tsx | 0 fresh.gen.ts | 14 +- lib/docs/fs.ts | 185 ++++++++++++++++++ lib/docs/items.ts | 8 + lib/docs/md.ts | 50 +++++ lib/docs/mod_client.ts | 2 + lib/docs/mod_server.ts | 2 + lib/docs/nodes.ts | 19 ++ lib/examples/examples.ts | 24 +++ {server => lib}/examples/mod.ts | 0 {client => lib/meta}/meta.ts | 8 +- lib/meta/mod.ts | 1 + .../playgrounds/deno_kv/kv.ts | 11 +- lib/playgrounds/deno_kv/mod.ts | 1 + lib/playgrounds/expressions/expressions.ts | 102 ++++++++++ lib/playgrounds/expressions/mod.ts | 1 + lib/playgrounds/mod.ts | 1 + lib/playgrounds/playgrounds.ts | 34 ++++ lib/resources/docs.ts | 6 + lib/resources/examples.ts | 3 + {server => lib/resources}/kv.ts | 0 lib/to_path.ts | 6 + routes/[...path].ts | 1 + routes/_404.tsx | 7 - routes/_app.tsx | 12 +- routes/api/examples/{[id].ts => [name].ts} | 4 +- routes/{ => api}/meta.ts | 2 +- routes/api/playgrounds/[id].ts | 4 +- routes/api/playgrounds/index.ts | 6 +- routes/index.ts | 1 + routes/index.tsx | 42 ---- routes/playgrounds/[id].tsx | 59 ++++-- server/examples/examples.ts | 18 -- static/copy.js | 35 ++++ static/global.css | 69 +++++++ static/md.css | 115 +++++++++++ static/playground.css | 61 ------ static/script.js | 21 +- 62 files changed, 1268 insertions(+), 237 deletions(-) delete mode 100644 client/components/playground/scripts.tsx delete mode 100644 client/nav.tsx delete mode 100644 client/playgrounds.ts create mode 100644 components/doc/doc.tsx create mode 100644 components/doc/doc_content.tsx create mode 100644 components/foot.tsx create mode 100644 components/hljs.tsx create mode 100644 components/nav.tsx rename {client/components => components}/playground/playground.tsx (93%) create mode 100644 components/playground/scripts.tsx create mode 100644 components/playground_aside.tsx create mode 100644 components/toc.tsx create mode 100644 docs/00_index.md create mode 100644 docs/01_getting_started/00_index.md create mode 100644 docs/02_playgrounds/00_index.md create mode 100644 docs/02_playgrounds/01_new.md create mode 100644 docs/02_playgrounds/02_handbook.md create mode 100644 docs/03_jsx/00_index.md create mode 100644 docs/03_jsx/01_theory.md create mode 100644 docs/04_examples/00_index.md create mode 100644 docs/04_examples/01_hello.md create mode 100644 docs/98_api_docs.md create mode 100644 docs/99_github.md rename {server/examples => examples}/01_animals.tsx (100%) create mode 100644 lib/docs/fs.ts create mode 100644 lib/docs/items.ts create mode 100644 lib/docs/md.ts create mode 100644 lib/docs/mod_client.ts create mode 100644 lib/docs/mod_server.ts create mode 100644 lib/docs/nodes.ts create mode 100644 lib/examples/examples.ts rename {server => lib}/examples/mod.ts (100%) rename {client => lib/meta}/meta.ts (73%) create mode 100644 lib/meta/mod.ts rename server/playgrounds.ts => lib/playgrounds/deno_kv/kv.ts (79%) create mode 100644 lib/playgrounds/deno_kv/mod.ts create mode 100644 lib/playgrounds/expressions/expressions.ts create mode 100644 lib/playgrounds/expressions/mod.ts create mode 100644 lib/playgrounds/mod.ts create mode 100644 lib/playgrounds/playgrounds.ts create mode 100644 lib/resources/docs.ts create mode 100644 lib/resources/examples.ts rename {server => lib/resources}/kv.ts (100%) create mode 100644 lib/to_path.ts create mode 100644 routes/[...path].ts rename routes/api/examples/{[id].ts => [name].ts} (55%) rename routes/{ => api}/meta.ts (80%) create mode 100644 routes/index.ts delete mode 100644 routes/index.tsx delete mode 100644 server/examples/examples.ts create mode 100644 static/copy.js create mode 100644 static/global.css create mode 100644 static/md.css diff --git a/client/components/playground/scripts.tsx b/client/components/playground/scripts.tsx deleted file mode 100644 index d07b1ac..0000000 --- a/client/components/playground/scripts.tsx +++ /dev/null @@ -1,23 +0,0 @@ -export interface PlaygroundScriptsProps { - code: string; - autoplay?: boolean; -} - -export default function PlaygroundScripts(props: PlaygroundScriptsProps) { - return ( -
`, - }} - > -
- ); -} - -function initializeData(props: PlaygroundScriptsProps) { - return ``; -} diff --git a/client/nav.tsx b/client/nav.tsx deleted file mode 100644 index 7afc393..0000000 --- a/client/nav.tsx +++ /dev/null @@ -1,28 +0,0 @@ -export default function Nav() { - return ( - - ); -} diff --git a/client/playgrounds.ts b/client/playgrounds.ts deleted file mode 100644 index 2db0a0a..0000000 --- a/client/playgrounds.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Playground is a jsonx playground. - */ -export interface Playground { - id: string; - version: string; - code: string; -} - -/** - * AddPlaygroundRequest is the request to add a playground. - */ -export type AddPlaygroundRequest = Omit; diff --git a/components/doc/doc.tsx b/components/doc/doc.tsx new file mode 100644 index 0000000..5910c67 --- /dev/null +++ b/components/doc/doc.tsx @@ -0,0 +1,37 @@ +import { contents } from "#/lib/resources/docs.ts"; +import { fromExpression } from "#/lib/playgrounds/expressions/mod.ts"; +import { getMeta } from "#/lib/meta/mod.ts"; +import { toPath } from "#/lib/to_path.ts"; +import type { DocContentProps } from "./doc_content.tsx"; +import DocContent from "./doc_content.tsx"; + +export default async function DocumentationPage(request: Request) { + const content = contentOf(request); + const playground = await playgroundOf(content.playground); + return ( + + ); +} + +function contentOf(request: Request) { + const url = new URL(request.url); + const path = toPath(url.pathname).join("/"); + const content = contents.get(path); + if (!content) { + throw new Error(`Content not found: ${path}`); + } + + return content; +} + +async function playgroundOf(expression?: string) { + let playground: DocContentProps["playground"]; + if (expression) { + playground = { + data: await fromExpression(expression), + meta: await getMeta(), + }; + } + + return playground; +} diff --git a/components/doc/doc_content.tsx b/components/doc/doc_content.tsx new file mode 100644 index 0000000..e1ef9be --- /dev/null +++ b/components/doc/doc_content.tsx @@ -0,0 +1,63 @@ +import type { PlaygroundData } from "#/lib/playgrounds/mod.ts"; +import { Meta } from "#/lib/meta/mod.ts"; +import Playground from "#/components/playground/playground.tsx"; +import { Head } from "$fresh/runtime.ts"; +import Hljs from "#/components/hljs.tsx"; + +/** + * DocContentProps are the properties for the DocContent component. + */ +export interface DocContentProps { + /** + * body is the html content of the documentation page. + */ + body: string; + + /** + * toc is the table of contents of the documentation page. + */ + toc?: string; + + /** + * playground is the playground data for the documentation page. + */ + playground?: { + data: PlaygroundData; + meta: Meta; + }; +} + +/** + * DocContent is the content of a jsonx documentation page. + */ +export default function DocContent(props: DocContentProps) { + return ( + <> + + + + + + + + +
+
+
+ {props.playground && ( + + )} +
+ + ); +} diff --git a/components/foot.tsx b/components/foot.tsx new file mode 100644 index 0000000..bc52d66 --- /dev/null +++ b/components/foot.tsx @@ -0,0 +1,19 @@ +/** + * Foot is the site footer. + */ +export default function Foot( + props: { year?: number } = { year: new Date().getFullYear() }, +) { + return ( + + ); +} diff --git a/components/hljs.tsx b/components/hljs.tsx new file mode 100644 index 0000000..c4411b3 --- /dev/null +++ b/components/hljs.tsx @@ -0,0 +1,13 @@ +/** + * Hljs is a component that loads the highlight.js styles. + */ +export default function Hljs(props: { id: string }) { + return ( + <> + + + ); +} diff --git a/components/nav.tsx b/components/nav.tsx new file mode 100644 index 0000000..85b2aab --- /dev/null +++ b/components/nav.tsx @@ -0,0 +1,43 @@ +import ToC from "#/components/toc.tsx"; +import { nodes } from "#/lib/resources/docs.ts"; + +/** + * NavProps are the properties for the Nav component. + */ +export interface NavProps { + path: string[]; +} + +/** + * Nav is the navigation bar for the documentation. + */ +export default function Nav(props: NavProps) { + return ( + + ); +} + +function startsWith(path: string[], prefix: string[]): boolean { + if (path.length < prefix.length) { + return false; + } + + for (let i = 0; i < prefix.length; i++) { + if (path[i] !== prefix[i]) { + return false; + } + } + + return true; +} diff --git a/client/components/playground/playground.tsx b/components/playground/playground.tsx similarity index 93% rename from client/components/playground/playground.tsx rename to components/playground/playground.tsx index 4f595a3..6a84991 100644 --- a/client/components/playground/playground.tsx +++ b/components/playground/playground.tsx @@ -1,4 +1,5 @@ -import type { Meta } from "#/client/meta.ts"; +import { Head } from "$fresh/runtime.ts"; +import type { Meta } from "#/lib/meta/mod.ts"; import PlaygroundScripts from "./scripts.tsx"; export interface PlaygroundProps { @@ -11,6 +12,9 @@ export interface PlaygroundProps { export default function Playground(props: PlaygroundProps) { return ( <> + + +
diff --git a/components/playground/scripts.tsx b/components/playground/scripts.tsx new file mode 100644 index 0000000..861c433 --- /dev/null +++ b/components/playground/scripts.tsx @@ -0,0 +1,22 @@ +export interface PlaygroundScriptsProps { + code: string; + autoplay?: boolean; +} + +export default function PlaygroundScripts(props: PlaygroundScriptsProps) { + return ( + <> + +