diff --git a/www/components/api.tsx b/www/components/api.tsx
new file mode 100644
index 0000000..bde9f04
--- /dev/null
+++ b/www/components/api.tsx
@@ -0,0 +1,25 @@
+import type { JSXElement } from "revolution";
+import type { Package } from "../hooks/use-package.tsx";
+
+interface DescriptionProps {
+ pkg: Package
+}
+
+export function API({ pkg }: DescriptionProps): JSXElement {
+ return (
+ <>
+ {Object.keys(pkg.docs).flatMap((exportName) => {
+ const nodes = pkg.docs[exportName];
+ return nodes.map(node => {
+ const { MDXDoc = () => <>> } = node
+ return (
+ <>
+
{node.name}
+
+ >
+ )
+ })
+ })}
+ >
+ );
+}
\ No newline at end of file
diff --git a/www/components/exports.tsx b/www/components/exports.tsx
new file mode 100644
index 0000000..7819788
--- /dev/null
+++ b/www/components/exports.tsx
@@ -0,0 +1,42 @@
+import { join } from "jsr:@std/path@1.0.6";
+import type { JSXElement } from "revolution/jsx-runtime";
+
+import type { DocNode } from "../hooks/use-deno-doc.tsx";
+import { DEFAULT_MODULE_KEY, RenderableDocNode, type Package } from "../hooks/use-package.tsx";
+
+export function Exports({ pkg }: { pkg: Package }): JSXElement {
+ return (
+ <>
+ {Object.keys(pkg.docs).map((exportName) => (
+
+ ))}
+ >
+ );
+}
+
+interface PackageExportOptions {
+ packageName: string;
+ exportName: string;
+ doc: Array;
+}
+
+function PackageExport({ packageName, exportName, doc }: PackageExportOptions) {
+ const exports = doc.flatMap((doc) => {
+ if (doc.declarationKind === "export") {
+ return [
+ {doc.name}, ", "];
+ } else {
+ return [];
+ }
+ }).slice(0, -1);
+
+ return (
+
+ import {{" "}<>{exports}>{" "}} from "{join(packageName, exportName)}"
+
+ );
+}
\ No newline at end of file
diff --git a/www/components/package-exports.tsx b/www/components/package-exports.tsx
deleted file mode 100644
index 98ed49f..0000000
--- a/www/components/package-exports.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-import { join } from "jsr:@std/path@1.0.6";
-import type { JSXElement } from "revolution/jsx-runtime";
-
-import type { DocNode } from "../hooks/use-deno-doc.tsx";
-import type { Package } from "../hooks/use-package.tsx";
-
-export function PackageExports({ pkg }: { pkg: Package }): JSXElement {
- if (isDocArray(pkg.docs)) {
- if (typeof pkg.exports === "string") {
- return (
-
- );
- }
- } else {
- const doc = pkg.docs;
- return (
- <>
- {Object.keys(pkg.docs).map((exportName) => (
-
- ))}
- >
- );
- }
- return <>>
-}
-
-interface PackageExportOptions {
- packageName: string;
- exportName: string;
- doc: Array;
-}
-
-function PackageExport({ packageName, exportName, doc }: PackageExportOptions) {
- const exports = doc.flatMap((doc) => {
- if (doc.declarationKind === "export") {
- return [doc.name];
- } else {
- return [];
- }
- });
- return (
-
- import { {exports.join(", ")}{" "}
- } from "{join(packageName, exportName)}"
-
- );
-}
-
-function isDocArray(
- doc: Array | Record>,
-): doc is Array {
- return Array.isArray(doc);
-}
diff --git a/www/hooks/use-package.tsx b/www/hooks/use-package.tsx
index f03fbc0..a4e865c 100644
--- a/www/hooks/use-package.tsx
+++ b/www/hooks/use-package.tsx
@@ -1,7 +1,8 @@
-import { call, type Operation } from "effection";
+import { all, call, type Operation } from "effection";
import { join, resolve } from "jsr:@std/path@1.0.6";
import type { VFile } from "npm:vfile@6.0.3";
import { z } from "npm:zod@3.23.8";
+import type { JSXElement } from "revolution";
import { PrivatePackageError } from "../errors.ts";
import { type DocNode, useDenoDoc } from "./use-deno-doc.tsx";
@@ -13,12 +14,17 @@ export interface Package {
workspace: string;
packageName: string;
readme: string;
- exports: string | Record;
- docs: Array | Record>;
+ exports: Record;
+ docs: Record>;
MDXContent: () => JSX.Element;
MDXDescription: () => JSX.Element;
}
+export type RenderableDocNode = DocNode & {
+ id: string;
+ MDXDoc?: () => JSXElement;
+};
+
const DenoJson = z.object({
name: z.string(),
version: z.optional(z.string()),
@@ -26,6 +32,8 @@ const DenoJson = z.object({
private: z.union([z.undefined(), z.literal(true)]),
});
+export const DEFAULT_MODULE_KEY = ".";
+
export function* usePackage(workspace: string): Operation {
const workspacePath = resolve(
import.meta.dirname ?? "",
@@ -52,28 +60,56 @@ export function* usePackage(workspace: string): Operation {
let file: VFile = yield* useRemarkParse(readme);
- let docs: Package["docs"];
- if (typeof denoJson.exports === "string") {
- docs = yield* useDenoDoc(
- `${new URL(join(workspacePath, denoJson.exports), "file://")}`,
- );
- } else {
- docs = {};
- for (const key of Object.keys(denoJson.exports)) {
- docs[key] = yield* useDenoDoc(
- `${new URL(join(workspacePath, denoJson.exports[key]), "file://")}`,
- );
+ const exports = typeof denoJson.exports === "string"
+ ? {
+ [DEFAULT_MODULE_KEY]: denoJson.exports,
}
+ : denoJson.exports;
+
+ const entrypoints: Record = {};
+ for (const key of Object.keys(exports)) {
+ entrypoints[key] = new URL(join(workspacePath, exports[key]), "file://");
+ }
+
+ let docs: Package["docs"] = {};
+ for (const key of Object.keys(entrypoints)) {
+ const docNodes = yield* useDenoDoc(String(entrypoints[key]));
+ docs[key] = yield* all(docNodes.map(function* (node) {
+ if (node.jsDoc && node.jsDoc.doc) {
+ try {
+ const mod = yield* useMDX(node.jsDoc.doc);
+ return {
+ id: exportHash(key, node),
+ ...node,
+ MDXDoc: () => mod.default({})
+ };
+ } catch (e) {
+ console.error(`Could not parse doc string for ${node.name} at ${node.location}`, e)
+ }
+ }
+ return {
+ id: exportHash(key, node),
+ ...node
+ };
+ }));
}
return {
workspace: workspace.replace("./", ""),
path: workspacePath,
packageName: denoJson.name,
- exports: denoJson.exports,
+ exports,
readme,
docs,
MDXContent: () => content,
MDXDescription: () => <>{file.data?.meta?.description}>,
};
}
+
+function exportHash(exportName: string, doc: DocNode): string {
+ if (exportName === DEFAULT_MODULE_KEY) {
+ return doc.name
+ } else {
+ return `${exportName}__${doc.name}`;
+ }
+}
\ No newline at end of file
diff --git a/www/routes/package.tsx b/www/routes/package.tsx
index e23c08b..7a60c23 100644
--- a/www/routes/package.tsx
+++ b/www/routes/package.tsx
@@ -4,7 +4,8 @@ import { useAppHtml } from "./app.html.tsx";
import type { Package } from "../hooks/use-package.tsx";
import type { RoutePath, SitemapRoute } from "effection-www/plugins/sitemap.ts";
import { usePackages } from "../hooks/use-packages.ts";
-import { PackageExports } from "../components/package-exports.tsx";
+import { Exports } from "../components/exports.tsx";
+import { API } from "../components/api.tsx";
export function packageRoute(): SitemapRoute {
return {
@@ -56,7 +57,8 @@ export function packageRoute(): SitemapRoute {
-
+
+
>
);