From 233c6f0e55060c38b41e88e9d4de001dfa1914c1 Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 16 Jun 2023 10:52:19 +1200 Subject: [PATCH] chore: add doc generation for AI --- docs/modules/Config.ts.md | 1 + docs/modules/Domain.ts.md | 25 ++++++++++++++++ docs/modules/Markdown.ts.md | 15 ++++++++++ src/Config.ts | 3 ++ src/Core.ts | 58 +++++++++++++++++++++++++++++-------- src/Domain.ts | 31 ++++++++++++++++++++ src/Markdown.ts | 51 ++++++++++++++++++-------------- test/Parser.ts | 1 + 8 files changed, 151 insertions(+), 34 deletions(-) diff --git a/docs/modules/Config.ts.md b/docs/modules/Config.ts.md index b20197d..8e78e28 100644 --- a/docs/modules/Config.ts.md +++ b/docs/modules/Config.ts.md @@ -49,6 +49,7 @@ export interface Config { readonly outDir: string readonly theme: string readonly enableSearch: boolean + readonly enableAI: boolean readonly enforceDescriptions: boolean readonly enforceExamples: boolean readonly enforceVersion: boolean diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 95e821d..408b88e 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -12,6 +12,8 @@ Added in v1.0.0

Table of contents

+- [accessors](#accessors) + - [printablesFromModule](#printablesfrommodule) - [constructors](#constructors) - [createClass](#createclass) - [createConstant](#createconstant) @@ -35,11 +37,24 @@ Added in v1.0.0 - [Interface (interface)](#interface-interface) - [Method (interface)](#method-interface) - [Module (interface)](#module-interface) + - [Printable (type alias)](#printable-type-alias) - [Property (interface)](#property-interface) - [TypeAlias (interface)](#typealias-interface) --- +# accessors + +## printablesFromModule + +**Signature** + +```ts +export declare const printablesFromModule: (module: Module) => ReadonlyArray +``` + +Added in v1.0.0 + # constructors ## createClass @@ -303,6 +318,16 @@ export interface Module extends Documentable { Added in v1.0.0 +## Printable (type alias) + +**Signature** + +```ts +export type Printable = Class | Constant | Export | Function | Interface | TypeAlias +``` + +Added in v1.0.0 + ## Property (interface) **Signature** diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index a306d73..1993e27 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -14,6 +14,7 @@ Added in v1.0.0 - [printers](#printers) - [printModule](#printmodule) + - [printPrintableForAI](#printprintableforai) --- @@ -28,3 +29,17 @@ export declare const printModule: (module: Domain.Module, order: number) => stri ``` Added in v1.0.0 + +## printPrintableForAI + +**Signature** + +```ts +export declare const printPrintableForAI: ( + projectName: string, + module: Domain.Module, + printable: Domain.Printable +) => string +``` + +Added in v1.0.0 diff --git a/src/Config.ts b/src/Config.ts index 0315117..95507b8 100644 --- a/src/Config.ts +++ b/src/Config.ts @@ -28,6 +28,7 @@ export interface Config { readonly outDir: string readonly theme: string readonly enableSearch: boolean + readonly enableAI: boolean readonly enforceDescriptions: boolean readonly enforceExamples: boolean readonly enforceVersion: boolean @@ -62,6 +63,7 @@ const ConfigSchema = Schema.struct({ srcDir: Schema.string, outDir: Schema.string, theme: Schema.string, + enableAI: Schema.boolean, enableSearch: Schema.boolean, enforceDescriptions: Schema.boolean, enforceExamples: Schema.boolean, @@ -99,6 +101,7 @@ const getDefaultConfig = (projectName: string, projectHomepage: string): Config srcDir: "src", outDir: "docs", theme: "pmarsceill/just-the-docs", + enableAI: false, enableSearch: true, enforceDescriptions: false, enforceExamples: false, diff --git a/src/Core.ts b/src/Core.ts index 1e093e8..7eed695 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -14,10 +14,10 @@ import chalk from "chalk" import * as NodePath from "path" import * as ChildProcess from "./ChildProcess" import * as Config from "./Config" -import type * as Domain from "./Domain" +import * as Domain from "./Domain" import * as FileSystem from "./FileSystem" import { SimpleLogger } from "./Logger" -import { printModule } from "./Markdown" +import { printModule, printPrintableForAI } from "./Markdown" import * as Parser from "./Parser" import * as Process from "./Process" @@ -35,10 +35,8 @@ const readFiles = pipe( Effect.tap((paths) => Effect.logInfo(chalk.bold(`${paths.length} module(s) found`))), Effect.flatMap( Effect.forEachPar((path) => - Effect.map( - fileSystem.readFile(path), - (content) => FileSystem.makeFile(path, content, false) - ) + Effect.map(fileSystem.readFile(path), (content) => + FileSystem.makeFile(path, content, false)) ) ) ) @@ -320,12 +318,9 @@ const getMarkdown = (modules: ReadonlyArray) => Effect.bind("home", () => getHome), Effect.bind("index", () => getModulesIndex), Effect.bind("yml", () => getConfigYML), - Effect.flatMap(({ home, index, yml }) => - pipe( - getModuleMarkdownFiles(modules), - Effect.map((files) => [home, index, yml].concat(files)) - ) - ) + Effect.bind("modules", () => getModuleMarkdownFiles(modules)), + Effect.bind("ai", () => maybeGetAIMarkdownFiles(modules)), + Effect.map(({ ai, home, index, modules, yml }) => [home, index, yml].concat(modules).concat(ai)) ) const getHome = pipe( @@ -441,6 +436,14 @@ const getMarkdownOutputPath = (module: Domain.Module) => `${module.path.slice(1).join(NodePath.sep)}.md` )) +const getAIMarkdownOutputPath = (module: Domain.Module, printable: Domain.Printable) => + Effect.map(Config.Config, (config) => + join( + config.outDir, + "ai", + `${module.path.slice(1).join("-").replace(/\.ts$/, "")}-${printable.name}.md` + )) + const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.forEachWithIndex(modules, (module, order) => pipe( @@ -450,6 +453,37 @@ const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.map(({ content, outputPath }) => FileSystem.makeFile(outputPath, content, true)) )) +const getAIMarkdownFiles = (projectName: string, modules: ReadonlyArray) => + pipe( + modules, + ReadonlyArray.flatMap((module) => + pipe( + Domain.printablesFromModule(module), + ReadonlyArray.map((printable) => [module, printable] as const) + ) + ), + ReadonlyArray.filter(([, printable]) => + printable.description._tag === "Some" && + (printable.examples.length > 0 || printable.description.value.includes("```") || + printable.description.value.length >= 115) + ), + Effect.forEach(([module, printable]) => + pipe( + Effect.Do(), + Effect.bind("outputPath", () => getAIMarkdownOutputPath(module, printable)), + Effect.let("content", () => printPrintableForAI(projectName, module, printable)), + Effect.map(({ content, outputPath }) => FileSystem.makeFile(outputPath, content, true)) + ) + ) + ) + +const maybeGetAIMarkdownFiles = (modules: ReadonlyArray) => + Effect.flatMap( + Config.Config, + (config) => + config.enableAI ? getAIMarkdownFiles(config.projectName, modules) : Effect.succeed([]) + ) + // ------------------------------------------------------------------------------------- // writeMarkdown // ------------------------------------------------------------------------------------- diff --git a/src/Domain.ts b/src/Domain.ts index 69aa8da..e619bba 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -3,6 +3,7 @@ */ import type * as Option from "@effect/data/Option" +import * as ReadonlyArray from "@effect/data/ReadonlyArray" import * as String from "@effect/data/String" import * as order from "@effect/data/typeclass/Order" @@ -112,6 +113,18 @@ export interface Export extends Documentable { */ export type Example = string +/** + * @category model + * @since 1.0.0 + */ +export type Printable = + | Class + | Constant + | Export + | Function + | Interface + | TypeAlias + // ------------------------------------------------------------------------------------- // constructors // ------------------------------------------------------------------------------------- @@ -268,6 +281,24 @@ export const createExport = ( signature }) +// ------------------------------------------------------------------------------------- +// accessors +// ------------------------------------------------------------------------------------- + +/** + * @category accessors + * @since 1.0.0 + */ +export const printablesFromModule = (module: Module): ReadonlyArray => + ReadonlyArray.getMonoid().combineAll([ + module.classes, + module.constants, + module.exports, + module.functions, + module.interfaces, + module.typeAliases + ]) + /** * @category instances * @since 1.0.0 diff --git a/src/Markdown.ts b/src/Markdown.ts index f148498..23ca2a6 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -8,19 +8,11 @@ import * as ReadonlyRecord from "@effect/data/ReadonlyRecord" import * as String from "@effect/data/String" import * as Order from "@effect/data/typeclass/Order" import * as Prettier from "prettier" -import type * as Domain from "./Domain" +import * as Domain from "./Domain" // eslint-disable-next-line @typescript-eslint/no-var-requires const toc = require("markdown-toc") -type Printable = - | Domain.Class - | Domain.Constant - | Domain.Export - | Domain.Function - | Domain.Interface - | Domain.TypeAlias - const bold = (s: string) => `**${s}**` const fence = (language: string, content: string) => @@ -191,7 +183,7 @@ const fromTypeAlias = (ta: Domain.TypeAlias): string => ) /** @internal */ -export const fromPrintable = (p: Printable): string => { +export const fromPrintable = (p: Domain.Printable): string => { switch (p._tag) { case "Class": return fromClass(p) @@ -208,16 +200,6 @@ export const fromPrintable = (p: Printable): string => { } } -const getPrintables = (module: Domain.Module): ReadonlyArray => - ReadonlyArray.getMonoid().combineAll([ - module.classes, - module.constants, - module.exports, - module.functions, - module.interfaces, - module.typeAliases - ]) - /** * @category printers * @since 1.0.0 @@ -230,7 +212,7 @@ export const printModule = (module: Domain.Module, order: number): string => { const description = paragraph(getModuleDescription(module)) const content = pipe( - getPrintables(module), + Domain.printablesFromModule(module), ReadonlyArray.groupBy(({ category }) => pipe( category, @@ -249,7 +231,7 @@ export const printModule = (module: Domain.Module, order: number): string => { ReadonlyArray.sort( Order.contramap( String.Order, - (printable: Printable) => printable.name + (printable: Domain.Printable) => printable.name ) ), ReadonlyArray.map(fromPrintable) @@ -275,6 +257,31 @@ export const printModule = (module: Domain.Module, order: number): string => { ) } +/** + * @category printers + * @since 1.0.0 + */ +export const printPrintableForAI = ( + projectName: string, + module: Domain.Module, + printable: Domain.Printable +): string => { + const namespace = module.path.slice(1).join("/").replace(/\.ts$/, "") + return prettify( + [ + h1(printable.name), + getDescription(printable.description), + paragraph( + `Part of the \`${namespace}\` module from the \`${projectName}\` package. Also known as \`${namespace}.${printable.name}\`.` + ), + printable.examples.map((code) => + [h3("Example"), paragraph(fence("typescript", code))].join("\n") + ) + .join("\n\n") + ].join("\n") + ) +} + const defaultPrettierOptions: Prettier.Options = { parser: "markdown", semi: false, diff --git a/test/Parser.ts b/test/Parser.ts index d8a5ea5..e2cc683 100644 --- a/test/Parser.ts +++ b/test/Parser.ts @@ -21,6 +21,7 @@ const defaultConfig: Config.Config = { srcDir: "src", outDir: "docs", theme: "pmarsceill/just-the-docs", + enableAI: false, enableSearch: true, enforceDescriptions: false, enforceExamples: false,