docs: Generate markdown for config reference (#74)

This commit is contained in:
Aaron
2023-08-13 12:51:19 -05:00
committed by GitHub
parent d54d6111e6
commit 6ee8a43677
8 changed files with 414 additions and 31 deletions
+1
View File
@@ -1,2 +1,3 @@
* text=auto eol=lf
pnpm-lock.yaml linguist-generated
docs/config.md linguist-generated
+5
View File
@@ -1,8 +1,13 @@
import { defineConfig } from 'vitepress';
import { generateConfigDocs } from './plugins/generate-config-docs';
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: 'WXT',
vite: {
clearScreen: false,
plugins: [generateConfigDocs()],
},
description: 'Next gen framework for developing web extensions',
lastUpdated: true,
@@ -0,0 +1,148 @@
import { resolve } from 'node:path';
import { Project, ts, Type, Node, JSDocableNode } from 'ts-morph';
import Ora from 'ora';
import { readFileSync, writeFileSync } from 'node:fs';
const externalTypesPath = resolve('src/core/types/external.ts');
const configTemplatePath = resolve('docs/config.tpl.md');
const configPath = resolve('docs/config.md');
const PREFACE = `<!--
DO NOT EDIT
Generated by \`wxt/docs/.vitepress/plugins/generate-config-docs.ts\`
To make changes to the config reference, update the JSDoc in \`src/core/types/external.ts\`.
-->`;
/**
* Custom property paths that should not be recursively inspected. Usually 3rd party types.
*/
const LEAF_PATHS = ['imports', 'vite', 'server'];
/**
* Override any types that resolve to `import(...)` instead of their type names when calling
* `type.getText()`
*/
const CUSTOM_TYPES = {
manifest:
'Manifest | Promise<Manifest> | () => Manifest | () => Promise<Manifest>',
};
export function generateConfigDocs() {
const generateDocs = () => {
const spinner = Ora('Generating /config.md').start();
try {
const project = new Project({
tsConfigFilePath: resolve('tsconfig.json'),
});
// Load file containing "UserConfig"
const externalTypesFile = project.addSourceFileAtPath(externalTypesPath);
project.resolveSourceFileDependencies();
const typeChecker = project.getProgram().getTypeChecker();
const inlineConfigInterface =
externalTypesFile.getInterfaceOrThrow('InlineConfig');
const getDocsFor = (
path: string[],
node: Node<ts.Node>,
depth = 0,
): string[] => {
if (depth > 3) throw Error('Recursion to deep for ' + path.join('.'));
const pathStr = path.join('.');
let type: Type<ts.Type>;
if (node.isKind(ts.SyntaxKind.InterfaceDeclaration)) {
type = node.getType();
} else if (node.isKind(ts.SyntaxKind.PropertySignature)) {
type = node.getTypeNodeOrThrow()?.getType();
} else if (node.isKind(ts.SyntaxKind.MethodSignature)) {
type = node.getType();
} else {
throw Error('Unsupported type node: ' + node.getKindName());
}
if (type.isObject() && !type.isArray()) {
return (
type
.getProperties()
// .sort((l, r) => l.getName().localeCompare(r.getName()))
.flatMap((property) => {
const childPath = [...path, property.getName()];
if (LEAF_PATHS.includes(childPath.join('.'))) return [];
return getDocsFor(
childPath,
property.getDeclarations()[0],
depth + 1,
);
})
);
}
if ('getJsDocs' in node) {
const lines: string[] = [];
const docs = (node as unknown as JSDocableNode).getJsDocs();
let typeText: string;
if (CUSTOM_TYPES[pathStr]) {
typeText = CUSTOM_TYPES[pathStr];
} else if (type.isUnion() && !type.isBoolean()) {
typeText = type
.getUnionTypes()
.map((type) => type.getText())
.join(' | ');
} else {
typeText = type.getText();
}
const defaultValue = docs
.flatMap((doc) => doc.getTags())
.find((tag) => tag.getTagName() === 'default')
?.getCommentText();
lines.push(
'',
`## ${pathStr}`,
'',
`- **Type**: \`${typeText}\``,
`- **Default**: \`${defaultValue}\``,
...docs.flatMap((doc) => doc.getDescription()),
);
return lines;
}
return [];
};
const lines = getDocsFor([], inlineConfigInterface);
const text =
PREFACE +
'\n\n' +
readFileSync(configTemplatePath, 'utf-8').replace(
'{{ DOCS }}',
lines.join('\n'),
);
writeFileSync(configPath, text);
spinner.succeed('Generated /config.md');
} catch (err) {
spinner.fail('Failed to generate /config.md');
console.error(err.message);
}
};
return {
name: 'docs:generate-config-docs',
buildStart() {
generateDocs();
},
configureServer(server: any) {
server.watcher.add(externalTypesPath);
},
handleHotUpdate(ctx: { file: string }) {
if ([externalTypesPath, configTemplatePath].includes(ctx.file)) {
generateDocs();
}
},
};
}
+199 -4
View File
@@ -1,5 +1,200 @@
# Config
<!--
DO NOT EDIT
Generated by `wxt/docs/.vitepress/plugins/generate-config-docs.ts`
To make changes to the config reference, update the JSDoc in `src/core/types/external.ts`.
-->
:::warning 🚧&ensp;Under construction
This documentation does not exist yet.
:::
# Config Reference
Discover all the options you can use in your `wxt.config.ts` file.
## root
- **Type**: `string`
- **Default**: `process.cwd()`
Your project's root directory containing the `package.json` used to fill out the
`manifest.json`.
## srcDir
- **Type**: `string`
- **Default**: `config.root`
Directory containing all source code. Set to `"src"` to move all source code to a `src/`
directory.
## publicDir
- **Type**: `string`
- **Default**: `"${config.root}/public"`
Directory containing files that will be copied to the output directory as-is.
## entrypointsDir
- **Type**: `string`
- **Default**: `"${config.srcDir}/entrypoints"`
## configFile
- **Type**: `string | false`
- **Default**: `"wxt.config.ts"`
Path to `"wxt.config.ts"` file or false to disable config file discovery.
## storeIds.chrome
- **Type**: `string`
- **Default**: `undefined`
## storeIds.firefox
- **Type**: `string`
- **Default**: `undefined`
## storeIds.edge
- **Type**: `string`
- **Default**: `undefined`
## mode
- **Type**: `string`
- **Default**: `undefined`
Explicitly set a mode to run in. This will override the default mode for each command, and can
be overridden by the command line `--mode` option.
## browser
- **Type**: `"chrome" | "firefox" | "safari" | "edge" | "opera"`
- **Default**: `"chrome"`
Explicitly set a browser to build for. This will override the default browser for each command,
and can be overridden by the command line `--browser` option.
## manifestVersion
- **Type**: `2 | 3`
- **Default**: `undefined`
Explicitly set a manifest version to target. This will override the default manifest version
for each command, and can be overridden by the command line `--mv2` or `--mv3` option.
## manifest
- **Type**: `Manifest | Promise<Manifest> | () => Manifest | () => Promise<Manifest>`
- **Default**: `undefined`
Customize the `manifest.json` output. Can be an object, promise, or function that returns an
object or promise.
## runner.openConsole
- **Type**: `boolean`
- **Default**: `undefined`
## runner.openDevtools
- **Type**: `boolean`
- **Default**: `undefined`
## runner.binaries.chrome
- **Type**: `string`
- **Default**: `undefined`
## runner.binaries.edge
- **Type**: `string`
- **Default**: `undefined`
## runner.binaries.opera
- **Type**: `string`
- **Default**: `undefined`
## runner.binaries.firefox
- **Type**: `string`
- **Default**: `undefined`
## runner.firefoxProfile
- **Type**: `string`
- **Default**: `undefined`
## runner.chromiumProfile
- **Type**: `string`
- **Default**: `undefined`
## runner.firefoxArgs
- **Type**: `string[]`
- **Default**: `undefined`
## runner.chromiumArgs
- **Type**: `string[]`
- **Default**: `undefined`
## runner.startUrls
- **Type**: `string[]`
- **Default**: `undefined`
## zip.artifactTemplate
- **Type**: `string`
- **Default**: `"{name}-{version}-{browser}.zip"`
Configure the filename output when zipping files.
Available template variables:
- `{name}` - The project's name converted to kebab-case
- `{version}` - The version_name or version from the manifest
- `{browser}` - The target browser from the `--browser` CLI flag
- `{manifestVersion}` - Either "2" or "3"
## zip.sourcesTemplate
- **Type**: `string`
- **Default**: `"{name}-{version}-sources.zip"`
Configure the filename output when zipping files.
Available template variables:
- `{name}` - The project's name converted to kebab-case
- `{version}` - The version_name or version from the manifest
- `{browser}` - The target browser from the `--browser` CLI flag
- `{manifestVersion}` - Either "2" or "3"
## zip.name
- **Type**: `string`
- **Default**: `undefined`
Override the artifactTemplate's `{name}` template variable. Defaults to the `package.json`'s
name, or if that doesn't exist, the current working directories name.
## zip.sourcesRoot
- **Type**: `string`
- **Default**: `config.root`
Root directory to ZIP when generating the sources ZIP.
## zip.ignoredSources
- **Type**: `string[]`
- **Default**: `undefined`
[Minimatch](https://www.npmjs.com/package/minimatch) patterns of files to exclude when
creating a ZIP of all your source code for Firfox. Patterns are relative to your
`config.zip.sourcesRoot`.
Hidden files, node_modules, and tests are ignored by default.
+5
View File
@@ -0,0 +1,5 @@
# Config Reference
Discover all the options you can use in your `wxt.config.ts` file.
{{ DOCS }}
+1
View File
@@ -102,6 +102,7 @@
"prettier": "^2.8.8",
"pretty-quick": "^3.1.3",
"simple-git-hooks": "^2.9.0",
"ts-morph": "^19.0.0",
"tsup": "^7.1.0",
"tsx": "^3.12.7",
"typescript": "^5.1.6",
+33 -2
View File
@@ -120,6 +120,9 @@ importers:
simple-git-hooks:
specifier: ^2.9.0
version: 2.9.0
ts-morph:
specifier: ^19.0.0
version: 19.0.0
tsup:
specifier: ^7.1.0
version: 7.1.0(typescript@5.1.6)
@@ -1004,6 +1007,15 @@ packages:
defer-to-connect: 2.0.1
dev: false
/@ts-morph/common@0.20.0:
resolution: {integrity: sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q==}
dependencies:
fast-glob: 3.3.1
minimatch: 7.4.6
mkdirp: 2.1.6
path-browserify: 1.0.1
dev: true
/@types/chai-subset@1.3.3:
resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==}
dependencies:
@@ -1684,7 +1696,6 @@ packages:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: false
/braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
@@ -1927,6 +1938,10 @@ packages:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
engines: {node: '>=0.8'}
/code-block-writer@12.0.0:
resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==}
dev: true
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@@ -3924,7 +3939,6 @@ packages:
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: false
/minimatch@9.0.3:
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
@@ -3985,6 +3999,12 @@ packages:
hasBin: true
dev: false
/mkdirp@2.1.6:
resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==}
engines: {node: '>=10'}
hasBin: true
dev: true
/mlly@1.4.0:
resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==}
dependencies:
@@ -4370,6 +4390,10 @@ packages:
entities: 4.5.0
dev: false
/path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
dev: true
/path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -5446,6 +5470,13 @@ packages:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
dev: true
/ts-morph@19.0.0:
resolution: {integrity: sha512-D6qcpiJdn46tUqV45vr5UGM2dnIEuTGNxVhg0sk5NX11orcouwj6i1bMqZIz2mZTZB1Hcgy7C3oEVhAT+f6mbQ==}
dependencies:
'@ts-morph/common': 0.20.0
code-block-writer: 12.0.0
dev: true
/tsconfck@2.1.1(typescript@5.1.6):
resolution: {integrity: sha512-ZPCkJBKASZBmBUNqGHmRhdhM8pJYDdOXp4nRgj/O0JwUwsMq50lCDRQP/M5GBNAA0elPrq4gAeu4dkaVCuKWww==}
engines: {node: ^14.13.1 || ^16 || >=18}
+22 -25
View File
@@ -5,37 +5,33 @@ import { EntrypointGroup } from '.';
export interface InlineConfig {
/**
* Project root directory.
* Your project's root directory containing the `package.json` used to fill out the
* `manifest.json`.
*
* @default
* process.cwd()
* @default process.cwd()
*/
root?: string;
/**
* Directory containing all source code. Set to `"src"` to move all source code to a `src/`
* directory.
*
* @default
* "<rootDir>"
* @default config.root
*/
srcDir?: string;
/**
* Directory containing files that will be copied to the output directory as-is.
*
* @default
* "<rootDir>/publicDir"
* @default "${config.root}/public"
*/
publicDir?: string;
/**
* @default
* "<srcDir>/entrypoints"
* @default "${config.srcDir}/entrypoints"
*/
entrypointsDir?: string;
/**
* Path to `"wxt.config.ts"` file or false to disable config file discovery.
*
* @default
* "wxt.config.ts"
* @default "wxt.config.ts"
*/
configFile?: string | false;
/**
@@ -56,7 +52,7 @@ export interface InlineConfig {
*/
imports?: Partial<UnimportOptions>;
/**
* Explicitly set a browser to target. This will override the default browser for each command,
* Explicitly set a browser to build for. This will override the default browser for each command,
* and can be overridden by the command line `--browser` option.
*
* @default
@@ -98,12 +94,12 @@ export interface InlineConfig {
*
* Available template variables:
*
* - `{{name}}` - The project's name converted to kebab-case
* - `{{version}} - The version_name or version from the manifest
* - `{{browser}} - The target browser from the `--browser` CLI flag
* - `{{manifestVersion}}` - Either "2" or "3"
* - `{name}` - The project's name converted to kebab-case
* - `{version}` - The version_name or version from the manifest
* - `{browser}` - The target browser from the `--browser` CLI flag
* - `{manifestVersion}` - Either "2" or "3"
*
* @default "{{name}}-{{version}}-{{browser}}.zip"
* @default "{name}-{version}-{browser}.zip"
*/
artifactTemplate?: string;
/**
@@ -111,22 +107,23 @@ export interface InlineConfig {
*
* Available template variables:
*
* - `{{name}}` - The project's name converted to kebab-case
* - `{{version}} - The version_name or version from the manifest
* - `{{browser}} - The target browser from the `--browser` CLI flag
* - `{{manifestVersion}}` - Either "2" or "3"
* - `{name}` - The project's name converted to kebab-case
* - `{version}` - The version_name or version from the manifest
* - `{browser}` - The target browser from the `--browser` CLI flag
* - `{manifestVersion}` - Either "2" or "3"
*
* @default "{{name}}-{{version}}-sources.zip"
* @default "{name}-{version}-sources.zip"
*/
sourcesTemplate?: string;
/**
* Override the artifactTemplate's `{{name}}` template variable. Defaults to the package.json's
* Override the artifactTemplate's `{name}` template variable. Defaults to the `package.json`'s
* name, or if that doesn't exist, the current working directories name.
*/
name?: string;
/**
* Root directory to ZIP. The ZIP can be uploaded to the Firefox Addon Store as your source
* code. Defaults to the `config.root` directory.
* Root directory to ZIP when generating the sources ZIP.
*
* @default config.root
*/
sourcesRoot?: string;
/**