Skip to content

Commit

Permalink
Don't load all docs just to render the sidebar.
Browse files Browse the repository at this point in the history
In order to render 1 doc, you need to load them all. This is because
the `title` attribute of each guide is stored inside the doc itself
within the YAML frontmatter. Which means in order to render the title
in the side bar, you have to load and parse all of the the documents.

This pops the title into `structure.json`. That way, we can construct
all the doc metadata without ever having to load or parse anything but
the document that is being requested.

This actually simplifies things considerably, as we can now hang the
list of topics on the doc itself which means no need for a separate
`getTopics()` operation, and no need to maintain a document context.
  • Loading branch information
cowboyd committed Nov 7, 2023
1 parent 9c0a21a commit 214a6ed
Show file tree
Hide file tree
Showing 18 changed files with 71 additions and 202 deletions.
64 changes: 0 additions & 64 deletions www/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions www/docs/actions.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Actions and Suspensions
---

In this section, we'll cover the first two fundamental operations in Effection:
`suspend()` and `action()`, and how we can use them in tandem to serve as a safe
alternative to the [Promise constructor][promise-constructor].
Expand Down
4 changes: 0 additions & 4 deletions www/docs/collections.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Streams and Subscriptions
---

For every tool in the `async/await` toolbox, there is an equilavent in
Effection. We were already introduced to the most important of these in
[the introduction][introduction].
Expand Down
115 changes: 52 additions & 63 deletions www/docs/docs.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import { createContext, all, call, spawn, type Operation, type Task } from "effection";
import { call, spawn, type Operation, type Task } from "effection";
import structure from "./structure.json" assert { type: "json" };

import { basename } from "https://deno.land/[email protected]/path/posix/basename.ts";

import remarkFrontmatter from "npm:[email protected]";
import remarkMdxFrontmatter from "npm:[email protected]";
import remarkGfm from "npm:[email protected]";
import rehypePrismPlus from "npm:[email protected]";

import { evaluate } from "npm:@mdx-js/[email protected]";

import { Fragment, jsx, jsxs } from "hastx/jsx-runtime";

export const Docs = createContext<Docs>("docs");
export const useDocs = () => Docs;

