-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from woocommerce/add/jsdoc
- Loading branch information
Showing
6 changed files
with
261 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
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,84 @@ | ||
# woocommerce-grow-tracking-jsdoc | ||
|
||
JSDoc template to report Tracking events to markdown file. | ||
|
||
## Usage | ||
|
||
0. `npm i jsdoc` and configure jsdoc according to your source code, so the `npx jsdoc ./your/source/` runs successfully. | ||
1. Install or link this package via npm | ||
2. Add your `/TRACKING.md` template | ||
|
||
```md | ||
# Usage Tracking | ||
|
||
Some nice general description. | ||
|
||
<woocommerce-grow-tracking-jsdoc></woocommerce-grow-tracking-jsdoc> | ||
``` | ||
3. Generate the docs | ||
```sh | ||
jsdoc -r your/source/files/ -t ./node_modules/woocommerce-grow-tracking-jsdoc | ||
``` | ||
|
||
|
||
|
||
## Config | ||
|
||
You may add any of the following properties to your JSDoc config (`.jsdocrc.json`) to change those default values: | ||
```js | ||
{ | ||
"templates": { | ||
"woocommerce-grow-tracking-jsdoc": { | ||
// Path to the markdown file to which the tracking events' docs should be added | ||
"path": "TRACKING.md", | ||
// Pattern to be used to match the content to be replaced. The groups are respectively: start marker, replaceable content, end marker. | ||
"replacement": "(<woocommerce-grow-tracking-jsdoc(?:\\s[^>]*)?>)([\\s\\S]*)(<\\/woocommerce-grow-tracking-jsdoc.*>)" | ||
} | ||
} | ||
``` | ||
Then make sure `jsdoc` uses it, by `jsdoc -r your/source/files/ -c .jsdocrc.json`. | ||
|
||
## Emitters | ||
If you would like to add some descriptions to `@fires` or `@emmits` tags, for example to specify what data is attached to the event, add `fires-description` to your plugins list: | ||
|
||
```json | ||
{ | ||
"plugins": [ | ||
// To be able to add descriptions to `@fires` & `@emmits` | ||
"woocommerce-grow-tracking-jsdoc/fires-description" | ||
], | ||
// … | ||
``` | ||
|
||
|
||
## Imported types | ||
|
||
If your codebase uses TS-style of importing types `{import('foo').bar}`, you will most probably get an error, like: | ||
``` | ||
ERROR: Unable to parse a tag's type expression for source file … Invalid type expression "import('foo').bar" | ||
``` | ||
To mitigate that use a `jsdoc-plugin-typescript` plugin to skip those. `npm install --save-dev jsdoc-plugin-typescript` and add this to your config: | ||
```js | ||
{ | ||
"plugins": [ | ||
"jsdoc-plugin-typescript" | ||
], | ||
"typescript": { | ||
"moduleRoot": "assets/source" // Path to your module's root directory. | ||
} | ||
// … | ||
``` | ||
|
||
## `~` Alias | ||
|
||
If your codebase uses a `.~` or `~` alias for the root directory, you may use `tilde-alias`. | ||
|
||
```js | ||
{ | ||
"plugins": [ | ||
"woocommerce-grow-tracking-jsdoc/tilde-alias", | ||
"jsdoc-plugin-typescript" | ||
], | ||
// … | ||
``` |
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,21 @@ | ||
/** | ||
* JSDoc plugin that allows to use descriptions for built-in `@fires` & `@emmits` tags. | ||
* | ||
* Overwrites the standard definition with `canHaveName: true` option, | ||
* and tweaks `applyNamespace` to apply it only to `value.name`. | ||
*/ | ||
const { applyNamespace } = require( 'jsdoc/name' ); | ||
|
||
exports.defineTags = function ( dictionary ) { | ||
dictionary | ||
.defineTag( 'fires', { | ||
mustHaveValue: true, | ||
canHaveName: true, | ||
onTagged( doclet, tag ) { | ||
doclet.fires = doclet.fires || []; | ||
tag.value.name = applyNamespace( tag.value.name, 'event' ); | ||
doclet.fires.push( tag.value ); | ||
}, | ||
} ) | ||
.synonym( ' emmits' ); | ||
}; |
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,18 @@ | ||
{ | ||
"name": "woocommerce-grow-tracking-jsdoc", | ||
"version": "0.0.1", | ||
"description": "JSDoc template to report Tracking events to markdown file", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+ssh://[email protected]/woocommerce/grow.git" | ||
}, | ||
"author": "WooCommerce", | ||
"license": "GPL-3.0-or-later", | ||
"bugs": { | ||
"url": "https://github.com/woocommerce/grow/issues" | ||
}, | ||
"homepage": "https://github.com/woocommerce/grow#readme", | ||
"peerDependencies": { | ||
"jsdoc": "^3.6.10" | ||
} | ||
} |
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,132 @@ | ||
const fs = require( 'jsdoc/fs' ); | ||
const env = require( 'jsdoc/env' ); | ||
const path = require( 'jsdoc/path' ); | ||
|
||
/** @module publish */ | ||
|
||
// RegExp used to match the replacement. The groups are respectively: start marker, replacable content, end marker. | ||
const defaultReplacementRegex = /(<woocommerce-grow-tracking-jsdoc(?:\s[^>]*)?>)([\s\S]*)(<\/woocommerce-grow-tracking-jsdoc.*>)/; | ||
|
||
const disclaimerStart = `<!--- | ||
Everything below will be automatically generated by \`woocommerce-grow-tracking-jsdoc\`. | ||
Do not edit it manually! | ||
-->`; | ||
const disclaimerEnd = `<!--- | ||
End of \`woocommerce-grow-tracking-jsdoc\`-generated content. | ||
--> | ||
`; | ||
|
||
/** | ||
* Creates MD link to the line of code, where the symbol was defined. | ||
* | ||
* @param {Object} symbol JSDoc symbol object. | ||
* @param {string} readmeDir The absolute path to the directory of README file. | ||
*/ | ||
function getLineLink( symbol, readmeDir ) { | ||
const localLocation = | ||
path.relative( | ||
readmeDir, | ||
path.join( symbol.meta.path, symbol.meta.filename ) | ||
) + | ||
'#L' + | ||
symbol.meta.lineno; | ||
return `[\`${ symbol.name }\`](${ localLocation })`; | ||
} | ||
|
||
/** | ||
* Generate documentation output. | ||
* | ||
* @param {Object} data - A TaffyDB collection representing | ||
* all the symbols documented in your code. | ||
*/ | ||
exports.publish = function ( data ) { | ||
const { | ||
conf: { | ||
templates: { | ||
'woocommerce-grow-tracking-jsdoc': { | ||
path: readmePath = 'TRACKING.md', | ||
replacement, | ||
} = {}, | ||
} = {}, | ||
} = {}, | ||
pwd, | ||
} = env; | ||
|
||
const readmeDir = path.join( pwd, path.dirname( readmePath ) ); | ||
const replacementRegex = replacement | ||
? new RegExp( replacement ) | ||
: defaultReplacementRegex; | ||
|
||
let mdResult = ''; | ||
|
||
data( { kind: 'event' } ) | ||
.order( 'name' ) | ||
.each( ( symbol ) => { | ||
// Build the event title with the link to its source. | ||
mdResult += `\n### ${ getLineLink( symbol, readmeDir ) }\n`; | ||
// description | ||
mdResult += ( symbol.description || '' ) + '\n'; | ||
// Build properites table. | ||
if ( symbol.properties ) { | ||
mdResult += `#### Properties | ||
| name | type | description | | ||
| ---- | ---- | ----------- |\n`; | ||
symbol.properties.forEach( ( property ) => { | ||
// Escape `|` for markdown table. | ||
const type = property.type.parsedType.typeExpression.replace( | ||
/\|/g, | ||
'\\|' | ||
); | ||
const description = property.description.replace( | ||
/\|/g, | ||
'\\|' | ||
); | ||
mdResult += `\`${ | ||
property.name | ||
}\` | \`${ type }\` | ${ description.replace( | ||
/\s*\n\s*/g, | ||
' <br> ' | ||
) }\n`; | ||
} ); | ||
} | ||
|
||
// Find all places that fires the event. | ||
const emitters = new Map(); | ||
// TaffyDB#has is buggy https://github.com/typicaljoe/taffydb/issues/19, so let's filter it manually. | ||
data( { fires: { isArray: true } } ).each( ( emitter ) => { | ||
const firesCurrent = emitter.fires.filter( | ||
( fires ) => fires.name === 'event:' + symbol.name | ||
); | ||
if ( firesCurrent.length ) { | ||
emitters.set( emitter, firesCurrent ); | ||
} | ||
} ); | ||
if ( emitters.size ) { | ||
mdResult += `#### Emitters\n`; | ||
emitters.forEach( ( fires, emitter ) => { | ||
mdResult += '- ' + getLineLink( emitter, readmeDir ); | ||
if ( fires.length > 1 ) { | ||
mdResult += | ||
`\n` + | ||
fires | ||
.map( | ||
( evt ) => ` - ${ evt.description || '' }` | ||
) | ||
.join( '\n' ); | ||
} else if ( fires[ 0 ] && fires[ 0 ].description ) { | ||
mdResult += ' ' + fires[ 0 ].description; | ||
} | ||
mdResult += '\n'; | ||
} ); | ||
} | ||
} ); | ||
|
||
let readme = fs.readFileSync( readmePath, 'utf8' ); | ||
// Replace the marker with generated content. | ||
readme = readme.replace( | ||
replacementRegex, | ||
`$1\n${ disclaimerStart }\n${ mdResult }\n${ disclaimerEnd }$3` | ||
); | ||
fs.writeFileSync( readmePath, readme, 'utf8' ); | ||
return mdResult; | ||
}; |
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,5 @@ | ||
exports.handlers = { | ||
beforeParse( e ) { | ||
e.source = e.source.replace( /(import\(["'])\.?~\//g, `$1` ); | ||
}, | ||
}; |