Skip to content

Commit

Permalink
chore: add doc generation for AI
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart committed Nov 29, 2024
1 parent d98a42a commit 868083a
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 16 deletions.
2 changes: 2 additions & 0 deletions docs/modules/Configuration.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export declare const ConfigurationSchema: Schema.Struct<{
examplesCompilerOptions: Schema.optional<
Schema.Union<[typeof Schema.String, Schema.Record$<typeof Schema.String, typeof Schema.Unknown>]>
>
enableAI: Schema.optional<typeof Schema.Boolean>
}>
```

Expand All @@ -77,6 +78,7 @@ export interface ConfigurationShape {
readonly exclude: ReadonlyArray<string>
readonly parseCompilerOptions: Record<string, unknown>
readonly examplesCompilerOptions: Record<string, unknown>
readonly enableAI: boolean
}
```

Expand Down
25 changes: 25 additions & 0 deletions docs/modules/Domain.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Added in v1.0.0

<h2 class="text-delta">Table of contents</h2>

- [accessors](#accessors)
- [printablesFromModule](#printablesfrommodule)
- [constructors](#constructors)
- [createClass](#createclass)
- [createConstant](#createconstant)
Expand All @@ -37,13 +39,26 @@ Added in v1.0.0
- [Module (interface)](#module-interface)
- [NamedDoc (interface)](#nameddoc-interface)
- [Namespace (interface)](#namespace-interface)
- [Printable (type alias)](#printable-type-alias)
- [Property (interface)](#property-interface)
- [TypeAlias (interface)](#typealias-interface)
- [sorting](#sorting)
- [ByPath](#bypath)

---

# accessors

## printablesFromModule

**Signature**

```ts
export declare const printablesFromModule: (module: Module) => ReadonlyArray<Printable>
```
Added in v1.0.0
# constructors
## createClass
Expand Down Expand Up @@ -370,6 +385,16 @@ export interface Namespace extends NamedDoc {

Added in v1.0.0

## Printable (type alias)

**Signature**

```ts
export type Printable = Class | Constant | Export | Function | Interface | TypeAlias | Namespace
```
Added in v1.0.0
## Property (interface)
**Signature**
Expand Down
15 changes: 15 additions & 0 deletions docs/modules/Markdown.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Added in v1.0.0

- [printers](#printers)
- [printModule](#printmodule)
- [printPrintableForAI](#printprintableforai)

---

Expand All @@ -40,3 +41,17 @@ console.log(Markdown.printModule(m, 0))
```

Added in v1.0.0

## printPrintableForAI

**Signature**

```ts
export declare const printPrintableForAI: (
projectName: string,
module: Domain.Module,
printable: Domain.Printable
) => Effect.Effect<string, never, never>
```
Added in v1.0.0
5 changes: 5 additions & 0 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@
],
"description": "tsconfig for the examples options (or path to a tsconfig)",
"default": {}
},
"enableAI": {
"type": "boolean",
"description": "Whether or not to enable AI for the examples",
"default": true
}
},
"additionalProperties": false
Expand Down
14 changes: 13 additions & 1 deletion src/CLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ const examplesCompilerOptions = Options.file("examples-tsconfig-file", { exists:
Options.optional
)

const enableAI = Options.boolean("no-run-examples", {
ifPresent: false,
negationNames: ["run-examples"]
}).pipe(
Options.withFallbackConfig(Config.boolean("enableAI")),
Options.withDefault(true),
Options.withDescription(
"Whether or not to generate AI documentation for the project"
)
)

const options = {
projectHomepage,
srcDir,
Expand All @@ -168,7 +179,8 @@ const options = {
runExamples,
exclude,
parseCompilerOptions,
examplesCompilerOptions
examplesCompilerOptions,
enableAI
}

/** @internal */
Expand Down
6 changes: 6 additions & 0 deletions src/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export const ConfigurationSchema = Schema.Struct({
examplesCompilerOptions: Schema.optional(compilerOptionsSchema).annotations({
description: "tsconfig for the examples options (or path to a tsconfig)",
default: {}
}),
enableAI: Schema.optional(Schema.Boolean).annotations({
description: "Whether or not to enable AI for the examples",
default: true
})
}).annotations({ identifier: "ConfigurationSchema" })

Expand All @@ -100,6 +104,7 @@ export interface ConfigurationShape {
readonly exclude: ReadonlyArray<string>
readonly parseCompilerOptions: Record<string, unknown>
readonly examplesCompilerOptions: Record<string, unknown>
readonly enableAI: boolean
}

/**
Expand Down Expand Up @@ -244,6 +249,7 @@ export const load = (args: {
readonly exclude: ReadonlyArray<string>
readonly parseCompilerOptions: Option.Option<string | Record<string, unknown>>
readonly examplesCompilerOptions: Option.Option<string | Record<string, unknown>>
readonly enableAI: boolean
}) =>
Effect.gen(function*(_) {
// Extract the requisite services
Expand Down
44 changes: 41 additions & 3 deletions src/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ import { pipe } from "effect"
import * as Array from "effect/Array"
import * as Chunk from "effect/Chunk"
import * as Effect from "effect/Effect"
import { pipe } from "effect/Function"

Check failure on line 15 in src/Core.ts

View workflow job for this annotation

GitHub Actions / Types

Duplicate identifier 'pipe'.

Check failure on line 15 in src/Core.ts

View workflow job for this annotation

GitHub Actions / Types

Duplicate identifier 'pipe'.
import * as Stream from "effect/Stream"
import * as String from "effect/String"
import * as Glob from "glob"
import * as Configuration from "./Configuration.js"
import type * as Domain from "./Domain.js"
import * as Domain from "./Domain.js"
import { DocgenError } from "./Error.js"
import * as File from "./File.js"
import { printModule } from "./Markdown.js"
import { printModule, printPrintableForAI } from "./Markdown.js"
import * as Parser from "./Parser.js"
import * as Process from "./Process.js"

Expand Down Expand Up @@ -436,7 +437,8 @@ const getMarkdown = (modules: ReadonlyArray<Domain.Module>) =>
const index = yield* _(getMarkdownIndex)
const yml = yield* _(getMarkdownConfigYML)
const moduleFiles = yield* _(getModuleMarkdownFiles(modules))
return [homepage, index, yml, ...moduleFiles]
const aiFiles = yield* _(maybeGetAIMarkdownFiles(modules))
return [homepage, index, yml, ...moduleFiles, ...aiFiles]
})

const getMarkdownHomepage = Effect.gen(function*(_) {
Expand Down Expand Up @@ -538,6 +540,14 @@ const getModuleMarkdownOutputPath = (module: Domain.Module) =>
))
)

const getAIMarkdownOutputPath = (module: Domain.Module, printable: Domain.Printable) =>
Effect.map(Effect.all([Configuration.Configuration, Path.Path]), ([config, path]) =>
path.join(
config.outDir,
"ai",
`${module.path.slice(1).join("-").replace(/\.ts$/, "")}-${printable.name}.md`
))

const getModuleMarkdownFiles = (modules: ReadonlyArray<Domain.Module>) =>
Effect.forEach(modules, (module, order) =>
Effect.gen(function*(_) {
Expand All @@ -546,6 +556,34 @@ const getModuleMarkdownFiles = (modules: ReadonlyArray<Domain.Module>) =>
return File.createFile(outputPath, content, true)
}))

const getAIMarkdownFiles = (projectName: string, modules: ReadonlyArray<Domain.Module>) =>
Effect.gen(function*(_) {
const aiModules = pipe(
modules,
Array.flatMap((module) =>
pipe(
Domain.printablesFromModule(module),
Array.map((printable) => ({ module, printable }))
)
),
Array.filter(({ printable }) => printable.description._tag === "Some")
)

return yield* _(Effect.forEach(aiModules, ({ module, printable }) =>
Effect.gen(function*(_) {
const outputPath = yield* _(getAIMarkdownOutputPath(module, printable))
const content = yield* _(printPrintableForAI(projectName, module, printable))
return File.createFile(outputPath, content, true)
})))
})

const maybeGetAIMarkdownFiles = (modules: ReadonlyArray<Domain.Module>) =>
Effect.flatMap(
Configuration.Configuration,
(config) =>
config.enableAI ? getAIMarkdownFiles(config.projectName, modules) : Effect.succeed([])
)

const writeMarkdown = (files: ReadonlyArray<File.File>) =>
Effect.gen(function*(_) {
const config = yield* _(Configuration.Configuration)
Expand Down
31 changes: 31 additions & 0 deletions src/Domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ export interface Namespace extends NamedDoc {
readonly namespaces: ReadonlyArray<Namespace>
}

/**
* @category model
* @since 1.0.0
*/
export type Printable =
| Class
| Constant
| Export
| Function
| Interface
| TypeAlias
| Namespace

// -------------------------------------------------------------------------------------
// constructors
// -------------------------------------------------------------------------------------
Expand Down Expand Up @@ -282,6 +295,24 @@ export const createExport = (doc: NamedDoc, signature: string): Export => ({
signature
})

// -------------------------------------------------------------------------------------
// accessors
// -------------------------------------------------------------------------------------

/**
* @category accessors
* @since 1.0.0
*/
export const printablesFromModule = (module: Module): ReadonlyArray<Printable> =>
[
module.classes,
module.constants,
module.exports,
module.functions,
module.interfaces,
module.typeAliases
].flat()

/**
* @category constructors
* @since 1.0.0
Expand Down
60 changes: 48 additions & 12 deletions src/Markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ import * as String from "effect/String"
import * as Prettier from "prettier"
import type * as Domain from "./Domain.js"

type Printable =
| Domain.Class
| Domain.Constant
| Domain.Export
| Domain.Function
| Domain.Interface
| Domain.TypeAlias
| Domain.Namespace

const createHeaderPrinter = (level: number) => (content: string): string =>
"#".repeat(level) + " " + content + "\n\n"

Expand Down Expand Up @@ -72,6 +63,28 @@ const printExamples = (es: ReadonlyArray<Domain.Example>): string =>
)
.join("\n\n")

const printImportDescription = (
projectName: string,
module: Domain.Module,
method: string
): string => {
const namespace = module.path.slice(1).join("/").replace(/\.ts$/, "")

return (
MarkdownPrinter.paragraph(
`To import and use \`${method}\` from the "${module.name}" module:`
) +
MarkdownPrinter.paragraph(
MarkdownPrinter.fence(

Check failure on line 78 in src/Markdown.ts

View workflow job for this annotation

GitHub Actions / Types

Expected 3 arguments, but got 2.

Check failure on line 78 in src/Markdown.ts

View workflow job for this annotation

GitHub Actions / Types

Expected 3 arguments, but got 2.

Check failure on line 78 in src/Markdown.ts

View workflow job for this annotation

GitHub Actions / Types

Expected 3 arguments, but got 2.
"ts",
`import * as ${module.name} from "${projectName}/${namespace}"
// Can be accessed like this
${module.name}.${method}`
)
)
)
}

const printStaticMethod = (m: Domain.Method): string =>
MarkdownPrinter.paragraph(
MarkdownPrinter.h3(printTitle(m.name, m.deprecated, "(static method)")),
Expand Down Expand Up @@ -229,7 +242,7 @@ export const printNamespace = (ns: Domain.Namespace, indentation: number): strin
)

/** @internal */
export const print = (p: Printable): string => {
export const print = (p: Domain.Printable): string => {
switch (p._tag) {
case "Class":
return printClass(p)
Expand All @@ -248,7 +261,7 @@ export const print = (p: Printable): string => {
}
}

const getPrintables = (module: Domain.Module): ReadonlyArray<Printable> =>
const getPrintables = (module: Domain.Module): ReadonlyArray<Domain.Printable> =>
Array.flatten([
module.classes,
module.constants,
Expand Down Expand Up @@ -301,7 +314,7 @@ export const printModule = (
Array.sort(
Order.mapInput(
String.Order,
(printable: Printable) => printable.name
(printable: Domain.Printable) => printable.name
)
),
Array.map(print)
Expand Down Expand Up @@ -337,6 +350,29 @@ export const printModule = (
))
})

/**
* @category printers
* @since 1.0.0
*/
export const printPrintableForAI = (
projectName: string,
module: Domain.Module,
printable: Domain.Printable
) =>
prettify(
[
MarkdownPrinter.h1(printable.name),
printDescription(printable.description),
printImportDescription(projectName, module, printable.name),
printExamples(printable.examples),
printable._tag === "Function"
? printSignatures(printable.signatures)
: printable._tag === "Constant"
? printSignature(printable.signature)
: ""
].join("\n")
)

const defaultPrettierOptions: Prettier.Options = {
parser: "markdown",
semi: false,
Expand Down
1 change: 1 addition & 0 deletions test/Parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultConfig: Configuration.ConfigurationShape = {
srcDir: "src",
outDir: "docs",
theme: "pmarsceill/just-the-docs",
enableAI: true,
enableSearch: true,
enforceDescriptions: false,
enforceExamples: false,
Expand Down

0 comments on commit 868083a

Please sign in to comment.