Skip to content

Commit c4441f6

Browse files
authored
docs: change docs rendering and split up markdown files (#290)
1 parent 89fd832 commit c4441f6

34 files changed

+635
-528
lines changed

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"compilerOptions": {
33
"jsx": "react-jsx",
44
"jsxImportSource": "npm:preact"
5-
}
5+
},
66
"tasks": {
77
"bundle": "deno run --unstable -A ./bundle.ts",
88
"lume": "echo \"import 'lume/cli.ts'\" | deno run --unstable -A -",

web/_components/nav.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default ({ title, href, currentUrl, nav }) => {
2+
const menu = nav.menu(href);
3+
const showChildren = currentUrl.includes(href) && menu.children.length > 0;
4+
return (
5+
<>
6+
<h5><a href={href}>{title}</a></h5>
7+
{showChildren && <div><ul>{menu.children.map(child => <li><a href={child.data.url}>{child.data.title}</a></li>)}</ul></div>}
8+
</>
9+
);
10+
}

web/_includes/layouts/docs.tsx

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,28 @@ export const title = "Docs";
22
export const active = "docs";
33
export const heading = "Documentation";
44
export const layout = "layouts/default.tsx";
5-
export default ({toc, url, children, comp}) => (
6-
<section>
7-
<div class="row justify-center items-start sm:stack" style="gap: var(--16);">
8-
<nav style="flex: none; min-width: 256px;">
9-
<h5><a href="/docs/quickstart">Quickstart</a></h5>
10-
{(url==="/docs/quickstart/") && <div dangerouslySetInnerHTML={{"__html": comp.toc({toc}) }} />}
11-
<h5><a href="/docs/user">User Guide</a></h5>
12-
{(url==="/docs/user/") && <div dangerouslySetInnerHTML={{"__html": comp.toc({toc}) }} />}
13-
<h5><a href="/docs/dev">Developer Guide</a></h5>
14-
{(url==="/docs/dev/") && <div dangerouslySetInnerHTML={{"__html": comp.toc({toc}) }} />}
15-
<h5><a href="/docs/project">Project Guide</a></h5>
16-
{(url==="/docs/project/") && <div dangerouslySetInnerHTML={{"__html": comp.toc({toc}) }} />}
17-
</nav>
18-
<article class="grow">
19-
{children}
20-
</article>
21-
</div>
22-
</section>
23-
)
5+
export default ({url, nav, comp, children}) => {
6+
const header = () => {
7+
if (url.includes('/docs/quickstart')) return 'Quickstart';
8+
if (url.includes('/docs/user')) return 'User Guide';
9+
if (url.includes('/docs/dev')) return 'Developer Guide';
10+
if (url.includes('/docs/project')) return 'Project Guide';
11+
return 'Documentation';
12+
};
13+
return (
14+
<section>
15+
<div class="row justify-center items-start sm:stack" style="gap: var(--16);">
16+
<nav style="flex: none; min-width: 256px;">
17+
<comp.Nav title="Quickstart" href="/docs/quickstart/" currentUrl={url} nav={nav} />
18+
<comp.Nav title="User Guide" href="/docs/user/" currentUrl={url} nav={nav} />
19+
<comp.Nav title="Developer Guide" href="/docs/dev/" currentUrl={url} nav={nav} />
20+
<comp.Nav title="Project Guide" href="/docs/project/" currentUrl={url} nav={nav} />
21+
</nav>
22+
<article class="grow">
23+
<h1>{header()}</h1>
24+
{children}
25+
</article>
26+
</div>
27+
</section>
28+
)
29+
}

web/docs/dev.md

Lines changed: 0 additions & 133 deletions
This file was deleted.

web/docs/dev/1-overview.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: Overview
4+
---
5+
## Overview
6+
7+
Treehouse is a frontend written in TypeScript made to be rendered in a browser or webview for building note-taking and information management tools. It is a "thick" frontend in that it holds most application state in-memory and executes user triggered commands to mutate that state. Persistence of that state, and a few other features, are expected to be provided by a "backend", which the frontend code interacts with via a backend adapter.
8+
Even without a backend adapter, the Treehouse frontend is still a fully functional application packaged as a JavaScript library that can be loaded onto any HTML page.
9+
10+
### Architecture
11+
12+
The library exposes a `setup()` function that:
13+
14+
1. Takes a DOM document and backend adapter object
15+
1. Sets up a central controller for the UI called Workbench
16+
1. Loads a Workspace using the backend adapter
17+
1. Registers built-in commands and keybindings
18+
1. Uses [Mithril.js](https://mithril.js.org/) to mount a top level Mithril component to the document
19+
20+
The UI is represented by a class called Workbench. This class orchestrates and provides most of the API for the rest of the system. The UI is broken down into Mithril components that implement the views for each part of the UI, pulling state from Workbench and connecting interactions to registered commands that represent all user actions. The Workbench and commands manipulate a Workspace, which represents the main data model for the system.
21+
22+
### Stack
23+
24+
To avoid the complexity and dependency hell, Treehouse avoids most common JavaScript tooling such as Node.js and NPM. Instead, Treehouse uses [Deno](https://deno.land/) as a toolchain and otherwise avoids dependencies as much as possible. The other main dependency we have is [Mithril.js](https://mithril.js.org/), which was chosen for its simplicity and lack of further dependencies.
25+
26+
That said, there are other dependencies beyond this core stack which are chosen very deliberately. Out of the box search indexing depends on [MiniSearch](https://lucaong.github.io/minisearch/), and our most complex (but unavoidable) dependency is [CodeMirror](https://codemirror.net/). We're very conscious of project dependencies, including development and toolchain dependencies.

web/docs/dev/2-data-model.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: Data Model
4+
---
5+
## Data Model
6+
7+
The "document" for Treehouse is the Workspace, which is mostly a container for nodes. These nodes are based on a versatile and extensible API and data model called Manifold. In short, nodes:
8+
9+
* have a unique ID
10+
* have a text name
11+
* can be children to other nodes
12+
* can have key-value attributes
13+
* can have components
14+
15+
Most importantly, nodes build a tree-like structure where each node can be extended with components. Components extend the state and functionality of a node. For example, a checkbox component can be added to a node. This gives it a state (checked or not) and allows the UI to render it differently (add a checkbox).

web/docs/dev/3-user-actions.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: User Actions
4+
---
5+
## User Actions
6+
7+
All user performable actions are modeled as commands and registered with a command system. Commands are functions with some extra metadata, like a user displayable name and system identifier. They can be called throughout the system by their system identifier, such as when a user clicks a something.
8+
9+
Menus are often defined upfront, usually by commands. Commands can have keybindings registered for them for keyboard shortcuts. These systems work together. For example, a menu item for a command will show the keybinding for it.
10+
11+
Commands can take arguments and usually take at least a single argument called a context. This is a way to represent state of the user’s current context, such as the currently selected node.
12+
13+
In addition to menus, keyboard shortcuts, and UI event handlers, there is a command palette the user can trigger to show all commands that can be run in the current context.

web/docs/dev/4-workbench-ui.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: Workbench UI
4+
---
5+
## Workbench UI
6+
7+
### Components
8+
9+
The workbench UI is made up of Mithril components, which are similar to React components. They take parameters, can have state, and specify a view using JSX. Instead of many atomic components like buttons and labels, Treehouse focuses on larger functional components that map to areas of the UI. Reusable visual elements are represented by CSS classes. Only if a reusable atomic visual element becomes so re-used and is too complex to re-implement is it made into a Mithril component.
10+
11+
All the Mithril components can be found under `lib/ui`. We use Typescript to make sure their parameters are typed so they're picked up by API documentation; no need for custom documentation for view components. Mithril components are just plain old JavaScript objects with a `view` method.
12+
13+
### User Context
14+
15+
Most components are explicitly passed a reference to the Workbench, which they can use to execute commands or pull data in the current Workspace or Context. The Workbench provides a top level context that has the current selected node or nodes, the current panel, etc. However, when passing a Context around it can be given overrides. For example, you may be currently editing a particular node, but you use the mouse to perform a command on another node. The menu ensures the command will receive a Context with that node being acted on.
16+
17+
### Design System
18+
19+
Our design system is inspired by projects like [Pollen](https://www.pollen.style/), where instead of generating CSS classes from JavaScript like Tailwind (which requires a compile step and Node.js based tooling), we simply use and override CSS custom properties. This means they can be used in inline styles as well. We also have a subset of common Tailwind utility classes defined, though using the custom properties.

web/docs/dev/5-backend-adapters.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: Backend Adapters
4+
---
5+
## Backend Adapters
6+
7+
Backend adapters are classes that implement the backend API for a given backend. If you wanted to make your own custom backend, you would implement your own backend adapter
8+
implementing the APIs you wish to hook into and pass that into the `setup` function when initializing Treehouse. We also have a handful of built-in adapters for public or
9+
well-known backend interfaces:
10+
11+
### lib/backend/browser.ts
12+
13+
This backend implements the FileStorage API using localStorage. This means data will be stored in the browser for a particular device. It also implements search indexing
14+
using MiniSearch. It does not implement the Authenticator API.
15+
16+
### lib/backend/github.ts
17+
18+
This backend implements the FileStorage API using the GitHub API to store data in a GitHub hosted Git repository. It also implements the Authenticator API against a
19+
script that can be hosted on CloudFlare Workers that implements an OAuth client for the GitHub API. This backend adapter does not implement a search index, it simply
20+
uses the browser implementation (MiniSearch).
21+
22+
### lib/backend/filesystem.ts (coming soon)
23+
24+
This backend implements the FileStorage API using a local filesystem. Since there isn't a good standard filesystem API in browsers, this implementation operates against
25+
a simple REST API that can be implemented by a backend host process, such as Electron, Apptron, or something custom.
26+
27+
### Writing an Adapter
28+
29+
An adapter is just an object that implements this API:
30+
31+
```js
32+
interface Backend {
33+
auth: Authenticator|null;
34+
index: SearchIndex;
35+
files: FileStore;
36+
}
37+
38+
interface Authenticator {
39+
login();
40+
logout();
41+
currentUser(): User|null;
42+
}
43+
44+
interface User {
45+
userID(): string;
46+
displayName(): string;
47+
avatarURL(): string;
48+
}
49+
50+
interface SearchIndex {
51+
index(node: RawNode);
52+
remove(id: string);
53+
search(query: string): string[];
54+
}
55+
56+
interface FileStore {
57+
async readFile(path: string): string|null;
58+
async writeFile(path: string, contents: string);
59+
}
60+
```
61+
62+
The Authenticator API is optional (and soon so might the SearchIndex API, always defaulting to MiniSearch). Typically a backend adapter will
63+
set `auth`, `index`, and `files` to `this` and implement each of those interfaces on that same object.

web/docs/dev/6-api-reference.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
layout: layouts/docs.tsx
3+
title: API Reference
4+
---
5+
## API Reference
6+
7+
TypeScript documentation for Treehouse is available via [Deno Land](https://deno.land/x/treehouse@0.1.0).

0 commit comments

Comments
 (0)