Skip to content

Commit

Permalink
feat(compodoc): add compodoc plugin
Browse files Browse the repository at this point in the history
New Compodoc Nx Plugin

Adds a builder that execute Compodoc CLI to enable the generation of documentation as Angular CLI target.
Adds a schematic to simply configure the builder for projects inside a workspace.
Adds an `ng add` schematic to install the plugin as easy as possible.
  • Loading branch information
twittwer committed May 2, 2020
1 parent bbc3a70 commit 04402fb
Show file tree
Hide file tree
Showing 25 changed files with 718 additions and 223 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
## Projects

| Status | Project | Description |
| :----: | --------- | ---------------------------------------------------------------- |
| 🗓️ | Compodoc | Integrate Compodoc generation in the Nx workflow. |
| 🗓️ | Storydocs | Combine Compodoc & Storybook plugins for Storybook's Docs addon. |
| Status | Project | Description |
| :----: | --------------------------- | ---------------------------------------------------------------- |
| | [Compodoc](./libs/compodoc) | Integrate Compodoc generation in the Nx workflow. |
| 🗓️ | Storydocs | Combine Compodoc & Storybook plugins for Storybook's Docs addon. |
110 changes: 107 additions & 3 deletions libs/compodoc/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,111 @@
# compodoc

This library was generated with [Nx](https://nx.dev).
> Nx Plugin to integrate the generation of documentation with [Compodoc](https://compodoc.app/) in the [Nx workflow](https://nx.dev/angular).
## Running unit tests
## Installation

Run `ng test compodoc` to execute the unit tests via [Jest](https://jestjs.io).
Add the plugin to your Nx workspace:

```
ng add @twittwer/compodoc
// adds `@compdoc/compodoc` & `@twittwer/compodoc` as devDependencies
```

Configure Compodoc for a project:

```
ng g @twittwer/compodoc:config <project>
// adds a `compodoc` target to the specified project in your `angular.json`
```

## Usage

Generate Compodoc documentation for a project:

```
// HTML Format
ng run <project>:compodoc
// JSON Format
ng run <project>:compodoc:json
```

## Configuration Options

The builder support several configuration options which are passed to Compodoc command.

> [Original documentation of Compodoc options](https://compodoc.app/guides/options.html)
> (Defaults mainly correspond to the original default values - asterisks mark the exceptions)
| Option | Default | Description |
| --------------------- | ----------------------------- | ---------------------------------------------------------------------------------- |
| tsConfig | `<projectRoot>/tsconfig.json` | Path to project's TypeScript configuration file. |
| outputPath | `dist/compodoc/<projectName>` | The output path of the generated files. |
| exportFormat | `html` | Output format (html, json). |
| | | |
| name | `<projectName>` | Title of the documentation. |
| language | `en-US` | Language used for the generated documentation. |
| | | |
| theme | `gitbook` | Theme used for the generated documentation. |
| extTheme | | Path to external theme file. |
| templates | | Path to directory of Handlebars templates to override built-in templates. |
| | | |
| customLogo | | Path to custom logo. |
| customFavicon | | Path to custom favicon. |
| hideGenerator | `false` | Do not print the Compodoc logo at the bottom of the page. |
| | | |
| includes | | Path of external markdown files to include (folder should contain a summary.json). |
| includesName | `Additional documentation` | Name of item menu of externals markdown files. |
| | | |
| disableCoverage | `true`\* | Do not add the documentation coverage report. |
| disableSourceCode | `false` | Do not add source code tab and links to source code. |
| disableDomTree | `false` | Do not add dom tree tab. |
| disableTemplateTab | `false` | Do not add template tab. |
| disableStyleTab | `false` | Do not add style tab. |
| disableGraph | `false` | Disable rendering of the dependency graph. |
| disablePrivate | `true`\* | Do not show private in generated documentation. |
| disableProtected | `false` | Do not show protected in generated documentation. |
| disableInternal | `true`\* | Do not show @internal in generated documentation. |
| disableLifeCycleHooks | `true`\* | Do not show Angular lifecycle hooks in generated documentation. |
| disableRoutesGraph | `false` | Do not add the routes graph. |
| disableSearch | `false` | Do not add the search input. |
| disableDependencies | `false` | Do not add the dependencies list. |
| | | |
| assetsFolder | | External assets folder to copy in generated documentation folder. |
| | | |
| serve | `false` | Serve generated documentation. |
| port | `8080` | Port for serving of documentation (default: 8080). |
| | | |
| silent | `true`\* | Suppress verbose build output. |
| | | |

> More details can be found in the builder's [schema.json](./src/builders/compodoc/schema.json).
### How to configure the builder?

The options can be defined in the `angular.json`:

```json5
{
projects: {
'<project>': {
architects: {
compodoc: {
builder: '@twittwer/compodoc:compodoc',
options: {
/* Define your options here */
},
configurations: {
'<configuration name>': {
/* or here in case they are required under specific conditions only. */
},
},
},
},
},
},
}
```

## Planned Features

- Enable compodoc builder to generate a workspace wide documentation including the Readmes of all projects automatically.
4 changes: 2 additions & 2 deletions libs/compodoc/builders.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "../../node_modules/@angular-devkit/architect/src/builders-schema.json",
"builders": {
"build": {
"compodoc": {
"implementation": "./src/builders/compodoc/builder",
"schema": "./src/builders/compodoc/schema.json",
"description": "compodoc builder"
"description": "Builder for Compodoc documentation."
}
}
}
16 changes: 11 additions & 5 deletions libs/compodoc/collection.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{
"$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json",
"name": "compodoc",
"name": "Compodoc",
"version": "0.0.1",
"schematics": {
"compodoc": {
"factory": "./src/schematics/compodoc/schematic",
"schema": "./src/schematics/compodoc/schema.json",
"description": "compodoc schematic"
"ng-add": {
"factory": "./src/schematics/ng-add/schematic",
"schema": "./src/schematics/ng-add/schema.json",
"save": "devDependencies",
"description": "Install compodoc plugin."
},
"config": {
"factory": "./src/schematics/config/schematic",
"schema": "./src/schematics/config/schema.json",
"description": "Configure compodoc target for a project."
}
}
}
22 changes: 21 additions & 1 deletion libs/compodoc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
{
"name": "@twittwer/compodoc",
"version": "0.0.1",
"description": "Nx Plugin to integrate the generation of documentation with compodoc in the Nx workflow.",
"version": "0.0.3",
"private": false,
"license": "MIT",
"author": "Tobias Wittwer <t.wittwer95@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/twittwer/nx-tools.git"
},
"homepage": "https://github.com/twittwer/nx-tools/blob/master/libs/compodoc#readme",
"bugs": {
"url": "https://github.com/twittwer/nx-tools/issues"
},
"keywords": [
"angular",
"angular-builders",
"angular-schematics",
"nx",
"nx-plugin",
"compodoc"
],
"main": "src/index.js",
"schematics": "./collection.json",
"builders": "./builders.json"
Expand Down
80 changes: 38 additions & 42 deletions libs/compodoc/src/builders/compodoc/builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
import { Architect } from '@angular-devkit/architect';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
import { schema } from '@angular-devkit/core';
import { join } from 'path';
import { CompodocBuilderSchema } from './schema';

const options: CompodocBuilderSchema = {};

describe('Command Runner Builder', () => {
let architect: Architect;
let architectHost: TestingArchitectHost;

beforeEach(async () => {
const registry = new schema.CoreSchemaRegistry();
registry.addPostTransform(schema.transforms.addUndefinedDefaults);

architectHost = new TestingArchitectHost('/root', '/root');
architect = new Architect(architectHost, registry);

// This will either take a Node package name, or a path to the directory
// for the package.json file.
await architectHost.addBuilderFromPackage(join(__dirname, '../../..'));
});

it('can run', async () => {
// A "run" can have multiple outputs, and contains progress information.
const run = await architect.scheduleBuilder(
'@twittwer/compodoc:build',
options,
);
// The "result" member (of type BuilderOutput) is the next output.
const output = await run.result;

// Stop the builder from running. This stops Architect from keeping
// the builder-associated states in memory, since builders keep waiting
// to be scheduled.
await run.stop();

// Expect that it succeeded.
expect(output.success).toBe(true);
});
});
it.todo('Compodoc Builder');

// const options: CompodocBuilderSchema = {};
//
// describe('Compodoc Builder', () => {
// let architect: Architect;
// let architectHost: TestingArchitectHost;
//
// beforeEach(async () => {
// const registry = new schema.CoreSchemaRegistry();
// registry.addPostTransform(schema.transforms.addUndefinedDefaults);
//
// architectHost = new TestingArchitectHost('/root', '/root');
// architect = new Architect(architectHost, registry);
//
// // This will either take a Node package name, or a path to the directory
// // for the package.json file.
// await architectHost.addBuilderFromPackage(join(__dirname, '../../..'));
// });
//
// it('can run', async () => {
// // A "run" can have multiple outputs, and contains progress information.
// const run = await architect.scheduleBuilder(
// '@twittwer/compodoc:build',
// options,
// );
// // The "result" member (of type BuilderOutput) is the next output.
// const output = await run.result;
//
// // Stop the builder from running. This stops Architect from keeping
// // the builder-associated states in memory, since builders keep waiting
// // to be scheduled.
// await run.stop();
//
// // Expect that it succeeded.
// expect(output.success).toBe(true);
// });
// });
56 changes: 45 additions & 11 deletions libs/compodoc/src/builders/compodoc/builder.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
import {
BuilderContext,
BuilderOutput,
createBuilder
createBuilder,
} from '@angular-devkit/architect';
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { CompodocBuilderSchema } from './schema';
import { spawn } from 'child_process';
import { resolve } from 'path';
import { buildCompodocArgs, buildCompodocCmd } from './compodoc-utils';
import { ProjectType } from '@nrwl/workspace';

export function runBuilder(
async function runBuilder(
options: CompodocBuilderSchema,
context: BuilderContext
): Observable<BuilderOutput> {
return of({ success: true }).pipe(
tap(() => {
context.logger.info('Builder ran for compodoc');
})
);
context: BuilderContext,
): Promise<BuilderOutput> {
const {
workspaceRoot,
currentDirectory,
target: { project, target, configuration },
} = context;
const projectMetadata = await context.getProjectMetadata(project);
const { root: projectRoot, projectType } = projectMetadata as {
root: string;
projectType: ProjectType;
target: string;
configuration: string;
};

options.tsConfig = options.tsConfig ?? resolve(projectRoot, 'tsconfig.json');
options.outputPath =
options.outputPath ?? resolve('dist', 'compodoc', project);

return new Promise<BuilderOutput>(res => {
const childProcess = spawn(
buildCompodocCmd(context),
buildCompodocArgs(options, context),
{ cwd: projectRoot },
);

process.on('exit', () => childProcess.kill());

childProcess.stdout.on('data', data => {
context.logger.info(data.toString());
});
childProcess.stderr.on('data', data => {
context.logger.error(data.toString());
});

childProcess.on('close', code => {
res({ success: code === 0 });
});
});
}

export default createBuilder(runBuilder);
Loading

0 comments on commit 04402fb

Please sign in to comment.