@open-agent-toolkit/docs-transforms 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @open-agent-toolkit/docs-transforms
2
+
3
+ Remark plugins and default transform bundle for OAT-powered Fumadocs apps.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @open-agent-toolkit/docs-transforms
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import {
15
+ defaultTransforms,
16
+ remarkLinks,
17
+ remarkMermaid,
18
+ remarkTabs,
19
+ } from '@open-agent-toolkit/docs-transforms';
20
+
21
+ export const remarkPlugins = defaultTransforms;
22
+
23
+ export const customRemarkPlugins = [remarkLinks, remarkTabs, remarkMermaid];
24
+ ```
25
+
26
+ ## Exports
27
+
28
+ - `defaultTransforms`
29
+ - `remarkLinks`
30
+ - `remarkMermaid`
31
+ - `remarkTabs`
@@ -0,0 +1,7 @@
1
+ import type { Root } from 'mdast';
2
+ import type { Plugin } from 'unified';
3
+ export { remarkLinks } from './remark-links.js';
4
+ export { remarkMermaid } from './remark-mermaid.js';
5
+ export { remarkTabs } from './remark-tabs.js';
6
+ export declare const defaultTransforms: Plugin<[], Root>[];
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,EAI/C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ import { remarkLinks } from './remark-links.js';
2
+ import { remarkMermaid } from './remark-mermaid.js';
3
+ import { remarkTabs } from './remark-tabs.js';
4
+ export { remarkLinks } from './remark-links.js';
5
+ export { remarkMermaid } from './remark-mermaid.js';
6
+ export { remarkTabs } from './remark-tabs.js';
7
+ export const defaultTransforms = [
8
+ remarkLinks,
9
+ remarkTabs,
10
+ remarkMermaid,
11
+ ];
@@ -0,0 +1,20 @@
1
+ import type { Root } from 'mdast';
2
+ import type { Plugin } from 'unified';
3
+ /**
4
+ * Remark plugin that rewrites relative `.md` links to extensionless paths
5
+ * for Fumadocs routing.
6
+ *
7
+ * URL rewriting:
8
+ * - `quickstart.md` → `./quickstart`
9
+ * - `cli/index.md` → `./cli`
10
+ * - `../reference/index.md` → `../reference`
11
+ * - Absolute URLs and anchors are left unchanged.
12
+ *
13
+ * Display text cleanup:
14
+ * - When a link's only child is an `inlineCode` node whose value looks like
15
+ * a `.md` path (e.g., `` [`cli/index.md`](cli/index.md) ``), the extension
16
+ * is stripped from the display text too, keeping the raw markdown AI-navigable
17
+ * while rendering clean labels on the web.
18
+ */
19
+ export declare const remarkLinks: Plugin<[], Root>;
20
+ //# sourceMappingURL=remark-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remark-links.d.ts","sourceRoot":"","sources":["../src/remark-links.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,IAAI,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAsBtC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CAuCxC,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { visit } from 'unist-util-visit';
2
+ /**
3
+ * Strip `.md` extension and collapse `/index` from a relative path.
4
+ * Returns null if the path is not a `.md` link that should be rewritten.
5
+ */
6
+ function cleanMdPath(raw) {
7
+ if (!raw.endsWith('.md'))
8
+ return null;
9
+ let cleaned = raw.slice(0, -3);
10
+ if (cleaned.endsWith('/index')) {
11
+ cleaned = cleaned.slice(0, -'/index'.length) || '.';
12
+ }
13
+ if (cleaned === 'index') {
14
+ cleaned = '.';
15
+ }
16
+ return cleaned;
17
+ }
18
+ /**
19
+ * Remark plugin that rewrites relative `.md` links to extensionless paths
20
+ * for Fumadocs routing.
21
+ *
22
+ * URL rewriting:
23
+ * - `quickstart.md` → `./quickstart`
24
+ * - `cli/index.md` → `./cli`
25
+ * - `../reference/index.md` → `../reference`
26
+ * - Absolute URLs and anchors are left unchanged.
27
+ *
28
+ * Display text cleanup:
29
+ * - When a link's only child is an `inlineCode` node whose value looks like
30
+ * a `.md` path (e.g., `` [`cli/index.md`](cli/index.md) ``), the extension
31
+ * is stripped from the display text too, keeping the raw markdown AI-navigable
32
+ * while rendering clean labels on the web.
33
+ */
34
+ export const remarkLinks = function remarkLinks() {
35
+ return (tree) => {
36
+ visit(tree, 'link', (node) => {
37
+ const { url } = node;
38
+ // Skip absolute URLs, protocol links, and pure anchors
39
+ if (/^[a-z]+:/i.test(url) || url.startsWith('#')) {
40
+ return;
41
+ }
42
+ // Split off any anchor fragment
43
+ const hashIndex = url.indexOf('#');
44
+ const path = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
45
+ const fragment = hashIndex >= 0 ? url.slice(hashIndex) : '';
46
+ const cleaned = cleanMdPath(path);
47
+ if (cleaned === null)
48
+ return;
49
+ // With trailingSlash enabled, each page URL has an extra directory level
50
+ // (e.g., /guide/commands/ instead of /guide/commands), so ../ links need
51
+ // one additional ../ to reach the correct parent.
52
+ const adjusted = cleaned.startsWith('..') ? `../${cleaned}` : cleaned;
53
+ // Rewrite URL
54
+ const prefix = adjusted.startsWith('.') || adjusted.startsWith('/') ? '' : './';
55
+ node.url = prefix + adjusted + fragment;
56
+ // Clean display text when it's a single inlineCode child with a .md path
57
+ const firstChild = node.children[0];
58
+ if (node.children.length === 1 && firstChild?.type === 'inlineCode') {
59
+ const code = firstChild;
60
+ const cleanedText = cleanMdPath(code.value);
61
+ if (cleanedText !== null) {
62
+ code.value = cleanedText;
63
+ }
64
+ }
65
+ });
66
+ };
67
+ };
@@ -0,0 +1,13 @@
1
+ import type { Root } from 'mdast';
2
+ import type { Plugin } from 'unified';
3
+ /**
4
+ * Remark plugin that transforms fenced code blocks with `lang: "mermaid"`
5
+ * into `<Mermaid chart="...">` MDX JSX elements.
6
+ *
7
+ * Replaces literal `\n` sequences with `<br/>` since mermaid flowcharts
8
+ * use HTML break tags for line breaks within node labels.
9
+ *
10
+ * Paired with the `Mermaid` component from `@open-agent-toolkit/docs-theme` for client-side rendering.
11
+ */
12
+ export declare const remarkMermaid: Plugin<[], Root>;
13
+ //# sourceMappingURL=remark-mermaid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remark-mermaid.d.ts","sourceRoot":"","sources":["../src/remark-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,IAAI,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CA0B1C,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { visit } from 'unist-util-visit';
2
+ /**
3
+ * Remark plugin that transforms fenced code blocks with `lang: "mermaid"`
4
+ * into `<Mermaid chart="...">` MDX JSX elements.
5
+ *
6
+ * Replaces literal `\n` sequences with `<br/>` since mermaid flowcharts
7
+ * use HTML break tags for line breaks within node labels.
8
+ *
9
+ * Paired with the `Mermaid` component from `@open-agent-toolkit/docs-theme` for client-side rendering.
10
+ */
11
+ export const remarkMermaid = function remarkMermaid() {
12
+ return (tree) => {
13
+ visit(tree, 'code', (node, index, parent) => {
14
+ if (node.lang !== 'mermaid' || index === undefined || !parent) {
15
+ return;
16
+ }
17
+ const chart = node.value.replace(/\\n/g, '<br/>');
18
+ const jsxNode = {
19
+ type: 'mdxJsxFlowElement',
20
+ name: 'Mermaid',
21
+ attributes: [
22
+ {
23
+ type: 'mdxJsxAttribute',
24
+ name: 'chart',
25
+ value: chart,
26
+ },
27
+ ],
28
+ children: [],
29
+ data: { _mdxExplicitJsx: true },
30
+ };
31
+ parent.children[index] = jsxNode;
32
+ });
33
+ };
34
+ };
@@ -0,0 +1,4 @@
1
+ import type { Root } from 'mdast';
2
+ import type { Plugin } from 'unified';
3
+ export declare const remarkTabs: Plugin<[], Root>;
4
+ //# sourceMappingURL=remark-tabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remark-tabs.d.ts","sourceRoot":"","sources":["../src/remark-tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,IAAI,EAAe,MAAM,OAAO,CAAC;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAwCtC,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,CAyCvC,CAAC"}
@@ -0,0 +1,65 @@
1
+ import remarkParse from 'remark-parse';
2
+ import { unified } from 'unified';
3
+ const TAB_MARKER_RE = /^===\s+"(.+)"$/;
4
+ function extractTabTitle(node) {
5
+ if (node.type !== 'paragraph')
6
+ return null;
7
+ const paragraph = node;
8
+ const firstChild = paragraph.children[0];
9
+ if (!firstChild || firstChild.type !== 'text')
10
+ return null;
11
+ const match = TAB_MARKER_RE.exec(firstChild.value);
12
+ return match?.[1] ?? null;
13
+ }
14
+ function reparseContent(value) {
15
+ const tree = unified().use(remarkParse).parse(value);
16
+ return tree.children;
17
+ }
18
+ function createTabsElement(tabs) {
19
+ return {
20
+ type: 'mdxJsxFlowElement',
21
+ name: 'Tabs',
22
+ attributes: [],
23
+ children: tabs.map((tab) => ({
24
+ type: 'mdxJsxFlowElement',
25
+ name: 'Tab',
26
+ attributes: [
27
+ { type: 'mdxJsxAttribute', name: 'title', value: tab.title },
28
+ ],
29
+ children: tab.content,
30
+ })),
31
+ };
32
+ }
33
+ export const remarkTabs = () => (tree) => {
34
+ const newChildren = [];
35
+ let i = 0;
36
+ while (i < tree.children.length) {
37
+ const node = tree.children[i];
38
+ const title = extractTabTitle(node);
39
+ if (title === null) {
40
+ newChildren.push(node);
41
+ i++;
42
+ continue;
43
+ }
44
+ // Collect consecutive tabs into a group
45
+ const tabs = [];
46
+ while (i < tree.children.length) {
47
+ const current = tree.children[i];
48
+ const currentTitle = extractTabTitle(current);
49
+ if (currentTitle === null)
50
+ break;
51
+ i++; // advance past tab marker
52
+ // Check if next node is an indented code block (tab content)
53
+ const content = [];
54
+ if (i < tree.children.length && tree.children[i].type === 'code') {
55
+ const codeBlock = tree.children[i];
56
+ // Re-parse the code block value as markdown to restore original structure
57
+ content.push(...reparseContent(codeBlock.value));
58
+ i++;
59
+ }
60
+ tabs.push({ title: currentTitle, content });
61
+ }
62
+ newChildren.push(createTabsElement(tabs));
63
+ }
64
+ tree.children = newChildren;
65
+ };
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@open-agent-toolkit/docs-transforms",
3
+ "version": "0.0.10",
4
+ "private": false,
5
+ "description": "Remark/unified transforms for OAT documentation",
6
+ "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/docs-transforms",
7
+ "bugs": {
8
+ "url": "https://github.com/voxmedia/open-agent-toolkit/issues"
9
+ },
10
+ "license": "MIT",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/voxmedia/open-agent-toolkit.git",
14
+ "directory": "packages/docs-transforms"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "type": "module",
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ }
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc",
34
+ "clean": "rm -rf dist",
35
+ "check": "oxlint . && oxfmt --check .",
36
+ "check:fix": "oxlint --fix . && oxfmt .",
37
+ "format": "oxfmt --check .",
38
+ "format:fix": "oxfmt .",
39
+ "lint": "oxlint .",
40
+ "lint:fix": "oxlint --fix .",
41
+ "test": "vitest run",
42
+ "test:watch": "vitest",
43
+ "type-check": "tsc --noEmit"
44
+ },
45
+ "dependencies": {
46
+ "remark-parse": "^11.0.0",
47
+ "unified": "^11.0.5",
48
+ "unist-util-visit": "^5.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/mdast": "^4.0.4",
52
+ "@types/node": "^22.10.0",
53
+ "typescript": "^5.8.3",
54
+ "vitest": "^4.0.18"
55
+ },
56
+ "engines": {
57
+ "node": ">=22.17.0"
58
+ }
59
+ }