Skip to content

Commit

Permalink
Merge pull request #21 from GaryB432/feature/doc-generator
Browse files Browse the repository at this point in the history
Feature/doc generator
  • Loading branch information
GaryB432 committed Jan 26, 2024
2 parents da69b59 + 721a232 commit e8b4847
Show file tree
Hide file tree
Showing 10 changed files with 316 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jobs:
- 20
- 18
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
Expand Down
5 changes: 5 additions & 0 deletions tools/workspace-plugin/generators.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"factory": "./src/generators/make-schemas/generator",
"schema": "./src/generators/make-schemas/schema.json",
"description": "make-schemas generator"
},
"doc": {
"factory": "./src/generators/doc/generator",
"schema": "./src/generators/doc/schema.json",
"description": "Generate documentation for packages"
}
}
}
5 changes: 4 additions & 1 deletion tools/workspace-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
"name": "@gb-nx/workspace-plugin",
"version": "0.0.1",
"type": "commonjs",
"generators": "./generators.json"
"generators": "./generators.json",
"dependencies": {
"@nx/devkit": "17.2.7"
}
}
18 changes: 18 additions & 0 deletions tools/workspace-plugin/src/generators/doc/generator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { type Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { docGenerator } from './generator';
import { type DocGeneratorSchema } from './schema';

describe('doc generator', () => {
let tree: Tree;

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});

it('should run successfully', async () => {
await docGenerator(tree, {});
// const config = readProjectConfiguration(tree, 'test');
expect(2 + 2).not.toEqual(5);
});
});
69 changes: 69 additions & 0 deletions tools/workspace-plugin/src/generators/doc/generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {
formatFiles,
getProjects,
joinPathFragments,
readJson,
type GeneratorsJson,
type Tree,
} from '@nx/devkit';
import { type JSONSchema } from 'json-schema-to-typescript';
import { type PackageJson } from 'nx/src/utils/package-json';
import { Document, h1, h2, h3, table } from '../../markdown';
import { type DocGeneratorSchema } from './schema';

export async function docGenerator(
tree: Tree,
_options: DocGeneratorSchema
): Promise<void> {
for (const [, b] of getProjects(tree)) {
const pj = joinPathFragments(b.root, 'package.json');
if (tree.exists(pj)) {
const pkg = readJson<PackageJson>(tree, pj);
const lines = [
h1(pkg.name),
'',
`See \`nx list ${pkg.name}\` for more information.`,
'',
];
if (pkg.generators) {
const generatorsf = joinPathFragments(b.root, pkg.generators);
if (tree.exists(generatorsf)) {
lines.push(h2('Generators'));
const jgens = readJson<GeneratorsJson>(tree, generatorsf);

for (const [gn, generator] of Object.entries(
jgens.generators ?? {}
)) {
const tbody: [string, string, string][] = [];
const schm = readJson<JSONSchema>(
tree,
joinPathFragments(b.root, generator.schema)
);
if (schm.properties) {
for (const [n, prop] of Object.entries(schm.properties)) {
if (typeof prop.type === 'string') {
tbody.push([`${n}`, prop.type, prop.description ?? '']);
}
}
lines.push(
h3(gn),
schm.title ?? '',
'',
generator.description ?? '',
'',
...table(['Option', 'Type', 'Description'], tbody)
);
}
}
}
}
tree.write(
joinPathFragments(b.root, 'commands.md'),
new Document(lines).print().join('\n')
);
}
}
await formatFiles(tree);
}

export default docGenerator;
3 changes: 3 additions & 0 deletions tools/workspace-plugin/src/generators/doc/schema.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface DocGeneratorSchema {
exclude?: string[];
}
27 changes: 27 additions & 0 deletions tools/workspace-plugin/src/generators/doc/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Create markdown documents for a plugin workspace",
"description": "Create a document detailing options for plugin projects",
"examples": [
{
"command": "nx g doc",
"description": "Create a document listing every project"
},
{
"command": "nx g doc --exclude=my-app --exclude=other-plugin",
"description": "Create a document listing every project except my-app and other-plugin"
}
],
"type": "object",
"properties": {
"exclude": {
"type": "array",
"description": "Projects to exclude",
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"required": []
}
100 changes: 100 additions & 0 deletions tools/workspace-plugin/src/markdown/doc.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Document, bulletList, headingLevel, table } from './doc';

