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..066ba2d 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)
+ - [getPrintables](#getprintables)
- [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
+
+## getPrintables
+
+**Signature**
+
+```ts
+export declare const getPrintables: (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..d6e35b4 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))
)
)
)
@@ -106,9 +104,7 @@ const getModules = (files: ReadonlyArray) =>
Parser.parseFiles(files),
Effect.mapError((errors) =>
ParseError({
- message: errors
- .map((errors) => errors.join("\n"))
- .join("\n")
+ message: errors.map((errors) => errors.join("\n")).join("\n")
})
)
)
@@ -143,9 +139,7 @@ const getExampleFiles = (modules: ReadonlyArray) =>
const prefix = module.path.join("-")
const getDocumentableExamples = (id: string) =>
- (
- documentable: Domain.Documentable
- ): ReadonlyArray =>
+ (documentable: Domain.Documentable): ReadonlyArray =>
pipe(
documentable.examples,
ReadonlyArray.map((content, i) =>
@@ -273,9 +267,8 @@ const spawnTsNode = pipe(
)
)
-const writeFiles = (
- files: ReadonlyArray
-) => Effect.forEachDiscard(files, writeFile)
+const writeFiles = (files: ReadonlyArray) =>
+ Effect.forEachDiscard(files, writeFile)
const writeExamples = (examples: ReadonlyArray) =>
pipe(
@@ -320,12 +313,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 +431,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 +448,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.getPrintables(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
// -------------------------------------------------------------------------------------
@@ -487,7 +516,9 @@ export const main: Effect.Effect = pipe(
Effect.flatMap(getMarkdown),
Effect.zipLeft(Effect.logInfo("writing markdown files...")),
Effect.flatMap(writeMarkdown),
- Effect.zipLeft(Effect.logInfo(chalk.bold.green("Docs generation succeeded!"))),
+ Effect.zipLeft(
+ Effect.logInfo(chalk.bold.green("Docs generation succeeded!"))
+ ),
Logger.withMinimumLogLevel(LogLevel.Debug),
Effect.provideLayer(MainLayer),
Effect.catchTags({
@@ -508,7 +539,11 @@ export const main: Effect.Effect = pipe(
),
SpawnError: ({ args, command, error }) =>
Effect.dieMessage(
- `Unable to spawn child process for command: '${command} ${args.join(" ")}'\n${error}`
+ `Unable to spawn child process for command: '${command} ${
+ args.join(
+ " "
+ )
+ }'\n${error}`
),
// Parsing errors
ParseJsonError: ({ content }) => Effect.dieMessage(`Unable to parse JSON: ${content}`),
diff --git a/src/Domain.ts b/src/Domain.ts
index 69aa8da..a127412 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 getPrintables = (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..e88ccf6 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.getPrintables(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,