Skip to content

Commit

Permalink
feat(prettier-plugin-jsdoc): add function to format TS types
Browse files Browse the repository at this point in the history
  • Loading branch information
homer0 committed Oct 5, 2020
1 parent c6a5d3b commit e4766a2
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/fns/formatTSTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const R = require('ramda');
const { capitalize, ensureArray } = require('./utils');

/**
* Utility function generated by {@link getFormater} and that can be used to modify a type name.
* The difference between the formatter and the modifier is that the formatter can extract single
* types from a comple type and run them through the modifier, where the modifier can only handle
* one type.
*
* @callback TypeFormatter
* @param {string} type The original type.
* @returns {string}
*/

/**
* Utility function that is sent to {@link getFormatter} and that the formatter will use to modify
* each single type name referenced on the given type.
*
* @callback TypeModifier
* @param {string} type The original type.
* @returns {string}
*/

/**
* Generates a formatter function that will replace a type (or types) after sending it through
* a modification function.
*
* @param {string|string[]} type The type or types to format.
* @param {TypeModifier} modifier The function that will modify each type.
* @returns {TypeFormatter}
*/
const getFormater = (type, modifier) => R.compose(
(types) => R.replace(
new RegExp(`([^\\w]|^)(${types})([^\\w]|$)`, 'g'),
(_, before, rawType, after) => `${before}${modifier(rawType)}${after}`,
),
R.join('|'),
ensureArray,
)(type);

/**
* Formats each type reference on a type in order to match the casing allowed by TypeScript.
*
* @callback FormatTSTypesFn
* @param {string} type The type to format.
* @returns {string}
*/

/**
* @type {FormatTSTypesFn}
*/
const formatTSTypes = R.compose(
getFormater(['array', 'object'], capitalize),
getFormater(['String', 'Number', 'Boolean'], R.toLower),
);

module.exports.formatTSTypes = formatTSTypes;
17 changes: 17 additions & 0 deletions src/fns/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,22 @@ const replaceDotOnTypeGeneric = R.curry((targetType, useDot, type) => R.ifElse(
R.replace(new RegExp(`([^\\w]|^)${targetType}\\s*\\.\\s*<`, 'g'), `$1${targetType}<`),
)(type));

/**
* Capitalizes a string.
*
* @callback CapitalizeFn
* @param {string} str The string to capitalize.
* @returns {string}
*/

/**
* @type {CapitalizeFn}
*/
const capitalize = R.compose(
R.join(''),
R.juxt([R.compose(R.toUpper, R.head), R.tail]),
);

module.exports.ensureArray = ensureArray;
module.exports.findTagIndex = findTagIndex;
module.exports.appendIfNotPresent = appendIfNotPresent;
Expand All @@ -155,3 +171,4 @@ module.exports.replaceLastItem = replaceLastItem;
module.exports.hasItems = hasItems;
module.exports.isMatch = isMatch;
module.exports.replaceDotOnTypeGeneric = replaceDotOnTypeGeneric;
module.exports.capitalize = capitalize;
29 changes: 29 additions & 0 deletions test/fns/formatTSTypes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
jest.unmock('../../src/fns/formatTSTypes');
jest.unmock('../../src/fns/utils');

const { formatTSTypes } = require('../../src/fns/formatTSTypes');

describe('formatTSTypes', () => {
it
.each([
['String', 'string'],
['string', 'string'],
['Number', 'number'],
['number', 'number'],
['Boolean', 'boolean'],
['boolean', 'boolean'],
['Array', 'Array'],
['array', 'Array'],
['Object', 'Object'],
['object', 'Object'],
['otherType', 'otherType'],
['OtherType', 'OtherType'],
])('should transform \'%s\' into \'%s\'', (input, output) => {
// Given
let result = null;
// When
result = formatTSTypes(input);
// Then
expect(result).toBe(output);
});
});

0 comments on commit e4766a2

Please sign in to comment.