describe('Doc', () => {
const br = '<<<<';
let doc: Document;

test('prints', () => {
doc = new Document(['a', 'b', 'c', 'd', 'e']);
expect(doc.print(br)).toEqual(['a', 'b', 'c', 'd', 'e', br]);
});
test('prints reduced', () => {
doc = new Document(['a', 'b', '', '', 'c', 'd', '', '', 'e', '', '', '']);
expect(doc.print(br)).toEqual(['a', 'b', '', 'c', 'd', '', 'e', '', br]);
});

// TODO remove extra blank line at end of sections
test('prints reduced', () => {
doc = new Document(['a', 'b', '', '', 'c', 'd', '', '', 'e', '', '', '']);
expect(doc.print(br)).toMatchInlineSnapshot(`
[
"a",
"b",
"",
"c",
"d",
"",
"e",
"",
"<<<<",
]
`);
});

test('prints reduced', () => {
doc = new Document([
'# Part 1',
'',
'i have a blank line here',
'',
'## subpart',
'',
'I also have a blank line',
'and another one too',
'',
'another couple is here',
'omg here',
]);
expect(doc.print(br)).toMatchInlineSnapshot(`
[
"# Part 1",
"",
"i have a blank line here",
"",
"<<<<",
"## subpart",
"",
"I also have a blank line",
"and another one too",
"",
"another couple is here",
"omg here",
"<<<<",
]
`);
});

test('outline', () => {
expect(doc.outline()).toEqual(['# Part 1', '## subpart']);
});
});

describe('functions', () => {
test('headingLevel works', () => {
expect(
headingLevel('##### my heading with another # and more ## at the end')
).toEqual(5);
});
test('works', () => {
expect(bulletList(['a', 'b', 'c'])).toEqual(['- a', '- b', '- c']);
});

test('table', () => {
expect(
table(
['a', 'b', 'c'],
[
['d', 'e', 'f'],
['g', 'h', 'i'],
['j', 'k', 'l'],
]
)
).toEqual([
'| a | b | c |',
'| --- | --- | --- |',
'| d | e | f |',
'| g | h | i |',
'| j | k | l |',
]);
});
});
87 changes: 87 additions & 0 deletions tools/workspace-plugin/src/markdown/doc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
export type Section = string[];

export function codeBlock(block: string[], lang: string): string[] {
return ['```'.concat(lang), ...block, '```'];
}

export function bulletList(block: string[]): string[] {
return block.map((l) => '- '.concat(l));
}

export function table(headings: string[], body: string[][]): string[] {
const tline = (parts: string[]) =>
['', ...parts, ''].join(' | ').slice(1, -1);
const dashes = Array(headings.length).fill('---');
const result = [headings, dashes, ...body].map(tline);
return result;
}

export function headingLevel(line: string): number {
let lvl = 0;
for (const c of line) {
if (c === '#') {
lvl += 1;
} else {
break;
}
}
return lvl;
}

export function h1(s: string): string {
return h(s, 1);
}

export function h2(s: string): string {
return h(s, 2);
}

export function h3(s: string): string {
return h(s, 3);
}

function h(s: string, level: number): string {
return '#'.repeat(level).concat(' ').concat(s);
}

export class Document {
public readonly sections: Section[] = [];

public constructor(lines: string[]) {
const block: string[] = [];
let last = '';
for (const line of lines) {
const h = headingLevel(line);
if (h > 0) {
if (block.length) {
this.sections.push(block.splice(0, block.length));
}
block.push(line);
last = '';
block.push(last);
} else {
if (line === '') {
if (last !== '') {
block.push(line);
last = line;
}
} else {
block.push(line);
last = line;
}
}
}

if (block.length) {
this.sections.push(block.splice(0, block.length));
}
}

public outline(): string[] {
return this.sections.map((s) => s[0]);
}

public print(breakLine = ''): string[] {
return this.sections.map((s) => [...s, breakLine]).flat();
}
}
1 change: 1 addition & 0 deletions tools/workspace-plugin/src/markdown/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './doc';

0 comments on commit e8b4847

Please sign in to comment.