Skip to content

Commit ab0a4d6

Browse files
committed
🎉 initial commit (WIP)
1 parent 0394c75 commit ab0a4d6

File tree

6 files changed

+222
-19
lines changed

6 files changed

+222
-19
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,6 @@ dist
102102

103103
# TernJS port file
104104
.tern-port
105+
106+
# Pika
107+
pkg/

README.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,35 @@
1-
# My Typescript Template
1+
# Docusaurus Plugin `react-docgen`
22

3-
A small template that I use to build node typescript-based projects.
3+
A Docusaurus 2.x plugin that help generate and consume auto-generated docs from `react-docgen`.
44

5-
## Stack
5+
## Installation
66

7-
* `typescript`
8-
* `@pika/pack`
9-
* `eslint`
10-
* `prettier`
7+
Grab from NPM and install along with `react-docgen`:
8+
9+
```sh
10+
npm i docusaurus-plugin-react-docgen react-docgen # or
11+
yarn add docusaurus-plugin-react-docgen react-docgen
12+
```
13+
14+
## Usage
15+
16+
Inside your `docusaurus.config.js` add to the `plugins` field and configure with the `src` option with full glob support :+1:
17+
18+
```js
19+
module.exports = {
20+
plugins: [
21+
[
22+
'docusaurus-plugin-react-docgen',
23+
{
24+
// pass in a single string or an array
25+
src: [
26+
'path/to/**/*.tsx',
27+
'!path/to/**/*test.*',
28+
]
29+
}
30+
]
31+
]
32+
}
33+
```
34+
35+
Any pattern supported by [`fast-glob`](https://github.com/mrmlnc/fast-glob) is allowed here (including negations)

package.json

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,91 @@
11
{
2-
"name": "your-module",
3-
"version": "1.0.0",
4-
"description": "Some awesome description about your module",
5-
"main": "index.js",
2+
"name": "docusaurus-plugin-react-docgen",
3+
"version": "0.0.1",
4+
"description": "A small plugin that integrates react-docgen with docusaurus 2.x",
65
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1",
8-
"lint": "eslint 'src/index.{ts,js,tsx}'"
6+
"test": "jest --silent",
7+
"lint": "eslint 'src/index.{ts,js,tsx}'",
8+
"build": "pika build"
99
},
10-
"keywords": [],
10+
"keywords": [
11+
"docusaurus",
12+
"plugin",
13+
"react-docgen"
14+
],
1115
"repository": {
12-
"url": "",
16+
"url": "https://github.com/atomicpages/docusaurus-plugin-react-docgen",
1317
"type": "git"
1418
},
1519
"author": "Dennis Thompson",
1620
"license": "MIT",
21+
"dependencies": {
22+
"@hapi/joi": "^17.0.0",
23+
"globby": "^11.0.1"
24+
},
25+
"peerDependencies": {
26+
"react-docgen": "^5.0.0"
27+
},
1728
"devDependencies": {
29+
"@babel/parser": "^7.11.4",
1830
"@djthoms/eslint-config": "^3.0.0",
1931
"@djthoms/prettier-config": "^2.0.0",
32+
"@docusaurus/types": "^2.0.0-alpha.61",
2033
"@pika/pack": "^0.5.0",
2134
"@pika/plugin-build-node": "^0.9.2",
2235
"@pika/plugin-ts-standard-pkg": "^0.9.2",
36+
"@types/jest": "^26.0.10",
37+
"@types/node": "^14.6.1",
2338
"eslint": "^7.7.0",
39+
"jest": "^26.4.2",
2440
"prettier": "^2.1.1",
41+
"react-docgen": "^5.3.0",
42+
"ts-jest": "^26.3.0",
2543
"typescript": "^4.0.2"
2644
},
45+
"@pika/pack": {
46+
"pipeline": [
47+
[
48+
"@pika/plugin-ts-standard-pkg",
49+
{
50+
"args": [
51+
"--target",
52+
"es2019"
53+
]
54+
}
55+
],
56+
[
57+
"@pika/plugin-build-node"
58+
]
59+
]
60+
},
2761
"prettier": "@djthoms/prettier-config",
2862
"eslintConfig": {
2963
"env": {
30-
"node": true
64+
"node": true,
65+
"jest": true
3166
},
3267
"extends": [
3368
"@djthoms/eslint-config",
3469
"@djthoms/eslint-config/esmodules",
3570
"@djthoms/eslint-config/typescript"
3671
]
72+
},
73+
"jest": {
74+
"preset": "ts-jest",
75+
"collectCoverage": true,
76+
"coverageDirectory": "<rootDir>/coverage",
77+
"coverageReporters": [
78+
"text",
79+
"html",
80+
"text-summary",
81+
"lcov"
82+
],
83+
"collectCoverageFrom": [
84+
"src/**/*.ts"
85+
],
86+
"testPathIgnorePatterns": [
87+
"pkg",
88+
"node_modules"
89+
]
3790
}
3891
}

