Skip to content

Commit 8cf8288

Browse files
committed
Complete signature details of values
1 parent 32e7129 commit 8cf8288

File tree

9 files changed

+176
-57
lines changed

9 files changed

+176
-57
lines changed

astro.config.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { readFileSync } from "node:fs";
22
import { defineConfig } from "astro/config";
33
import starlight from "@astrojs/starlight";
4-
import { apiModules } from "./docs/pages/apidocs/utils";
4+
import { apiModules } from "./docs/utils";
55

66
const rescriptTM = JSON.parse(
77
readFileSync("./docs/assets/rescript.tmLanguage.json", "utf-8"),
88
);
99

10-
const apiSidebarItems = apiModules.map(({ moduleName, link, items }) => {
10+
const apiSidebarItems = apiModules.map(({ moduleName, link, items }) => {
1111
const nestedItems = Object.values(items).map(({ moduleName, link }) => ({
1212
label: moduleName,
1313
link

docs/components/record.astro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ const { name, items, typesInOwnModule } = Astro.props;
3131
grid-template-rows: repeat(2, auto);
3232
grid-template-columns: repeat(2, 1fr);
3333
gap: 0.5rem;
34-
3534
border-bottom: 1px solid var(--sl-color-gray-7);
3635

3736
& .type {

docs/components/signature.astro

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ function parseTokens(tokens) {
1515
let index = 0;
1616
1717
const parseNode = () => {
18-
const ident = tokens[index++]; // Read the current token and increment index
19-
let genericArguments = [];
18+
const path = tokens[index++]; // Read the current token and increment index
19+
let genericTypeParameters = [];
2020
2121
if (tokens[index] === "<") {
2222
// Check for generics
2323
index++; // Consume "<"
2424
while (tokens[index] !== ">") {
25-
genericArguments.push(parseNode());
25+
genericTypeParameters.push(parseNode());
2626
if (tokens[index] === ",") index++; // Consume ","
2727
}
2828
index++; // Consume ">"
2929
}
3030
31-
return { ident, genericArguments };
31+
return { path, genericTypeParameters };
3232
};
3333
3434
return parseNode();

docs/components/signatureItem.astro

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
11
---
2-
import { createModuleLink } from "../pages/apidocs/utils.js";
2+
import { createAPIModuleLink } from "../utils.js";
33
const { item, typesInOwnModule } = Astro.props;
44
55
let link;
6-
if (typesInOwnModule.has(item.ident)) {
7-
link = `#${item.ident}`;
6+
if (typesInOwnModule && typesInOwnModule.has(item.path)) {
7+
link = `#${item.path}`;
88
}
99
10-
if (item.ident.startsWith("WebAPI.")) {
11-
const idents = item.ident.split(".");
12-
if (idents.length === 3){
13-
link = `${createModuleLink(idents[1])}#${idents[2]}`;
10+
if (item.path.startsWith("WebAPI.")) {
11+
const paths = item.path.split(".");
12+
if (paths.length === 3) {
13+
link = `${import.meta.env.BASE_URL}/${createAPIModuleLink(paths[1])}#${paths[2]}`;
1414
}
1515
}
16+
17+
const genericTypeParameters = item.genericTypeParameters || [];
1618
---
1719

18-
{link ? <a href={link}>{item.ident}</a> : item.ident}
19-
{
20-
item.genericArguments.length > 0 && (
21-
<>
22-
{"<"}
23-
{item.genericArguments.map((subItem) => (
24-
<Astro.self typesInOwnModule={typesInOwnModule} item={subItem} />
25-
))}
26-
{">"}
27-
</>
28-
)
29-
}
20+
<span>
21+
{link ? <a href={link}>{item.path}</a> : item.path}{
22+
genericTypeParameters.length > 0 && (
23+
<>
24+
{"<"}
25+
{genericTypeParameters.map((subItem) => (
26+
<Astro.self typesInOwnModule={typesInOwnModule} item={subItem} />
27+
))}
28+
{">"}
29+
</>
30+
)
31+
}
32+
</span>
33+
<style>
34+
span {
35+
display: inline-flex;
36+
color: var(--sl-color-accent-low);
37+
}
38+
</style>

docs/components/value.astro

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
import SignatureItem from "./signatureItem.astro";
3+
const { parameters, returnType } = Astro.props;
4+
---
5+
6+
<div class="value">
7+
<h4>Parameters</h4>
8+
{
9+
parameters.map((p) => (
10+
<SignatureItem item={p} />
11+
))
12+
}
13+
<h4>Return type</h4>
14+
<SignatureItem item={returnType} />
15+
</div>
16+
<style>
17+
.value {
18+
display: flex;
19+
flex-direction: column;
20+
padding-bottom: 1rem;
21+
border-bottom: 1px solid var(--sl-color-gray-7);
22+
23+
.signature {
24+
margin-top: 0rem;
25+
}
26+
}
27+
</style>

docs/pages/apidocs/[API].astro

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
---
2-
import { apiModules, getDoc } from "./utils";
2+
import * as path from "node:path";
3+
import { existsSync } from "fs";
4+
import { apiModules, getDoc, createTypeModuleLink } from "../../utils";
35
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
46
import { Code } from "@astrojs/starlight/components";
57
import { micromark } from "micromark";
@@ -20,7 +22,17 @@ function showRecord(details) {
2022
return details && details.kind === "record" && details.items.length > 0;
2123
}
2224
23-
const { moduleName, filePath } = Astro.props;
25+
function getModuleFileName(typeName) {
26+
return `${typeName[0].toUpperCase()}${typeName.slice(1)}`;
27+
}
28+
29+
function showModule(typeName, filePath) {
30+
const moduleFileName = `${getModuleFileName(typeName)}.res`;
31+
const potentialPath = path.join(filePath.replace(".res", ""), moduleFileName);
32+
return existsSync(potentialPath);
33+
}
34+
35+
const { moduleName, filePath, link } = Astro.props;
2436
2537
const docInfo = await getDoc(filePath);
2638
@@ -76,6 +88,20 @@ const headings = [
7688
{...type.detail}
7789
/>
7890
) : null}
91+
{showModule(type.name, filePath) && (
92+
<>
93+
<h4>Module</h4>
94+
<p>
95+
There are methods and helpers defined in{" "}
96+
<a
97+
href={`${import.meta.env.BASE_URL}/${createTypeModuleLink(link, type.name)}`}
98+
>
99+
{getModuleFileName(type.name)}
100+
</a>
101+
.
102+
</p>
103+
</>
104+
)}
79105
</div>
80106
))
81107
}

docs/pages/apidocs/[API]/[Module].astro

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
import { apiModules, getDoc } from "../utils";
3-
// import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
4-
// import { Code } from "@astrojs/starlight/components";
5-
// import { micromark } from "micromark";
6-
// import Record from "../../components/record.astro";
2+
import { apiModules, getDoc } from "../../../utils";
3+
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
4+
import { Code } from "@astrojs/starlight/components";
5+
import { micromark } from "micromark";
6+
import Value from "../../../components/value.astro";
77
88
export async function getStaticPaths() {
99
return apiModules.flatMap((apiModule) => {
@@ -19,7 +19,68 @@ export async function getStaticPaths() {
1919
});
2020
}
2121
22-
const name = Astro.props.currentModule.moduleName;
22+
function showValue(detail) {
23+
return (
24+
detail?.kind === "signature" && detail?.details?.parameters?.length > 0
25+
);
26+
}
27+
28+
const { filePath, moduleName } = Astro.props.currentModule;
29+
const docInfo = await getDoc(filePath);
30+
31+
const values = docInfo.items
32+
.filter((item) => item.kind === "value")
33+
.sort((a, b) => a.name.localeCompare(b.name))
34+
.map((value) => {
35+
const documentation =
36+
value.docstrings && micromark(value.docstrings.join("\n"));
37+
return {
38+
name: value.name,
39+
documentation,
40+
signature: value.signature,
41+
detail: value.detail,
42+
};
43+
});
44+
45+
const valueHeadings = values.map((value) => ({
46+
depth: 3,
47+
slug: value.name,
48+
text: value.name,
49+
}));
50+
51+
const frontmatter = {
52+
title: moduleName,
53+
};
54+
55+
const headings = [
56+
{
57+
depth: 2,
58+
slug: "values",
59+
text: "Values",
60+
},
61+
...valueHeadings,
62+
];
2363
---
2464

25-
<h1>Yupla {name}</h1>
65+
<StarlightPage frontmatter={frontmatter} headings={headings}>
66+
<h2 id="values">Values</h2>
67+
{
68+
values.map((value) => (
69+
<div class="rescript_value">
70+
<h3 id={value.name}>{value.name}</h3>
71+
<div set:html={value.documentation} />
72+
<Code lang="ReScript" code={value.signature} />
73+
{showValue(value.detail) && <Value {...value.detail.details} />}
74+
</div>
75+
))
76+
}
77+
<pre>
78+
{JSON.stringify(docInfo, null, 4)}
79+
</pre>
80+
</StarlightPage>
81+
<style>
82+
pre {
83+
max-width: 100%;
84+
overflow-x: auto;
85+
}
86+
</style>

docs/pages/apidocs/index.astro

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
3-
import { apiModules } from "./utils";
3+
import { apiModules } from "../../utils";
44
55
const frontmatter = {
66
title: "API Documentation",
@@ -14,14 +14,13 @@ const headings = [
1414
},
1515
];
1616
17-
const resFiles = apiModules;
1817
---
1918

2019
<StarlightPage frontmatter={frontmatter} headings={headings}>
2120
<h2 id="web-apis">Web APIs</h2>
2221
<ul>
2322
{
24-
resFiles.map(({ moduleName, link }) => (
23+
apiModules.map(({ moduleName, link }) => (
2524
<li>
2625
<a href={link}>{moduleName}</a>
2726
</li>

docs/pages/apidocs/utils.js renamed to docs/utils.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ function toKebabCase(input) {
1212
.toLowerCase(); // Convert to lowercase
1313
}
1414

15-
export function createModuleLink(moduleName) {
16-
return `/apidocs/${toKebabCase(moduleName)}`;
15+
export function createAPIModuleLink(moduleName) {
16+
// This function is called before import.meta.env.BASE_URL is set.
17+
// So, I'm hardcoding the path here.
18+
return `apidocs/${toKebabCase(moduleName)}`;
19+
}
20+
21+
export function createTypeModuleLink(parentModuleLink, typeName) {
22+
return `${parentModuleLink}/${toKebabCase(typeName)}`;
1723
}
1824

1925
function mapTypeModules(parentModuleLink, file) {
@@ -27,20 +33,20 @@ function mapTypeModules(parentModuleLink, file) {
2733
return files
2834
.filter((f) => f.endsWith(".res"))
2935
.map((file) => {
30-
const fullPath = path.join(folder, file);
36+
const filePath = path.join(folder, file);
3137

3238
const moduleName = file
3339
.replace("$", "")
3440
.replace(folder, "")
3541
.replace(".res", "");
3642
const apiRouteParameter = toKebabCase(moduleName);
37-
const link = `${parentModuleLink}/${apiRouteParameter}`;
43+
const link = createTypeModuleLink(parentModuleLink, moduleName);
3844
const typeName = moduleName[0].toLocaleLowerCase() + moduleName.slice(1);
3945

4046
return [
4147
typeName,
4248
{
43-
fullPath,
49+
filePath,
4450
moduleName,
4551
link,
4652
apiRouteParameter,
@@ -49,13 +55,10 @@ function mapTypeModules(parentModuleLink, file) {
4955
});
5056
}
5157

52-
function mapRescriptFile(file) {
53-
const moduleName = path
54-
.basename(file, ".res")
55-
.replace("$", "")
56-
.replace("API", " API");
57-
const filePath = path.join(import.meta.dirname, file);
58-
const link = createModuleLink(moduleName);
58+
function mapRescriptFile(srcDir, file) {
59+
const moduleName = path.basename(file, ".res").replace("$", "");
60+
const filePath = path.join(srcDir, file);
61+
const link = createAPIModuleLink(moduleName);
5962
const items = Object.fromEntries(mapTypeModules(link, filePath));
6063

6164
return {
@@ -67,13 +70,8 @@ function mapRescriptFile(file) {
6770
};
6871
}
6972

70-
export const apiModules = Object.keys(
71-
import.meta.glob("../../../src/*.res"),
72-
).map(mapRescriptFile);
73-
74-
export const fileModules = Object.keys(
75-
import.meta.glob("../../../src/**/*.res"),
76-
).map(mapRescriptFile);
73+
const srcDir = path.resolve(process.cwd(), "src");
74+
export const apiModules = readdirSync(srcDir).filter(f => f.endsWith(".res")).map(r => mapRescriptFile(srcDir, r));
7775

7876
export async function getDoc(absoluteFilePath) {
7977
const { stdout, stderr } = await execAsync(

0 commit comments

Comments
 (0)