chore(docutils): reorganize some build-related modules into a 'builder' subdir
Also rename a few things.  `typedoc` module is now `reference` and `mkdocs` module is now `site`.
Moved a couple things into `util` as well
The `nav` module will be in stacked PR
ADD
packages/docutils/lib/builder/index.ts
+export * from './site';
+export * from './reference';

RENAME
packages/docutils/lib/typedoc.ts
packages/docutils/lib/builder/reference.ts
/**
- * Runs TypeDoc
+ * Builds reference documentation via TypeDoc. The output is _markdown_, intended to be imported into MkDocs.
*
* @module
*/
@@ -14,13 +14,13 @@ import {
DEFAULT_REL_TYPEDOC_OUT_PATH,
NAME_BIN,
NAME_TYPEDOC_JSON,
-} from './constants';
-import {DocutilsError} from './error';
-import {findTypeDocJsonPath, readTypedocJson} from './fs';
-import logger from './logger';
-import {relative, stopwatch} from './util';
+} from '../constants';
+import {DocutilsError} from '../error';
+import {findTypeDocJsonPath, readTypedocJson} from '../fs';
+import logger from '../logger';
+import {argify, relative, stopwatch} from '../util';
-const log = logger.withTag('typedoc');
+const log = logger.withTag('builder:reference');
/**
* Replaces TypeDoc's homebrew "glob" implementation with a real one
@@ -42,17 +42,12 @@ const monkeyPatchGlob = _.once((pkgRoot) => {
tdFs.glob = glob.sync;
});
-/**
- * Converts an object of string values to an array of arguments for CLI
- */
-const argify: (obj: Record<string, string>) => string[] = _.flow(_.entries, _.flatten, (list) =>
- list.map((v, idx) => (idx % 2 === 0 ? `--${v}` : v))
-);
-
/**
* Executes TypeDoc _in the current process_
*
- * Monkeypatches TypeDoc's homebrew "glob" implementation because it is broken
+ * You will probably want to run `updateNav()` after this.
+ *
+ * @privateRemarks Monkeypatches TypeDoc's homebrew "glob" implementation because it is broken
* @param pkgRoot - Package root path
* @param opts - TypeDoc options
*/
@@ -77,7 +72,7 @@ export async function runTypedoc(pkgRoot: string, opts: Record<string, string>)
}
/**
- * Options for {@linkcode buildReference}
+ * Options for {@linkcode buildReferenceDocs}
*/
export interface BuildReferenceOptions {
/**
@@ -130,15 +125,17 @@ const TypeDocLogLevelMap: Record<LogLevelName, string> = {
* Build reference documentation via TypeDoc
* @param opts - Options
*/
-export async function buildReference({
+export async function buildReferenceDocs({
typedocJson: typeDocJsonPath,
cwd = process.cwd(),
tsconfigJson: tsconfig,
logLevel = DEFAULT_LOG_LEVEL,
title,
}: BuildReferenceOptions = {}) {
- const stop = stopwatch('buildReference');
- typeDocJsonPath = typeDocJsonPath ?? (await findTypeDocJsonPath(cwd));
+ const stop = stopwatch('buildReferenceDocs');
+ typeDocJsonPath = typeDocJsonPath
+ ? path.resolve(cwd, typeDocJsonPath)
+ : await findTypeDocJsonPath(cwd);
if (!typeDocJsonPath) {
throw new DocutilsError(
`Could not find ${NAME_TYPEDOC_JSON} from ${cwd}; run "${NAME_BIN}" to create it`

RENAME
packages/docutils/lib/mkdocs.ts
packages/docutils/lib/builder/site.ts
/**
- * Functions for running `mkdocs`
+ * Runs `mkdocs`, pulling in reference markdown from TypeDoc and any other documentation from the
+ * `docs_dir` directory (as configured in `mkdocs.yml`).
*
* @module
*/
+import path from 'node:path';
import {exec, SubProcess, TeenProcessExecOptions} from 'teen_process';
-import {NAME_BIN, NAME_MKDOCS, NAME_MKDOCS_YML} from './constants';
-import {findMkDocsYml, readYaml, whichMkDocs} from './fs';
-import logger from './logger';
-import {relative, stopwatch, TupleToObject} from './util';
-import _ from 'lodash';
-import {DocutilsError} from './error';
+import {NAME_BIN, NAME_MKDOCS, NAME_MKDOCS_YML} from '../constants';
+import {DocutilsError} from '../error';
+import {findMkDocsYml, readMkDocsYml, whichMkDocs} from '../fs';
+import logger from '../logger';
+import {relative, stopwatch, TeenProcessSubprocessStartOpts} from '../util';
const log = logger.withTag('mkdocs');
@@ -53,8 +54,8 @@ async function doBuild(
* Runs `mkdocs build` or `mkdocs serve`
* @param opts
*/
-export async function buildMkDocs({
- mkdocsYml: mkdocsYmlPath,
+export async function buildSite({
+ mkdocsYml: mkDocsYmlPath,
siteDir,
theme = NAME_MKDOCS,
cwd = process.cwd(),
@@ -63,14 +64,15 @@ export async function buildMkDocs({
execOpts,
}: BuildMkDocsOpts = {}) {
const stop = stopwatch('build-mkdocs');
- mkdocsYmlPath = mkdocsYmlPath ?? (await findMkDocsYml(cwd));
- if (!mkdocsYmlPath) {
+ mkDocsYmlPath = mkDocsYmlPath
+ ? path.resolve(process.cwd(), mkDocsYmlPath)
+ : await findMkDocsYml(cwd);
+ if (!mkDocsYmlPath) {
throw new DocutilsError(
`Could not find ${NAME_MKDOCS_YML} from ${cwd}; run "${NAME_BIN} init" to create it`
);
}
- const relativePath = relative(cwd);
- const mkdocsArgs = ['-f', mkdocsYmlPath, '-t', theme];
+ const mkdocsArgs = ['-f', mkDocsYmlPath, '-t', theme];
if (siteDir) {
mkdocsArgs.push('-d', siteDir);
}
@@ -81,17 +83,18 @@ export async function buildMkDocs({
await doBuild(mkdocsArgs, execOpts);
let relSiteDir;
if (siteDir) {
- relSiteDir = relativePath(siteDir);
+ relSiteDir = relative(cwd, siteDir);
} else {
- ({site_dir: siteDir} = await readYaml(mkdocsYmlPath));
- relSiteDir = relativePath(siteDir!);
+ ({site_dir: siteDir} = await readMkDocsYml(mkDocsYmlPath));
+ log.debug('Found site_dir %s', siteDir);
+ relSiteDir = relative(path.dirname(mkDocsYmlPath), siteDir!);
}
log.success('MkDocs finished building into %s (%dms)', relSiteDir, stop());
}
}
/**
- * Options for {@linkcode buildMkDocs}.
+ * Options for {@linkcode buildSite}.
*/
export interface BuildMkDocsOpts {
/**
@@ -138,10 +141,3 @@ export interface BuildMkDocsOpts {
*/
serveOpts?: TeenProcessSubprocessStartOpts;
}
-
-/**
- * Conversion of the parameters of {@linkcode Subprocess.start} to an object.
- */
-export type TeenProcessSubprocessStartOpts = Partial<
- TupleToObject<Parameters<SubProcess['start']>, ['startDetector', 'detach', 'timeoutMs']>
->;

MODIFY
packages/docutils/lib/cli/command/build.ts
packages/docutils/lib/cli/command/build.ts
import {CommandModule, InferredOptionTypes, Options} from 'yargs';
-import {buildMkDocs} from '../../mkdocs';
-import {buildReference} from '../../typedoc';
+import {buildReferenceDocs, buildSite} from '../../builder';
import logger from '../../logger';
import {updateNav} from '../../nav';
import {stopwatch} from '../../util';
@@ -100,11 +99,11 @@ const buildCommand: CommandModule<{}, BuildOptions> = {
);
}
if (args.site) {
- await buildReference(args);
+ await buildReferenceDocs(args);
}
if (args.reference) {
await updateNav(args);
- await buildMkDocs(args);
+ await buildSite(args);
}
log.success('Done! (total: %dms)', stop());
},

DELETE
packages/docutils/lib/index.js
-// eslint-disable-next-line import/no-unresolved
-export * from './mkdocs';
-export * from './mike';

ADD
packages/docutils/lib/index.ts
+export * from './mike';
+export * from './builder';
+export * from './validate';
+export * from './scaffold';
+export * from './constants';

MODIFY
packages/docutils/lib/util.ts
packages/docutils/lib/util.ts
import _ from 'lodash';
import path from 'node:path';
+import type {SubProcess} from 'teen_process';
/**
* Computes a relative path, prepending `./`
@@ -44,3 +45,32 @@ export type TupleToObject<
export const isStringArray = _.overEvery(_.isArray, _.partial(_.every, _, _.isString)) as (
value: any
) => value is string[];
+
+/**
+ * Converts an object of string values to an array of arguments for CLI
+ *
+ * Supports `boolean` and `number` values as well. `boolean`s are assumed to be flags which default
+ * to `false`, so they will only be added to the array if the value is `true`.
+ */
+export const argify: (obj: Record<string, string | number | boolean | undefined>) => string[] =
+ _.flow(
+ _.entries,
+ _.flatten,
+ (list) =>
+ list.map((value, idx) => {
+ if (value === true) {
+ return `--${value}`;
+ } else if (value === false || value === undefined) {
+ return;
+ }
+ return idx % 2 === 0 ? `--${value}` : value;
+ }),
+ _.compact
+ );
+
+/**
+ * Conversion of the parameters of {@linkcode Subprocess.start} to an object.
+ */
+export type TeenProcessSubprocessStartOpts = Partial<
+ TupleToObject<Parameters<SubProcess['start']>, ['startDetector', 'detach', 'timeoutMs']>
+>;

MODIFY
packages/docutils/test/unit/mike.spec.js
packages/docutils/test/unit/mike.spec.js
-import {Mike} from '../../lib';
+import {Mike} from '../..';
import {expect} from 'chai';
describe('Mike', function () {

chore(docutils): reorganize some build-related modules into a 'builder' subdir

Also rename a few things.  `typedoc` module is now `reference` and `mkdocs` module is now `site`.

Moved a couple things into `util` as well

The `nav` module will be in stacked PR