src/index.ts

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,112 @@
1-
// create some magic here!
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
import globby from 'globby';
5+
import { promisify } from 'util';
6+
7+
import Joi from '@hapi/joi';
8+
import reactDocgen from 'react-docgen';
9+
10+
import { ParserOptions } from '@babel/parser';
11+
import { Plugin, OptionValidationContext, DocusaurusContext } from '@docusaurus/types';
12+
import { asyncMap } from './utils';
13+
14+
type Handler = (doc: any, definition: any, parser: { parse: (s: string) => {} }) => void;
15+
16+
type Options = {
17+
src: string | string[];
18+
docgen?: {
19+
/**
20+
* See react-docgen docs
21+
* @see https://github.com/reactjs/react-docgen#resolver
22+
*/
23+
resolver?: (ast: Record<any, any>) => any;
24+
25+
/**
26+
* See react-docgen docs
27+
* @see https://github.com/reactjs/react-docgen#handlers
28+
*/
29+
handlers?: Handler[];
30+
};
31+
parserOptions?: ParserOptions;
32+
babel?: {
33+
babelrc?: boolean;
34+
babelrcRoots?: boolean | string | string[];
35+
root?: string;
36+
rootMode?: 'root' | 'upward' | 'upward-optional';
37+
envName?: string;
38+
configFile?: string | boolean;
39+
};
40+
};
41+
42+
const readFile = promisify(fs.readFile);
43+
44+
export default function plugin(
45+
context: DocusaurusContext,
46+
{ src, docgen = {}, babel = {}, parserOptions }: Options
47+
): Plugin<{ file: string; docgen: Record<any, any> }[]> {
48+
return {
49+
name: 'docusaurus-plugin-react-docgen',
50+
async loadContent() {
51+
const fileOpts: { encoding: BufferEncoding } = { encoding: 'utf-8' };
52+
const files = await globby(src);
53+
54+
return (
55+
await asyncMap(files, async file => {
56+
try {
57+
return {
58+
docgen: reactDocgen.parse(
59+
await readFile(file, fileOpts),
60+
docgen.resolver,
61+
docgen.handlers,
62+
{
63+
filename: file,
64+
parserOptions,
65+
...babel,
66+
}
67+
),
68+
file,
69+
};
70+
} catch (e) {
71+
console.warn(e.message, file);
72+
}
73+
})
74+
).filter(Boolean);
75+
},
76+
async contentLoaded({ content, actions }) {
77+
const re = /(?:\.d)?\.[jt]sx?$/gi;
78+
const { createData } = actions;
79+
80+
for (let i = 0; i < content.length; i++) {
81+
await createData(
82+
path.basename(content[i].file.toLowerCase()).replace(re, '.json'),
83+
JSON.stringify(content[i].docgen)
84+
);
85+
}
86+
},
87+
};
88+
}
89+
90+
export const validateOptions = ({ options, validate }: OptionValidationContext<Options>) => {
91+
return validate(
92+
Joi.object({
93+
src: Joi.alternatives(Joi.string(), Joi.array().min(1).items(Joi.string())).required(),
94+
docgen: Joi.object({
95+
resolver: Joi.object().instance(Function),
96+
handlers: Joi.alternatives(
97+
Joi.object().instance(Function),
98+
Joi.array().min(1).items(Joi.object().instance(Function))
99+
),
100+
}),
101+
babel: Joi.object({
102+
babelrc: Joi.boolean(),
103+
babelrcRoots: [Joi.boolean(), Joi.string(), Joi.array().items(Joi.string())],
104+
root: Joi.string(),
105+
rootMode: Joi.string().pattern(/root | upward | upward-optional/),
106+
envName: Joi.string(),
107+
configFile: [Joi.string(), Joi.boolean()],
108+
}),
109+
}),
110+
options
111+
);
112+
};

src/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type Callback<T, U> = (value: T, index: number, array: T[]) => U;
2+
3+
export const asyncMap = (array: string[], cb: Callback<string, Promise<any>>): Promise<any> => {
4+
const promises = new Array(array.length);
5+
6+
for (let i = 0; i < array.length; i++) {
7+
promises.push(cb(array[i], i, array));
8+
}
9+
10+
return Promise.all(promises);
11+
};

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"compilerOptions": {
33
"downlevelIteration": true,
44
"esModuleInterop": true,
5-
"target": "ESNext",
6-
"module": "ES2020",
5+
"target": "ES2020",
6+
"module": "ESNext",
77
"moduleResolution": "node"
88
},
99
"include": ["src/"]

0 commit comments

Comments
 (0)