Skip to content

Commit

Permalink
feat(prettier-plugin-jsdoc): add option to disable the plugin when ex…
Browse files Browse the repository at this point in the history
…tended
  • Loading branch information
homer0 committed Nov 1, 2020
1 parent 406b28d commit 2dcb2db
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 22 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -835,12 +835,12 @@ Whether or not the plugin will parse and transform JSDoc blocks.

##### Let the plugin know that it's being extended

This will prevent the plugin from running from the original package. The idea is for it to be enabled when the plugin is being extended on the implementation.

| Option | Type | Default |
| ------ | ---- | ------- |
| `jsdocPluginExtended` | boolean | `false` |

This will prevent the plugin from running from the original package. The idea is for it to be enabled when the plugin is being extended on the implementation.

### 🚫 Ignoring blocks

If you have some blocks where you don't the plugin to make any modification, you can add the `@prettierignore` tag and it/they will be skipped:
Expand Down
8 changes: 8 additions & 0 deletions src/fns/getOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ const getOptions = () => ({
default: true,
description: 'Whether or not the plugin will parse and transform JSDoc blocks.',
},
jsdocPluginExtended: {
type: 'boolean',
category: 'jsdoc',
default: false,
description:
'This will prevent the plugin from running from the original package. The idea is for it ' +
'to be enabled when the plugin is being extended on the implementation.',
},
jsdocAllowDescriptionTag: {
type: 'boolean',
category: 'jsdoc',
Expand Down
54 changes: 38 additions & 16 deletions src/fns/getParsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,18 @@ const getRenderer = (options) => {
/**
* Generates the parser that will modify the comments.
*
* @param {PrettierParseFn} originalParser The Prettier built in parser the plugin will use to
* extract the AST.
* @param {PrettierParseFn} originalParser The Prettier built in parser the plugin will use to
* extract the AST.
* @param {boolean} checkExtendOption Whether or not to check for the option that tells
* the plugin that it's being extended.
* @returns {PrettierParseFn}
*/
const createParser = (originalParser) => (text, parsers, options) => {
const createParser = (originalParser, checkExtendOption) => (text, parsers, options) => {
const ast = originalParser(text, parsers, options);
if (options.jsdocPluginEnabled) {
if (
options.jsdocPluginEnabled &&
(!checkExtendOption || !options.jsdocPluginExtended)
) {
const formatter = R.compose(
get(prepareCommentTags)(options),
get(formatCommentTags)(options),
Expand All @@ -283,33 +288,49 @@ const createParser = (originalParser) => (text, parsers, options) => {
return ast;
};

/**
* Extends an existing parser using one generated by {@link createParser}.
*
* @callback ExtendParserFn
* @param {PrettierParser} parser The original parser.
* @param {boolean} checkExtendOption Whether or not the parser should check the option that
* tells the plugin that it's being extended.
* @returns {PrettierParser}
*/

/**
* @type {ExtendParserFn}
*/
const extendParser = R.curry((parser, checkExtendOption) => ({
...parser,
parse: get(createParser)(parser.parse, checkExtendOption),
}));

/**
* A dictionary with the supported parsers the plugin can use.
*
* @param {boolean} [checkExtendOption] Whether or not, the function that creates the parsers should
* check for the option that tells the plugin that it's being
* extended.
* @returns {Object.<string,PrettierParser>}
*/
const getParsers = () => {
const useCreateParser = get(createParser);
const getParsers = (checkExtendOption) => {
const useExtendParser = get(extendParser)(R.__, checkExtendOption);
return {
get babel() {
const parser = babelParser.parsers.babel;
return { ...parser, parse: useCreateParser(parser.parse) };
return useExtendParser(babelParser.parsers.babel);
},
get 'babel-flow'() {
const parser = babelParser.parsers['babel-flow'];
return { ...parser, parse: useCreateParser(parser.parse) };
return useExtendParser(babelParser.parsers['babel-flow']);
},
get 'babel-ts'() {
const parser = babelParser.parsers['babel-ts'];
return { ...parser, parse: useCreateParser(parser.parse) };
return useExtendParser(babelParser.parsers['babel-ts']);
},
get flow() {
const parser = flowParser.parsers.flow;
return { ...parser, parse: useCreateParser(parser.parse) };
return useExtendParser(flowParser.parsers.flow);
},
get typescript() {
const parser = tsParser.parsers.typescript;
return { ...parser, parse: useCreateParser(parser.parse) };
return useExtendParser(tsParser.parsers.typescript);
},
};
};
Expand All @@ -327,4 +348,5 @@ module.exports.formatCommentBlock = formatCommentBlock;
module.exports.formatCommentTags = formatCommentTags;
module.exports.prepareCommentTags = prepareCommentTags;
module.exports.getRenderer = getRenderer;
module.exports.extendParser = extendParser;
module.exports.provider = provider('getParsers', module.exports);
8 changes: 6 additions & 2 deletions src/fns/getPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ const { get, provider } = require('./app');
/**
* Generates the plugin definition.
*
* @param {boolean} [checkExtendOption] Whether or not, the function that creates the parsers
* should check for the option that tells the plugin that it's
* being extended, thus, the original package shouldn't do
* anything.
* @returns {Plugin}
*/
const getPlugin = () => ({
const getPlugin = (checkExtendOption) => ({
languages: get(getLanguages)(),
options: get(getOptions)(),
defaultOptions: get(getDefaultOptions)(),
parsers: get(getParsers)(),
parsers: get(getParsers)(checkExtendOption),
});

module.exports.getPlugin = getPlugin;
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ const { loadFns } = require('./loader');

loadFns();

module.exports = get(getPlugin)();
module.exports = get(getPlugin)(true);
3 changes: 3 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
* needs to be different. Default `0`.
* @property {boolean} jsdocPluginEnabled
* Whether or not the plugin will parse and transform JSDoc blocks. Default `true`.
* @property {boolean} jsdocPluginExtended
* This will prevent the plugin from running from the original package. The idea is for it to be
* enabled when the plugin is being extended on the implementation.
*/

/* eslint-disable max-len */
Expand Down
31 changes: 31 additions & 0 deletions test/e2e/fixtures/disabled.fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* This fixture will validate that there's no formatting when the plugin is disabled by options.
*/

module.exports = {
jsdocPluginEnabled: false,
};

//# input

/**
* @throws {Error} If something goes wrong.
* @description Creates a person.
* @param {String} name The name of the person.
* @return {Person}
* @author homer0
* @param {number} age The person's age.
* @callback CreatePersonFn
*/

//# output

/**
* @throws {Error} If something goes wrong.
* @description Creates a person.
* @param {String} name The name of the person.
* @return {Person}
* @author homer0
* @param {number} age The person's age.
* @callback CreatePersonFn
*/
32 changes: 32 additions & 0 deletions test/e2e/fixtures/extended.fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* This fixture will validate that there's no formatting when the plugin is disabled in order to be
* extended.
*/

module.exports = {
jsdocPluginExtended: true,
};

//# input

/**
* @throws {Error} If something goes wrong.
* @description Creates a person.
* @param {String} name The name of the person.
* @return {Person}
* @author homer0
* @param {number} age The person's age.
* @callback CreatePersonFn
*/

//# output

/**
* @throws {Error} If something goes wrong.
* @description Creates a person.
* @param {String} name The name of the person.
* @return {Person}
* @author homer0
* @param {number} age The person's age.
* @callback CreatePersonFn
*/
73 changes: 72 additions & 1 deletion test/unit/fns/getParsers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,18 @@ describe('getParsers', () => {

it('shouldn\'t do anything if the plugin is disabled', () => {
// Given
const commentStr = '*\n * @typedef {string} MyStr\n ';
const column = 2;
const astBase = {
comments: [],
comments: [{
type: 'CommentBlock',
value: commentStr,
loc: {
start: {
column,
},
},
}],
};
const parsersToTest = [
{
Expand Down Expand Up @@ -132,6 +142,67 @@ describe('getParsers', () => {
});
});

it('shouldn\'t do anything if the plugin is being extended', () => {
// Given
const commentStr = '*\n * @typedef {string} MyStr\n ';
const column = 2;
const astBase = {
comments: [{
type: 'CommentBlock',
value: commentStr,
loc: {
start: {
column,
},
},
}],
};
const parsersToTest = [
{
name: 'babel',
ast: R.clone(astBase),
uses: babelParser.parsers.babel,
},
{
name: 'babel-flow',
ast: R.clone(astBase),
uses: babelParser.parsers['babel-flow'],
},
{
name: 'babel-ts',
ast: R.clone(astBase),
uses: babelParser.parsers['babel-ts'],
},
{
name: 'flow',
ast: R.clone(astBase),
uses: flowParser.parsers.flow,
},
{
name: 'typescript',
ast: R.clone(astBase),
uses: tsParser.parsers.typescript,
},
];
parsersToTest.forEach((info) => {
info.uses.parse.mockImplementationOnce(() => info.ast);
});
const text = 'lorem ipsum';
const parsers = ['babel'];
const options = {
jsdocPluginEnabled: true,
jsdocPluginExtended: true,
printWidth: 80,
};
let sut = null;
// When/Then
sut = getParsers(true);
parsersToTest.forEach((info) => {
sut[info.name].parse(text, parsers, options);
expect(info.ast).toEqual(astBase);
});
});

it('should render a comment', () => {
// Given
const commentStr = '*\n * @typedef {string} MyStr\n ';
Expand Down

0 comments on commit 2dcb2db

Please sign in to comment.