Skip to content

Commit

Permalink
feat(prettier-plugin-jsdoc): add option to add a separator line on @e…
Browse files Browse the repository at this point in the history
  • Loading branch information
homer0 committed Oct 22, 2020
1 parent 3e9cd9d commit 99ac641
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 22 deletions.
21 changes: 15 additions & 6 deletions src/fns/prepareTags.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const R = require('ramda');
const { prepareExampleTag } = require('./prepareExampleTag');
const { prepareTagName } = require('./prepareTagName');
const { prepareTagPrettyType } = require('./prepareTagPrettyType');

Expand All @@ -22,12 +23,20 @@ const { prepareTagPrettyType } = require('./prepareTagPrettyType');
/**
* @type {PrepareTagsFn}
*/
const prepareTags = R.curry((tags, options) => R.map(
R.compose(
prepareTagPrettyType(R.__, options),
const prepareTags = R.curry((tags, options) => {
const fns = [
prepareTagName,
),
tags,
));
prepareTagPrettyType(R.__, options),
];

if (options.jsdocFormatExamples) {
fns.push(prepareExampleTag(R.__, options));
}

return R.map(
R.compose(...fns.reverse()),
tags,
);
});

module.exports.prepareTags = prepareTags;
11 changes: 8 additions & 3 deletions src/fns/renderExampleTag.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
const R = require('ramda');

/**
* @typedef {import('../types').PJPExamplesOptions} PJPExamplesOptions
* @typedef {import('../types').CommentTag} CommentTag
*/

/**
* Renders an `example` tag by just adding the code below the tag.
*
* @param {CommentTag} tag The tag to render.
* @param {CommentTag} tag The tag to render.
* @param {PJPExamplesOptions} options The options related to the `example` tags.
* @returns {string[]}
*/
const renderExampleTag = (tag) => [
const renderExampleTag = R.curry((tag, options) => [
`@${tag.tag}`,
...((new Array(options.jsdocLinesBetweenExampleTagAndCode)).fill('')),
...tag.description.split('\n'),
];
]);

module.exports.renderExampleTag = renderExampleTag;
28 changes: 28 additions & 0 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,34 @@ const options = {
'Whether or not to use the @description tag when a description is found in the "body" ' +
'or following a type/callback definition.',
},
jsdocFormatExamples: {
type: 'boolean',
category: 'jsdoc',
default: true,
description: 'Whether or not to attemp to format the @example tags using Prettier.',
},
jsdocLinesBetweenExampleTagAndCode: {
type: 'int',
category: 'jsdoc',
default: 1,
description: 'How many lines should there be between an @example tag and its code.',
},
jsdocIndentFormattedExamples: {
type: 'boolean',
category: 'jsdoc',
default: true,
description:
'Whether or not to add an indentation level to the code snippets of @example tags. The ' +
'indentation space will be taken from the `tabWidth` option.',
},
jsdocIndentUnformattedExamples: {
type: 'boolean',
category: 'jsdoc',
default: false,
description:
'Whether or not to add an indentation level to the code snippets of @example tags that ' +
'couldn\'t be formatted with Prettier. This is only valid if `jsdocFormatExamples` is `true`',
},
jsdocAllowAccessTag: {
type: 'boolean',
category: 'jsdoc',
Expand Down
16 changes: 15 additions & 1 deletion src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@
* following a type/callback definition. Default `false`.
*/

/**
* @typedef {Object} PJPExamplesOptions
* @property {boolean} jsdocFormatExamples
* Whether or not to attemp to format the `example` tags using Prettier. Default `true`.
* @property {number} jsdocLinesBetweenExampleTagAndCode
* How many lines should there be between an `example` tag and its code. Default `1`.
* @property {boolean} jsdocIndentFormattedExamples
* Whether or not to add an indentation level to the code snippets of `example` tags. The
* indentation space will be taken from the `tabWidth` option. Default `true`.
* @property {boolean} jsdocIndentUnformattedExamples
* Whether or not to add an indentation level to the code snippets of `example` tags that
* couldn't be formatted with Prettier. Default `false`.
*/

/**
* @typedef {Object} PJPAccessTagOptions
* @property {boolean} jsdocAllowAccessTag
Expand Down Expand Up @@ -102,7 +116,7 @@

/* eslint-disable max-len */
/**
* @typedef {PJPDescriptionTagOptions & PJPAccessTagOptions & PJPTypesOptions & PJPTagsOptions & PJPStyleOptions } PJPOptions
* @typedef {PJPDescriptionTagOptions & PJPExamplesOptions & PJPAccessTagOptions & PJPTypesOptions & PJPTagsOptions & PJPStyleOptions } PJPOptions
*/
/* eslint-enable max-len */

Expand Down
49 changes: 37 additions & 12 deletions test/unit/fns/renderExampleTag.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,46 @@ jest.unmock('../../../src/fns/renderExampleTag');
const { renderExampleTag } = require('../../../src/fns/renderExampleTag');

describe('renderExampleTag', () => {
it('should ignore a tag that\'s not @example', () => {
const cases = [
{
it: 'should render an @example tag',
input: {
tag: 'example',
description: 'const fn = (msg) => console.log(msg);\nfn(\'hello world!\');',
},
output: [
'@example',
'const fn = (msg) => console.log(msg);',
'fn(\'hello world!\');',
],
options: {
jsdocLinesBetweenExampleTagAndCode: 0,
},
},
{
it: 'should render an @example tag with an empty line before the code',
input: {
tag: 'example',
description: 'const fn = (msg) => console.log(msg);\nfn(\'hello world!\');',
},
output: [
'@example',
'',
'const fn = (msg) => console.log(msg);',
'fn(\'hello world!\');',
],
options: {
jsdocLinesBetweenExampleTagAndCode: 1,
},
},
];

it.each(cases)('should correctly format the case %#', (caseInfo) => {
// Given
const input = {
tag: 'example',
description: 'const fn = (msg) => console.log(msg);\nfn(\'hello world!\');',
};
const output = [
'@example',
'const fn = (msg) => console.log(msg);',
'fn(\'hello world!\');',
];
let result = null;
// When
result = renderExampleTag(input);
result = renderExampleTag(caseInfo.input, caseInfo.options);
// Then
expect(result).toEqual(output);
expect(result).toEqual(caseInfo.output);
});
});

0 comments on commit 99ac641

Please sign in to comment.