diff --git a/deno.jsonc b/deno.jsonc
index aeddca6..e198c75 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -35,6 +35,7 @@
"@std/http": "jsr:@std/http@^0.220.1",
"@std/path": "jsr:@std/path@^0.220.1",
"@std/semver": "jsr:@std/semver@^0.220.1",
+ "@std/ulid": "jsr:@std/ulid@^0.220.1",
"@std/yaml": "jsr:@std/yaml@^0.220.1",
"preact": "https://esm.sh/preact@10.19.2",
"preact/": "https://esm.sh/preact@10.19.2/"
diff --git a/routes/_app.tsx b/routes/_app.tsx
index 2748bee..eaedfbb 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,15 +1,22 @@
-import { type PageProps } from "$fresh/server.ts";
+import type { PageProps } from "$fresh/server.ts";
+import Nav from "#/components/nav.tsx";
-export default function App({ Component }: PageProps) {
+export default function App({ Component, route }: PageProps) {
+ const path = route.split("/").filter(Boolean);
return (
jsonx | Documentation
+
-
+
+
+
+
+
);
diff --git a/routes/index.tsx b/routes/index.tsx
index 3196172..8b36ac3 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -24,19 +24,10 @@ export default async function Home(request: Request) {
}
const meta = await getMeta();
- const path = url.pathname.split("/").filter((part) => part !== "");
return (
<>
-
- jsonx | Documentation
-
-
-
-
-
-
-
-
+ jsonx
+
>
);
}
diff --git a/routes/playgrounds/[id].tsx b/routes/playgrounds/[id].tsx
index 08ef679..0ebe162 100644
--- a/routes/playgrounds/[id].tsx
+++ b/routes/playgrounds/[id].tsx
@@ -20,18 +20,13 @@ export default async function PlaygroundHandler(
<>
jsonx | Playground
-
-
-
-
-
-
+
>
);
}
diff --git a/server/docs/fs.ts b/server/docs/fs.ts
index a0288fc..76dc232 100644
--- a/server/docs/fs.ts
+++ b/server/docs/fs.ts
@@ -2,7 +2,7 @@ import type { RenderOptions } from "@deno/gfm";
import { render } from "@deno/gfm";
import { extract } from "@std/front-matter/any";
import { test } from "@std/front-matter/test";
-import { walk } from "@std/fs/walk";
+import { walk } from "@std/fs";
import { fromFileUrl, normalize, parse, SEPARATOR_PATTERN } from "@std/path";
import type { FSItem } from "./items.ts";
import type { Node } from "./nodes.ts";
diff --git a/server/kv/playgrounds.ts b/server/kv/playgrounds.ts
index 58a5917..e6a3baa 100644
--- a/server/kv/playgrounds.ts
+++ b/server/kv/playgrounds.ts
@@ -1,5 +1,6 @@
///
+import { ulid } from "@std/ulid";
import type { AddPlaygroundRequest, Playground } from "#/client/playgrounds.ts";
/**
@@ -20,7 +21,7 @@ export async function addPlayground(
kv: Deno.Kv,
request: AddPlaygroundRequest,
): Promise {
- const id = crypto.randomUUID();
+ const id = ulid();
const playground = { ...request, id };
const result = await kv.set(playgroundKey(id), playground);
if (!result) {
@@ -43,6 +44,8 @@ export async function setPlayground(
}
}
+// TODO: Add list recent playgrounds.
+
function playgroundKey(id: string): Deno.KvKey {
return ["playgrounds", id];
}
diff --git a/static/global.css b/static/global.css
new file mode 100644
index 0000000..5abfbb7
--- /dev/null
+++ b/static/global.css
@@ -0,0 +1,22 @@
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
+}
+
+body {
+ background-color: #bbb;
+}
+
+nav {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1em 1em 0 1em;
+}
+
+main {
+ padding: 0 0.7em;
+}
diff --git a/static/playground.css b/static/playground.css
index cfc3ff1..649831e 100644
--- a/static/playground.css
+++ b/static/playground.css
@@ -1,70 +1,9 @@
-* {
- box-sizing: border-box;
- margin: 0;
- padding: 0;
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
- Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
-}
-
body {
- background-color: #bbb;
overflow-y: scroll;
overflow-x: hidden;
margin: 0 -5px 0 0;
}
-nav {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 1em 1em 0 1em;
-}
-
-.badges {
- display: flex;
- gap: 0.5em;
-}
-
-.badges a {
- display: flex;
- align-items: center;
- justify-content: center;
- outline: 2px solid #333;
- color: #333;
- border-radius: 0.5em;
- transition: outline 0.2s;
- padding: 0.5em;
- text-decoration: none;
- font-weight: bold;
-}
-
-.badges a:hover {
- outline: 5px solid #333;
-}
-
-@media (max-width: 400px) {
- .badges a {
- outline: none;
- }
-
- .badges a:hover {
- outline: none;
- }
-
- .badges a span {
- display: none;
- }
-}
-
-.badges img {
- height: 1.5em;
- align-self: center;
-}
-
-main {
- padding: 0 0.7em;
-}
-
details {
color: #bbb;
outline: 2px solid #333;
From cb27a2b725d9d46496a0d1730481d22719e585e6 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Fri, 22 Mar 2024 22:20:47 -0700
Subject: [PATCH 14/34] add `toPath`
---
components/nav.tsx | 7 +++++++
routes/_app.tsx | 5 ++---
routes/index.tsx | 4 +---
server/kv/playgrounds.ts | 2 ++
4 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/components/nav.tsx b/components/nav.tsx
index 931e222..1e78633 100644
--- a/components/nav.tsx
+++ b/components/nav.tsx
@@ -22,3 +22,10 @@ export default function Nav(props: NavProps) {
);
}
+
+/**
+ * toPath returns the path from the path string.
+ */
+export function toPath(path: string): string[] {
+ return path.split("/").filter(Boolean);
+}
diff --git a/routes/_app.tsx b/routes/_app.tsx
index eaedfbb..eb9293d 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,8 +1,7 @@
import type { PageProps } from "$fresh/server.ts";
-import Nav from "#/components/nav.tsx";
+import Nav, { toPath } from "#/components/nav.tsx";
export default function App({ Component, route }: PageProps) {
- const path = route.split("/").filter(Boolean);
return (
@@ -12,7 +11,7 @@ export default function App({ Component, route }: PageProps) {
-
+
diff --git a/routes/index.tsx b/routes/index.tsx
index 8b36ac3..6f95ce5 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -1,6 +1,4 @@
-import { Head } from "$fresh/runtime.ts";
import Playground from "#/components/playground/playground.tsx";
-import Nav from "#/components/nav.tsx";
import { getMeta } from "#/client/meta.ts";
import { kv } from "#/server/kv/kv.ts";
import { getExampleByName } from "#/server/examples/mod.ts";
@@ -26,7 +24,7 @@ export default async function Home(request: Request) {
const meta = await getMeta();
return (
<>
- jsonx
+ Meet jsonx.
>
);
diff --git a/server/kv/playgrounds.ts b/server/kv/playgrounds.ts
index e6a3baa..0671dc5 100644
--- a/server/kv/playgrounds.ts
+++ b/server/kv/playgrounds.ts
@@ -45,6 +45,8 @@ export async function setPlayground(
}
// TODO: Add list recent playgrounds.
+// TODO: Add playground title in playground storage via
+// https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt
function playgroundKey(id: string): Deno.KvKey {
return ["playgrounds", id];
From dd09995ebfc601caaba81eb9a1df6d276b3cfc47 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Sat, 23 Mar 2024 14:42:32 -0700
Subject: [PATCH 15/34] add `components\doc\expression.ts`
---
components/doc/doc.tsx | 46 ++++++++++
components/doc/expression.ts | 89 +++++++++++++++++++
components/nav.tsx | 2 +-
components/playground/playground.tsx | 2 +-
components/replace.tsx | 50 +++++++++++
components/toc.tsx | 3 +-
{server/docs => docs}/00_index.md | 2 +
.../01_getting_started/00_index.md | 0
.../01_getting_started/01_install.md | 0
.../01_getting_started/02_use.md | 0
.../01_getting_started/03_foo/00_index.md | 0
.../01_getting_started/03_foo/01_bar.md | 0
{server/docs => docs}/98_api_docs.md | 2 +-
{server/docs => docs}/99_view_on_github.md | 0
{server/examples => examples}/01_animals.tsx | 0
fresh.gen.ts | 8 +-
{server => lib}/docs/fs.ts | 6 +-
{server => lib}/docs/items.ts | 0
lib/docs/mod_client.ts | 2 +
lib/docs/mod_server.ts | 2 +
{server => lib}/docs/nodes.ts | 0
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 | 5 +-
lib/playgrounds/deno_kv/mod.ts | 1 +
lib/playgrounds/mod.ts | 1 +
{client => lib/playgrounds}/playgrounds.ts | 5 ++
lib/resources/docs.ts | 13 +++
lib/resources/examples.ts | 3 +
{server/kv => lib/resources}/kv.ts | 0
routes/api/examples/{[id].ts => [name].ts} | 4 +-
routes/{ => api}/meta.ts | 2 +-
routes/api/playgrounds/[id].ts | 7 +-
routes/api/playgrounds/index.ts | 6 +-
routes/index.tsx | 34 ++-----
routes/playgrounds/[id].tsx | 7 +-
server/docs/docs.ts | 6 --
server/examples/examples.ts | 18 ----
40 files changed, 276 insertions(+), 83 deletions(-)
create mode 100644 components/doc/doc.tsx
create mode 100644 components/doc/expression.ts
create mode 100644 components/replace.tsx
rename {server/docs => docs}/00_index.md (69%)
rename {server/docs => docs}/01_getting_started/00_index.md (100%)
rename {server/docs => docs}/01_getting_started/01_install.md (100%)
rename {server/docs => docs}/01_getting_started/02_use.md (100%)
rename {server/docs => docs}/01_getting_started/03_foo/00_index.md (100%)
rename {server/docs => docs}/01_getting_started/03_foo/01_bar.md (100%)
rename {server/docs => docs}/98_api_docs.md (98%)
rename {server/docs => docs}/99_view_on_github.md (100%)
rename {server/examples => examples}/01_animals.tsx (100%)
rename {server => lib}/docs/fs.ts (97%)
rename {server => lib}/docs/items.ts (100%)
create mode 100644 lib/docs/mod_client.ts
create mode 100644 lib/docs/mod_server.ts
rename {server => lib}/docs/nodes.ts (100%)
create mode 100644 lib/examples/examples.ts
rename {server => lib}/examples/mod.ts (100%)
rename {client => lib/meta}/meta.ts (78%)
create mode 100644 lib/meta/mod.ts
rename server/kv/playgrounds.ts => lib/playgrounds/deno_kv/kv.ts (93%)
create mode 100644 lib/playgrounds/deno_kv/mod.ts
create mode 100644 lib/playgrounds/mod.ts
rename {client => lib/playgrounds}/playgrounds.ts (63%)
create mode 100644 lib/resources/docs.ts
create mode 100644 lib/resources/examples.ts
rename {server/kv => lib/resources}/kv.ts (100%)
rename routes/api/examples/{[id].ts => [name].ts} (55%)
rename routes/{ => api}/meta.ts (80%)
delete mode 100644 server/docs/docs.ts
delete mode 100644 server/examples/examples.ts
diff --git a/components/doc/doc.tsx b/components/doc/doc.tsx
new file mode 100644
index 0000000..01b832b
--- /dev/null
+++ b/components/doc/doc.tsx
@@ -0,0 +1,46 @@
+import type { Meta } from "#/lib/meta/mod.ts";
+import Replace from "#/components/replace.tsx";
+import Playground from "#/components/playground/playground.tsx";
+import {
+ getDataByRegExpMatchArray,
+ PLAYGROUND_EXPRESSION_REGEX,
+} from "./expression.ts";
+
+/**
+ * DocProps are the properties for the Doc component.
+ */
+export interface DocProps {
+ /**
+ * html is the html content of the documentation page.
+ */
+ html: string;
+
+ /**
+ * meta is the meta data for the documentation page's playgrounds.
+ */
+ meta: Meta;
+}
+
+/**
+ * Doc is a jsonx documentation page component.
+ */
+export default function Doc(props: DocProps) {
+ // TODO: Replace with actual MDX parsing because the async isn't working
+ // with Preact hydration.
+ return (
+ {
+ const data = await getDataByRegExpMatchArray(match);
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/components/doc/expression.ts b/components/doc/expression.ts
new file mode 100644
index 0000000..f3c19ff
--- /dev/null
+++ b/components/doc/expression.ts
@@ -0,0 +1,89 @@
+/**
+ * @fileoverview
+ *
+ * This file contains the helper functions for parsing and evaluating playground
+ * expressions. Playground expressions are a simple syntax for embedding
+ * playgrounds directly into markdown files.
+ */
+
+import { getPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
+import { kv } from "#/lib/resources/kv.ts";
+import { readExample } from "#/lib/examples/mod.ts";
+
+/**
+ * PLAYGROUND_EXPRESSION_REGEX is the regular expression for parsing playground
+ * expressions.
+ */
+export const PLAYGROUND_EXPRESSION_REGEX =
+ //g;
+
+/**
+ * fromRegExpMatchArray converts a regular expression match array to a
+ * PlaygroundExpression.
+ */
+export function fromRegExpMatchArray(
+ match: RegExpMatchArray,
+): PlaygroundExpression {
+ return parsePlaygroundExpression(match[0]);
+}
+
+/**
+ * PlaygroundExpression is a playground expression.
+ */
+export type PlaygroundExpression =
+ | { id: string }
+ | { example: string };
+
+/**
+ * parsePlaygroundExpression parses a playground expression.
+ *
+ * Example playground expressions:
+ *
+ *
+ *
+ */
+export function parsePlaygroundExpression(
+ expression: string,
+): PlaygroundExpression {
+ const idMatch = expression.match(/id:([a-zA-Z0-9-_.]+)/);
+ if (idMatch) {
+ return { id: idMatch[1] };
+ }
+
+ const exampleMatch = expression.match(/example:([a-zA-Z0-9-_.]+)/);
+ if (exampleMatch) {
+ return { example: exampleMatch[1] };
+ }
+
+ throw new Error(`Invalid playground expression: ${expression}`);
+}
+
+/**
+ * getDataByRegExpMatchArray converts a regular expression match array to
+ * playground data.
+ */
+export async function getDataByRegExpMatchArray(
+ match: RegExpMatchArray,
+): Promise<{ code: string; version?: string }> {
+ const expr = fromRegExpMatchArray(match);
+ console.log({ expr });
+ if ("id" in expr) {
+ const playground = await getPlayground(kv, expr.id);
+ if (!playground) {
+ throw new Error(`Playground not found: ${expr.id}`);
+ }
+
+ return { code: playground.code, version: playground.version };
+ }
+
+ if ("example" in expr) {
+ const example = await readExample(`./examples/${expr.example}`);
+ if (!example) {
+ throw new Error(`Example not found: ${expr.example}`);
+ }
+
+ return { code: example };
+ }
+
+ throw new Error(`Invalid playground expression: ${expr}`);
+}
diff --git a/components/nav.tsx b/components/nav.tsx
index 1e78633..1a2a619 100644
--- a/components/nav.tsx
+++ b/components/nav.tsx
@@ -1,5 +1,5 @@
import ToC from "#/components/toc.tsx";
-import { nodes } from "#/server/docs/docs.ts";
+import { nodes } from "#/lib/resources/docs.ts";
/**
* NavProps are the properties for the Nav component.
diff --git a/components/playground/playground.tsx b/components/playground/playground.tsx
index c9f9594..6a84991 100644
--- a/components/playground/playground.tsx
+++ b/components/playground/playground.tsx
@@ -1,5 +1,5 @@
import { Head } from "$fresh/runtime.ts";
-import type { Meta } from "#/client/meta.ts";
+import type { Meta } from "#/lib/meta/mod.ts";
import PlaygroundScripts from "./scripts.tsx";
export interface PlaygroundProps {
diff --git a/components/replace.tsx b/components/replace.tsx
new file mode 100644
index 0000000..47fe398
--- /dev/null
+++ b/components/replace.tsx
@@ -0,0 +1,50 @@
+import type { JSX } from "preact/jsx-runtime";
+
+/**
+ * ReplaceProps
+ */
+export interface ReplaceProps {
+ /**
+ * html is the html content to be replaced.
+ */
+ html: string;
+
+ /**
+ * pattern is the pattern to inject the component by.
+ */
+ pattern: RegExp;
+
+ /**
+ * component is the component to be injected in place of the content.
+ */
+ component: (
+ props: { match: RegExpMatchArray },
+ ) => JSX.Element | Promise;
+}
+
+/**
+ * Replace is a component that replaces the content of the element with the content of the component.
+ */
+export default function Replace(props: ReplaceProps) {
+ const segments = props.html.split(props.pattern);
+ if (segments.length === 1) {
+ return {props.html} ;
+ }
+
+ const matches = [...props.html.matchAll(props.pattern)];
+ return (
+ <>
+ {segments.map(async (segment, index) => (
+ <>
+ {segment}
+ {index < matches.length &&
+ await props.component({ match: matches[index] })}
+ >
+ ))}
+ >
+ );
+}
+
+function Raw(props: { children: string }) {
+ return ;
+}
diff --git a/components/toc.tsx b/components/toc.tsx
index 4a78cf9..2f44c19 100644
--- a/components/toc.tsx
+++ b/components/toc.tsx
@@ -1,5 +1,4 @@
-import type { Node } from "#/server/docs/nodes.ts";
-import type { FSItem } from "#/server/docs/items.ts";
+import type { FSItem, Node } from "#/lib/docs/mod_client.ts";
/**
* ToCProps are the properties for the ToC component.
diff --git a/server/docs/00_index.md b/docs/00_index.md
similarity index 69%
rename from server/docs/00_index.md
rename to docs/00_index.md
index beb6f19..9cd719c 100644
--- a/server/docs/00_index.md
+++ b/docs/00_index.md
@@ -5,3 +5,5 @@ title: Overview
# Overview
The jsonx library exposes a JSX runtime for composing JSON data.
+
+
diff --git a/server/docs/01_getting_started/00_index.md b/docs/01_getting_started/00_index.md
similarity index 100%
rename from server/docs/01_getting_started/00_index.md
rename to docs/01_getting_started/00_index.md
diff --git a/server/docs/01_getting_started/01_install.md b/docs/01_getting_started/01_install.md
similarity index 100%
rename from server/docs/01_getting_started/01_install.md
rename to docs/01_getting_started/01_install.md
diff --git a/server/docs/01_getting_started/02_use.md b/docs/01_getting_started/02_use.md
similarity index 100%
rename from server/docs/01_getting_started/02_use.md
rename to docs/01_getting_started/02_use.md
diff --git a/server/docs/01_getting_started/03_foo/00_index.md b/docs/01_getting_started/03_foo/00_index.md
similarity index 100%
rename from server/docs/01_getting_started/03_foo/00_index.md
rename to docs/01_getting_started/03_foo/00_index.md
diff --git a/server/docs/01_getting_started/03_foo/01_bar.md b/docs/01_getting_started/03_foo/01_bar.md
similarity index 100%
rename from server/docs/01_getting_started/03_foo/01_bar.md
rename to docs/01_getting_started/03_foo/01_bar.md
diff --git a/server/docs/98_api_docs.md b/docs/98_api_docs.md
similarity index 98%
rename from server/docs/98_api_docs.md
rename to docs/98_api_docs.md
index aa86d0f..1a9ca2d 100644
--- a/server/docs/98_api_docs.md
+++ b/docs/98_api_docs.md
@@ -1,4 +1,4 @@
---
title: API Docs
href: https://jsr.io/@fartlabs/jsonx
----
+---
diff --git a/server/docs/99_view_on_github.md b/docs/99_view_on_github.md
similarity index 100%
rename from server/docs/99_view_on_github.md
rename to docs/99_view_on_github.md
diff --git a/server/examples/01_animals.tsx b/examples/01_animals.tsx
similarity index 100%
rename from server/examples/01_animals.tsx
rename to examples/01_animals.tsx
diff --git a/fresh.gen.ts b/fresh.gen.ts
index 9b2bbd7..9b98fa7 100644
--- a/fresh.gen.ts
+++ b/fresh.gen.ts
@@ -4,11 +4,11 @@
import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
-import * as $api_examples_id_ from "./routes/api/examples/[id].ts";
+import * as $api_examples_name_ from "./routes/api/examples/[name].ts";
+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.tsx";
-import * as $meta from "./routes/meta.ts";
import * as $playgrounds_id_ from "./routes/playgrounds/[id].tsx";
import { type Manifest } from "$fresh/server.ts";
@@ -17,11 +17,11 @@ const manifest = {
routes: {
"./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app,
- "./routes/api/examples/[id].ts": $api_examples_id_,
+ "./routes/api/examples/[name].ts": $api_examples_name_,
+ "./routes/api/meta.ts": $api_meta,
"./routes/api/playgrounds/[id].ts": $api_playgrounds_id_,
"./routes/api/playgrounds/index.ts": $api_playgrounds_index,
"./routes/index.tsx": $index,
- "./routes/meta.ts": $meta,
"./routes/playgrounds/[id].tsx": $playgrounds_id_,
},
islands: {},
diff --git a/server/docs/fs.ts b/lib/docs/fs.ts
similarity index 97%
rename from server/docs/fs.ts
rename to lib/docs/fs.ts
index 76dc232..69ad78d 100644
--- a/server/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -1,7 +1,7 @@
import type { RenderOptions } from "@deno/gfm";
import { render } from "@deno/gfm";
+import { test } from "@std/front-matter";
import { extract } from "@std/front-matter/any";
-import { test } from "@std/front-matter/test";
import { walk } from "@std/fs";
import { fromFileUrl, normalize, parse, SEPARATOR_PATTERN } from "@std/path";
import type { FSItem } from "./items.ts";
@@ -59,7 +59,6 @@ export async function readFSItems(
);
for await (const file of walkIt) {
let md = await Deno.readTextFile(file.path);
- const html = render(md, options.renderOptions);
const path = parse(file.path);
// Remove index suffix from the name.
@@ -94,7 +93,8 @@ export async function readFSItems(
items.push(item);
// Store the item contents.
- contents.set(file.path, { md, html });
+ const html = render(md, options.renderOptions);
+ contents.set(name.join(NAME_SEPARATOR), { md, html });
}
// Return items relative to the root.
diff --git a/server/docs/items.ts b/lib/docs/items.ts
similarity index 100%
rename from server/docs/items.ts
rename to lib/docs/items.ts
diff --git a/lib/docs/mod_client.ts b/lib/docs/mod_client.ts
new file mode 100644
index 0000000..1952f46
--- /dev/null
+++ b/lib/docs/mod_client.ts
@@ -0,0 +1,2 @@
+export * from "./items.ts";
+export * from "./nodes.ts";
diff --git a/lib/docs/mod_server.ts b/lib/docs/mod_server.ts
new file mode 100644
index 0000000..a2d16b6
--- /dev/null
+++ b/lib/docs/mod_server.ts
@@ -0,0 +1,2 @@
+export * from "./mod_client.ts";
+export * from "./fs.ts";
diff --git a/server/docs/nodes.ts b/lib/docs/nodes.ts
similarity index 100%
rename from server/docs/nodes.ts
rename to lib/docs/nodes.ts
diff --git a/lib/examples/examples.ts b/lib/examples/examples.ts
new file mode 100644
index 0000000..a8456c6
--- /dev/null
+++ b/lib/examples/examples.ts
@@ -0,0 +1,24 @@
+/**
+ * readExample reads the example file and returns the content.
+ */
+export async function readExample(path: string | URL): Promise {
+ try {
+ const text = await Deno.readTextFile(path);
+ return trimJSXImportSource(text);
+ } catch (error) {
+ if (error instanceof Deno.errors.NotFound) {
+ return null;
+ }
+
+ throw error;
+ }
+}
+
+function trimJSXImportSource(code: string): string {
+ const jsxImportSource = "/** @jsxImportSource @fartlabs/jsonx */\n\n";
+ if (code.startsWith(jsxImportSource)) {
+ return code.substring(jsxImportSource.length);
+ }
+
+ return code;
+}
diff --git a/server/examples/mod.ts b/lib/examples/mod.ts
similarity index 100%
rename from server/examples/mod.ts
rename to lib/examples/mod.ts
diff --git a/client/meta.ts b/lib/meta/meta.ts
similarity index 78%
rename from client/meta.ts
rename to lib/meta/meta.ts
index 216f79e..ba999b0 100644
--- a/client/meta.ts
+++ b/lib/meta/meta.ts
@@ -24,9 +24,11 @@ function playgroundMeta({ latest, versions }: {
// https://github.com/FartLabs/jsonx/issues/13
const minCompatible = parse("0.0.8");
return {
- latest: latest,
+ latest,
versions: Object.keys(versions)
- .filter((versionTag) => greaterThan(parse(versionTag), minCompatible))
- .sort((a, b) => compare(parse(b), parse(a))),
+ .map((versionTag) => parse(versionTag))
+ .filter((v) => greaterThan(v, minCompatible))
+ .sort((a, b) => compare(b, a))
+ .map((v) => v.toString()),
};
}
diff --git a/lib/meta/mod.ts b/lib/meta/mod.ts
new file mode 100644
index 0000000..934df4c
--- /dev/null
+++ b/lib/meta/mod.ts
@@ -0,0 +1 @@
+export * from "./meta.ts";
diff --git a/server/kv/playgrounds.ts b/lib/playgrounds/deno_kv/kv.ts
similarity index 93%
rename from server/kv/playgrounds.ts
rename to lib/playgrounds/deno_kv/kv.ts
index 0671dc5..e49c5fc 100644
--- a/server/kv/playgrounds.ts
+++ b/lib/playgrounds/deno_kv/kv.ts
@@ -1,7 +1,10 @@
///
import { ulid } from "@std/ulid";
-import type { AddPlaygroundRequest, Playground } from "#/client/playgrounds.ts";
+import type {
+ AddPlaygroundRequest,
+ Playground,
+} from "#/lib/playgrounds/mod.ts";
/**
* getPlayground gets a playground by ID.
diff --git a/lib/playgrounds/deno_kv/mod.ts b/lib/playgrounds/deno_kv/mod.ts
new file mode 100644
index 0000000..b076734
--- /dev/null
+++ b/lib/playgrounds/deno_kv/mod.ts
@@ -0,0 +1 @@
+export * from "./kv.ts";
diff --git a/lib/playgrounds/mod.ts b/lib/playgrounds/mod.ts
new file mode 100644
index 0000000..8510bd9
--- /dev/null
+++ b/lib/playgrounds/mod.ts
@@ -0,0 +1 @@
+export * from "./playgrounds.ts";
diff --git a/client/playgrounds.ts b/lib/playgrounds/playgrounds.ts
similarity index 63%
rename from client/playgrounds.ts
rename to lib/playgrounds/playgrounds.ts
index 2db0a0a..efc24b1 100644
--- a/client/playgrounds.ts
+++ b/lib/playgrounds/playgrounds.ts
@@ -11,3 +11,8 @@ export interface Playground {
* AddPlaygroundRequest is the request to add a playground.
*/
export type AddPlaygroundRequest = Omit;
+
+// TODO: Write HTML comment parser for rendering comments in playground.
+
+// function parsePlaygroundExpression(expression: string): string {
+// }
diff --git a/lib/resources/docs.ts b/lib/resources/docs.ts
new file mode 100644
index 0000000..79c8e16
--- /dev/null
+++ b/lib/resources/docs.ts
@@ -0,0 +1,13 @@
+import { readFSItems } from "#/lib/docs/mod_server.ts";
+
+export const { items, contents, nodes } = await readFSItems({
+ root: "./docs",
+ isIndex: (suffix) => suffix.startsWith("00_"),
+ renderOptions: {
+ // Preserve HTML comments as-is.
+ disableHtmlSanitization: true,
+ //
+ // TODO: Define the base URL for the site with environment variables.
+ //
+ },
+});
diff --git a/lib/resources/examples.ts b/lib/resources/examples.ts
new file mode 100644
index 0000000..2192601
--- /dev/null
+++ b/lib/resources/examples.ts
@@ -0,0 +1,3 @@
+import { readExample } from "#/lib/examples/examples.ts";
+
+export const defaultExample = (await readExample("./examples/01_animals.tsx"))!;
diff --git a/server/kv/kv.ts b/lib/resources/kv.ts
similarity index 100%
rename from server/kv/kv.ts
rename to lib/resources/kv.ts
diff --git a/routes/api/examples/[id].ts b/routes/api/examples/[name].ts
similarity index 55%
rename from routes/api/examples/[id].ts
rename to routes/api/examples/[name].ts
index 19dfb2c..0073252 100644
--- a/routes/api/examples/[id].ts
+++ b/routes/api/examples/[name].ts
@@ -1,9 +1,9 @@
import type { Handlers } from "$fresh/server.ts";
-import { getExampleByName } from "#/server/examples/mod.ts";
+import { readExample } from "#/lib/examples/mod.ts";
export const handler: Handlers = {
async GET(_request, ctx) {
- const example = await getExampleByName(ctx.params.id);
+ const example = await readExample(`./examples/${ctx.params.name}`);
return new Response(example);
},
};
diff --git a/routes/meta.ts b/routes/api/meta.ts
similarity index 80%
rename from routes/meta.ts
rename to routes/api/meta.ts
index 9f05d69..59ece56 100644
--- a/routes/meta.ts
+++ b/routes/api/meta.ts
@@ -1,5 +1,5 @@
import type { Handlers } from "$fresh/server.ts";
-import { getMeta } from "#/client/meta.ts";
+import { getMeta } from "#/lib/meta/mod.ts";
export const handler: Handlers = {
async GET(_request, _ctx) {
diff --git a/routes/api/playgrounds/[id].ts b/routes/api/playgrounds/[id].ts
index 58ca265..ff74134 100644
--- a/routes/api/playgrounds/[id].ts
+++ b/routes/api/playgrounds/[id].ts
@@ -1,9 +1,6 @@
import type { Handlers } from "$fresh/server.ts";
-import {
- getPlayground,
- setPlayground,
-} from "../../../server/kv/playgrounds.ts";
-import { kv } from "#/server/kv/kv.ts";
+import { kv } from "#/lib/resources/kv.ts";
+import { getPlayground, setPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
export const handler: Handlers = {
async GET(_request, ctx) {
diff --git a/routes/api/playgrounds/index.ts b/routes/api/playgrounds/index.ts
index 94751ef..3bf8d70 100644
--- a/routes/api/playgrounds/index.ts
+++ b/routes/api/playgrounds/index.ts
@@ -1,7 +1,7 @@
import type { Handlers } from "$fresh/server.ts";
-import type { AddPlaygroundRequest } from "#/client/playgrounds.ts";
-import { addPlayground } from "#/server/kv/playgrounds.ts";
-import { kv } from "#/server/kv/kv.ts";
+import type { AddPlaygroundRequest } from "#/lib/playgrounds/mod.ts";
+import { addPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
+import { kv } from "#/lib/resources/kv.ts";
export const handler: Handlers = {
async POST(request, _ctx) {
diff --git a/routes/index.tsx b/routes/index.tsx
index 6f95ce5..8ba1ecf 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -1,31 +1,9 @@
-import Playground from "#/components/playground/playground.tsx";
-import { getMeta } from "#/client/meta.ts";
-import { kv } from "#/server/kv/kv.ts";
-import { getExampleByName } from "#/server/examples/mod.ts";
-import { getPlayground } from "#/server/kv/playgrounds.ts";
-
-export default async function Home(request: Request) {
- const url = new URL(request.url);
- const id = url.searchParams.get("id");
- let code = "";
- let version: string | undefined = undefined;
- if (id) {
- const playground = await getPlayground(kv, id);
- if (!playground) {
- throw new Error("Playground not found!");
- }
-
- code = playground.code;
- version = playground.version;
- } else {
- code = await getExampleByName("01_animals.tsx");
- }
+import { contents } from "#/lib/resources/docs.ts";
+import Doc from "#/components/doc/doc.tsx";
+import { getMeta } from "#/lib/meta/mod.ts";
+export default async function Home(_request: Request) {
+ const html = contents.get("")!.html;
const meta = await getMeta();
- return (
- <>
- Meet jsonx.
-
- >
- );
+ return ;
}
diff --git a/routes/playgrounds/[id].tsx b/routes/playgrounds/[id].tsx
index 0ebe162..23d86fb 100644
--- a/routes/playgrounds/[id].tsx
+++ b/routes/playgrounds/[id].tsx
@@ -1,10 +1,9 @@
import type { FreshContext } from "$fresh/server.ts";
import { Head } from "$fresh/runtime.ts";
-import Nav from "#/components/nav.tsx";
import Playground from "#/components/playground/playground.tsx";
-import { getMeta } from "#/client/meta.ts";
-import { getPlayground } from "#/server/kv/playgrounds.ts";
-import { kv } from "#/server/kv/kv.ts";
+import { getMeta } from "#/lib/meta/meta.ts";
+import { getPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
+import { kv } from "#/lib/resources/kv.ts";
export default async function PlaygroundHandler(
_request: Request,
diff --git a/server/docs/docs.ts b/server/docs/docs.ts
deleted file mode 100644
index fc9515d..0000000
--- a/server/docs/docs.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { readFSItems } from "./fs.ts";
-
-export const { items, contents, nodes } = await readFSItems({
- root: new URL(".", import.meta.url),
- isIndex: (suffix) => suffix.startsWith("00_"),
-});
diff --git a/server/examples/examples.ts b/server/examples/examples.ts
deleted file mode 100644
index 058160f..0000000
--- a/server/examples/examples.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * getExampleByName gets an example by example name.
- */
-export async function getExampleByName(name: string): Promise {
- const text = await Deno.readTextFile(
- new URL(import.meta.resolve("./" + name)),
- );
- return trimJSXImportSource(text);
-}
-
-function trimJSXImportSource(code: string): string {
- const jsxImportSource = "/** @jsxImportSource @fartlabs/jsonx */\n\n";
- if (code.startsWith(jsxImportSource)) {
- return code.substring(jsxImportSource.length);
- }
-
- return code;
-}
From a9893df324ad0f73b41dbb9f2f60f3e7c260d59d Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Sat, 23 Mar 2024 16:45:24 -0700
Subject: [PATCH 16/34] Update deno.jsonc
---
deno.jsonc | 1 +
1 file changed, 1 insertion(+)
diff --git a/deno.jsonc b/deno.jsonc
index e198c75..0c48040 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -31,6 +31,7 @@
"@preact/signals": "https://esm.sh/*@preact/signals@1.2.1",
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.0",
"@std/front-matter": "jsr:@std/front-matter@^0.220.1",
+ "@std/front-matter/any": "jsr:@std/front-matter@^0.220.1/any",
"@std/fs": "jsr:@std/fs@^0.220.1",
"@std/http": "jsr:@std/http@^0.220.1",
"@std/path": "jsr:@std/path@^0.220.1",
From 3ed5cd012ea5de241fe073550f5f93515df45f7b Mon Sep 17 00:00:00 2001
From: EthanThatOneKid <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Sat, 23 Mar 2024 19:00:33 -0700
Subject: [PATCH 17/34] wip
---
components/doc.tsx | 30 +++++++++++
components/doc/doc.tsx | 46 -----------------
components/playground/scripts.tsx | 24 ++++-----
components/replace.tsx | 50 -------------------
docs/00_index.md | 3 +-
lib/docs/fs.ts | 6 ++-
.../playgrounds/expressions/expressions.ts | 34 +++----------
lib/playgrounds/expressions/mod.ts | 0
lib/playgrounds/playgrounds.ts | 30 ++++++++---
routes/index.tsx | 3 +-
10 files changed, 79 insertions(+), 147 deletions(-)
create mode 100644 components/doc.tsx
delete mode 100644 components/doc/doc.tsx
delete mode 100644 components/replace.tsx
rename components/doc/expression.ts => lib/playgrounds/expressions/expressions.ts (66%)
create mode 100644 lib/playgrounds/expressions/mod.ts
diff --git a/components/doc.tsx b/components/doc.tsx
new file mode 100644
index 0000000..bc48f20
--- /dev/null
+++ b/components/doc.tsx
@@ -0,0 +1,30 @@
+import type { Playground } from "#/lib/playgrounds/mod.ts";
+
+/**
+ * DocProps are the properties for the Doc component.
+ */
+export interface DocProps {
+ /**
+ * html is the html content of the documentation page.
+ */
+ html: string;
+
+ /**
+ * playground is the playground data for the documentation page.
+ */
+ playground?: Playground;
+}
+
+/**
+ * Doc is a jsonx documentation page component.
+ */
+export default function Doc(props: DocProps) {
+ return (
+ // TODO: Add sidenav for the documentation page.
+
+
+ );
+}
diff --git a/components/doc/doc.tsx b/components/doc/doc.tsx
deleted file mode 100644
index 01b832b..0000000
--- a/components/doc/doc.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { Meta } from "#/lib/meta/mod.ts";
-import Replace from "#/components/replace.tsx";
-import Playground from "#/components/playground/playground.tsx";
-import {
- getDataByRegExpMatchArray,
- PLAYGROUND_EXPRESSION_REGEX,
-} from "./expression.ts";
-
-/**
- * DocProps are the properties for the Doc component.
- */
-export interface DocProps {
- /**
- * html is the html content of the documentation page.
- */
- html: string;
-
- /**
- * meta is the meta data for the documentation page's playgrounds.
- */
- meta: Meta;
-}
-
-/**
- * Doc is a jsonx documentation page component.
- */
-export default function Doc(props: DocProps) {
- // TODO: Replace with actual MDX parsing because the async isn't working
- // with Preact hydration.
- return (
- {
- const data = await getDataByRegExpMatchArray(match);
- return (
-
- );
- }}
- />
- );
-}
diff --git a/components/playground/scripts.tsx b/components/playground/scripts.tsx
index d07b1ac..c109357 100644
--- a/components/playground/scripts.tsx
+++ b/components/playground/scripts.tsx
@@ -5,19 +5,15 @@ export interface PlaygroundScriptsProps {
export default function PlaygroundScripts(props: PlaygroundScriptsProps) {
return (
- `,
- }}
- >
-
+ <>
+
+
+ >
);
}
-
-function initializeData(props: PlaygroundScriptsProps) {
- return ``;
-}
diff --git a/components/replace.tsx b/components/replace.tsx
deleted file mode 100644
index 47fe398..0000000
--- a/components/replace.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { JSX } from "preact/jsx-runtime";
-
-/**
- * ReplaceProps
- */
-export interface ReplaceProps {
- /**
- * html is the html content to be replaced.
- */
- html: string;
-
- /**
- * pattern is the pattern to inject the component by.
- */
- pattern: RegExp;
-
- /**
- * component is the component to be injected in place of the content.
- */
- component: (
- props: { match: RegExpMatchArray },
- ) => JSX.Element | Promise;
-}
-
-/**
- * Replace is a component that replaces the content of the element with the content of the component.
- */
-export default function Replace(props: ReplaceProps) {
- const segments = props.html.split(props.pattern);
- if (segments.length === 1) {
- return {props.html} ;
- }
-
- const matches = [...props.html.matchAll(props.pattern)];
- return (
- <>
- {segments.map(async (segment, index) => (
- <>
- {segment}
- {index < matches.length &&
- await props.component({ match: matches[index] })}
- >
- ))}
- >
- );
-}
-
-function Raw(props: { children: string }) {
- return ;
-}
diff --git a/docs/00_index.md b/docs/00_index.md
index 9cd719c..0d272a1 100644
--- a/docs/00_index.md
+++ b/docs/00_index.md
@@ -1,9 +1,8 @@
---
title: Overview
+playground: 'example:01_animals.tsx'
---
# Overview
The jsonx library exposes a JSX runtime for composing JSON data.
-
-
diff --git a/lib/docs/fs.ts b/lib/docs/fs.ts
index 69ad78d..528b6b1 100644
--- a/lib/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -23,6 +23,8 @@ export interface ReadFSItemsOptions {
export interface Content {
md: string;
html: string;
+ // TODO: Add recursive list of heading nodes (ID and title). Render the
+ // heading nodes as a sidenav component.
}
/**
@@ -77,7 +79,9 @@ export async function readFSItems(
let title: string | undefined;
let href: string | undefined;
if (test(md)) {
- const extracted = extract<{ title: string; href: string }>(md);
+ const extracted = extract<
+ { title: string; href: string; playground: string }
+ >(md);
if (extracted.attrs.title !== undefined) {
title = extracted.attrs.title;
}
diff --git a/components/doc/expression.ts b/lib/playgrounds/expressions/expressions.ts
similarity index 66%
rename from components/doc/expression.ts
rename to lib/playgrounds/expressions/expressions.ts
index f3c19ff..041ea4d 100644
--- a/components/doc/expression.ts
+++ b/lib/playgrounds/expressions/expressions.ts
@@ -6,26 +6,10 @@
* playgrounds directly into markdown files.
*/
+import type { PlaygroundData } from "#/lib/playgrounds/mod.ts";
import { getPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
-import { kv } from "#/lib/resources/kv.ts";
import { readExample } from "#/lib/examples/mod.ts";
-
-/**
- * PLAYGROUND_EXPRESSION_REGEX is the regular expression for parsing playground
- * expressions.
- */
-export const PLAYGROUND_EXPRESSION_REGEX =
- //g;
-
-/**
- * fromRegExpMatchArray converts a regular expression match array to a
- * PlaygroundExpression.
- */
-export function fromRegExpMatchArray(
- match: RegExpMatchArray,
-): PlaygroundExpression {
- return parsePlaygroundExpression(match[0]);
-}
+import { kv } from "#/lib/resources/kv.ts";
/**
* PlaygroundExpression is a playground expression.
@@ -45,7 +29,7 @@ export type PlaygroundExpression =
export function parsePlaygroundExpression(
expression: string,
): PlaygroundExpression {
- const idMatch = expression.match(/id:([a-zA-Z0-9-_.]+)/);
+ const idMatch = expression.match(/id:([a- zA-Z0-9-_.]+)/);
if (idMatch) {
return { id: idMatch[1] };
}
@@ -59,14 +43,12 @@ export function parsePlaygroundExpression(
}
/**
- * getDataByRegExpMatchArray converts a regular expression match array to
- * playground data.
+ * fromExpression converts a playground expression to playground data.
*/
-export async function getDataByRegExpMatchArray(
- match: RegExpMatchArray,
-): Promise<{ code: string; version?: string }> {
- const expr = fromRegExpMatchArray(match);
- console.log({ expr });
+export async function fromExpression(
+ expression: string,
+): Promise {
+ const expr = parsePlaygroundExpression(expression);
if ("id" in expr) {
const playground = await getPlayground(kv, expr.id);
if (!playground) {
diff --git a/lib/playgrounds/expressions/mod.ts b/lib/playgrounds/expressions/mod.ts
new file mode 100644
index 0000000..e69de29
diff --git a/lib/playgrounds/playgrounds.ts b/lib/playgrounds/playgrounds.ts
index efc24b1..baaf663 100644
--- a/lib/playgrounds/playgrounds.ts
+++ b/lib/playgrounds/playgrounds.ts
@@ -1,18 +1,34 @@
/**
- * Playground is a jsonx playground.
+ * Playground is a stored jsonx playground.
*/
-export interface Playground {
+export interface Playground extends PlaygroundData {
+ /**
+ * id is the playground ID.
+ */
id: string;
+
+ /**
+ * version is the playground version.
+ */
version: string;
+}
+
+/**
+ * PlaygroundData is the data for a playground.
+ */
+export interface PlaygroundData {
+ /**
+ * code is the playground code.
+ */
code: string;
+
+ /**
+ * version is the playground version.
+ */
+ version?: string;
}
/**
* AddPlaygroundRequest is the request to add a playground.
*/
export type AddPlaygroundRequest = Omit;
-
-// TODO: Write HTML comment parser for rendering comments in playground.
-
-// function parsePlaygroundExpression(expression: string): string {
-// }
diff --git a/routes/index.tsx b/routes/index.tsx
index 8ba1ecf..d4a722e 100644
--- a/routes/index.tsx
+++ b/routes/index.tsx
@@ -1,9 +1,10 @@
import { contents } from "#/lib/resources/docs.ts";
-import Doc from "#/components/doc/doc.tsx";
+import Doc from "#/components/doc.tsx";
import { getMeta } from "#/lib/meta/mod.ts";
export default async function Home(_request: Request) {
const html = contents.get("")!.html;
const meta = await getMeta();
+ // TODO: wip.
return ;
}
From b81905a168b9daa200d7635482bf40640e0b26c9 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Sun, 24 Mar 2024 09:42:54 -0700
Subject: [PATCH 18/34] 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.
```
---
components/doc.tsx | 12 +++++++-----
components/drawer.tsx | 26 ++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 5 deletions(-)
create mode 100644 components/drawer.tsx
diff --git a/components/doc.tsx b/components/doc.tsx
index bc48f20..19828ce 100644
--- a/components/doc.tsx
+++ b/components/doc.tsx
@@ -21,10 +21,12 @@ export interface DocProps {
export default function Doc(props: DocProps) {
return (
// TODO: Add sidenav for the documentation page.
-
-
+ <>
+
+
+ >
);
}
diff --git a/components/drawer.tsx b/components/drawer.tsx
new file mode 100644
index 0000000..cbf9ce5
--- /dev/null
+++ b/components/drawer.tsx
@@ -0,0 +1,26 @@
+import { JSX } from "preact/jsx-runtime";
+
+export interface DrawerProps {
+ summary: string;
+ children: JSX.Element[];
+}
+
+// Reference:
+// https://web.dev/articles/codelab-building-a-sidenav-component
+
+// 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. TODO: Remove this comment when done.
+
+export default function Drawer(props: DrawerProps) {
+ return (
+
+
+ {props.summary}
+
+ {props.children}
+
+ );
+}
From 5b7501fb174631db37536b3448e3c27daccb55cb Mon Sep 17 00:00:00 2001
From: EthanThatOneKid <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Sun, 24 Mar 2024 21:40:54 -0700
Subject: [PATCH 19/34] add playground to doc component
---
components/doc.tsx | 17 +++++++++---
components/nav.tsx | 7 -----
fresh.gen.ts | 4 +--
lib/docs/fs.ts | 7 ++++-
lib/playgrounds/expressions/expressions.ts | 2 +-
lib/playgrounds/expressions/mod.ts | 1 +
lib/to_path.ts | 6 +++++
routes/[[...path]].tsx | 30 ++++++++++++++++++++++
routes/_404.tsx | 7 -----
routes/_app.tsx | 3 ++-
routes/index.tsx | 10 --------
11 files changed, 62 insertions(+), 32 deletions(-)
create mode 100644 lib/to_path.ts
create mode 100644 routes/[[...path]].tsx
delete mode 100644 routes/index.tsx
diff --git a/components/doc.tsx b/components/doc.tsx
index 19828ce..65637a0 100644
--- a/components/doc.tsx
+++ b/components/doc.tsx
@@ -1,4 +1,6 @@
-import type { Playground } from "#/lib/playgrounds/mod.ts";
+import type { PlaygroundData } from "#/lib/playgrounds/mod.ts";
+import { Meta } from "#/lib/meta/mod.ts";
+import Playground from "#/components/playground/playground.tsx";
/**
* DocProps are the properties for the Doc component.
@@ -12,7 +14,10 @@ export interface DocProps {
/**
* playground is the playground data for the documentation page.
*/
- playground?: Playground;
+ playground?: {
+ data: PlaygroundData;
+ meta: Meta;
+ };
}
/**
@@ -20,13 +25,19 @@ export interface DocProps {
*/
export default function Doc(props: DocProps) {
return (
- // TODO: Add sidenav for the documentation page.
<>
+ {props.playground && (
+
+ )}
>
);
}
diff --git a/components/nav.tsx b/components/nav.tsx
index 1a2a619..78dd809 100644
--- a/components/nav.tsx
+++ b/components/nav.tsx
@@ -22,10 +22,3 @@ export default function Nav(props: NavProps) {
);
}
-
-/**
- * toPath returns the path from the path string.
- */
-export function toPath(path: string): string[] {
- return path.split("/").filter(Boolean);
-}
diff --git a/fresh.gen.ts b/fresh.gen.ts
index 9b98fa7..bfc3675 100644
--- a/fresh.gen.ts
+++ b/fresh.gen.ts
@@ -2,26 +2,26 @@
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.
+import * as $_path_ from "./routes/[[...path]].tsx";
import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
import * as $api_examples_name_ from "./routes/api/examples/[name].ts";
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.tsx";
import * as $playgrounds_id_ from "./routes/playgrounds/[id].tsx";
import { type Manifest } from "$fresh/server.ts";
const manifest = {
routes: {
+ "./routes/[[...path]].tsx": $_path_,
"./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app,
"./routes/api/examples/[name].ts": $api_examples_name_,
"./routes/api/meta.ts": $api_meta,
"./routes/api/playgrounds/[id].ts": $api_playgrounds_id_,
"./routes/api/playgrounds/index.ts": $api_playgrounds_index,
- "./routes/index.tsx": $index,
"./routes/playgrounds/[id].tsx": $playgrounds_id_,
},
islands: {},
diff --git a/lib/docs/fs.ts b/lib/docs/fs.ts
index 528b6b1..f7215e1 100644
--- a/lib/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -23,6 +23,7 @@ export interface ReadFSItemsOptions {
export interface Content {
md: string;
html: string;
+ playground?: string;
// TODO: Add recursive list of heading nodes (ID and title). Render the
// heading nodes as a sidenav component.
}
@@ -78,6 +79,7 @@ export async function readFSItems(
// Render the FSItem.
let title: string | undefined;
let href: string | undefined;
+ let playground: string | undefined;
if (test(md)) {
const extracted = extract<
{ title: string; href: string; playground: string }
@@ -98,7 +100,10 @@ export async function readFSItems(
// Store the item contents.
const html = render(md, options.renderOptions);
- contents.set(name.join(NAME_SEPARATOR), { md, html });
+ contents.set(
+ name.join(NAME_SEPARATOR),
+ { md, html, playground },
+ );
}
// Return items relative to the root.
diff --git a/lib/playgrounds/expressions/expressions.ts b/lib/playgrounds/expressions/expressions.ts
index 041ea4d..17ac994 100644
--- a/lib/playgrounds/expressions/expressions.ts
+++ b/lib/playgrounds/expressions/expressions.ts
@@ -29,7 +29,7 @@ export type PlaygroundExpression =
export function parsePlaygroundExpression(
expression: string,
): PlaygroundExpression {
- const idMatch = expression.match(/id:([a- zA-Z0-9-_.]+)/);
+ const idMatch = expression.match(/id:([a-zA-Z0-9-_.]+)/);
if (idMatch) {
return { id: idMatch[1] };
}
diff --git a/lib/playgrounds/expressions/mod.ts b/lib/playgrounds/expressions/mod.ts
index e69de29..845c542 100644
--- a/lib/playgrounds/expressions/mod.ts
+++ b/lib/playgrounds/expressions/mod.ts
@@ -0,0 +1 @@
+export * from "./expressions.ts";
diff --git a/lib/to_path.ts b/lib/to_path.ts
new file mode 100644
index 0000000..8473b96
--- /dev/null
+++ b/lib/to_path.ts
@@ -0,0 +1,6 @@
+/**
+ * toPath returns the path from the path string.
+ */
+export function toPath(path: string): string[] {
+ return path.split("/").filter(Boolean);
+}
diff --git a/routes/[[...path]].tsx b/routes/[[...path]].tsx
new file mode 100644
index 0000000..d67a02b
--- /dev/null
+++ b/routes/[[...path]].tsx
@@ -0,0 +1,30 @@
+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 { DocProps } from "#/components/doc.tsx";
+import Doc from "#/components/doc.tsx";
+
+export default async function DocumentationPage(request: Request) {
+ const content = contentOf(request);
+ let playground: DocProps["playground"];
+ if (content.playground) {
+ playground = {
+ data: await fromExpression(content.playground),
+ meta: await getMeta(),
+ };
+ }
+
+ 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;
+}
diff --git a/routes/_404.tsx b/routes/_404.tsx
index c63ae2e..e7a38b5 100644
--- a/routes/_404.tsx
+++ b/routes/_404.tsx
@@ -8,13 +8,6 @@ export default function Error404() {
-
404 - Page not found
The page you were looking for doesn't exist.
diff --git a/routes/_app.tsx b/routes/_app.tsx
index eb9293d..aea0eb3 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,5 +1,6 @@
import type { PageProps } from "$fresh/server.ts";
-import Nav, { toPath } from "#/components/nav.tsx";
+import { toPath } from "#/lib/to_path.ts";
+import Nav from "#/components/nav.tsx";
export default function App({ Component, route }: PageProps) {
return (
diff --git a/routes/index.tsx b/routes/index.tsx
deleted file mode 100644
index d4a722e..0000000
--- a/routes/index.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { contents } from "#/lib/resources/docs.ts";
-import Doc from "#/components/doc.tsx";
-import { getMeta } from "#/lib/meta/mod.ts";
-
-export default async function Home(_request: Request) {
- const html = contents.get("")!.html;
- const meta = await getMeta();
- // TODO: wip.
- return ;
-}
From 168fd70ef825d89c27c68549f0036f84a7da8727 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 11:51:20 -0700
Subject: [PATCH 20/34] import shared code in 2 route files
---
.../[[...path]].tsx => components/doc/doc.tsx | 27 +++++++++++--------
components/{doc.tsx => doc/doc_content.tsx} | 8 +++---
components/playground/scripts.tsx | 7 +++--
docs/01_getting_started/03_foo/01_bar.md | 2 ++
fresh.gen.ts | 6 +++--
lib/docs/fs.ts | 4 +++
lib/meta/meta.ts | 8 +++---
lib/playgrounds/expressions/expressions.ts | 12 ++++-----
routes/[...path].ts | 1 +
routes/index.ts | 1 +
10 files changed, 47 insertions(+), 29 deletions(-)
rename routes/[[...path]].tsx => components/doc/doc.tsx (60%)
rename components/{doc.tsx => doc/doc_content.tsx} (77%)
create mode 100644 routes/[...path].ts
create mode 100644 routes/index.ts
diff --git a/routes/[[...path]].tsx b/components/doc/doc.tsx
similarity index 60%
rename from routes/[[...path]].tsx
rename to components/doc/doc.tsx
index d67a02b..aa433c6 100644
--- a/routes/[[...path]].tsx
+++ b/components/doc/doc.tsx
@@ -2,20 +2,13 @@ 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 { DocProps } from "#/components/doc.tsx";
-import Doc from "#/components/doc.tsx";
+import type { DocContentProps } from "./doc_content.tsx";
+import DocContent from "./doc_content.tsx";
export default async function DocumentationPage(request: Request) {
const content = contentOf(request);
- let playground: DocProps["playground"];
- if (content.playground) {
- playground = {
- data: await fromExpression(content.playground),
- meta: await getMeta(),
- };
- }
-
- return ;
+ const playground = await playgroundOf(content.playground);
+ return ;
}
function contentOf(request: Request) {
@@ -28,3 +21,15 @@ function contentOf(request: Request) {
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.tsx b/components/doc/doc_content.tsx
similarity index 77%
rename from components/doc.tsx
rename to components/doc/doc_content.tsx
index 65637a0..d5db07b 100644
--- a/components/doc.tsx
+++ b/components/doc/doc_content.tsx
@@ -3,9 +3,9 @@ import { Meta } from "#/lib/meta/mod.ts";
import Playground from "#/components/playground/playground.tsx";
/**
- * DocProps are the properties for the Doc component.
+ * DocContentProps are the properties for the DocContent component.
*/
-export interface DocProps {
+export interface DocContentProps {
/**
* html is the html content of the documentation page.
*/
@@ -21,9 +21,9 @@ export interface DocProps {
}
/**
- * Doc is a jsonx documentation page component.
+ * DocContent is the content of a jsonx documentation page.
*/
-export default function Doc(props: DocProps) {
+export default function DocContent(props: DocContentProps) {
return (
<>
-
+
+
+ >
+ );
+}
diff --git a/docs/98_api_docs.md b/docs/98_api_docs.md
index 1a9ca2d..5e05d12 100644
--- a/docs/98_api_docs.md
+++ b/docs/98_api_docs.md
@@ -1,4 +1,4 @@
---
-title: API Docs
+title: View API Docs
href: https://jsr.io/@fartlabs/jsonx
---
diff --git a/lib/resources/docs.ts b/lib/resources/docs.ts
index 79c8e16..be380d7 100644
--- a/lib/resources/docs.ts
+++ b/lib/resources/docs.ts
@@ -1,13 +1,13 @@
import { readFSItems } from "#/lib/docs/mod_server.ts";
+import { Renderer } from "@deno/gfm";
export const { items, contents, nodes } = await readFSItems({
root: "./docs",
isIndex: (suffix) => suffix.startsWith("00_"),
renderOptions: {
- // Preserve HTML comments as-is.
- disableHtmlSanitization: true,
- //
- // TODO: Define the base URL for the site with environment variables.
+ // TODO: Reference
+ // https://github.com/denoland/fresh/blob/main/www/utils/markdown.ts
//
+ renderer: new Renderer(),
},
});
diff --git a/routes/_app.tsx b/routes/_app.tsx
index aea0eb3..428cf17 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,8 +1,9 @@
import type { PageProps } from "$fresh/server.ts";
import { toPath } from "#/lib/to_path.ts";
import Nav from "#/components/nav.tsx";
+// import Hljs from "#/components/hljs.tsx";
-export default function App({ Component, route }: PageProps) {
+export default function App({ Component, url }: PageProps) {
return (
@@ -10,9 +11,10 @@ export default function App({ Component, route }: PageProps) {
jsonx | Documentation
+ {/* */}
-
+
diff --git a/static/global.css b/static/global.css
index 5abfbb7..6d2ae05 100644
--- a/static/global.css
+++ b/static/global.css
@@ -8,15 +8,46 @@
body {
background-color: #bbb;
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr 3fr;
+ grid-template-areas: "nav" "main";
}
nav {
- display: flex;
- justify-content: space-between;
- align-items: center;
+ grid-area: nav;
padding: 1em 1em 0 1em;
}
+nav ul {
+ padding: 0;
+ margin-left: 1em;
+}
+
main {
+ grid-area: main;
padding: 0 0.7em;
}
+
+pre,
+code {
+ font-family: monospace;
+ background-color: #f8f8f8;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ padding: 0.1em 0.2em;
+}
+
+pre code {
+ display: block;
+ padding: 1em;
+ overflow-x: auto;
+}
+
+@media (min-width: 768px) {
+ body {
+ grid-template-columns: 1fr 3fr;
+ grid-template-rows: 1fr;
+ grid-template-areas: "nav main";
+ }
+}
From beee12482a9a9f47d1747d5acae7322334392c29 Mon Sep 17 00:00:00 2001
From: EthanThatOneKid <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 16:44:38 -0700
Subject: [PATCH 23/34] add alias `p` for route `playgrounds`
Reference: .
---
routes/playgrounds/[id].tsx | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/routes/playgrounds/[id].tsx b/routes/playgrounds/[id].tsx
index 23d86fb..907df11 100644
--- a/routes/playgrounds/[id].tsx
+++ b/routes/playgrounds/[id].tsx
@@ -1,10 +1,14 @@
-import type { FreshContext } from "$fresh/server.ts";
+import type { FreshContext, RouteConfig } from "$fresh/server.ts";
import { Head } from "$fresh/runtime.ts";
import Playground from "#/components/playground/playground.tsx";
import { getMeta } from "#/lib/meta/meta.ts";
import { getPlayground } from "#/lib/playgrounds/deno_kv/mod.ts";
import { kv } from "#/lib/resources/kv.ts";
+export const config: RouteConfig = {
+ routeOverride: "/(p|playgrounds)/:id",
+};
+
export default async function PlaygroundHandler(
_request: Request,
ctx: FreshContext,
From 901e721a8c2f6c393c4a1a98add920ea43d24f6a Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 20:33:55 -0700
Subject: [PATCH 24/34] add footer (w/ css grid)
---
components/foot.tsx | 19 +++++++++++++++++++
deno.jsonc | 1 +
routes/_app.tsx | 8 ++++++++
static/global.css | 28 +++++++++++++++++++++++-----
static/script.js | 6 +++++-
5 files changed, 56 insertions(+), 6 deletions(-)
create mode 100644 components/foot.tsx
diff --git a/components/foot.tsx b/components/foot.tsx
new file mode 100644
index 0000000..f3177cd
--- /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/deno.jsonc b/deno.jsonc
index 0c48040..3048ab7 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -38,6 +38,7 @@
"@std/semver": "jsr:@std/semver@^0.220.1",
"@std/ulid": "jsr:@std/ulid@^0.220.1",
"@std/yaml": "jsr:@std/yaml@^0.220.1",
+ // "markdown-it": "https://esm.sh/markdown-it@14.1.0",
"preact": "https://esm.sh/preact@10.19.2",
"preact/": "https://esm.sh/preact@10.19.2/"
},
diff --git a/routes/_app.tsx b/routes/_app.tsx
index 428cf17..3f202f6 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,6 +1,7 @@
import type { PageProps } from "$fresh/server.ts";
import { toPath } from "#/lib/to_path.ts";
import Nav from "#/components/nav.tsx";
+import Foot from "#/components/foot.tsx";
// import Hljs from "#/components/hljs.tsx";
export default function App({ Component, url }: PageProps) {
@@ -19,6 +20,13 @@ export default function App({ Component, url }: PageProps) {
+
+
+
+
);
diff --git a/static/global.css b/static/global.css
index 6d2ae05..976f9f8 100644
--- a/static/global.css
+++ b/static/global.css
@@ -10,8 +10,10 @@ body {
background-color: #bbb;
display: grid;
grid-template-columns: 1fr;
- grid-template-rows: 1fr 3fr;
- grid-template-areas: "nav" "main";
+ grid-template-rows: repeat(auto, 4);
+ /* grid-auto-flow: row; */
+ grid-template-areas: "nav" "aside" "main" "footer";
+ gap: 0px 0px;
}
nav {
@@ -29,6 +31,20 @@ main {
padding: 0 0.7em;
}
+aside {
+ grid-area: aside;
+ padding: 1em;
+}
+
+footer {
+ grid-area: footer;
+}
+
+footer p {
+ text-align: center;
+ padding: 1em;
+}
+
pre,
code {
font-family: monospace;
@@ -46,8 +62,10 @@ pre code {
@media (min-width: 768px) {
body {
- grid-template-columns: 1fr 3fr;
- grid-template-rows: 1fr;
- grid-template-areas: "nav main";
+ grid-template-columns: 1fr 3fr 1fr;
+ grid-template-rows: 1fr auto;
+ grid-template-areas:
+ "nav main aside"
+ "footer footer footer";
}
}
diff --git a/static/script.js b/static/script.js
index f25be11..fa052a3 100644
--- a/static/script.js
+++ b/static/script.js
@@ -42,7 +42,11 @@ function createEditor(options) {
}
function sharePlayground() {
- if (!confirm("Are you sure you want to share this playground?")) {
+ if (
+ !confirm(
+ "Are you sure you want to share this playground?\nPlaygrounds cannot be searched or deleted at a later time.",
+ )
+ ) {
return;
}
From f09d78296da098a3571b3f5bc7bd05193a0ce951 Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 21:51:59 -0700
Subject: [PATCH 25/34] replace gfm with markdown-it
---
deno.jsonc | 4 ++--
lib/docs/fs.ts | 7 +++----
lib/docs/md.ts | 23 +++++++++++++++++++++++
lib/resources/docs.ts | 7 -------
static/global.css | 1 +
5 files changed, 29 insertions(+), 13 deletions(-)
create mode 100644 lib/docs/md.ts
diff --git a/deno.jsonc b/deno.jsonc
index 3048ab7..1146824 100644
--- a/deno.jsonc
+++ b/deno.jsonc
@@ -26,7 +26,6 @@
"#/": "./",
"$fresh/": "https://deno.land/x/fresh@1.6.5/",
"$std/": "https://deno.land/std@0.211.0/",
- "@deno/gfm": "jsr:@deno/gfm@^0.8.0",
"@fartlabs/jsonx": "jsr:@fartlabs/jsonx@^0.0.10",
"@preact/signals": "https://esm.sh/*@preact/signals@1.2.1",
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.0",
@@ -38,7 +37,8 @@
"@std/semver": "jsr:@std/semver@^0.220.1",
"@std/ulid": "jsr:@std/ulid@^0.220.1",
"@std/yaml": "jsr:@std/yaml@^0.220.1",
- // "markdown-it": "https://esm.sh/markdown-it@14.1.0",
+ "highlight.js": "https://esm.sh/highlight.js@11.9.0",
+ "markdown-it": "https://esm.sh/markdown-it@14.1.0",
"preact": "https://esm.sh/preact@10.19.2",
"preact/": "https://esm.sh/preact@10.19.2/"
},
diff --git a/lib/docs/fs.ts b/lib/docs/fs.ts
index 26970e0..a65990c 100644
--- a/lib/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -1,5 +1,3 @@
-import type { RenderOptions } from "@deno/gfm";
-import { render } from "@deno/gfm";
import { test } from "@std/front-matter";
import { extract } from "@std/front-matter/any";
import { walk } from "@std/fs";
@@ -7,6 +5,7 @@ import { fromFileUrl, normalize, parse, SEPARATOR_PATTERN } from "@std/path";
import type { FSItem } from "./items.ts";
import type { Node } from "./nodes.ts";
import { sortChildren } from "./nodes.ts";
+import { renderer } from "./md.ts";
/**
* RenderFSItemsOptions represents the options for rendering file-based items.
@@ -14,7 +13,6 @@ import { sortChildren } from "./nodes.ts";
export interface ReadFSItemsOptions {
root: string | URL;
isIndex?: (suffix: string) => boolean;
- renderOptions?: RenderOptions;
}
/**
@@ -65,6 +63,7 @@ export async function readFSItems(
const path = parse(file.path);
// Remove index suffix from the name.
+ // TODO: First extract possible name override from front matter.
const name = options.isIndex?.(path.name) ? [] : [path.name];
// If the path has a directory, add it to the name.
@@ -103,7 +102,7 @@ export async function readFSItems(
items.push(item);
// Store the item contents.
- const html = render(md, options.renderOptions);
+ const html = renderer.render(md);
contents.set(
name.join(NAME_SEPARATOR),
{ md, html, playground },
diff --git a/lib/docs/md.ts b/lib/docs/md.ts
new file mode 100644
index 0000000..1ee7d8e
--- /dev/null
+++ b/lib/docs/md.ts
@@ -0,0 +1,23 @@
+import MarkdownIt from "markdown-it";
+import hljs from "highlight.js";
+
+/**
+ * renderer is the markdown renderer used for rendering markdown content.
+ *
+ * @see
+ * https://github.com/markdown-it/markdown-it/blob/0fe7ccb4b7f30236fb05f623be6924961d296d3d/README.md?plain=1#L154
+ */
+export const renderer: MarkdownIt = new MarkdownIt({
+ html: true,
+ linkify: true,
+ typographer: true,
+ highlight(content, lang) {
+ const html = lang && hljs.getLanguage(lang)
+ ? hljs.highlight(
+ content,
+ { language: lang, ignoreIllegals: true },
+ ).value
+ : renderer.utils.escapeHtml(content);
+ return `${html}
`;
+ },
+});
diff --git a/lib/resources/docs.ts b/lib/resources/docs.ts
index be380d7..4b7096d 100644
--- a/lib/resources/docs.ts
+++ b/lib/resources/docs.ts
@@ -1,13 +1,6 @@
import { readFSItems } from "#/lib/docs/mod_server.ts";
-import { Renderer } from "@deno/gfm";
export const { items, contents, nodes } = await readFSItems({
root: "./docs",
isIndex: (suffix) => suffix.startsWith("00_"),
- renderOptions: {
- // TODO: Reference
- // https://github.com/denoland/fresh/blob/main/www/utils/markdown.ts
- //
- renderer: new Renderer(),
- },
});
diff --git a/static/global.css b/static/global.css
index 976f9f8..1c009cc 100644
--- a/static/global.css
+++ b/static/global.css
@@ -29,6 +29,7 @@ nav ul {
main {
grid-area: main;
padding: 0 0.7em;
+ min-height: 95vh;
}
aside {
From a20df34ec2ca39b1125a166b32e303e3dbe48ecd Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 22:07:01 -0700
Subject: [PATCH 26/34] Update fs.ts
---
lib/docs/fs.ts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/docs/fs.ts b/lib/docs/fs.ts
index a65990c..8f8a355 100644
--- a/lib/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -66,6 +66,10 @@ export async function readFSItems(
// TODO: First extract possible name override from front matter.
const name = options.isIndex?.(path.name) ? [] : [path.name];
+ // TODO: Text-manip toc to be used as sidenav.
+ // https://github.com/cmaas/markdown-it-table-of-contents?tab=readme-ov-file#full-example-with-unusual-headline-order
+ //
+
// If the path has a directory, add it to the name.
if (path.dir !== "") {
// https://discord.com/channels/684898665143206084/684898665151594506/1217030758686785556
From 81d7436cc89b793417fbb17859ef565e41ef8eb6 Mon Sep 17 00:00:00 2001
From: EthanThatOneKid <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Tue, 26 Mar 2024 01:30:18 -0700
Subject: [PATCH 27/34] fix toc component
---
components/doc/doc_content.tsx | 30 +++++++++------
components/foot.tsx | 2 +-
components/nav.tsx | 21 ++++++++++-
components/toc.tsx | 41 ++++++---------------
docs/{99_view_on_github.md => 99_github.md} | 0
routes/_app.tsx | 9 +----
routes/playgrounds/[id].tsx | 17 ++++++---
static/global.css | 2 +-
8 files changed, 64 insertions(+), 58 deletions(-)
rename docs/{99_view_on_github.md => 99_github.md} (100%)
diff --git a/components/doc/doc_content.tsx b/components/doc/doc_content.tsx
index d5db07b..f85764d 100644
--- a/components/doc/doc_content.tsx
+++ b/components/doc/doc_content.tsx
@@ -26,18 +26,24 @@ export interface DocContentProps {
export default function DocContent(props: DocContentProps) {
return (
<>
-
-
- {props.playground && (
-
- )}
+
+
+
+
+ {props.playground && (
+
+ )}
+
>
);
}
diff --git a/components/foot.tsx b/components/foot.tsx
index f3177cd..5290909 100644
--- a/components/foot.tsx
+++ b/components/foot.tsx
@@ -2,7 +2,7 @@
* Foot is the site footer.
*/
export default function Foot(
- props: { year: number } = { year: new Date().getFullYear() },
+ props: { year?: number } = { year: new Date().getFullYear() },
) {
return (
jsonx
+Meet jsonx.
Meet jsonx.
-
+ {props.summary}
+
+ {props.children}
+ 404 - Page not found
The page you were looking for doesn't exist.
diff --git a/routes/_app.tsx b/routes/_app.tsx
index eb9293d..aea0eb3 100644
--- a/routes/_app.tsx
+++ b/routes/_app.tsx
@@ -1,5 +1,6 @@
import type { PageProps } from "$fresh/server.ts";
-import Nav, { toPath } from "#/components/nav.tsx";
+import { toPath } from "#/lib/to_path.ts";
+import Nav from "#/components/nav.tsx";
export default function App({ Component, route }: PageProps) {
return (
diff --git a/routes/index.tsx b/routes/index.tsx
deleted file mode 100644
index d4a722e..0000000
--- a/routes/index.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { contents } from "#/lib/resources/docs.ts";
-import Doc from "#/components/doc.tsx";
-import { getMeta } from "#/lib/meta/mod.ts";
-
-export default async function Home(_request: Request) {
- const html = contents.get("")!.html;
- const meta = await getMeta();
- // TODO: wip.
- return
${html}
`;
+ },
+});
diff --git a/lib/resources/docs.ts b/lib/resources/docs.ts
index be380d7..4b7096d 100644
--- a/lib/resources/docs.ts
+++ b/lib/resources/docs.ts
@@ -1,13 +1,6 @@
import { readFSItems } from "#/lib/docs/mod_server.ts";
-import { Renderer } from "@deno/gfm";
export const { items, contents, nodes } = await readFSItems({
root: "./docs",
isIndex: (suffix) => suffix.startsWith("00_"),
- renderOptions: {
- // TODO: Reference
- // https://github.com/denoland/fresh/blob/main/www/utils/markdown.ts
- //
- renderer: new Renderer(),
- },
});
diff --git a/static/global.css b/static/global.css
index 976f9f8..1c009cc 100644
--- a/static/global.css
+++ b/static/global.css
@@ -29,6 +29,7 @@ nav ul {
main {
grid-area: main;
padding: 0 0.7em;
+ min-height: 95vh;
}
aside {
From a20df34ec2ca39b1125a166b32e303e3dbe48ecd Mon Sep 17 00:00:00 2001
From: Ethan Davidson <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Mon, 25 Mar 2024 22:07:01 -0700
Subject: [PATCH 26/34] Update fs.ts
---
lib/docs/fs.ts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/docs/fs.ts b/lib/docs/fs.ts
index a65990c..8f8a355 100644
--- a/lib/docs/fs.ts
+++ b/lib/docs/fs.ts
@@ -66,6 +66,10 @@ export async function readFSItems(
// TODO: First extract possible name override from front matter.
const name = options.isIndex?.(path.name) ? [] : [path.name];
+ // TODO: Text-manip toc to be used as sidenav.
+ // https://github.com/cmaas/markdown-it-table-of-contents?tab=readme-ov-file#full-example-with-unusual-headline-order
+ //
+
// If the path has a directory, add it to the name.
if (path.dir !== "") {
// https://discord.com/channels/684898665143206084/684898665151594506/1217030758686785556
From 81d7436cc89b793417fbb17859ef565e41ef8eb6 Mon Sep 17 00:00:00 2001
From: EthanThatOneKid <31261035+EthanThatOneKid@users.noreply.github.com>
Date: Tue, 26 Mar 2024 01:30:18 -0700
Subject: [PATCH 27/34] fix toc component
---
components/doc/doc_content.tsx | 30 +++++++++------
components/foot.tsx | 2 +-
components/nav.tsx | 21 ++++++++++-
components/toc.tsx | 41 ++++++---------------
docs/{99_view_on_github.md => 99_github.md} | 0
routes/_app.tsx | 9 +----
routes/playgrounds/[id].tsx | 17 ++++++---
static/global.css | 2 +-
8 files changed, 64 insertions(+), 58 deletions(-)
rename docs/{99_view_on_github.md => 99_github.md} (100%)
diff --git a/components/doc/doc_content.tsx b/components/doc/doc_content.tsx
index d5db07b..f85764d 100644
--- a/components/doc/doc_content.tsx
+++ b/components/doc/doc_content.tsx
@@ -26,18 +26,24 @@ export interface DocContentProps {
export default function DocContent(props: DocContentProps) {
return (
<>
-