Skip to content

Commit

Permalink
feat(prettier-plugin-jsdoc): add function to prepare complex types
Browse files Browse the repository at this point in the history
  • Loading branch information
homer0 committed Oct 6, 2020
1 parent 6db0bf0 commit 2a14e24
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/fns/preparePrettyType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { format } = require('prettier');
const R = require('ramda');

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

/**
* This function is used to prepare a complex type in order to render it by creating a TS code and
* sending it through Prettier.
*
* @callback PreparePrettyTypeFn
* @param {string} type The type to prepare.
* @param {PrettierOptions} options The options sent to the plugin.
* @returns {string}
*/

/**
* @type {PreparePrettyTypeFn}
*/
const preparePrettyType = R.curry((type, options) => {
if (!type.match(/[&<\.]/)) return type;
let result;
try {
const useType = type.replace(/\*/g, 'any');
const prefix = 'type complex = ';
result = format(`${prefix}${useType}`, {
...options,
parser: 'typescript',
})
.substr(prefix.length)
.trim()
.replace(/;$/, '');
} catch (ignore) {
// Ignore the error because if it failed, it's an issue with Pettier.
result = type;
}

return result;
});

module.exports.preparePrettyType = preparePrettyType;
5 changes: 5 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

/**
* @typedef {import('prettier').SupportOption} PrettierSupportOption
* @typedef {import('prettier').Options} PrettierBaseOptions
*/

// =========================================
Expand Down Expand Up @@ -97,6 +98,10 @@
*/
/* eslint-enable max-len */

/**
* @typedef {PrettierBaseOptions & PJPOptions} PrettierOptions
*/

// =========================================
// Parser
// =========================================
Expand Down
63 changes: 63 additions & 0 deletions test/fns/preparePrettyType.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
jest.unmock('../../src/fns/preparePrettyType');
jest.mock('prettier');

const { format } = require('prettier');
const { preparePrettyType } = require('../../src/fns/preparePrettyType');

describe('preparePrettyType', () => {
beforeEach(() => {
format.mockClear();
});

it('should ignore a basic type', () => {
// Given
const input = 'string';
const output = 'string';
let result = null;
// When
result = preparePrettyType(input, {});
// Then
expect(result).toBe(output);
expect(format).toHaveBeenCalledTimes(0);
});

it('should call prettier for a complex type', () => {
// Given
const prettierResponse = 'prettier-response';
format.mockImplementationOnce((code) => code.replace(/=.*?$/, `= ${prettierResponse};`));
const input = 'React.FC<string>';
const options = {
semi: true,
indent: 2,
};
let result = null;
// When
result = preparePrettyType(input, options);
// Then
expect(result).toBe(prettierResponse);
expect(format).toHaveBeenCalledTimes(1);
expect(format).toHaveBeenCalledWith(`type complex = ${input}`, {
...options,
parser: 'typescript',
});
});

it('should return the original type if prettier throws an error', () => {
// Given
format.mockImplementationOnce(() => {
throw new Error();
});
const input = 'React.FC<string>';
const output = 'React.FC<string>';
const options = {
semi: true,
indent: 2,
};
let result = null;
// When
result = preparePrettyType(input, options);
// Then
expect(result).toBe(output);
expect(format).toHaveBeenCalledTimes(1);
});
});

0 comments on commit 2a14e24

Please sign in to comment.