Skip to content

Commit 65020f5

Browse files
committed
feat: added markdown alternate support
1 parent 336c5f4 commit 65020f5

19 files changed

Lines changed: 200 additions & 96 deletions

File tree

apps/site/pages/components/open.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: Open Component
3+
---
4+
5+
6+
The `open` component is a component that permits to open:
7+
8+
* alternate version of your pages such as [Markdown](../reference/ai.md#markdown-format-for-all-pages)
9+
* your page in an `agent`
10+

apps/site/pages/reference/ai.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: AI Agent Support
3+
---
4+
5+
## Markdown format for all pages
6+
7+
All [pages](page.md) gets by default a Markdown version.
8+
9+
The Markdown version can be asked:
10+
11+
* by adding tne `md` at the end of the URL path
12+
* by setting the `accept` request header to `text/markdown`
13+
14+
The elements that have the class `print:hidden` are not part of the output.
15+
16+
Every HTML page announces this alternate version in a link head element:
17+
18+
Example:
19+
20+
```html
21+
<link rel="alternate" type="text/markdown" href="/index.md">
22+
```
23+
24+
This alternate version is then used by the [Open Component](../components/open.md)
25+
26+
The [static server generation](build.md#static-server-generation) generates also the Markdown version

apps/site/pages/reference/build.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,10 @@ Example:
1515
"build": "interact favicon && interact build"
1616
}
1717
}
18-
```
18+
```
19+
20+
## Static Server Generation
21+
22+
On static server generation, an alternate markdown version
23+
is also generated for [AI agent consumption](ai.md#markdown-format-for-all-pages).
24+

apps/site/pages/reference/markdown.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ We support the following 2 Markdown files type:
1818
They all share the common [Markdown syntax](markdown-syntax.md)
1919

2020
Note that you can add support for more with [unified plugins](remark-rehype-unified.md).
21-
By [default](remark-rehype-unified.md#default), we apply the [Remark Gfm](https://github.com/remarkjs/remark-gfm) plugin to add
21+
By [default](remark-rehype-unified.md#default), we apply the [Remark Gfm](https://github.com/remarkjs/remark-gfm) plugin
22+
to add
2223
the [GitHub Syntax](https://github.github.com/gfm/)
2324

2425
### Custom components
@@ -34,3 +35,8 @@ They are recognized by the [2 Markdown file types](#file-types)
3435
You can change how Markdown is parsed with [remark and rehype plugins](remark-rehype-unified.md).
3536

3637
The plugins are applied to all Markdown files.
38+
39+
### AI Agent Support
40+
41+
We also create Markdown version of every pages for consumption by [Ai Agent](ai.md#markdown-format-for-all-pages).
42+

apps/site/pages/reference/remark-rehype-unified.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,12 @@ To define the location of the configuration file, you can:
7171
the [root](directory-layout.md)
7272
* or set the value in the `markdown.configImportPath` of the [configuration file](conf.md). If the value starts with a
7373
`.`, it's considered a path from the [root directory](directory-layout.md) otherwise, it's considered a module name to
74-
be searched from `nodes_modules`
74+
be searched from `nodes_modules`
75+
76+
## Usage
77+
78+
They are used:
79+
80+
* when reading [markdown page](markdown.md)
81+
* but also when writing [markdown page for agents](ai.md#markdown-format-for-all-pages)
82+

src/interact/componentsProvider/contextProps.d.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
// don't use the relative path (not resolved)
22
import type {FinalPage} from "../pages/interactPage.js";
33

4-
// Parsed request information used to route between RSC/SSR rendering.
5-
// Created by parseRenderRequest() from incoming HTTP requests.
6-
export type RscProps = {
7-
isRsc: boolean // true if request should return RSC payload (via _.rsc suffix)
8-
isAction: boolean // true if this is a server action call (POST request)
9-
actionId?: string // server action ID from x-rsc-action header
10-
}
114

125
/**
136
* The context request props
@@ -20,7 +13,14 @@ export type ContextProps = {
2013
request: Request, // the original request
2114
// the routing normalized URL (with _.rsc suffix removed, no base, rewrite url, host may be fake)
2215
url: URL
23-
rsc: RscProps
16+
// derived information
17+
meta: {
18+
isRsc: boolean // true if request should return RSC payload (via _.rsc suffix)
19+
isRscAction: boolean // true if this is a server action call (POST request)
20+
rscActionId?: string // server action ID from x-rsc-action header
21+
isMarkdown: boolean // true if this is a Markdown request
22+
lastModified?: string; // last time modified (iso string)
23+
} & Record<string, string | boolean | undefined>
2424
response: {
2525
status?: number
2626
headers?: HeadersInit;

src/interact/config/configSchema.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,7 @@ const Header = BaseComponentSchema.extend({
308308

309309
const ComponentsConfigSetSchema = z.object({
310310
Header: Header.optional(),
311-
Toc: TocSchema.optional(),
312-
NotFound: BaseComponentSchema.optional(),
311+
Toc: TocSchema.optional()
313312
}).catchall(BaseComponentSchema); // unknown keys fall back to base schema
314313

315314

@@ -321,6 +320,8 @@ const handlerConfigSchema = z.object({
321320

322321
const MiddlewaresSchema = z.object({
323322
pipeline: z.array(handlerConfigSchema).describe("A list of middlewares").default([]),
323+
// 404 is the default for GitHub
324+
// https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-custom-404-page-for-your-github-pages-site
324325
notFoundPath: z.string().describe("The page returned if no middleware answers the request").default("/404"),
325326
}).describe("Middleware Properties");
326327

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {visit, SKIP} from 'unist-util-visit';
2+
import type {Root} from "hast";
3+
4+
5+
/**
6+
* Unified rehype plugin that removes elements with the class "print:hidden"
7+
*/
8+
export default function rehypeRemoveNoPrint() {
9+
return (tree: Root) => {
10+
visit(tree, 'element', (node, index, parent) => {
11+
if (!parent || index == null) return;
12+
13+
const classes = node.properties?.["className"];
14+
const hasNoPrint = Array.isArray(classes)
15+
? classes.includes('print:hidden')
16+
: typeof classes === 'string' && classes.split(' ').includes('print:hidden');
17+
18+
if (hasNoPrint) {
19+
parent.children.splice(index, 1);
20+
return [SKIP, index]; // don't descend, and re-check current index
21+
}
22+
});
23+
};
24+
}

src/interact/pages/interactPage.d.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,13 @@ export type Frontmatter = {
3131
lang?: string;
3232
} & Record<string, string | undefined>
3333

34-
/**
35-
* Derived meta
36-
*/
37-
export type Derived = {
38-
// iso string
39-
lastModified?: string;
40-
} & Record<string, string | undefined>
4134

4235
/**
4336
* The page meta
4437
*/
4538
export type PageMeta<F = unknown, D = unknow> = {
4639
frontmatter?: F & Frontmatter;
4740
toc?: TocNode[];
48-
derived?: D & Derived
4941
};
5042

5143
/**

src/interact/tsconfig.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
44
"moduleResolution": "NodeNext",
5-
"module": "NodeNext"
5+
"module": "NodeNext",
6+
// needed because ssg uses the type of the generated entry.rsc.tsx
7+
// not needed otherwise it will check go into the resources directory
8+
// "jsx": "react-jsx"
69
},
710
"include": [
811
"**/*",

0 commit comments

Comments
 (0)