feat(misc): updated documentation generation scripts and removed shelljs (#5381)
cleanup(repo): updated documentation generation scripts and removed shelljs
This commit is contained in:
parent
6bd6e1485f
commit
27df60164d
@ -22,7 +22,7 @@
|
|||||||
"lint": "nx run-many --target=lint --all --parallel",
|
"lint": "nx run-many --target=lint --all --parallel",
|
||||||
"depcheck": "ts-node -P ./scripts/tsconfig.scripts.json ./scripts/depcheck",
|
"depcheck": "ts-node -P ./scripts/tsconfig.scripts.json ./scripts/depcheck",
|
||||||
"local-registry": "./scripts/local-registry.sh",
|
"local-registry": "./scripts/local-registry.sh",
|
||||||
"documentation": "./scripts/documentation/documentation.sh && ./scripts/documentation/check-documentation.sh && yarn check-documentation-map && yarn check-internal-links",
|
"documentation": "ts-node -P scripts/tsconfig.scripts.json ./scripts/documentation/documentation.ts && yarn check-documentation-map && yarn check-internal-links",
|
||||||
"submit-plugin": "node ./scripts/submit-plugin.js"
|
"submit-plugin": "node ./scripts/submit-plugin.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -209,7 +209,6 @@
|
|||||||
"sass": "1.26.3",
|
"sass": "1.26.3",
|
||||||
"sass-loader": "8.0.2",
|
"sass-loader": "8.0.2",
|
||||||
"semver": "7.3.4",
|
"semver": "7.3.4",
|
||||||
"shelljs": "^0.8.3",
|
|
||||||
"source-map": "0.7.3",
|
"source-map": "0.7.3",
|
||||||
"source-map-loader": "0.2.4",
|
"source-map-loader": "0.2.4",
|
||||||
"source-map-support": "0.5.16",
|
"source-map-support": "0.5.16",
|
||||||
|
|||||||
@ -16,8 +16,8 @@ import { join } from 'path';
|
|||||||
import { gt } from 'semver';
|
import { gt } from 'semver';
|
||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import { dasherize } from '../packages/workspace/src/utils/strings';
|
import { dasherize } from '../packages/workspace/src/utils/strings';
|
||||||
import * as shell from 'shelljs';
|
|
||||||
import * as glob from 'glob';
|
import * as glob from 'glob';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
const excluded = ['nxVersion'];
|
const excluded = ['nxVersion'];
|
||||||
const scoped = [
|
const scoped = [
|
||||||
@ -123,7 +123,9 @@ function getVersionData(
|
|||||||
} {
|
} {
|
||||||
try {
|
try {
|
||||||
const latest = JSON.parse(
|
const latest = JSON.parse(
|
||||||
shell.exec(`npm view ${p} version --json --silent`, { silent: true })
|
execSync(`npm view ${p} version --json --silent`, {
|
||||||
|
stdio: ['ignore'],
|
||||||
|
}).toString('utf-8')
|
||||||
);
|
);
|
||||||
if (gt(latest, v)) {
|
if (gt(latest, v)) {
|
||||||
return { package: p, outdated: true, invalid: false, latest, prev: v };
|
return { package: p, outdated: true, invalid: false, latest, prev: v };
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
const shell = require('shelljs');
|
const fs = require('fs');
|
||||||
|
|
||||||
shell.chmod('+x', process.argv[2]);
|
fs.chmodSync(process.argv[2], 0o777);
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if [ -z "$(git status --porcelain ./docs)" ]; then
|
|
||||||
echo "📄 Documentation not modified";
|
|
||||||
exit 0;
|
|
||||||
else
|
|
||||||
echo "📄 Documentation has been modified, you need to commit the changes.";
|
|
||||||
git status --porcelain ./docs
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "Generating API documentation"
|
|
||||||
ts-node -r tsconfig-paths/register --project=scripts/tsconfig.scripts.json ./scripts/documentation/generate-executors-data.ts
|
|
||||||
ts-node -r tsconfig-paths/register --project=scripts/tsconfig.scripts.json ./scripts/documentation/generate-generators-data.ts
|
|
||||||
ts-node -r tsconfig-paths/register --project=scripts/tsconfig.scripts.json ./scripts/documentation/generate-cli-data.ts
|
|
||||||
echo 'Done generating all Documentation'
|
|
||||||
51
scripts/documentation/documentation.ts
Normal file
51
scripts/documentation/documentation.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import * as chalk from 'chalk';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
|
||||||
|
import { generateCLIDocumentation } from './generate-cli-data';
|
||||||
|
import { generateExecutorsDocumentation } from './generate-executors-data';
|
||||||
|
import { generateGeneratorsDocumentation } from './generate-generators-data';
|
||||||
|
|
||||||
|
async function generate() {
|
||||||
|
console.log(`${chalk.blue('i')} Generating Documentation`);
|
||||||
|
|
||||||
|
await generateGeneratorsDocumentation();
|
||||||
|
await generateExecutorsDocumentation();
|
||||||
|
await generateCLIDocumentation();
|
||||||
|
|
||||||
|
console.log(`\n${chalk.green('🗸')} Generated Documentation\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkDocumentation() {
|
||||||
|
const output = execSync('git status --porcelain ./docs').toString('utf-8');
|
||||||
|
|
||||||
|
if (output) {
|
||||||
|
console.log(
|
||||||
|
`${chalk.red(
|
||||||
|
'!'
|
||||||
|
)} 📄 Documentation has been modified, you need to commit the changes. ${chalk.red(
|
||||||
|
'!'
|
||||||
|
)} `
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('\nChanged Docs:');
|
||||||
|
execSync('git status --porcelain ./docs', { stdio: 'inherit' });
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
console.log('📄 Documentation not modified');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generate().then(() => {
|
||||||
|
checkDocumentation();
|
||||||
|
});
|
||||||
|
|
||||||
|
function printInfo(
|
||||||
|
str: string,
|
||||||
|
newLine: boolean = true,
|
||||||
|
newLineAfter: boolean = true
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
`${newLine ? '\n' : ''}${chalk.blue('i')} ${str}${newLineAfter ? '\n' : ''}`
|
||||||
|
);
|
||||||
|
}
|
||||||
2
scripts/documentation/frameworks.ts
Normal file
2
scripts/documentation/frameworks.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const Frameworks = ['angular', 'react', 'node'] as const;
|
||||||
|
export type Framework = typeof Frameworks[number];
|
||||||
@ -1,9 +1,10 @@
|
|||||||
|
import * as chalk from 'chalk';
|
||||||
import * as fs from 'fs-extra';
|
import * as fs from 'fs-extra';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { dedent } from 'tslint/lib/utils';
|
import { dedent } from 'tslint/lib/utils';
|
||||||
import { commandsObject } from '../../packages/workspace';
|
import { commandsObject } from '../../packages/workspace';
|
||||||
|
import { Framework, Frameworks } from './frameworks';
|
||||||
import { generateMarkdownFile, sortAlphabeticallyFunction } from './utils';
|
import { generateMarkdownFile, sortAlphabeticallyFunction } from './utils';
|
||||||
|
|
||||||
const importFresh = require('import-fresh');
|
const importFresh = require('import-fresh');
|
||||||
|
|
||||||
const examples = {
|
const examples = {
|
||||||
@ -395,55 +396,59 @@ const sharedCommands = [
|
|||||||
'test',
|
'test',
|
||||||
];
|
];
|
||||||
|
|
||||||
console.log('Generating Nx Commands Documentation');
|
export async function generateCLIDocumentation() {
|
||||||
Promise.all(
|
console.log(`\n${chalk.blue('i')} Generating Documentation for Nx Commands`);
|
||||||
['angular', 'react', 'node'].map(async (framework) => {
|
|
||||||
const commandsOutputDirectory = path.join(
|
await Promise.all(
|
||||||
__dirname,
|
Frameworks.map(async (framework: Framework) => {
|
||||||
'../../docs/',
|
const commandsOutputDirectory = path.join(
|
||||||
framework,
|
__dirname,
|
||||||
'cli'
|
'../../docs/',
|
||||||
);
|
framework,
|
||||||
fs.removeSync(commandsOutputDirectory);
|
'cli'
|
||||||
function getCommands(command) {
|
);
|
||||||
return command.getCommandInstance().getCommandHandlers();
|
fs.removeSync(commandsOutputDirectory);
|
||||||
}
|
function getCommands(command) {
|
||||||
async function parseCommandInstance(name, command) {
|
return command.getCommandInstance().getCommandHandlers();
|
||||||
// It is not a function return a strip down version of the command
|
}
|
||||||
if (
|
async function parseCommandInstance(name, command) {
|
||||||
!(
|
// It is not a function return a strip down version of the command
|
||||||
command.builder &&
|
if (
|
||||||
command.builder.constructor &&
|
!(
|
||||||
command.builder.call &&
|
command.builder &&
|
||||||
command.builder.apply
|
command.builder.constructor &&
|
||||||
)
|
command.builder.call &&
|
||||||
) {
|
command.builder.apply
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
command: name,
|
||||||
|
description: command['description'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Show all the options we can get from yargs
|
||||||
|
const builder = await command.builder(
|
||||||
|
importFresh('yargs')().resetOptions()
|
||||||
|
);
|
||||||
|
const builderDescriptions = builder
|
||||||
|
.getUsageInstance()
|
||||||
|
.getDescriptions();
|
||||||
|
const builderDefaultOptions = builder.getOptions().default;
|
||||||
return {
|
return {
|
||||||
command: name,
|
command: name,
|
||||||
description: command['description'],
|
description: command['description'],
|
||||||
|
options:
|
||||||
|
Object.keys(builderDescriptions).map((key) => ({
|
||||||
|
command: '--'.concat(key),
|
||||||
|
description: builderDescriptions[key]
|
||||||
|
? builderDescriptions[key].replace('__yargsString__:', '')
|
||||||
|
: '',
|
||||||
|
default: builderDefaultOptions[key],
|
||||||
|
})) || null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Show all the options we can get from yargs
|
function generateMarkdown(command) {
|
||||||
const builder = await command.builder(
|
let template = dedent`
|
||||||
importFresh('yargs')().resetOptions()
|
|
||||||
);
|
|
||||||
const builderDescriptions = builder.getUsageInstance().getDescriptions();
|
|
||||||
const builderDefaultOptions = builder.getOptions().default;
|
|
||||||
return {
|
|
||||||
command: name,
|
|
||||||
description: command['description'],
|
|
||||||
options:
|
|
||||||
Object.keys(builderDescriptions).map((key) => ({
|
|
||||||
command: '--'.concat(key),
|
|
||||||
description: builderDescriptions[key]
|
|
||||||
? builderDescriptions[key].replace('__yargsString__:', '')
|
|
||||||
: '',
|
|
||||||
default: builderDefaultOptions[key],
|
|
||||||
})) || null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function generateMarkdown(command) {
|
|
||||||
let template = dedent`
|
|
||||||
# ${command.command}
|
# ${command.command}
|
||||||
${command.description}
|
${command.description}
|
||||||
|
|
||||||
@ -454,31 +459,31 @@ Promise.all(
|
|||||||
|
|
||||||
Install \`nx\` globally to invoke the command directly using \`nx\`, or use \`npm run nx\` or \`yarn nx\`.\n`;
|
Install \`nx\` globally to invoke the command directly using \`nx\`, or use \`npm run nx\` or \`yarn nx\`.\n`;
|
||||||
|
|
||||||
if (examples[command.command] && examples[command.command].length > 0) {
|
if (examples[command.command] && examples[command.command].length > 0) {
|
||||||
template += `### Examples`;
|
template += `### Examples`;
|
||||||
examples[command.command].forEach((example) => {
|
examples[command.command].forEach((example) => {
|
||||||
template += dedent`
|
template += dedent`
|
||||||
${example.description}:
|
${example.description}:
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
nx ${example.command}
|
nx ${example.command}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(command.options) && !!command.options.length) {
|
if (Array.isArray(command.options) && !!command.options.length) {
|
||||||
template += '\n## Options';
|
template += '\n## Options';
|
||||||
|
|
||||||
command.options
|
command.options
|
||||||
.sort((a, b) =>
|
.sort((a, b) =>
|
||||||
sortAlphabeticallyFunction(
|
sortAlphabeticallyFunction(
|
||||||
a.command.replace('--', ''),
|
a.command.replace('--', ''),
|
||||||
b.command.replace('--', '')
|
b.command.replace('--', '')
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.forEach(
|
||||||
.forEach(
|
(option) =>
|
||||||
(option) =>
|
(template += dedent`
|
||||||
(template += dedent`
|
|
||||||
### ${option.command.replace('--', '')}
|
### ${option.command.replace('--', '')}
|
||||||
${
|
${
|
||||||
option.default === undefined || option.default === ''
|
option.default === undefined || option.default === ''
|
||||||
@ -487,56 +492,57 @@ Promise.all(
|
|||||||
}
|
}
|
||||||
${option.description}
|
${option.description}
|
||||||
`)
|
`)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: command.command
|
||||||
|
.replace(':', '-')
|
||||||
|
.replace(' ', '-')
|
||||||
|
.replace(/[\]\[.]+/gm, ''),
|
||||||
|
template,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
// TODO: Try to add option's type, examples, and group?
|
||||||
name: command.command
|
const nxCommands = getCommands(commandsObject);
|
||||||
.replace(':', '-')
|
await Promise.all(
|
||||||
.replace(' ', '-')
|
Object.keys(nxCommands)
|
||||||
.replace(/[\]\[.]+/gm, ''),
|
.filter((name) => !sharedCommands.includes(name))
|
||||||
template,
|
.map((name) => parseCommandInstance(name, nxCommands[name]))
|
||||||
};
|
.map(async (command) => generateMarkdown(await command))
|
||||||
}
|
.map(async (templateObject) =>
|
||||||
|
generateMarkdownFile(commandsOutputDirectory, await templateObject)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Try to add option's type, examples, and group?
|
await Promise.all(
|
||||||
const nxCommands = getCommands(commandsObject);
|
sharedCommands.map((command) => {
|
||||||
await Promise.all(
|
const sharedCommandsDirectory = path.join(
|
||||||
Object.keys(nxCommands)
|
__dirname,
|
||||||
.filter((name) => !sharedCommands.includes(name))
|
'../../docs/shared/cli'
|
||||||
.map((name) => parseCommandInstance(name, nxCommands[name]))
|
);
|
||||||
.map(async (command) => generateMarkdown(await command))
|
const sharedCommandsOutputDirectory = path.join(
|
||||||
.map(async (templateObject) =>
|
__dirname,
|
||||||
generateMarkdownFile(commandsOutputDirectory, await templateObject)
|
'../../docs/',
|
||||||
)
|
framework,
|
||||||
);
|
'cli'
|
||||||
|
);
|
||||||
|
const templateObject = {
|
||||||
|
name: command,
|
||||||
|
template: fs
|
||||||
|
.readFileSync(path.join(sharedCommandsDirectory, `${command}.md`))
|
||||||
|
.toString('utf-8'),
|
||||||
|
};
|
||||||
|
|
||||||
await Promise.all(
|
return generateMarkdownFile(
|
||||||
sharedCommands.map((command) => {
|
sharedCommandsOutputDirectory,
|
||||||
const sharedCommandsDirectory = path.join(
|
templateObject
|
||||||
__dirname,
|
);
|
||||||
'../../docs/shared/cli'
|
})
|
||||||
);
|
);
|
||||||
const sharedCommandsOutputDirectory = path.join(
|
})
|
||||||
__dirname,
|
);
|
||||||
'../../docs/',
|
|
||||||
framework,
|
|
||||||
'cli'
|
|
||||||
);
|
|
||||||
const templateObject = {
|
|
||||||
name: command,
|
|
||||||
template: fs
|
|
||||||
.readFileSync(path.join(sharedCommandsDirectory, `${command}.md`))
|
|
||||||
.toString('utf-8'),
|
|
||||||
};
|
|
||||||
|
|
||||||
return generateMarkdownFile(
|
console.log(`${chalk.green('🗸')} Generated Documentation for Nx Commands`);
|
||||||
sharedCommandsOutputDirectory,
|
}
|
||||||
templateObject
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
).then(() => {
|
|
||||||
console.log('Finished generating Nx Commands Documentation');
|
|
||||||
});
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@ import {
|
|||||||
Configuration,
|
Configuration,
|
||||||
getPackageConfigurations,
|
getPackageConfigurations,
|
||||||
} from './get-package-configurations';
|
} from './get-package-configurations';
|
||||||
|
import { Framework } from './frameworks';
|
||||||
|
import * as chalk from 'chalk';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @WhatItDoes: Generates default documentation from the builders' schema.
|
* @WhatItDoes: Generates default documentation from the builders' schema.
|
||||||
@ -69,7 +71,7 @@ function generateSchematicList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateTemplate(
|
function generateTemplate(
|
||||||
framework,
|
framework: Framework,
|
||||||
builder
|
builder
|
||||||
): { name: string; template: string } {
|
): { name: string; template: string } {
|
||||||
const filename = framework === 'angular' ? 'angular.json' : 'workspace.json';
|
const filename = framework === 'angular' ? 'angular.json' : 'workspace.json';
|
||||||
@ -160,41 +162,62 @@ function generateTemplate(
|
|||||||
return { name: builder.name, template };
|
return { name: builder.name, template };
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(
|
export async function generateExecutorsDocumentation() {
|
||||||
getPackageConfigurations().map(({ framework, configs }) => {
|
console.log(`\n${chalk.blue('i')} Generating Documentation for Executors\n`);
|
||||||
return Promise.all(
|
|
||||||
configs
|
await Promise.all(
|
||||||
.filter((item) => item.hasBuilders)
|
getPackageConfigurations().map(({ framework, configs }) => {
|
||||||
.map((config) => {
|
return Promise.all(
|
||||||
Promise.all(generateSchematicList(config, registry))
|
configs
|
||||||
.then((builderList) =>
|
.filter((item) => item.hasBuilders)
|
||||||
builderList.map((b) => generateTemplate(framework, b))
|
.map(async (config) => {
|
||||||
)
|
const buildersList = await Promise.all(
|
||||||
.then((markdownList) =>
|
generateSchematicList(config, registry)
|
||||||
Promise.all(
|
);
|
||||||
markdownList.map((template) =>
|
|
||||||
generateMarkdownFile(config.builderOutput, template)
|
const markdownList = buildersList.map((b) =>
|
||||||
)
|
generateTemplate(framework, b)
|
||||||
)
|
);
|
||||||
)
|
|
||||||
.then(() =>
|
await Promise.all(
|
||||||
console.log(
|
markdownList.map((template) =>
|
||||||
`Generated documentation for ${config.root} to ${config.output}`
|
generateMarkdownFile(config.builderOutput, template)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
).then(() => {
|
|
||||||
console.log('Done generating documentation for executors');
|
|
||||||
});
|
|
||||||
|
|
||||||
getPackageConfigurations().forEach(async ({ framework, configs }) => {
|
console.log(
|
||||||
const builders = configs
|
` - ${chalk.blue(
|
||||||
.filter((item) => item.hasBuilders)
|
config.framework
|
||||||
.map((item) => item.name);
|
)} Documentation for ${chalk.magenta(
|
||||||
await generateJsonFile(
|
path.relative(process.cwd(), config.root)
|
||||||
path.join(__dirname, '../../docs', framework, 'executors.json'),
|
)} generated at ${chalk.grey(
|
||||||
builders
|
path.relative(process.cwd(), config.builderOutput)
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
console.log();
|
||||||
|
await Promise.all(
|
||||||
|
getPackageConfigurations().map(async ({ framework, configs }) => {
|
||||||
|
const builders = configs
|
||||||
|
.filter((item) => item.hasBuilders)
|
||||||
|
.map((item) => item.name);
|
||||||
|
|
||||||
|
await generateJsonFile(
|
||||||
|
path.join(__dirname, '../../docs', framework, 'executors.json'),
|
||||||
|
builders
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`${chalk.green('🗸')} Generated ${chalk.blue(
|
||||||
|
framework
|
||||||
|
)} executors.json at ${chalk.grey(`docs/${framework}/executors.json`)}`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`\n${chalk.green('🗸')} Generated Documentation for Executors`);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import * as fs from 'fs-extra';
|
import * as fs from 'fs-extra';
|
||||||
|
import * as chalk from 'chalk';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { dedent } from 'tslint/lib/utils';
|
import { dedent } from 'tslint/lib/utils';
|
||||||
import { FileSystemSchematicJsonDescription } from '@angular-devkit/schematics/tools';
|
import { FileSystemSchematicJsonDescription } from '@angular-devkit/schematics/tools';
|
||||||
@ -16,6 +17,7 @@ import {
|
|||||||
Configuration,
|
Configuration,
|
||||||
getPackageConfigurations,
|
getPackageConfigurations,
|
||||||
} from './get-package-configurations';
|
} from './get-package-configurations';
|
||||||
|
import { Framework } from './frameworks';
|
||||||
import { parseJsonSchemaToOptions } from './json-parser';
|
import { parseJsonSchemaToOptions } from './json-parser';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,7 +63,7 @@ function generateSchematicList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function generateTemplate(
|
function generateTemplate(
|
||||||
framework: string,
|
framework: Framework,
|
||||||
schematic
|
schematic
|
||||||
): { name: string; template: string } {
|
): { name: string; template: string } {
|
||||||
const cliCommand = 'nx';
|
const cliCommand = 'nx';
|
||||||
@ -163,43 +165,63 @@ function generateTemplate(
|
|||||||
return { name: schematic.name, template };
|
return { name: schematic.name, template };
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.all(
|
export async function generateGeneratorsDocumentation() {
|
||||||
getPackageConfigurations().map(({ framework, configs }) => {
|
console.log(`\n${chalk.blue('i')} Generating Documentation for Generators\n`);
|
||||||
return Promise.all(
|
|
||||||
configs
|
|
||||||
.filter((item) => item.hasSchematics)
|
|
||||||
.map((config) => {
|
|
||||||
return Promise.all(generateSchematicList(config, registry))
|
|
||||||
.then((schematicList) => {
|
|
||||||
return schematicList
|
|
||||||
.filter((s) => !s['hidden'])
|
|
||||||
.map((s) => generateTemplate(framework, s));
|
|
||||||
})
|
|
||||||
.then((markdownList) =>
|
|
||||||
Promise.all(
|
|
||||||
markdownList.map((template) =>
|
|
||||||
generateMarkdownFile(config.schematicOutput, template)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
console.log(
|
|
||||||
`Documentation from ${config.root} generated to ${config.schematicOutput}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
).then(() => {
|
|
||||||
console.log('Finished Generating Documentation for Generators');
|
|
||||||
});
|
|
||||||
|
|
||||||
getPackageConfigurations().forEach(async ({ framework, configs }) => {
|
await Promise.all(
|
||||||
const schematics = configs
|
getPackageConfigurations().map(({ framework, configs }) => {
|
||||||
.filter((item) => item.hasSchematics)
|
return Promise.all(
|
||||||
.map((item) => item.name);
|
configs
|
||||||
await generateJsonFile(
|
.filter((item) => item.hasSchematics)
|
||||||
path.join(__dirname, '../../docs', framework, 'generators.json'),
|
.map(async (config) => {
|
||||||
schematics
|
const schematicList = await Promise.all(
|
||||||
|
generateSchematicList(config, registry)
|
||||||
|
);
|
||||||
|
|
||||||
|
const markdownList = schematicList
|
||||||
|
.filter((s) => !s['hidden'])
|
||||||
|
.map((s_1) => generateTemplate(framework, s_1));
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
markdownList.map((template) =>
|
||||||
|
generateMarkdownFile(config.schematicOutput, template)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
` - ${chalk.blue(
|
||||||
|
config.framework
|
||||||
|
)} Documentation for ${chalk.magenta(
|
||||||
|
path.relative(process.cwd(), config.root)
|
||||||
|
)} generated at ${chalk.grey(
|
||||||
|
path.relative(process.cwd(), config.schematicOutput)
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
console.log();
|
||||||
|
await Promise.all(
|
||||||
|
getPackageConfigurations().map(({ framework, configs }) => {
|
||||||
|
const schematics = configs
|
||||||
|
.filter((item) => item.hasSchematics)
|
||||||
|
.map((item) => item.name);
|
||||||
|
return generateJsonFile(
|
||||||
|
path.join(__dirname, '../../docs', framework, 'generators.json'),
|
||||||
|
schematics
|
||||||
|
).then(() => {
|
||||||
|
console.log(
|
||||||
|
`${chalk.green('🗸')} Generated ${chalk.blue(
|
||||||
|
framework
|
||||||
|
)} generators.json at ${chalk.grey(
|
||||||
|
`docs/${framework}/generators.json`
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`\n${chalk.green('🗸')} Generated Documentation for Generators`);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
|
import * as glob from 'glob';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as shelljs from 'shelljs';
|
import { Framework, Frameworks } from './frameworks';
|
||||||
|
|
||||||
export interface Configuration {
|
export interface Configuration {
|
||||||
name: string;
|
name: string;
|
||||||
root: string;
|
root: string;
|
||||||
|
framework: Framework;
|
||||||
source: string;
|
source: string;
|
||||||
output: string;
|
output: string;
|
||||||
builderOutput: string;
|
builderOutput: string;
|
||||||
schematicOutput: string;
|
schematicOutput: string;
|
||||||
hasBuilders: string;
|
hasBuilders: boolean;
|
||||||
hasSchematics: string;
|
hasSchematics: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,37 +23,43 @@ export interface Configuration {
|
|||||||
export function getPackageConfigurations(
|
export function getPackageConfigurations(
|
||||||
packagesDirectory: string = 'packages',
|
packagesDirectory: string = 'packages',
|
||||||
documentationsDirectory: string = 'docs'
|
documentationsDirectory: string = 'docs'
|
||||||
): { framework: 'angular' | 'react' | 'node'; configs: Configuration[] }[] {
|
): { framework: Framework; configs: Configuration[] }[] {
|
||||||
return ['angular', 'react', 'node'].map((framework) => {
|
return Frameworks.map((framework: Framework) => {
|
||||||
const packagesDir = path.resolve(
|
const packagesDir = path.resolve(
|
||||||
path.join(__dirname, '../../', packagesDirectory)
|
path.join(__dirname, '../../', packagesDirectory)
|
||||||
);
|
);
|
||||||
const documentationDir = path.resolve(
|
const documentationDir = path.resolve(
|
||||||
path.join(__dirname, '../../', documentationsDirectory)
|
path.join(__dirname, '../../', documentationsDirectory)
|
||||||
);
|
);
|
||||||
const configs = shelljs.ls(packagesDir).map((folderName) => {
|
|
||||||
const itemList = shelljs.ls(path.join(packagesDir, folderName));
|
const configs = glob.sync(`${packagesDir}/*`).map(
|
||||||
const output = path.join(
|
(folderPath): Configuration => {
|
||||||
documentationDir,
|
const folderName = folderPath.substring(packagesDir.length + 1);
|
||||||
framework,
|
const itemList = glob
|
||||||
`api-${folderName}`
|
.sync(`${folderPath}/*`)
|
||||||
);
|
.map((item) => item.split(folderPath + '/')[1]);
|
||||||
return {
|
const output = path.join(
|
||||||
name: folderName,
|
documentationDir,
|
||||||
root: path.join(packagesDir, folderName),
|
framework,
|
||||||
source: path.join(packagesDir, `${folderName}/src`),
|
`api-${folderName}`
|
||||||
output,
|
);
|
||||||
framework,
|
return {
|
||||||
builderOutput: path.join(output, 'executors'),
|
name: folderName,
|
||||||
schematicOutput: path.join(output, 'generators'),
|
root: folderPath,
|
||||||
hasBuilders:
|
source: path.join(folderPath, '/src'),
|
||||||
itemList.includes('builders.json') ||
|
output,
|
||||||
itemList.includes('executors.json'),
|
framework,
|
||||||
hasSchematics:
|
builderOutput: path.join(output, 'executors'),
|
||||||
itemList.includes('collection.json') ||
|
schematicOutput: path.join(output, 'generators'),
|
||||||
itemList.includes('generators.json'),
|
hasBuilders:
|
||||||
};
|
itemList.includes('builders.json') ||
|
||||||
});
|
itemList.includes('executors.json'),
|
||||||
return { framework: framework as any, configs };
|
hasSchematics:
|
||||||
|
itemList.includes('collection.json') ||
|
||||||
|
itemList.includes('generators.json'),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return { framework, configs };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { green, red } from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import * as shell from 'shelljs';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as parseLinks from 'parse-markdown-links';
|
import * as parseLinks from 'parse-markdown-links';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as glob from 'glob';
|
||||||
|
|
||||||
|
console.log(`${chalk.blue('i')} Internal Link Check`);
|
||||||
|
|
||||||
const LOGGING_KEYS = [
|
const LOGGING_KEYS = [
|
||||||
'LOG_DOC_TREE',
|
'LOG_DOC_TREE',
|
||||||
@ -76,7 +78,7 @@ function expandFrameworks(linkPaths: string[]): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractAllInternalLinks(): Record<string, string[]> {
|
function extractAllInternalLinks(): Record<string, string[]> {
|
||||||
return shell.ls(`${BASE_PATH}/**/*.md`).reduce((acc, path) => {
|
return glob.sync(`${BASE_PATH}/**/*.md`).reduce((acc, path) => {
|
||||||
const fileContents = readFileContents(path);
|
const fileContents = readFileContents(path);
|
||||||
const directLinks = fileContents
|
const directLinks = fileContents
|
||||||
.split(/[ ,]+/)
|
.split(/[ ,]+/)
|
||||||
@ -103,7 +105,7 @@ function extractAllInternalLinks(): Record<string, string[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractAllInternalLinksWithAnchors(): Record<string, string[]> {
|
function extractAllInternalLinksWithAnchors(): Record<string, string[]> {
|
||||||
return shell.ls(`${BASE_PATH}/**/*.md`).reduce((acc, path) => {
|
return glob.sync(`${BASE_PATH}/**/*.md`).reduce((acc, path) => {
|
||||||
const links = parseLinks(readFileContents(path))
|
const links = parseLinks(readFileContents(path))
|
||||||
.filter(isLinkInternal)
|
.filter(isLinkInternal)
|
||||||
.filter(isNotAsset)
|
.filter(isNotAsset)
|
||||||
@ -138,7 +140,7 @@ function isCategoryNode(
|
|||||||
|
|
||||||
function getDocumentMap(): DocumentTree[] {
|
function getDocumentMap(): DocumentTree[] {
|
||||||
return JSON.parse(
|
return JSON.parse(
|
||||||
fs.readFileSync(path.join(BASE_PATH, 'map.json'), { encoding: 'utf-8' })
|
fs.readFileSync(path.join(BASE_PATH, 'map.json'), 'utf-8')
|
||||||
) as DocumentTree[];
|
) as DocumentTree[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,29 +255,27 @@ function checkInternalAnchoredLinks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!erroneousInternalLinks) {
|
if (!erroneousInternalLinks) {
|
||||||
console.log(green('All internal links appear to be valid!!'));
|
console.log(`${chalk.green('🗸')} All internal links appear to be valid!`);
|
||||||
console.log('Moving on to check internal anchors...');
|
|
||||||
const erroneousAnchoredInternalLinks = checkInternalAnchoredLinks(
|
const erroneousAnchoredInternalLinks = checkInternalAnchoredLinks(
|
||||||
validInternalLinksMap
|
validInternalLinksMap
|
||||||
);
|
);
|
||||||
if (!erroneousAnchoredInternalLinks) {
|
if (!erroneousAnchoredInternalLinks) {
|
||||||
console.log(green('All internal anchored links appear to be valid!!'));
|
console.log(
|
||||||
|
`${chalk.green('🗸')} All internal anchored links appear to be valid!`
|
||||||
|
);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(`${chalk.red(
|
||||||
red(
|
'ERROR'
|
||||||
'The following files appear to contain the following invalid anchored internal links:'
|
)} The following files appear to contain the following invalid anchored internal links:
|
||||||
)
|
${JSON.stringify(erroneousAnchoredInternalLinks, null, 2)}`);
|
||||||
);
|
|
||||||
console.log(red(JSON.stringify(erroneousAnchoredInternalLinks, null, 2)));
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(`${chalk.red(
|
||||||
red(
|
'ERROR'
|
||||||
'The following files appear to contain the following invalid internal links:'
|
)} The following files appear to contain the following invalid internal links:
|
||||||
)
|
${JSON.stringify(erroneousInternalLinks, null, 2)}`);
|
||||||
);
|
|
||||||
console.log(red(JSON.stringify(erroneousInternalLinks, null, 2)));
|
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
import { green, red } from 'chalk';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as shell from 'shelljs';
|
import * as glob from 'glob';
|
||||||
|
import * as chalk from 'chalk';
|
||||||
|
|
||||||
|
console.log(`${chalk.blue('i')} Documentation Map Check`);
|
||||||
|
|
||||||
const basePath = 'docs';
|
const basePath = 'docs';
|
||||||
const sharedFilesPattern = 'shared/cli';
|
const sharedFilesPattern = 'shared/cli';
|
||||||
|
|
||||||
const readmePathList: string[] = shell
|
const readmePathList: string[] = glob
|
||||||
.ls(`${basePath}/**/*.md`)
|
.sync(`${basePath}/**/*.md`)
|
||||||
.map((path: string) => path.split(basePath)[1])
|
.map((path: string) => path.split(basePath)[1])
|
||||||
.map((path: string) => path.slice(1, -3)) // Removing first `/` and `.md`
|
.map((path: string) => path.slice(1, -3)) // Removing first `/` and `.md`
|
||||||
.filter((path: string) => !path.startsWith(sharedFilesPattern));
|
.filter((path: string) => !path.startsWith(sharedFilesPattern));
|
||||||
@ -49,38 +51,44 @@ let scriptError = false;
|
|||||||
|
|
||||||
if (!!readmeMissList.length) {
|
if (!!readmeMissList.length) {
|
||||||
console.error(
|
console.error(
|
||||||
red("\n⚠️ Documentation files and 'map.json' file are out of sync!\n")
|
chalk.red(
|
||||||
|
"\n⚠️ Documentation files and 'map.json' file are out of sync!\n"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
console.log(readmeMissList.map((x) => x.concat('.md')).join('\n'));
|
console.log(readmeMissList.map((x) => x.concat('.md')).join('\n'));
|
||||||
console.error(
|
console.error(
|
||||||
red(
|
chalk.red(
|
||||||
`\nSome documentation files exist without any reference in \'map.json\', make sure to add an entry.`
|
`\nSome documentation files exist without any reference in \'map.json\', make sure to add an entry.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
scriptError = true;
|
scriptError = true;
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
green("Markdown files are in sync with 'map.json', everything is good 👍")
|
`${chalk.green('🗸')} Markdown files are in sync with ${chalk.grey(
|
||||||
|
'docs/maps.json'
|
||||||
|
)}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!mapMissList.length) {
|
if (!!mapMissList.length) {
|
||||||
console.error(
|
console.log(
|
||||||
red(
|
`\n${chalk.red(
|
||||||
"\n⚠️ The 'map.json' file and the documentation files are out of sync!\n"
|
'ERROR'
|
||||||
)
|
)} The 'map.json' file and the documentation files are out of sync!\n`
|
||||||
);
|
);
|
||||||
console.log(mapMissList.map((x) => x.concat('.md')).join('\n'));
|
console.log(mapMissList.map((x) => x.concat('.md')).join('\n'));
|
||||||
console.error(
|
console.log(
|
||||||
red(
|
`\n${chalk.red(
|
||||||
`\nThe \'map.json\' file is linking documenation files that do not exist.`
|
'ERROR'
|
||||||
)
|
)} The \'map.json\' file is linking documenation files that do not exist.`
|
||||||
);
|
);
|
||||||
scriptError = true;
|
scriptError = true;
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
green(
|
console.log(
|
||||||
"The 'map.json' file and the documentation files are in sync, everything is good 👍"
|
`${chalk.green(
|
||||||
|
'🗸'
|
||||||
|
)} The 'map.json' file and the documentation files are in sync.`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3190,6 +3190,7 @@
|
|||||||
url-loader "^4.0.0"
|
url-loader "^4.0.0"
|
||||||
util-deprecate "^1.0.2"
|
util-deprecate "^1.0.2"
|
||||||
webpack "^4.44.2"
|
webpack "^4.44.2"
|
||||||
|
|
||||||
webpack-dev-middleware "^3.7.0"
|
webpack-dev-middleware "^3.7.0"
|
||||||
webpack-filter-warnings-plugin "^1.2.1"
|
webpack-filter-warnings-plugin "^1.2.1"
|
||||||
webpack-hot-middleware "^2.25.0"
|
webpack-hot-middleware "^2.25.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user