diff --git a/src/generators/web/README.md b/src/generators/web/README.md index 17f8e138..6db51c3a 100644 --- a/src/generators/web/README.md +++ b/src/generators/web/README.md @@ -6,17 +6,18 @@ The `web` generator transforms JSX AST entries into complete web bundles, produc The `web` generator accepts the following configuration options: -| Name | Type | Default | Description | -| ----------------- | --------- | --------------------------------------------- | --------------------------------------------------------------------- | -| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written | -| `templatePath` | `string` | `'template.html'` | Path to the HTML template file | -| `project` | `string` | `'Node.js'` | Project name used in page titles and the version selector | -| `title` | `string` | `'{project} v{version} Documentation'` | Title template for HTML pages (supports `{project}`, `{version}`) | -| `useAbsoluteURLs` | `boolean` | `false` | When `true`, all internal links use absolute URLs based on `baseURL` | -| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links | -| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links | -| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization | -| `virtualImports` | `object` | `{}` | Additional virtual module mappings merged into the build | +| Name | Type | Default | Description | +| ----------------------- | ---------- | --------------------------------------------- | --------------------------------------------------------------------- | +| `output` | `string` | - | The directory where HTML, JavaScript, and CSS files will be written | +| `templatePath` | `string` | `'template.html'` | Path to the HTML template file | +| `project` | `string` | `'Node.js'` | Project name used in page titles and the version selector | +| `title` | `string` | `'{project} v{version} Documentation'` | Title template for HTML pages (supports `{project}`, `{version}`) | +| `useAbsoluteURLs` | `boolean` | `false` | When `true`, all internal links use absolute URLs based on `baseURL` | +| `editURL` | `string` | `'${GITHUB_EDIT_URL}/doc/api{path}.md'` | URL template for "edit this page" links | +| `pageURL` | `string` | `'{baseURL}/latest-{version}/api{path}.html'` | URL template for documentation page links | +| `imports` | `object` | See below | Object mapping `#theme/` aliases to component paths for customization | +| `virtualImports` | `object` | `{}` | Additional virtual module mappings merged into the build | +| `additionalPathsToCopy` | `string[]` | `[]` | Array of paths to copy to the output directory | #### Default `imports` diff --git a/src/generators/web/__tests__/generate.test.mjs b/src/generators/web/__tests__/generate.test.mjs index c4ba50db..e338ba61 100644 --- a/src/generators/web/__tests__/generate.test.mjs +++ b/src/generators/web/__tests__/generate.test.mjs @@ -1,10 +1,13 @@ import assert from 'node:assert/strict'; +import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; import { describe, it } from 'node:test'; import { setConfig } from '../../../utils/configuration/index.mjs'; import buildContent from '../../jsx-ast/utils/buildContent.mjs'; import { buildNotFoundPage } from '../../jsx-ast/utils/synthetic/404.mjs'; -import { generate } from '../generate.mjs'; +import { copyAdditionalPaths, generate } from '../generate.mjs'; const createEntry = (api, name) => { const heading = { @@ -54,4 +57,24 @@ describe('web generate', () => { assert.doesNotMatch(notFoundResult.html, /href=404\.json/); assert.doesNotMatch(notFoundResult.html, /href=404\.md/); }); + + it('copies additional paths to the output directory', async () => { + const temp = await mkdtemp(join(tmpdir(), 'doc-kit-web-')); + const source = join(temp, 'assets'); + const output = join(temp, 'output'); + + await mkdir(source); + await writeFile(join(source, 'logo.txt'), 'static asset'); + + try { + await copyAdditionalPaths([source], output); + + assert.equal( + await readFile(join(output, 'assets', 'logo.txt'), 'utf-8'), + 'static asset' + ); + } finally { + await rm(temp, { recursive: true, force: true }); + } + }); }); diff --git a/src/generators/web/generate.mjs b/src/generators/web/generate.mjs index 7ec803ef..5b93a5ba 100644 --- a/src/generators/web/generate.mjs +++ b/src/generators/web/generate.mjs @@ -1,12 +1,25 @@ 'use strict'; -import { readFile } from 'node:fs/promises'; -import { join } from 'node:path'; +import { cp, readFile } from 'node:fs/promises'; +import { basename, join } from 'node:path'; import { processJSXEntries } from './utils/processing.mjs'; import getConfig from '../../utils/configuration/index.mjs'; import { writeFile } from '../../utils/file.mjs'; +/** + * Copies configured static paths into the generator output directory. + * + * @param {Array} paths + * @param {string} output + */ +export const copyAdditionalPaths = (paths, output) => + Promise.all( + paths.map(path => + cp(path, join(output, basename(path)), { recursive: true }) + ) + ); + /** * Main generation function that processes JSX AST entries into web bundles. * @@ -39,6 +52,8 @@ export async function generate(input) { } await writeFile(join(config.output, 'styles.css'), css, 'utf-8'); + + await copyAdditionalPaths(config.additionalPathsToCopy, config.output); } return results.map(({ html }) => ({ html: html.toString(), css })); diff --git a/src/generators/web/index.mjs b/src/generators/web/index.mjs index 7f86ba9b..00422bda 100644 --- a/src/generators/web/index.mjs +++ b/src/generators/web/index.mjs @@ -44,5 +44,6 @@ export default createLazyGenerator({ '#theme/Layout': join(import.meta.dirname, './ui/components/Layout'), }, virtualImports: {}, + additionalPathsToCopy: [], }, }); diff --git a/src/generators/web/types.d.ts b/src/generators/web/types.d.ts index 0506b4be..698ac153 100644 --- a/src/generators/web/types.d.ts +++ b/src/generators/web/types.d.ts @@ -6,6 +6,7 @@ export type Configuration = { useAbsoluteURLs: boolean; imports: Record; virtualImports: Record; + additionalPathsToCopy: Array; }; export type Generator = GeneratorMetadata<