export interface DocModule {
default: () => JSX.Element;
frontmatter: {
Expand All @@ -24,22 +19,25 @@ export interface DocModule {
}

export interface Docs {
getTopics(): Operation<Topic[]>;
getDoc(id?: string): Operation<Doc | undefined>;
}

export interface Topic {
name: string;
items: Doc[];
items: DocMeta[];
}

export interface Doc {
export interface DocMeta {
id: string;
title: string;
MDXContent: () => JSX.Element;
filename: string;
nextId?: string;
previousId?: string;
topics: Topic[];
next?: DocMeta;
prev?: DocMeta;
}

export interface Doc extends DocMeta {
MDXContent: () => JSX.Element;
}

export function* loadDocs(): Operation<Docs> {
Expand All @@ -48,63 +46,54 @@ export function* loadDocs(): Operation<Docs> {

let entries = Object.entries(structure);

let topics = entries.map(([name]) => ({ name, items: []}) as Topic)

let topicsByName = new Map<string, Topic>(topics.map(topic => [topic.name, topic]));

let files = entries.flatMap(([topicName, files]) => {
return files.map((filename, topicIndex) => ({ topicName, topicIndex, filename, id: basename(filename, ".mdx") }));
})

for (let i = 0; i < files.length; i++ ) {
let file = files[i];
let nextId = files[i + 1]?.id;
let previousId = files[i - 1]?.id;
let { topicName, topicIndex, filename, id } = file;
let location = new URL(filename, import.meta.url);

loaders.set(id, yield* spawn(function*() {
let source = yield* call(Deno.readTextFile(location));
let mod = yield* call(evaluate(source, {
jsx,
jsxs,
jsxDEV: jsx,
Fragment,
remarkPlugins: [
remarkFrontmatter,
remarkMdxFrontmatter,
remarkGfm,
],
rehypePlugins: [
[rehypePrismPlus, { showLineNumbers: true }],
],
}));
let topics: Topic[] = [];

let { title } = mod.frontmatter as { id: string; title: string };
for (let [name, contents] of entries) {
let topic: Topic = { name, items: [] };
topics.push(topic);

let doc: Doc = {
id,
nextId,
previousId,
let current: DocMeta | undefined = void(0);
for (let i = 0; i < contents.length; i++) {
let prev: DocMeta | undefined = current;
let [filename, title] = contents[i];
let meta: DocMeta = current = {
id: basename(filename, ".mdx"),
title,
filename,
MDXContent: () => mod.default({}),
} as Doc;

let topic = topicsByName.get(topicName);

topic!.items[topicIndex] = doc;

return doc;
}));
topics,
prev
};
if (prev) {
prev.next = current;
}
topic.items.push(current);

loaders.set(meta.id, yield* spawn(function*() {
let location = new URL(filename, import.meta.url);
let source = yield* call(Deno.readTextFile(location));
let mod = yield* call(evaluate(source, {
jsx,
jsxs,
jsxDEV: jsx,
Fragment,
remarkPlugins: [
remarkGfm,
],
rehypePlugins: [
[rehypePrismPlus, { showLineNumbers: true }],
],
}));

return {
...meta,
MDXContent: () => mod.default({}),
} as Doc;

}));
}
}

return yield* Docs.set({
*getTopics() {
yield* all([...loaders.values()]);
return topics;
},
return {
*getDoc(id) {
if (id) {
let task = loaders.get(id);
Expand All @@ -113,5 +102,5 @@ export function* loadDocs(): Operation<Docs> {
}
}
},
});
};
}
4 changes: 0 additions & 4 deletions www/docs/errors.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Errors
---

We have previously discussed how correctness and proper handling of failure
cases is why we wrote Effection in the first place. In this chapter we will
take a more in-depth look at how Effection handles failures and how you can
Expand Down
4 changes: 0 additions & 4 deletions www/docs/events.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Events
---

Asynchronous code often needs to interact with evented code. Using
`async/await` this can be quite challenging. Evented code often needs
to be synchronous, because the timing of when to subscribe and
Expand Down
4 changes: 0 additions & 4 deletions www/docs/inspector.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Inspector
---

>⚠️ These docs have not been updated from version 2 of Effection, and do not
> apply to version 3. The information you find here may be of use, but may
> also be outdated or misleading.
Expand Down
4 changes: 0 additions & 4 deletions www/docs/introduction.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Introduction
---

## Why use Effection?

JavaScript has gone through multiple evolutionary steps in how to deal
Expand Down
4 changes: 0 additions & 4 deletions www/docs/operations.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Operations
---

In the introduction, we saw how to replace `async/await` by writing equivalent
code in Effection. We can do this because there are strong analogues between the
way both systems work. However, there are also two key differences that
Expand Down
4 changes: 0 additions & 4 deletions www/docs/processes.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Spawning processes
---

>⚠️ These docs have not been updated from version 2 of Effection, and do not
> apply to version 3. The information you find here may be of use, but may
> also be outdated or misleading.
Expand Down
4 changes: 0 additions & 4 deletions www/docs/resources.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Resources
---

The third fundamental Effection operation is [`resource()`][resource]. It can
seem a little complicated at first, but the reason for its existence is
rather simple. Sometimes there are operations which meet the following criteria:
Expand Down
4 changes: 0 additions & 4 deletions www/docs/scope.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Scope
---

We have talked about how Effection operations allow you to bundle setup and
teardown as a unit so that automatic cleanup is _guaranteed_, but how are
they able to do this, and how can you implement your own operations that clean
Expand Down
4 changes: 0 additions & 4 deletions www/docs/spawn.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
title: Spawn
---

Suppose we are using the `fetchWeekDay` function from the introduction to fetch the current weekday in multiple timezones:

``` javascript
Expand Down
Loading

0 comments on commit 214a6ed

Please sign in to comment.