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
This commit is contained in:
Christopher Hiller
2023-02-06 13:50:39 -08:00
parent cd72da3b3f
commit 5326cb1840
8 changed files with 77 additions and 51 deletions
+2
View File
@@ -0,0 +1,2 @@
export * from './site';
export * from './reference';
@@ -1,5 +1,5 @@
/**
* 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`
@@ -1,16 +1,17 @@
/**
* 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']>
>;
+3 -4
View File
@@ -1,6 +1,5 @@
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());
},
-3
View File
@@ -1,3 +0,0 @@
// eslint-disable-next-line import/no-unresolved
export * from './mkdocs';
export * from './mike';
+5
View File
@@ -0,0 +1,5 @@
export * from './mike';
export * from './builder';
export * from './validate';
export * from './scaffold';
export * from './constants';
+30
View File
@@ -5,6 +5,7 @@
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']>
>;
+1 -1
View File
@@ -1,4 +1,4 @@
import {Mike} from '../../lib';
import {Mike} from '../..';
import {expect} from 'chai';
describe('Mike', function () {