@functional-examples/documentation 0.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/generate.d.ts +21 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +243 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/index.d.ts +21 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +5 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/extractor/extractor.d.ts +9 -0
- package/dist/extractor/extractor.d.ts.map +1 -0
- package/dist/extractor/extractor.js +95 -0
- package/dist/extractor/extractor.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/renderers/markdoc.d.ts +13 -0
- package/dist/renderers/markdoc.d.ts.map +1 -0
- package/dist/renderers/markdoc.js +42 -0
- package/dist/renderers/markdoc.js.map +1 -0
- package/dist/renderers/markdown.d.ts +6 -0
- package/dist/renderers/markdown.d.ts.map +1 -0
- package/dist/renderers/markdown.js +12 -0
- package/dist/renderers/markdown.js.map +1 -0
- package/dist/renderers/types.d.ts +14 -0
- package/dist/renderers/types.d.ts.map +1 -0
- package/dist/renderers/types.js +2 -0
- package/dist/renderers/types.js.map +1 -0
- package/dist/schema.d.ts +63 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +49 -0
- package/dist/schema.js.map +1 -0
- package/dist/templates/consumption-tracker.d.ts +16 -0
- package/dist/templates/consumption-tracker.d.ts.map +1 -0
- package/dist/templates/consumption-tracker.js +21 -0
- package/dist/templates/consumption-tracker.js.map +1 -0
- package/dist/templates/engine.d.ts +123 -0
- package/dist/templates/engine.d.ts.map +1 -0
- package/dist/templates/engine.js +212 -0
- package/dist/templates/engine.js.map +1 -0
- package/dist/templates/guide-renderer.d.ts +59 -0
- package/dist/templates/guide-renderer.d.ts.map +1 -0
- package/dist/templates/guide-renderer.js +93 -0
- package/dist/templates/guide-renderer.js.map +1 -0
- package/dist/templates/helpers.d.ts +45 -0
- package/dist/templates/helpers.d.ts.map +1 -0
- package/dist/templates/helpers.js +104 -0
- package/dist/templates/helpers.js.map +1 -0
- package/dist/templates/prose-helpers.d.ts +26 -0
- package/dist/templates/prose-helpers.d.ts.map +1 -0
- package/dist/templates/prose-helpers.js +39 -0
- package/dist/templates/prose-helpers.js.map +1 -0
- package/dist/types.d.ts +48 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/package.json +62 -0
- package/templates/@slug.md.template +40 -0
- package/templates/@slug.mdoc.template +40 -0
- package/templates/index.md.template +9 -0
- package/templates/index.mdoc.template +9 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/renderers/types.ts"],"names":[],"mappings":""}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ValidationResult } from '@functional-examples/devkit';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for documentation-specific metadata.
|
|
5
|
+
*/
|
|
6
|
+
export declare const docsMetadataSchema: z.ZodObject<{
|
|
7
|
+
docs: z.ZodOptional<z.ZodObject<{
|
|
8
|
+
template: z.ZodOptional<z.ZodString>;
|
|
9
|
+
skip: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
outputName: z.ZodOptional<z.ZodString>;
|
|
11
|
+
/** Descriptions for specific hunks/regions, keyed by hunk ID */
|
|
12
|
+
hunks: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
13
|
+
}, z.core.$strict>>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type DocsMetadataSchemaType = z.infer<typeof docsMetadataSchema>;
|
|
16
|
+
/** JSON Schema for metadata plugin registration */
|
|
17
|
+
export declare const DOCS_METADATA_JSON_SCHEMA: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
|
|
18
|
+
docs: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
template: z.ZodOptional<z.ZodString>;
|
|
20
|
+
skip: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
outputName: z.ZodOptional<z.ZodString>;
|
|
22
|
+
/** Descriptions for specific hunks/regions, keyed by hunk ID */
|
|
23
|
+
hunks: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
24
|
+
}, z.core.$strict>>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
/**
|
|
27
|
+
* Zod schema for documentation plugin options.
|
|
28
|
+
* Fields with defaults are resolved via `docsOptionsSchema.parse(...)`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const docsOptionsSchema: z.ZodObject<{
|
|
31
|
+
outputDir: z.ZodDefault<z.ZodString>;
|
|
32
|
+
format: z.ZodDefault<z.ZodEnum<{
|
|
33
|
+
markdown: "markdown";
|
|
34
|
+
mdoc: "mdoc";
|
|
35
|
+
}>>;
|
|
36
|
+
templates: z.ZodOptional<z.ZodString>;
|
|
37
|
+
enableExtractor: z.ZodDefault<z.ZodBoolean>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
/** JSON Schema for options plugin registration */
|
|
40
|
+
export declare const DOCS_OPTIONS_JSON_SCHEMA: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
|
|
41
|
+
outputDir: z.ZodDefault<z.ZodString>;
|
|
42
|
+
format: z.ZodDefault<z.ZodEnum<{
|
|
43
|
+
markdown: "markdown";
|
|
44
|
+
mdoc: "mdoc";
|
|
45
|
+
}>>;
|
|
46
|
+
templates: z.ZodOptional<z.ZodString>;
|
|
47
|
+
enableExtractor: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
+
}, z.core.$strip>>;
|
|
49
|
+
/**
|
|
50
|
+
* Validate documentation metadata using Zod schema.
|
|
51
|
+
*/
|
|
52
|
+
export declare function validateDocsMetadata(metadata: unknown): ValidationResult;
|
|
53
|
+
/** Options for the documentation plugin factory (input — all optional). */
|
|
54
|
+
export type DocumentationPluginOptions = z.input<typeof docsOptionsSchema>;
|
|
55
|
+
/** Resolved options with defaults applied (output of parsing). */
|
|
56
|
+
export type ResolvedDocumentationPluginOptions = z.output<typeof docsOptionsSchema>;
|
|
57
|
+
/**
|
|
58
|
+
* Documentation-specific metadata that examples can declare.
|
|
59
|
+
*/
|
|
60
|
+
export interface DocsMetadata {
|
|
61
|
+
docs?: DocsMetadataSchemaType;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;QAMzB,gEAAgE;;;iBAIpE,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAExE,mDAAmD;AACnD,eAAO,MAAM,yBAAyB;;;;;QAThC,gEAAgE;;;kBASK,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;iBAK5B,CAAC;AAEH,kDAAkD;AAClD,eAAO,MAAM,wBAAwB;;;;;;;;kBAAoC,CAAC;AAW1E;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,gBAAgB,CAUxE;AAID,2EAA2E;AAC3E,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE3E,kEAAkE;AAClE,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACvD,OAAO,iBAAiB,CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for documentation-specific metadata.
|
|
4
|
+
*/
|
|
5
|
+
export const docsMetadataSchema = z.object({
|
|
6
|
+
docs: z
|
|
7
|
+
.strictObject({
|
|
8
|
+
template: z.string().optional(),
|
|
9
|
+
skip: z.boolean().optional(),
|
|
10
|
+
outputName: z.string().optional(),
|
|
11
|
+
/** Descriptions for specific hunks/regions, keyed by hunk ID */
|
|
12
|
+
hunks: z.record(z.string(), z.string()).optional(),
|
|
13
|
+
})
|
|
14
|
+
.optional(),
|
|
15
|
+
});
|
|
16
|
+
/** JSON Schema for metadata plugin registration */
|
|
17
|
+
export const DOCS_METADATA_JSON_SCHEMA = z.toJSONSchema(docsMetadataSchema);
|
|
18
|
+
/**
|
|
19
|
+
* Zod schema for documentation plugin options.
|
|
20
|
+
* Fields with defaults are resolved via `docsOptionsSchema.parse(...)`.
|
|
21
|
+
*/
|
|
22
|
+
export const docsOptionsSchema = z.object({
|
|
23
|
+
outputDir: z.string().default('./docs/examples'),
|
|
24
|
+
format: z.enum(['markdown', 'mdoc']).default('markdown'),
|
|
25
|
+
templates: z.string().optional(),
|
|
26
|
+
enableExtractor: z.boolean().default(false),
|
|
27
|
+
});
|
|
28
|
+
/** JSON Schema for options plugin registration */
|
|
29
|
+
export const DOCS_OPTIONS_JSON_SCHEMA = z.toJSONSchema(docsOptionsSchema);
|
|
30
|
+
function mapZodIssue(zIssue) {
|
|
31
|
+
return {
|
|
32
|
+
path: zIssue.path.join('.'),
|
|
33
|
+
message: zIssue.message,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validate documentation metadata using Zod schema.
|
|
38
|
+
*/
|
|
39
|
+
export function validateDocsMetadata(metadata) {
|
|
40
|
+
const result = docsMetadataSchema.safeParse(metadata);
|
|
41
|
+
if (result.success) {
|
|
42
|
+
return { success: true, errors: [] };
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
errors: result.error.issues.map(mapZodIssue),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC;SACJ,YAAY,CAAC;QACZ,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjC,gEAAgE;QAChE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACnD,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAIH,mDAAmD;AACnD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;IAChD,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACxD,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAC5C,CAAC,CAAC;AAEH,kDAAkD;AAClD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;AAE1E,SAAS,WAAW,CAClB,MAAwB;IAExB,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAiB;IACpD,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;KAC7C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ExampleFile } from '@functional-examples/devkit';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks which example files have been "consumed" by prose template helpers
|
|
4
|
+
* (e.g. `file()` or `region()`). Consumed files are excluded from the
|
|
5
|
+
* "remaining files" section in the rendered output.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ConsumptionTracker {
|
|
8
|
+
private consumed;
|
|
9
|
+
/** Mark a file as consumed by its relative path. */
|
|
10
|
+
consume(relativePath: string): void;
|
|
11
|
+
/** Check whether a file has been consumed. */
|
|
12
|
+
isConsumed(relativePath: string): boolean;
|
|
13
|
+
/** Return only those files that have NOT been consumed. */
|
|
14
|
+
getUnconsumedFiles(files: ExampleFile[]): ExampleFile[];
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=consumption-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumption-tracker.d.ts","sourceRoot":"","sources":["../../src/templates/consumption-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAqB;IAErC,oDAAoD;IACpD,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAInC,8CAA8C;IAC9C,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIzC,2DAA2D;IAC3D,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE;CAGxD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks which example files have been "consumed" by prose template helpers
|
|
3
|
+
* (e.g. `file()` or `region()`). Consumed files are excluded from the
|
|
4
|
+
* "remaining files" section in the rendered output.
|
|
5
|
+
*/
|
|
6
|
+
export class ConsumptionTracker {
|
|
7
|
+
consumed = new Set();
|
|
8
|
+
/** Mark a file as consumed by its relative path. */
|
|
9
|
+
consume(relativePath) {
|
|
10
|
+
this.consumed.add(relativePath);
|
|
11
|
+
}
|
|
12
|
+
/** Check whether a file has been consumed. */
|
|
13
|
+
isConsumed(relativePath) {
|
|
14
|
+
return this.consumed.has(relativePath);
|
|
15
|
+
}
|
|
16
|
+
/** Return only those files that have NOT been consumed. */
|
|
17
|
+
getUnconsumedFiles(files) {
|
|
18
|
+
return files.filter((f) => !this.consumed.has(f.relativePath));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=consumption-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumption-tracker.js","sourceRoot":"","sources":["../../src/templates/consumption-tracker.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACrB,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,oDAAoD;IACpD,OAAO,CAAC,YAAoB;QAC1B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAClC,CAAC;IAED,8CAA8C;IAC9C,UAAU,CAAC,YAAoB;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED,2DAA2D;IAC3D,kBAAkB,CAAC,KAAoB;QACrC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACjE,CAAC;CACF"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Example, ExampleFile } from '@functional-examples/devkit';
|
|
2
|
+
import { type TemplateHelpers } from './helpers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Template data model passed to Eta per-item templates as `it`.
|
|
5
|
+
*/
|
|
6
|
+
export interface TemplateData {
|
|
7
|
+
/** Example unique identifier */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Example title */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Example description */
|
|
12
|
+
description?: string;
|
|
13
|
+
/** Full metadata object */
|
|
14
|
+
metadata: Record<string, unknown>;
|
|
15
|
+
/** Example files */
|
|
16
|
+
files: ExampleFile[];
|
|
17
|
+
/** Template helper functions */
|
|
18
|
+
helpers: TemplateHelpers;
|
|
19
|
+
/** Prose files rendered through Eta (with file/region helpers expanded) */
|
|
20
|
+
renderedProse: string[];
|
|
21
|
+
/** Files not consumed by prose helpers — the "remaining" code files */
|
|
22
|
+
unconsumedFiles: ExampleFile[];
|
|
23
|
+
}
|
|
24
|
+
/** Data model for aggregate (index) templates. */
|
|
25
|
+
export interface IndexTemplateData {
|
|
26
|
+
examples: {
|
|
27
|
+
id: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
}[];
|
|
31
|
+
format: string;
|
|
32
|
+
helpers: TemplateHelpers;
|
|
33
|
+
}
|
|
34
|
+
/** Parsed template file descriptor. */
|
|
35
|
+
export interface TemplateDescriptor {
|
|
36
|
+
/** Absolute path to the .template source file */
|
|
37
|
+
sourcePath: string;
|
|
38
|
+
/** Filename minus '.template', e.g. '@slug.md' */
|
|
39
|
+
outputPattern: string;
|
|
40
|
+
/** File extension, e.g. '.md' or '.mdoc' */
|
|
41
|
+
format: string;
|
|
42
|
+
/** Whether the filename contains an @var placeholder */
|
|
43
|
+
perItem: boolean;
|
|
44
|
+
/** Variable name (e.g. 'slug') when perItem is true */
|
|
45
|
+
variable?: string;
|
|
46
|
+
/** Raw Eta template content */
|
|
47
|
+
content: string;
|
|
48
|
+
}
|
|
49
|
+
/** Rendered output ready to write. */
|
|
50
|
+
export interface RenderedFile {
|
|
51
|
+
/** Relative path for the output file */
|
|
52
|
+
relativePath: string;
|
|
53
|
+
/** Rendered content */
|
|
54
|
+
content: string;
|
|
55
|
+
}
|
|
56
|
+
/** Result of rendering prose files through Eta. */
|
|
57
|
+
export interface ProseRenderResult {
|
|
58
|
+
/** Rendered prose content strings (one per prose file). */
|
|
59
|
+
renderedProse: string[];
|
|
60
|
+
/** Files not consumed by prose file/region helpers. */
|
|
61
|
+
unconsumedFiles: ExampleFile[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Render prose files through Eta, expanding `file()` and `region()` helpers,
|
|
65
|
+
* and return which files remain unconsumed.
|
|
66
|
+
*/
|
|
67
|
+
export declare function renderProseFiles(files: ExampleFile[], metadata: Record<string, unknown>): ProseRenderResult;
|
|
68
|
+
/**
|
|
69
|
+
* Build the template data model from an Example.
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildTemplateData(example: Example): TemplateData;
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the built-in templates directory relative to this file.
|
|
74
|
+
* At runtime, this file lives at `dist/templates/engine.js`.
|
|
75
|
+
* The templates directory is at `packages/documentation/templates/`
|
|
76
|
+
* — two levels up from `dist/templates/`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function getBuiltinTemplatesDir(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Parse a template's relative path into its descriptor fields.
|
|
81
|
+
*
|
|
82
|
+
* The `@var` convention can appear in any path segment — either in the
|
|
83
|
+
* filename itself or in a directory name:
|
|
84
|
+
* - `@slug.md.template` → variable `slug` (flat, filename)
|
|
85
|
+
* - `examples/@example/index.md.template` → variable `example` (nested, directory)
|
|
86
|
+
*
|
|
87
|
+
* @param relativePath - Path relative to the templates root, e.g. `examples/@example/index.md.template`
|
|
88
|
+
*/
|
|
89
|
+
export declare function parseTemplateName(relativePath: string): Pick<TemplateDescriptor, 'outputPattern' | 'format' | 'perItem' | 'variable'>;
|
|
90
|
+
/**
|
|
91
|
+
* Replace `@var` placeholders in a pattern with values from a vars map.
|
|
92
|
+
*
|
|
93
|
+
* Example: `substituteVars('@slug.md', { slug: 'getting-started' })` → `getting-started.md`
|
|
94
|
+
*/
|
|
95
|
+
export declare function substituteVars(pattern: string, vars: Record<string, string>): string;
|
|
96
|
+
/**
|
|
97
|
+
* Load all `.template` files from a directory (recursively) and parse their paths.
|
|
98
|
+
*
|
|
99
|
+
* Supports nested directory structures like:
|
|
100
|
+
* ```
|
|
101
|
+
* templates/
|
|
102
|
+
* index.md.template
|
|
103
|
+
* examples/@example/index.md.template
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare function loadTemplates(dir?: string): Promise<TemplateDescriptor[]>;
|
|
107
|
+
/**
|
|
108
|
+
* Render a per-item template for a single example.
|
|
109
|
+
*/
|
|
110
|
+
export declare function renderItemTemplate(template: TemplateDescriptor, example: Example): Promise<RenderedFile>;
|
|
111
|
+
/**
|
|
112
|
+
* Render an aggregate template with all examples.
|
|
113
|
+
*/
|
|
114
|
+
export declare function renderIndexTemplate(template: TemplateDescriptor, examples: Example[]): Promise<RenderedFile>;
|
|
115
|
+
/**
|
|
116
|
+
* Render an example using the default or a custom template file.
|
|
117
|
+
*
|
|
118
|
+
* @param example - The example to render
|
|
119
|
+
* @param templatePath - Optional path to a custom .eta template file
|
|
120
|
+
* @returns Rendered string
|
|
121
|
+
*/
|
|
122
|
+
export declare function renderTemplate(example: Example, templatePath?: string): Promise<string>;
|
|
123
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/templates/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Eta } from 'eta';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { ConsumptionTracker } from './consumption-tracker.js';
|
|
6
|
+
import { isProseFile, templateHelpers } from './helpers.js';
|
|
7
|
+
import { createProseHelpers } from './prose-helpers.js';
|
|
8
|
+
const eta = new Eta({ autoEscape: false, autoTrim: false });
|
|
9
|
+
/**
|
|
10
|
+
* Separate Eta instance for prose files.
|
|
11
|
+
* Uses `functionHeader` to inject short helper names into template scope
|
|
12
|
+
* so authors write `<%= file('utils.ts') %>` instead of `<%= it.file('utils.ts') %>`.
|
|
13
|
+
*/
|
|
14
|
+
const proseEta = new Eta({
|
|
15
|
+
autoEscape: false,
|
|
16
|
+
autoTrim: false,
|
|
17
|
+
functionHeader: 'var file = it.file, region = it.region, files = it.files, helpers = it.helpers;',
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Render prose files through Eta, expanding `file()` and `region()` helpers,
|
|
21
|
+
* and return which files remain unconsumed.
|
|
22
|
+
*/
|
|
23
|
+
export function renderProseFiles(files, metadata) {
|
|
24
|
+
const tracker = new ConsumptionTracker();
|
|
25
|
+
const helpers = createProseHelpers(files, tracker);
|
|
26
|
+
const proseFiles = files.filter(isProseFile);
|
|
27
|
+
const renderedProse = [];
|
|
28
|
+
// Prose files themselves are always consumed (they render inline)
|
|
29
|
+
for (const pf of proseFiles) {
|
|
30
|
+
tracker.consume(pf.relativePath);
|
|
31
|
+
}
|
|
32
|
+
for (const pf of proseFiles) {
|
|
33
|
+
const content = pf.parsed ?? pf.raw ?? '';
|
|
34
|
+
const rendered = proseEta.renderString(content, {
|
|
35
|
+
...helpers,
|
|
36
|
+
metadata,
|
|
37
|
+
});
|
|
38
|
+
renderedProse.push(rendered);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
renderedProse,
|
|
42
|
+
unconsumedFiles: tracker.getUnconsumedFiles(files),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build the template data model from an Example.
|
|
47
|
+
*/
|
|
48
|
+
export function buildTemplateData(example) {
|
|
49
|
+
const metadata = example.metadata;
|
|
50
|
+
const { renderedProse, unconsumedFiles } = renderProseFiles(example.files, metadata);
|
|
51
|
+
return {
|
|
52
|
+
id: example.id,
|
|
53
|
+
title: example.title,
|
|
54
|
+
description: example.description,
|
|
55
|
+
metadata,
|
|
56
|
+
files: example.files,
|
|
57
|
+
helpers: templateHelpers,
|
|
58
|
+
renderedProse,
|
|
59
|
+
unconsumedFiles,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the built-in templates directory relative to this file.
|
|
64
|
+
* At runtime, this file lives at `dist/templates/engine.js`.
|
|
65
|
+
* The templates directory is at `packages/documentation/templates/`
|
|
66
|
+
* — two levels up from `dist/templates/`.
|
|
67
|
+
*/
|
|
68
|
+
export function getBuiltinTemplatesDir() {
|
|
69
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
70
|
+
return path.resolve(path.dirname(thisFile), '../../templates');
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse a template's relative path into its descriptor fields.
|
|
74
|
+
*
|
|
75
|
+
* The `@var` convention can appear in any path segment — either in the
|
|
76
|
+
* filename itself or in a directory name:
|
|
77
|
+
* - `@slug.md.template` → variable `slug` (flat, filename)
|
|
78
|
+
* - `examples/@example/index.md.template` → variable `example` (nested, directory)
|
|
79
|
+
*
|
|
80
|
+
* @param relativePath - Path relative to the templates root, e.g. `examples/@example/index.md.template`
|
|
81
|
+
*/
|
|
82
|
+
export function parseTemplateName(relativePath) {
|
|
83
|
+
const outputPattern = relativePath.replace(/\.template$/, '');
|
|
84
|
+
const format = path.extname(outputPattern);
|
|
85
|
+
// Scan all path segments for an @-prefixed name
|
|
86
|
+
const segments = outputPattern.split('/');
|
|
87
|
+
let variable;
|
|
88
|
+
for (const segment of segments) {
|
|
89
|
+
if (segment.startsWith('@')) {
|
|
90
|
+
// '@slug.md' → 'slug', '@example' → 'example'
|
|
91
|
+
const ext = path.extname(segment);
|
|
92
|
+
variable = ext ? segment.slice(1, -ext.length) : segment.slice(1);
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const perItem = variable !== undefined;
|
|
97
|
+
const result = {
|
|
98
|
+
outputPattern,
|
|
99
|
+
format,
|
|
100
|
+
perItem,
|
|
101
|
+
};
|
|
102
|
+
if (perItem) {
|
|
103
|
+
result.variable = variable;
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Replace `@var` placeholders in a pattern with values from a vars map.
|
|
109
|
+
*
|
|
110
|
+
* Example: `substituteVars('@slug.md', { slug: 'getting-started' })` → `getting-started.md`
|
|
111
|
+
*/
|
|
112
|
+
export function substituteVars(pattern, vars) {
|
|
113
|
+
let result = pattern;
|
|
114
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
115
|
+
result = result.replace(`@${key}`, value);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Recursively collect all `.template` files under a directory.
|
|
121
|
+
* Returns paths relative to `root`.
|
|
122
|
+
*/
|
|
123
|
+
async function collectTemplateFiles(root, current = root) {
|
|
124
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
125
|
+
const results = [];
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
const fullPath = path.join(current, entry.name);
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
results.push(...(await collectTemplateFiles(root, fullPath)));
|
|
130
|
+
}
|
|
131
|
+
else if (entry.name.endsWith('.template')) {
|
|
132
|
+
results.push(path.relative(root, fullPath));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return results;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Load all `.template` files from a directory (recursively) and parse their paths.
|
|
139
|
+
*
|
|
140
|
+
* Supports nested directory structures like:
|
|
141
|
+
* ```
|
|
142
|
+
* templates/
|
|
143
|
+
* index.md.template
|
|
144
|
+
* examples/@example/index.md.template
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export async function loadTemplates(dir) {
|
|
148
|
+
const templatesDir = dir ?? getBuiltinTemplatesDir();
|
|
149
|
+
const relativePaths = await collectTemplateFiles(templatesDir);
|
|
150
|
+
const descriptors = [];
|
|
151
|
+
for (const relPath of relativePaths) {
|
|
152
|
+
const sourcePath = path.join(templatesDir, relPath);
|
|
153
|
+
const content = await fs.readFile(sourcePath, 'utf-8');
|
|
154
|
+
const parsed = parseTemplateName(relPath);
|
|
155
|
+
descriptors.push({
|
|
156
|
+
sourcePath,
|
|
157
|
+
content,
|
|
158
|
+
...parsed,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return descriptors;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Render a per-item template for a single example.
|
|
165
|
+
*/
|
|
166
|
+
export async function renderItemTemplate(template, example) {
|
|
167
|
+
const data = buildTemplateData(example);
|
|
168
|
+
const content = eta.renderString(template.content, data);
|
|
169
|
+
const vars = {};
|
|
170
|
+
if (template.variable) {
|
|
171
|
+
vars[template.variable] = example.id;
|
|
172
|
+
}
|
|
173
|
+
const relativePath = substituteVars(template.outputPattern, vars);
|
|
174
|
+
return { relativePath, content };
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Render an aggregate template with all examples.
|
|
178
|
+
*/
|
|
179
|
+
export async function renderIndexTemplate(template, examples) {
|
|
180
|
+
const data = {
|
|
181
|
+
examples: examples.map((e) => ({
|
|
182
|
+
id: e.id,
|
|
183
|
+
title: e.title,
|
|
184
|
+
description: e.description,
|
|
185
|
+
})),
|
|
186
|
+
format: template.format,
|
|
187
|
+
helpers: templateHelpers,
|
|
188
|
+
};
|
|
189
|
+
const content = eta.renderString(template.content, data);
|
|
190
|
+
return { relativePath: template.outputPattern, content };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Render an example using the default or a custom template file.
|
|
194
|
+
*
|
|
195
|
+
* @param example - The example to render
|
|
196
|
+
* @param templatePath - Optional path to a custom .eta template file
|
|
197
|
+
* @returns Rendered string
|
|
198
|
+
*/
|
|
199
|
+
export async function renderTemplate(example, templatePath) {
|
|
200
|
+
const data = buildTemplateData(example);
|
|
201
|
+
if (templatePath) {
|
|
202
|
+
const absPath = path.resolve(templatePath);
|
|
203
|
+
const templateStr = await fs.readFile(absPath, 'utf-8');
|
|
204
|
+
return eta.renderString(templateStr, data);
|
|
205
|
+
}
|
|
206
|
+
// Fall back to built-in markdown template
|
|
207
|
+
const builtinDir = getBuiltinTemplatesDir();
|
|
208
|
+
const defaultTemplate = path.join(builtinDir, '@slug.md.template');
|
|
209
|
+
const templateStr = await fs.readFile(defaultTemplate, 'utf-8');
|
|
210
|
+
return eta.renderString(templateStr, data);
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/templates/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guide hydration renderer — expands example references in standalone
|
|
3
|
+
* markdown guides that reference files/regions from *any* scanned example.
|
|
4
|
+
*
|
|
5
|
+
* Unlike prose helpers (scoped to a single example), the guide renderer
|
|
6
|
+
* creates a cross-example lookup so authors can write:
|
|
7
|
+
*
|
|
8
|
+
* ```markdown
|
|
9
|
+
* <%= example('basic-usage').file('scan.ts') %>
|
|
10
|
+
* <%= example('basic-usage').region('config-setup') %>
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
import type { ExampleFile, ScannedExample } from '@functional-examples/devkit';
|
|
14
|
+
/**
|
|
15
|
+
* A renderer that expands example references in guide markdown.
|
|
16
|
+
*/
|
|
17
|
+
export interface GuideRenderer {
|
|
18
|
+
/** Render a markdown string, expanding example references. */
|
|
19
|
+
render(markdown: string): string;
|
|
20
|
+
/** Read a markdown file and render it, expanding example references. */
|
|
21
|
+
renderFile(filePath: string): Promise<string>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Scoped API returned by `example(id)` inside guide templates.
|
|
25
|
+
*/
|
|
26
|
+
export interface ExampleAccessor {
|
|
27
|
+
/** Render a file as a fenced code block. */
|
|
28
|
+
file(relativePath: string): string;
|
|
29
|
+
/** Render a region/hunk as a fenced code block. */
|
|
30
|
+
region(regionId: string): string;
|
|
31
|
+
/** All files in the example. */
|
|
32
|
+
files: ExampleFile[];
|
|
33
|
+
/** The example's metadata. */
|
|
34
|
+
metadata: Record<string, unknown>;
|
|
35
|
+
/** The example's title. */
|
|
36
|
+
title: string;
|
|
37
|
+
/** The example's description. */
|
|
38
|
+
description?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a guide renderer bound to a set of scanned examples.
|
|
42
|
+
*
|
|
43
|
+
* Guide templates can reference any example by ID:
|
|
44
|
+
* ```markdown
|
|
45
|
+
* <%= example('basic-usage').file('scan.ts') %>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* import { createGuideRenderer } from '@functional-examples/documentation';
|
|
51
|
+
* import { scan } from 'functional-examples';
|
|
52
|
+
*
|
|
53
|
+
* const { examples } = await scan({ root: workspaceRoot });
|
|
54
|
+
* const renderer = createGuideRenderer(examples);
|
|
55
|
+
* const html = await renderer.renderFile('docs/guides/getting-started.md');
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function createGuideRenderer(examples: ScannedExample[]): GuideRenderer;
|
|
59
|
+
//# sourceMappingURL=guide-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide-renderer.d.ts","sourceRoot":"","sources":["../../src/templates/guide-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAM/E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,wEAAwE;IACxE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,mDAAmD;IACnD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,gCAAgC;IAChC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,aAAa,CAwE7E"}
|