diff --git a/docs/components/apidoc.astro b/docs/components/apidoc.astro new file mode 100644 index 0000000..59e8fbb --- /dev/null +++ b/docs/components/apidoc.astro @@ -0,0 +1,59 @@ +--- +import { apiModules, getDoc } from "../utils"; +import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro"; +import Value from "./value.astro"; +import Type from "./type.astro"; + +const { moduleName, filePath, link } = Astro.props; + +const { types, typesInOwnModule, typeHeadings, values, valueHeadings } = + await getDoc(filePath); + +const frontmatter = { + title: moduleName, +}; + +const headings = []; +if (types.length > 0) { + headings.push({ + depth: 2, + slug: "types", + text: "Types", + }); + headings.push(...typeHeadings); +} + +if (values.length > 0) { + headings.push({ + depth: 2, + slug: "values", + text: "Values", + }); + headings.push(...valueHeadings); +} +--- + + { + types.length > 0 && ( + <> +

Types

+ {types.map((type) => ( + + ))} + + ) + } + { + values.length > 0 && ( + <> +

Values

+ {values.map((value) => )} + + ) + } +
diff --git a/docs/components/record.astro b/docs/components/record.astro index 366e3a7..a6f50e6 100644 --- a/docs/components/record.astro +++ b/docs/components/record.astro @@ -40,6 +40,7 @@ const { name, items, typesInOwnModule } = Astro.props; } & .doc { + margin-top: 0; padding-bottom: 0.5rem; grid-column: 1 / -1; grid-row: 2; diff --git a/docs/components/type.astro b/docs/components/type.astro new file mode 100644 index 0000000..4aa5ff5 --- /dev/null +++ b/docs/components/type.astro @@ -0,0 +1,67 @@ +--- +import * as path from "node:path"; +import { existsSync } from "node:fs"; +import { Code } from "@astrojs/starlight/components"; +import Record from "./record.astro"; +import { createTypeModuleLink } from "../utils"; + +const { type, typesInOwnModule, filePath, link } = Astro.props; + +function showRecord(details) { + return details && details.kind === "record" && details.items.length > 0; +} + +function getModuleFileName(typeName) { + return `${typeName[0].toUpperCase()}${typeName.slice(1)}`; +} + +/** + * Check if there is a file representing the module for the type. + * The location to be checked is a sub directory with the same name as the current file type. + * @param {string} typeName + * @param {string} filePath + * @returns {boolean} + */ +function showModule(typeName, filePath) { + const moduleFileName = `${getModuleFileName(typeName)}.res`; + const potentialPath = path.join(filePath.replace(".res", ""), moduleFileName); + return existsSync(potentialPath); +} +--- + +
+

{type.name}

+
+ + { + showRecord(type.detail) ? ( + + ) : null + } + { + showModule(type.name, filePath) && ( + <> +

Module

+

+ There are methods and helpers defined in{" "} + + {getModuleFileName(type.name)} + + . +

+ + ) + } +
+ + \ No newline at end of file diff --git a/docs/components/value.astro b/docs/components/value.astro index 66e9faa..5282dd1 100644 --- a/docs/components/value.astro +++ b/docs/components/value.astro @@ -1,20 +1,35 @@ --- +import { Code } from "@astrojs/starlight/components"; import SignatureItem from "./signatureItem.astro"; -const { parameters, returnType } = Astro.props; +const { value } = Astro.props; +const details = value.detail?.details || null; + +function showValue(detail) { + return detail?.kind === "signature" && detail.details?.parameters?.length > 0; +} + --- -
-

Parameters

+
+

{value.name}

+
+ { - parameters.map((p) => ( - - )) + showValue(value.detail) && ( +
+

Parameters

+ {details.parameters.map((p) => ( + + ))} +

Return type

+ +
+ ) } -

Return type

-
+ + diff --git a/docs/pages/apidocs/[API]/[Module].astro b/docs/pages/apidocs/[API]/[Module].astro index e6a5590..286b09a 100644 --- a/docs/pages/apidocs/[API]/[Module].astro +++ b/docs/pages/apidocs/[API]/[Module].astro @@ -1,9 +1,6 @@ --- import { apiModules, getDoc } from "../../../utils"; -import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro"; -import { Code } from "@astrojs/starlight/components"; -import { micromark } from "micromark"; -import Value from "../../../components/value.astro"; +import APIDoc from "../../../components/apidoc.astro"; export async function getStaticPaths() { return apiModules.flatMap((apiModule) => { @@ -19,68 +16,7 @@ export async function getStaticPaths() { }); } -function showValue(detail) { - return ( - detail?.kind === "signature" && detail?.details?.parameters?.length > 0 - ); -} - -const { filePath, moduleName } = Astro.props.currentModule; -const docInfo = await getDoc(filePath); - -const values = docInfo.items - .filter((item) => item.kind === "value") - .sort((a, b) => a.name.localeCompare(b.name)) - .map((value) => { - const documentation = - value.docstrings && micromark(value.docstrings.join("\n")); - return { - name: value.name, - documentation, - signature: value.signature, - detail: value.detail, - }; - }); - -const valueHeadings = values.map((value) => ({ - depth: 3, - slug: value.name, - text: value.name, -})); - -const frontmatter = { - title: moduleName, -}; - -const headings = [ - { - depth: 2, - slug: "values", - text: "Values", - }, - ...valueHeadings, -]; +const { filePath, moduleName, link } = Astro.props.currentModule; --- - -

Values

- { - values.map((value) => ( -
-

{value.name}

-
- - {showValue(value.detail) && } -
- )) - } -
-{JSON.stringify(docInfo, null, 4)}
-
- - + diff --git a/docs/styles/theme.css b/docs/styles/theme.css index 8915d1f..ef4a208 100644 --- a/docs/styles/theme.css +++ b/docs/styles/theme.css @@ -2,6 +2,8 @@ ::backdrop { --sl-font: "Inter", "Roboto Mono"; --sl-sidebar-width: 23rem; + --sl-text-3xl: 1.5rem; + --sl-text-2xl: 1.3rem; } /* diff --git a/docs/utils.js b/docs/utils.js index a34e781..4bdf816 100644 --- a/docs/utils.js +++ b/docs/utils.js @@ -2,6 +2,7 @@ import * as path from "node:path"; import { exec } from "node:child_process"; import { promisify } from "node:util"; import { readdirSync, existsSync } from "fs"; +import { micromark } from "micromark"; const execAsync = promisify(exec); @@ -73,7 +74,7 @@ function mapRescriptFile(srcDir, file) { const srcDir = path.resolve(process.cwd(), "src"); export const apiModules = readdirSync(srcDir).filter(f => f.endsWith(".res")).map(r => mapRescriptFile(srcDir, r)); -export async function getDoc(absoluteFilePath) { +async function getRescriptDoc(absoluteFilePath) { const { stdout, stderr } = await execAsync( `rescript-tools doc ${absoluteFilePath}`, { @@ -85,3 +86,58 @@ export async function getDoc(absoluteFilePath) { } return JSON.parse(stdout); } + +export async function getDoc(absoluteFilePath) { + const docInfo = await getRescriptDoc(absoluteFilePath); + + const types = docInfo.items + .filter((item) => item.kind === "type") + .sort((a, b) => a.name.localeCompare(b.name)) + .map((type) => { + const documentation = + type.docstrings && micromark(type.docstrings.join("\n")); + return { + name: type.name, + documentation, + signature: type.signature, + detail: type.detail, + }; + }); + + const typesInOwnModule = new Set(types.map((t) => t.name)); + + const typeHeadings = types.map((type) => ({ + depth: 3, + slug: type.name, + text: type.name, + })); + + const values = docInfo.items + .filter((item) => item.kind === "value") + .sort((a, b) => a.name.localeCompare(b.name)) + .map((value) => { + const documentation = + value.docstrings && micromark(value.docstrings.join("\n")); + return { + name: value.name, + documentation, + signature: value.signature, + detail: value.detail, + }; + }); + + const valueHeadings = values.map((value) => ({ + depth: 3, + slug: value.name, + text: value.name, + })); + + return { + docInfo, + types, + typesInOwnModule, + typeHeadings, + values, + valueHeadings, + }; +} \ No newline at end of file diff --git a/src/DOMAPI/FillStyle.res b/src/DOMAPI/FillStyle.res index 312f477..fdf4be2 100644 --- a/src/DOMAPI/FillStyle.res +++ b/src/DOMAPI/FillStyle.res @@ -6,6 +6,9 @@ external fromString: string => fillStyle = "%identity" external fromCanvasGradient: canvasGradient => fillStyle = "%identity" external fromCanvasPattern: canvasGradient => fillStyle = "%identity" +/** +Represents a decoded version of the abstract `fillStyle` type, used in Context2D. + */ type decoded = | String(string) | CanvasGradient(canvasGradient) diff --git a/tests/DOMAPI/Location__test.res b/tests/DOMAPI/Location__test.res index 7e89162..fa2d12f 100644 --- a/tests/DOMAPI/Location__test.res +++ b/tests/DOMAPI/Location__test.res @@ -9,4 +9,4 @@ let href = location.href // Invoke methods using the `->TypeModule` location->Location.reload -let a = 0 \ No newline at end of file +let a = 0