Skip to content

Commit

Permalink
Auto-generated ECS Docs. Needs work, but it's better than nothing.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderson1993 committed Mar 5, 2025
1 parent 6a45da9 commit d4d268a
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 0 deletions.
3 changes: 3 additions & 0 deletions app/ecs-components/isTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export const isTimeline = z
export const isTimelineStep = z
.object({
active: z.boolean().default(true),
/**
* What actions are assigned to this timeline step
*/
actions: actionSchema.default([]),
timelineId: z.number().optional(),
})
Expand Down
35 changes: 35 additions & 0 deletions app/routes/docs/Development/ECSComponentDocs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-expect-error
import { docs } from "virtual:ecs-component-docs";
import { Fragment } from "react";

export function ECSComponentDocs() {
console.log(docs);

return Object.values(docs)
.sort((a: any, b: any) => (a.component > b.component ? 1 : -1))
.map((doc) => {
const typedDoc: {
component: string;
comment: string;
properties: { name: string; comment: string }[];
} = doc as any;
return (
<Fragment key={typedDoc.component}>
<h3>
<code>{typedDoc.component}</code>
</h3>
<p>{typedDoc.comment}</p>
<ul>
{typedDoc.properties.map((p) => (
<li key={p.name}>
<code>
<strong>{p.name}</strong>
</code>
: {p.comment}
</li>
))}
</ul>
</Fragment>
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
title: ECS Components
---

import {ECSComponentDocs} from './ECSComponentDocs'

# ECS Components

ECS Components are the building blocks of entities. They define the data
Expand Down Expand Up @@ -46,3 +48,7 @@ export const identity = z.object({
description: z.string().optional()
}).default({})
```

## Component Properties

<ECSComponentDocs />
10 changes: 10 additions & 0 deletions app/routes/docs/docs.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ h6:hover .icon.icon-link {
background-repeat: no-repeat;
background-position: center;
}
.prose code:before, .prose code:after {
display:none;
}
.prose code {
font-family: monospace;
@apply p-1 rounded bg-purple-600/40;
}
.prose pre code {
@apply bg-transparent;
}
.prose a code {
@apply text-purple-300;
}
Expand Down
76 changes: 76 additions & 0 deletions scripts/componentDocs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// @ts-nocheck
import * as ts from "typescript";

const virtualModuleId = "virtual:ecs-component-docs";
const resolvedVirtualModuleId = `\0${virtualModuleId}`;
const docs: Record<
string,
{
component: string;
comment: string;
properties: { name: string; comment: string }[];
}
> = {};
const componentDocsRegex = /.*app\/ecs-components\/.*\.ts$/;
export function componentDocs() {
return {
name: "component-docs",
resolveId(id: string) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId;
}
},
load(id: string) {
if (id === resolvedVirtualModuleId) {
return `export const docs = ${JSON.stringify(docs)}`;
}
},
transform(src: string, id: string) {
if (componentDocsRegex.test(id)) {
const sourceFile = ts.createSourceFile(
id,
src,
ts.ScriptTarget.Latest,
true,
);
let currentExportKeyword = "";
function visit(node: ts.Node) {
if (ts.SyntaxKind[node.kind] === "ExportKeyword") {
const keyword =
node.parent.declarationList.declarations[0].name.getText();
console.log(keyword);
if (keyword) {
currentExportKeyword = keyword;
docs[currentExportKeyword] = {
component: currentExportKeyword,
comment: node.jsDoc?.[0]?.comment || "",
properties: [],
};
}
}
if (ts.SyntaxKind[node.kind] === "PropertyAssignment") {
const name = node.name.getText() || "";
if (!docs[currentExportKeyword]) {
docs[currentExportKeyword] = {
component: currentExportKeyword,
comment: "",
properties: [],
};
}
if (name) {
docs[currentExportKeyword].properties.push({
name,
comment: node.jsDoc?.[0]?.comment || "",
});
}
}
ts.forEachChild(node, visit);
}

visit(sourceFile);

return null;
}
},
};
}
2 changes: 2 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import rehypeAutolinkHeadings from "rehype-autolink-headings";
import rehypeSlug from "rehype-slug";
import rehypeShiki from "@shikijs/rehype";
import { iconsSpritesheet } from "vite-plugin-icons-spritesheet";
import { componentDocs } from "./scripts/componentDocs";

setDefaultResultOrder("ipv4first");

Expand Down Expand Up @@ -45,6 +46,7 @@ export default defineConfig({
}),
reactRouter(),
tsconfigPaths(),
componentDocs(),
],
build: {
outDir: "../build",
Expand Down

0 comments on commit d4d268a

Please sign in to comment.