-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement new build configuration systemcon
- Loading branch information
Showing
24 changed files
with
2,108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import type {Run} from '../run'; | ||
import type {BuildConfig, BuildRawConfig} from '..'; | ||
|
||
import {Mock, describe, expect, it, vi} from 'vitest'; | ||
import {Build} from '..'; | ||
import {handler as originalHandler} from '../handler'; | ||
import {withConfigUtils} from '~/config'; | ||
|
||
export const handler = originalHandler as Mock; | ||
|
||
// eslint-disable-next-line no-var | ||
var resolveConfig: Mock; | ||
|
||
vi.mock('shelljs'); | ||
vi.mock('../handler'); | ||
vi.mock('~/config', async (importOriginal) => { | ||
resolveConfig = vi.fn((_path, {defaults, fallback}) => { | ||
return defaults || fallback; | ||
}); | ||
|
||
return { | ||
...((await importOriginal()) as {}), | ||
resolveConfig, | ||
}; | ||
}); | ||
|
||
export async function runBuild(args: string) { | ||
const build = new Build(); | ||
|
||
build.apply(); | ||
|
||
await build.parse(['node', 'index'].concat(args.split(' '))); | ||
} | ||
|
||
export function testConfig(name: string, args: string, result: DeepPartial<BuildConfig>): void; | ||
export function testConfig(name: string, args: string, error: Error): void; | ||
export function testConfig( | ||
name: string, | ||
args: string, | ||
config: DeepPartial<BuildRawConfig>, | ||
result: DeepPartial<BuildConfig>, | ||
): void; | ||
export function testConfig( | ||
name: string, | ||
args: string, | ||
config: DeepPartial<BuildRawConfig>, | ||
error: Error, | ||
): void; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export function testConfig(name: string, args: string, config: any, result?: any): void { | ||
it(name, async () => { | ||
if (!result) { | ||
result = config; | ||
config = {}; | ||
} | ||
|
||
resolveConfig.mockImplementation((path, {defaults}) => { | ||
if (path.endsWith('.yfmlint')) { | ||
return withConfigUtils(path, {}); | ||
} | ||
|
||
if (path.endsWith('redirects.yaml')) { | ||
return withConfigUtils(null, {}); | ||
} | ||
|
||
return withConfigUtils(path, { | ||
...defaults, | ||
...config, | ||
}); | ||
}); | ||
|
||
handler.mockImplementation((run: Run) => { | ||
expect(run.config).toMatchObject(result as Partial<BuildRawConfig>); | ||
}); | ||
|
||
if (result instanceof Error) { | ||
await expect(() => | ||
runBuild('--input ./input --output ./output ' + args), | ||
).rejects.toThrow(result); | ||
} else { | ||
await runBuild('--input ./input --output ./output ' + args); | ||
|
||
expect(handler).toBeCalled(); | ||
} | ||
}); | ||
} | ||
|
||
export function testBooleanFlag(name: string, arg: string, defaults: boolean) { | ||
describe(name, () => { | ||
testConfig('should handle default', '', { | ||
[name]: defaults, | ||
}); | ||
|
||
testConfig('should handle arg', arg, { | ||
[name]: true, | ||
}); | ||
|
||
testConfig( | ||
'should handle config enabled', | ||
'', | ||
{ | ||
[name]: true, | ||
}, | ||
{ | ||
[name]: true, | ||
}, | ||
); | ||
|
||
testConfig( | ||
'should handle config disabled', | ||
'', | ||
{ | ||
[name]: false, | ||
}, | ||
{ | ||
[name]: false, | ||
}, | ||
); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import {bold, underline} from 'chalk'; | ||
import {options as globalOptions} from '~/program/config'; | ||
import {option} from '~/config'; | ||
import {Stage} from '~/constants'; | ||
|
||
export enum OutputFormat { | ||
md = 'md', | ||
html = 'html', | ||
} | ||
|
||
const outputFormat = option({ | ||
flags: '-f, --output-format <value>', | ||
defaultInfo: 'html', | ||
choices: ['html', 'md'], | ||
desc: ` | ||
Format of output files. (html or md) | ||
If ${bold('html')} is selected, then renders md to static html files. | ||
(See also ${underline('--static-content')} option) | ||
If ${bold('md')} is selected, then renders md to prepared md files | ||
enriched by additional metadata. | ||
(Useful for complex documentation servers with runtime rendering) | ||
`, | ||
}); | ||
|
||
const langs = option({ | ||
flags: '--lang, --langs <value...>', | ||
desc: 'Allow loading custom resources into statically generated pages.', | ||
// parser: toArray, | ||
}); | ||
|
||
const vars = option({ | ||
flags: '-v, --vars <json>', | ||
desc: ` | ||
Pass list of variables directly to build. | ||
Variables should be passed in JSON format. | ||
Passed variables overrides the same in presets.yaml | ||
Example: | ||
{{PROGRAM}} -i ./ -o ./build -v '{"name":"test"}' | ||
`, | ||
parser: (value) => JSON.parse(value), | ||
}); | ||
|
||
const varsPreset = option({ | ||
flags: '--vars-preset <value>', | ||
desc: ` | ||
Select vars preset of documentation. | ||
Selected preset will be merged with default section of presets.yaml | ||
`, | ||
}); | ||
|
||
const allowHtml = option({ | ||
flags: '--allow-html', | ||
desc: 'Allow to use HTML in Markdown files.', | ||
defaultInfo: true, | ||
}); | ||
|
||
const sanitizeHtml = option({ | ||
flags: '--sanitize-html', | ||
desc: 'Toggle transformed HTML sanitizing. (Slow but secure feature)', | ||
defaultInfo: true, | ||
}); | ||
|
||
const ignore = option({ | ||
flags: '--ignore <glob...>', | ||
desc: ` | ||
Do not process paths matched by glob. | ||
Example: | ||
{{PROGRAM}} -i ./input -o ./output --ignore *.bad.md | ||
or | ||
{{PROGRAM}} -i ./ -o ./build --ignore ./build | ||
`, | ||
}); | ||
|
||
// TODO: options below are not beautified. | ||
const addMapFile = option({ | ||
flags: '--add-map-file', | ||
desc: 'Should add all paths of documentation into file.json.', | ||
}); | ||
|
||
const removeHiddenTocItems = option({ | ||
flags: '--remove-hidden-toc-items', | ||
desc: 'Remove from Toc all items marked as hidden.', | ||
}); | ||
|
||
const mergeIncludes = option({ | ||
flags: '--merge-includes', | ||
desc: 'Merge includes syntax during md to md processing.', | ||
}); | ||
|
||
const resources = option({ | ||
flags: '--resource, --resources <value...>', | ||
desc: 'Allow loading custom resources into statically generated pages.', | ||
// parser: toArray, | ||
}); | ||
|
||
const allowCustomResources = option({ | ||
flags: '--allow-custom-resources', | ||
desc: 'Allow loading custom resources into statically generated pages.', | ||
}); | ||
|
||
const staticContent = option({ | ||
flags: '--static-content', | ||
desc: 'Allow loading custom resources into statically generated pages.', | ||
}); | ||
|
||
const ignoreStage = option({ | ||
flags: '--ignore-stage <value>', | ||
defaultInfo: Stage.SKIP, | ||
desc: 'Ignore tocs with stage.', | ||
}); | ||
|
||
const addSystemMeta = option({ | ||
flags: '--add-system-meta', | ||
desc: 'Should add system section variables form presets into files meta data.', | ||
}); | ||
|
||
const buildDisabled = option({ | ||
flags: '--build-disabled', | ||
desc: 'Disable building.', | ||
}); | ||
|
||
export const options = { | ||
input: globalOptions.input, | ||
output: globalOptions.output, | ||
config: globalOptions.config, | ||
langs, | ||
outputFormat, | ||
varsPreset, | ||
vars, | ||
allowHtml, | ||
sanitizeHtml, | ||
addMapFile, | ||
removeHiddenTocItems, | ||
mergeIncludes, | ||
resources, | ||
allowCustomResources, | ||
staticContent, | ||
ignore, | ||
ignoreStage, | ||
addSystemMeta, | ||
buildDisabled, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {option} from '~/config'; | ||
|
||
const changelogs = option({ | ||
flags: '--changelogs', | ||
desc: 'Beta functionality: Toggle processing of experimental changelogs syntax', | ||
}); | ||
|
||
export const options = { | ||
changelogs, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import type {Build} from '~/commands'; | ||
import type {Command} from '~/config'; | ||
import {defined} from '~/config'; | ||
import {options} from './config'; | ||
|
||
export type ChangelogsArgs = { | ||
changelogs: boolean | string; | ||
}; | ||
|
||
export type ChangelogsConfig = { | ||
changelogs: boolean | string; | ||
}; | ||
|
||
export class Changelogs { | ||
apply(program: Build) { | ||
program.hooks.Command.tap('Changelogs', (command: Command) => { | ||
command.addOption(options.changelogs); | ||
}); | ||
|
||
program.hooks.Config.tap('Changelogs', (config, args) => { | ||
config.changelogs = defined('changelogs', args, config) || false; | ||
|
||
return config; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {option} from '~/config'; | ||
|
||
const contributors = option({ | ||
flags: '--contributors', | ||
desc: 'Should attach contributors into files', | ||
}); | ||
|
||
const ignoreAuthorPatterns = option({ | ||
flags: '--ignore-author-patterns <string>', | ||
desc: 'Ignore authors if they contain passed string', | ||
}); | ||
|
||
export const options = { | ||
contributors, | ||
ignoreAuthorPatterns, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import type {Build} from '../..'; | ||
import type {Command} from '~/config'; | ||
import type {VCSConnectorConfig} from '~/vcs-connector/connector-models'; | ||
|
||
import {defined} from '~/config'; | ||
import {options} from './config'; | ||
|
||
interface VCSConfiguration { | ||
/** | ||
* Externally accessible base URI for a resource where a particular documentation | ||
* source is hosted. | ||
* | ||
* This configuration parameter is used to directly control the Edit button behaviour | ||
* in the Diplodoc documentation viewer(s). | ||
* | ||
* For example, if the following applies: | ||
* - Repo with doc source is hosted on GitHub (say, https://github.com/foo-org/bar), | ||
* - Within that particular repo, the directory that is being passed as an `--input` | ||
* parameter to the CLI is located at `docs/`, | ||
* - Whenever the Edit button is pressed, you wish to direct your readers to the | ||
* respective document's source on `main` branch | ||
* | ||
* you should pass `https://github.com/foo-org/bar/tree/main/docs` as a value for this parameter. | ||
*/ | ||
remoteBase?: string; | ||
connector?: VCSConnectorConfig; | ||
} | ||
|
||
export type ContributorsArgs = { | ||
contributors?: boolean; | ||
ignoreAuthorPatterns?: string[]; | ||
}; | ||
|
||
export type ContributorsConfig = { | ||
vcs: VCSConfiguration; | ||
contributors: boolean; | ||
ignoreAuthorPatterns: string[]; | ||
}; | ||
|
||
export class Contributors { | ||
apply(program: Build) { | ||
program.hooks.Command.tap('Contributors', (command: Command) => { | ||
command.addOption(options.contributors); | ||
command.addOption(options.ignoreAuthorPatterns); | ||
}); | ||
|
||
program.hooks.Config.tap('Contributors', (config, args) => { | ||
config.vcs = defined('vcs', config) || {}; | ||
config.contributors = defined('contributors', args, config) || false; | ||
config.ignoreAuthorPatterns = defined('ignoreAuthorPatterns', args, config) || []; | ||
|
||
return config; | ||
}); | ||
} | ||
} |
Oops, something went wrong.