@homer0/prettier-plugin-jsdoc
Advanced tools
Comparing version
@@ -6,2 +6,15 @@ # Change Log | ||
# [7.0.0](https://github.com/homer0/packages/compare/@homer0/prettier-plugin-jsdoc@6.0.5...@homer0/prettier-plugin-jsdoc@7.0.0) (2023-07-16) | ||
### Bug Fixes | ||
- **monorepo:** update all dependencies ([c3d837e](https://github.com/homer0/packages/commit/c3d837e5820d27a27e97322211478d880000c064)) | ||
- **prettier-config:** hardcode languages ([f5ea277](https://github.com/homer0/packages/commit/f5ea27794d1559c2770e35a48b4a65dc57351545)) | ||
- **prettier-plugin-jsdoc:** add support for Prettier v3 ([a64de80](https://github.com/homer0/packages/commit/a64de8086f7ec00ca69107de58149abb140cbdc3)) | ||
- **prettier-plugin-jsdoc:** update Prettier version ([23128e5](https://github.com/homer0/packages/commit/23128e5f27af899c85538c77fc6050f777b6fff9)) | ||
### BREAKING CHANGES | ||
- **prettier-plugin-jsdoc:** This plugin now uses Prettier v3 | ||
## [6.0.5](https://github.com/homer0/packages/compare/@homer0/prettier-plugin-jsdoc@6.0.4...@homer0/prettier-plugin-jsdoc@6.0.5) (2023-06-18) | ||
@@ -8,0 +21,0 @@ |
{ | ||
"name": "@homer0/prettier-plugin-jsdoc", | ||
"description": "A Prettier plugin to format JSDoc blocks.", | ||
"version": "6.0.5", | ||
"version": "7.0.0", | ||
"repository": { | ||
@@ -22,11 +22,12 @@ "type": "git", | ||
}, | ||
"type": "commonjs", | ||
"dependencies": { | ||
"comment-parser": "^1.3.1", | ||
"prettier": "^2.8.8", | ||
"prettier": "^3.0.0", | ||
"ramda": "0.29.0" | ||
}, | ||
"devDependencies": { | ||
"@homer0/eslint-plugin": "10.3.1", | ||
"jest": "^29.5.0", | ||
"jest-environment-node": "^29.5.0" | ||
"@homer0/eslint-plugin": "10.3.2", | ||
"jest": "^29.6.1", | ||
"jest-environment-node": "^29.6.1" | ||
}, | ||
@@ -40,7 +41,7 @@ "engine-strict": true, | ||
"lint": "eslint .", | ||
"test:unit": "jest -c ./.jestrc-unit.js", | ||
"test:e2e": "jest -c ./.jestrc-e2e.js", | ||
"test:unit": "NODE_OPTIONS=--experimental-vm-modules jest -c ./.jestrc-unit.js", | ||
"test:e2e": "NODE_OPTIONS=--experimental-vm-modules jest -c ./.jestrc-e2e.js", | ||
"test": "pnpm run test:unit && pnpm run test:e2e" | ||
}, | ||
"gitHead": "05356cf2f7d8f158a139c3e2a3fed025f60bbaad" | ||
"gitHead": "bab3ed6af9cf27c0d64e4169dc1f4825a978a717" | ||
} |
const { provider } = require('./app'); | ||
/** | ||
* @typedef {import('../types').PrettierSupportLanguage} PrettierSupportLanguage | ||
*/ | ||
/** | ||
* Gets a dictionary where the keys are old tags' names, and values the current tag name | ||
@@ -84,5 +88,150 @@ * for which they are synonym. | ||
* | ||
* @returns {string[]} | ||
* @returns {PrettierSupportLanguage[]} | ||
*/ | ||
const getSupportedLanguages = () => ['JavaScript', 'Flow', 'JSX', 'TSX', 'TypeScript']; | ||
const getSupportedLanguages = () => [ | ||
{ | ||
linguistLanguageId: 183, | ||
name: 'JavaScript', | ||
type: 'programming', | ||
tmScope: 'source.js', | ||
aceMode: 'javascript', | ||
codemirrorMode: 'javascript', | ||
codemirrorMimeType: 'text/javascript', | ||
color: '#f1e05a', | ||
aliases: ['js', 'node'], | ||
extensions: [ | ||
'.js', | ||
'._js', | ||
'.bones', | ||
'.cjs', | ||
'.es', | ||
'.es6', | ||
'.frag', | ||
'.gs', | ||
'.jake', | ||
'.javascript', | ||
'.jsb', | ||
'.jscad', | ||
'.jsfl', | ||
'.jslib', | ||
'.jsm', | ||
'.jspre', | ||
'.jss', | ||
'.mjs', | ||
'.njs', | ||
'.pac', | ||
'.sjs', | ||
'.ssjs', | ||
'.xsjs', | ||
'.xsjslib', | ||
'.wxs', | ||
], | ||
filenames: ['Jakefile'], | ||
interpreters: [ | ||
'chakra', | ||
'd8', | ||
'gjs', | ||
'js', | ||
'node', | ||
'nodejs', | ||
'qjs', | ||
'rhino', | ||
'v8', | ||
'v8-shell', | ||
'zx', | ||
], | ||
parsers: [ | ||
'babel', | ||
'acorn', | ||
'espree', | ||
'meriyah', | ||
'babel-flow', | ||
'babel-ts', | ||
'flow', | ||
'typescript', | ||
], | ||
vscodeLanguageIds: ['javascript', 'mongo'], | ||
}, | ||
{ | ||
linguistLanguageId: 183, | ||
name: 'Flow', | ||
type: 'programming', | ||
tmScope: 'source.js', | ||
aceMode: 'javascript', | ||
codemirrorMode: 'javascript', | ||
codemirrorMimeType: 'text/javascript', | ||
color: '#f1e05a', | ||
aliases: [], | ||
extensions: ['.js.flow'], | ||
filenames: [], | ||
interpreters: [ | ||
'chakra', | ||
'd8', | ||
'gjs', | ||
'js', | ||
'node', | ||
'nodejs', | ||
'qjs', | ||
'rhino', | ||
'v8', | ||
'v8-shell', | ||
], | ||
parsers: ['flow', 'babel-flow'], | ||
vscodeLanguageIds: ['javascript'], | ||
}, | ||
{ | ||
linguistLanguageId: 183, | ||
name: 'JSX', | ||
type: 'programming', | ||
tmScope: 'source.js.jsx', | ||
aceMode: 'javascript', | ||
codemirrorMode: 'jsx', | ||
codemirrorMimeType: 'text/jsx', | ||
color: undefined, | ||
aliases: undefined, | ||
extensions: ['.jsx'], | ||
filenames: undefined, | ||
interpreters: undefined, | ||
parsers: [ | ||
'babel', | ||
'babel-flow', | ||
'babel-ts', | ||
'flow', | ||
'typescript', | ||
'espree', | ||
'meriyah', | ||
], | ||
vscodeLanguageIds: ['javascriptreact'], | ||
group: 'JavaScript', | ||
}, | ||
{ | ||
linguistLanguageId: 378, | ||
name: 'TypeScript', | ||
type: 'programming', | ||
color: '#3178c6', | ||
aliases: ['ts'], | ||
interpreters: ['deno', 'ts-node'], | ||
extensions: ['.ts', '.cts', '.mts'], | ||
tmScope: 'source.ts', | ||
aceMode: 'typescript', | ||
codemirrorMode: 'javascript', | ||
codemirrorMimeType: 'application/typescript', | ||
parsers: ['typescript', 'babel-ts'], | ||
vscodeLanguageIds: ['typescript'], | ||
}, | ||
{ | ||
linguistLanguageId: 94901924, | ||
name: 'TSX', | ||
type: 'programming', | ||
color: '#3178c6', | ||
group: 'TypeScript', | ||
extensions: ['.tsx'], | ||
tmScope: 'source.tsx', | ||
aceMode: 'javascript', | ||
codemirrorMode: 'jsx', | ||
codemirrorMimeType: 'text/jsx', | ||
parsers: ['typescript', 'babel-ts'], | ||
vscodeLanguageIds: ['typescriptreact'], | ||
}, | ||
]; | ||
@@ -89,0 +238,0 @@ module.exports.getTagsSynonyms = getTagsSynonyms; |
const R = require('ramda'); | ||
const { hasValidProperty } = require('./utils'); | ||
const { hasValidProperty, composeWithPromise } = require('./utils'); | ||
const { formatTSTypes } = require('./formatTSTypes'); | ||
@@ -9,2 +9,3 @@ const { formatStringLiterals } = require('./formatStringLiterals'); | ||
const { get, provider } = require('./app'); | ||
const { reduceWithPromise } = require('./utils'); | ||
@@ -32,3 +33,3 @@ /** | ||
* @param {number} column The column where the comment will be rendered. | ||
* @returns {TypeFormatter} | ||
* @returns {Promise<TypeFormatter>} | ||
*/ | ||
@@ -56,3 +57,3 @@ const getTypeFormatter = (options, column) => { | ||
return fns.length ? R.compose(...fns.reverse()) : R.identity; | ||
return fns.length ? get(composeWithPromise)(...fns.reverse()) : R.identity; | ||
}; | ||
@@ -67,3 +68,3 @@ | ||
* @param {CommentTag} tag The tag which type will be formatted. | ||
* @returns {CommentTag} | ||
* @returns {Promise<CommentTag>} | ||
*/ | ||
@@ -75,3 +76,3 @@ | ||
const formatTagType = R.curry((formatter, tag) => | ||
R.compose((type) => ({ ...tag, type }), formatter, R.prop('type'))(tag), | ||
get(composeWithPromise)((type) => ({ ...tag, type }), formatter, R.prop('type'))(tag), | ||
); | ||
@@ -88,3 +89,3 @@ | ||
* involve Prettier itself. | ||
* @returns {CommentTag[]} | ||
* @returns {Promise<CommentTag[]>} | ||
*/ | ||
@@ -95,11 +96,15 @@ | ||
*/ | ||
const formatTagsTypes = R.curry((tags, options, column) => | ||
R.map( | ||
R.when( | ||
get(hasValidProperty)('type'), | ||
get(formatTagType)(get(getTypeFormatter)(options, column)), | ||
), | ||
)(tags), | ||
); | ||
const formatTagsTypes = R.curry(async (tags, options, column) => { | ||
const hasValidPropertyFn = get(hasValidProperty)('type'); | ||
const getTypeFormatterFn = get(getTypeFormatter)(options, column); | ||
const formatTagTypeFn = get(formatTagType)(getTypeFormatterFn); | ||
return get(reduceWithPromise)(tags, async (tag) => { | ||
if (hasValidPropertyFn(tag)) { | ||
return formatTagTypeFn(tag); | ||
} | ||
return tag; | ||
}); | ||
}); | ||
module.exports.formatTagsTypes = formatTagsTypes; | ||
@@ -106,0 +111,0 @@ module.exports.getTypeFormatter = getTypeFormatter; |
@@ -26,3 +26,3 @@ const { format } = require('prettier'); | ||
* @param {string} tag The type will be formatted. | ||
* @returns {string} | ||
* @returns {Promise<string>} | ||
*/ | ||
@@ -33,3 +33,3 @@ | ||
*/ | ||
const formatPrettyType = R.curry((options, column, type) => { | ||
const formatPrettyType = R.curry(async (options, column, type) => { | ||
let result; | ||
@@ -40,11 +40,8 @@ try { | ||
const prefix = 'type complex = '; | ||
const newType = format(`${prefix}${useType}`, { | ||
const newType = await format(`${prefix}${useType}`, { | ||
...options, | ||
printWidth, | ||
parser: 'typescript', | ||
}) | ||
.substr(prefix.length) | ||
.trim() | ||
.replace(/;$/, ''); | ||
result = newType; | ||
}); | ||
result = newType.substring(prefix.length).trim().replace(/;$/, ''); | ||
} catch (ignore) { | ||
@@ -68,3 +65,3 @@ result = type; | ||
* that Prettier can use. | ||
* @returns {CommentTag} | ||
* @returns {Promise<CommentTag>} | ||
*/ | ||
@@ -71,0 +68,0 @@ |
@@ -0,7 +1,7 @@ | ||
const babelParser = require('prettier/plugins/babel'); | ||
const flowParser = require('prettier/plugins/flow'); | ||
const tsParser = require('prettier/plugins/typescript'); | ||
const R = require('ramda'); | ||
const { parse: commentParser } = require('comment-parser'); | ||
const babelParser = require('prettier/parser-babel'); | ||
const flowParser = require('prettier/parser-flow'); | ||
const tsParser = require('prettier/parser-typescript'); | ||
const { isMatch } = require('./utils'); | ||
const { isMatch, composeWithPromise, reduceWithPromise } = require('./utils'); | ||
const { formatDescription } = require('./formatDescription'); | ||
@@ -169,15 +169,18 @@ const { formatTags } = require('./formatTags'); | ||
*/ | ||
const processComments = R.curry((options, nodes, formatterFn, processorFn) => | ||
R.compose( | ||
R.forEach( | ||
R.compose( | ||
R.ifElse(shouldIgnoreComment(options), R.identity, processorFn), | ||
formatterFn, | ||
get(generateCommentData), | ||
), | ||
), | ||
R.filter(R.allPass([get(isComment), get(matchesBlock)])), | ||
)(nodes), | ||
); | ||
const processComments = R.curry(async (options, nodes, formatterFn, processorFn) => { | ||
const useNodes = nodes.filter(R.allPass([get(isComment), get(matchesBlock)])); | ||
const shouldIgnoreFn = shouldIgnoreComment(options); | ||
const generateCommentDataFn = get(generateCommentData); | ||
return get(reduceWithPromise)(useNodes, async (node) => { | ||
const info = generateCommentDataFn(node); | ||
const formatted = await formatterFn(info); | ||
const shouldIgnore = await shouldIgnoreFn(formatted); | ||
if (shouldIgnore) { | ||
return formatted; | ||
} | ||
return processorFn(formatted); | ||
}); | ||
}); | ||
/** | ||
@@ -211,3 +214,3 @@ * Runs all the formatting functions that require the context of a comment block, not only | ||
* @param {ParsingInformation} info The parsed information of the comment. | ||
* @returns {ParsingInformation} | ||
* @returns {Promise<ParsingInformation>} | ||
*/ | ||
@@ -219,3 +222,3 @@ | ||
const formatCommentTags = R.curry((options, info) => | ||
R.compose( | ||
get(composeWithPromise)( | ||
R.assocPath(['block', 'tags'], R.__, info), | ||
@@ -244,3 +247,3 @@ get(formatTagsTypes)(R.__, options, info.column), | ||
const prepareCommentTags = R.curry((options, info) => | ||
R.compose( | ||
get(composeWithPromise)( | ||
R.assocPath(['block', 'tags'], R.__, info), | ||
@@ -292,25 +295,28 @@ get(prepareTags)(R.__, options, info.column), | ||
*/ | ||
const createParser = (originalParser, checkExtendOption) => (text, parsers, options) => { | ||
const ast = originalParser(text, parsers, options); | ||
if ( | ||
options && | ||
options.jsdocPluginEnabled && | ||
(!checkExtendOption || !options.jsdocPluginExtended) | ||
) { | ||
const formatter = R.compose( | ||
get(prepareCommentTags)(options), | ||
get(formatCommentTags)(options), | ||
get(formatCommentBlock)(options), | ||
); | ||
const renderer = getRenderer(options); | ||
if (ast.comments && ast.comments.length) { | ||
get(processComments)(options, ast.comments, formatter, (info) => { | ||
const { comment, column, block } = info; | ||
comment.value = renderer(column, block); | ||
}); | ||
const createParser = | ||
(originalParser, checkExtendOption) => async (text, parsers, options) => { | ||
const ast = originalParser(text, parsers, options); | ||
if ( | ||
options && | ||
options.jsdocPluginEnabled && | ||
(!checkExtendOption || !options.jsdocPluginExtended) | ||
) { | ||
const formatter = get(composeWithPromise)( | ||
get(prepareCommentTags)(options), | ||
get(formatCommentTags)(options), | ||
get(formatCommentBlock)(options), | ||
); | ||
const renderer = getRenderer(options); | ||
if (ast.comments && ast.comments.length) { | ||
await get(processComments)(options, ast.comments, formatter, (info) => { | ||
const { comment, column, block } = info; | ||
const value = renderer(column, block); | ||
comment.value = value; | ||
return info; | ||
}); | ||
} | ||
} | ||
} | ||
return ast; | ||
}; | ||
return ast; | ||
}; | ||
@@ -350,14 +356,17 @@ /** | ||
}, | ||
get typescript() { | ||
return useExtendParser(tsParser.parsers.typescript); | ||
}, | ||
/* istanbul ignore next */ | ||
get 'babel-flow'() { | ||
return useExtendParser(babelParser.parsers['babel-flow']); | ||
}, | ||
/* istanbul ignore next */ | ||
get 'babel-ts'() { | ||
return useExtendParser(babelParser.parsers['babel-ts']); | ||
}, | ||
/* istanbul ignore next */ | ||
get flow() { | ||
return useExtendParser(flowParser.parsers.flow); | ||
}, | ||
get typescript() { | ||
return useExtendParser(tsParser.parsers.typescript); | ||
}, | ||
}; | ||
@@ -364,0 +373,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
const { getLanguages } = require('./getLanguages'); | ||
const { getSupportedLanguages } = require('./constants'); | ||
const { getParsers } = require('./getParsers'); | ||
@@ -35,3 +35,3 @@ const { getOptions, getDefaultOptions } = require('./getOptions'); | ||
const getPlugin = (checkExtendOption) => ({ | ||
languages: get(getLanguages)(), | ||
languages: get(getSupportedLanguages)(), | ||
options: get(getOptions)(), | ||
@@ -38,0 +38,0 @@ defaultOptions: get(getDefaultOptions)(), |
const { format } = require('prettier'); | ||
const R = require('ramda'); | ||
const { isTag, prefixLines, splitLinesAndClean } = require('./utils'); | ||
const { isTag, prefixLines, splitLinesAndClean, reduceWithPromise } = require('./utils'); | ||
const { get, provider } = require('./app'); | ||
@@ -27,5 +27,5 @@ | ||
* @param {string} example The example code. | ||
* @returns {string} | ||
* @returns {Promise<string>} | ||
*/ | ||
const formatExample = (options, column, example) => { | ||
const formatExample = async (options, column, example) => { | ||
let code; | ||
@@ -40,3 +40,3 @@ let indent; | ||
code = format(example, { | ||
code = await format(example, { | ||
...options, | ||
@@ -65,18 +65,16 @@ printWidth, | ||
* @param {string} example The example code. | ||
* @returns {CommentTagExample[]} | ||
* @returns {Promise<CommentTagExample[]>} | ||
*/ | ||
const splitExamples = (options, column, example) => { | ||
const useSplitLinesAndClean = get(splitLinesAndClean); | ||
return R.compose( | ||
R.map( | ||
R.compose( | ||
([caption, code]) => ({ | ||
caption, | ||
code: get(formatExample)(options, column, code), | ||
}), | ||
useSplitLinesAndClean(/<\s*\/\s*caption\s*>/i), | ||
), | ||
), | ||
useSplitLinesAndClean(/<\s*caption\s*>/i), | ||
)(example); | ||
const splitExamples = async (options, column, example) => { | ||
const splitLinesAndCleanFn = get(splitLinesAndClean); | ||
const splitEndFn = splitLinesAndCleanFn(/<\s*\/\s*caption\s*>/i); | ||
const splitted = splitLinesAndCleanFn(/<\s*caption\s*>/i)(example); | ||
const formatExampleFn = get(formatExample); | ||
return get(reduceWithPromise)(splitted, async (item) => { | ||
const [caption, code] = splitEndFn(item); | ||
return { | ||
caption, | ||
code: await formatExampleFn(options, column, code), | ||
}; | ||
}); | ||
}; | ||
@@ -99,8 +97,9 @@ | ||
*/ | ||
const formatExampleTag = R.curry((options, column, tag) => { | ||
const formatExampleTag = R.curry(async (options, column, tag) => { | ||
let examples; | ||
if (tag.description.match(/<\s*caption\s*>/i)) { | ||
examples = get(splitExamples)(options, column, tag.description); | ||
examples = await get(splitExamples)(options, column, tag.description); | ||
} else if (tag.description.trim()) { | ||
examples = [{ code: get(formatExample)(options, column, tag.description) }]; | ||
const code = await get(formatExample)(options, column, tag.description); | ||
examples = [{ code }]; | ||
} else { | ||
@@ -107,0 +106,0 @@ examples = []; |
@@ -6,2 +6,3 @@ const R = require('ramda'); | ||
const { get, provider } = require('./app'); | ||
const { composeWithPromise, reduceWithPromise } = require('./utils'); | ||
@@ -25,3 +26,3 @@ /** | ||
* to call Prettier. | ||
* @returns {CommentTag[]} | ||
* @returns {Promise<CommentTag[]>} | ||
*/ | ||
@@ -32,3 +33,3 @@ | ||
*/ | ||
const prepareTags = R.curry((tags, options, column) => { | ||
const prepareTags = R.curry(async (tags, options, column) => { | ||
const fns = [get(prepareTagName)]; | ||
@@ -44,3 +45,4 @@ | ||
return R.map(R.compose(...fns.reverse()), tags); | ||
const pipeline = get(composeWithPromise)(...fns.reverse()); | ||
return get(reduceWithPromise)(tags, pipeline); | ||
}); | ||
@@ -47,0 +49,0 @@ |
@@ -354,2 +354,49 @@ const R = require('ramda'); | ||
/** | ||
* A version of Rambdas `compose` that can handle promises. | ||
* | ||
* @param {...*} args The list of functions to compose. | ||
* @returns {*} | ||
* @see https://gist.github.com/ehpc/2a524b78729ee6b4e8111f89c66d7ff5 | ||
*/ | ||
const composeWithPromise = (...args) => | ||
R.composeWith((f, val) => { | ||
if (val && val.then) { | ||
return val.then(f); | ||
} | ||
return f(val); | ||
})(args); | ||
/** | ||
* @callback ReduceWithPromiseFn | ||
* @param {TItem} item The item to process. | ||
* @returns {Promise<TOutput>} | ||
* @template TItem The type of the items on the list. | ||
* @template TOutput The type of the item that will be returned. | ||
*/ | ||
/** | ||
* A utility function that will process a list of items and return a promise with the | ||
* results. | ||
* The idea of this function is to replace a `for` loop with `await` inside. | ||
* | ||
* @param {TItem[]} items The list of items to process. | ||
* @param {ReduceWithPromiseFn<TItem, TOutput>} fn The function that will process each | ||
* item. | ||
* @returns {Promise<TOutput[]>} | ||
* @template TItem The type of the items on the list. | ||
* @template TOutput The type of the item that will be returned by the reducer. | ||
*/ | ||
const reduceWithPromise = (items, fn) => | ||
items.reduce( | ||
(accPromise, item) => | ||
accPromise.then(async (acc) => { | ||
const result = await fn(item); | ||
acc.push(result); | ||
return acc; | ||
}), | ||
Promise.resolve([]), | ||
); | ||
module.exports.ensureArray = ensureArray; | ||
@@ -373,2 +420,4 @@ module.exports.findTagIndex = findTagIndex; | ||
module.exports.ensureSentence = ensureSentence; | ||
module.exports.composeWithPromise = composeWithPromise; | ||
module.exports.reduceWithPromise = reduceWithPromise; | ||
module.exports.provider = provider('utils', module.exports); |
@@ -18,3 +18,2 @@ const path = require('path'); | ||
'formatTypeAsCode', | ||
'getLanguages', | ||
'getOptions', | ||
@@ -21,0 +20,0 @@ 'getParsers', |
@@ -15,2 +15,9 @@ //# input | ||
/** | ||
* @type {Object} SomethingToIgnore | ||
* @description transform this into a sentence | ||
* @see {@link SomethingElse} to see how this is not broken, as the parser thinks the link is a type. | ||
* @prettierignore | ||
*/ | ||
/** | ||
* @description logs something. | ||
@@ -70,2 +77,9 @@ * @param {string} [name='batman'] the name | ||
/** | ||
* @type {Object} SomethingToIgnore | ||
* @description transform this into a sentence | ||
* @see {@link SomethingElse} to see how this is not broken, as the parser thinks the link is a type. | ||
* @prettierignore | ||
*/ | ||
/** | ||
* Logs something. | ||
@@ -72,0 +86,0 @@ * |
@@ -14,13 +14,12 @@ const prettier = require('prettier'); | ||
const fixtures = global.e2eFixtures; | ||
fixtures.forEach((fixture) => { | ||
it(`should format fixture: ${fixture.name}`, () => { | ||
const output = prettier | ||
.format(fixture.input, { | ||
plugins: [...(fixture.plugins || []), prettierPluginJSDoc], | ||
...fixture.options, | ||
}) | ||
.trim(); | ||
expect(output).toBe(fixture.output); | ||
it(`should format fixture: ${fixture.name}`, async () => { | ||
const output = await prettier.format(fixture.input, { | ||
plugins: [...(fixture.plugins || []), prettierPluginJSDoc], | ||
...fixture.options, | ||
}); | ||
expect(output.trim()).toBe(fixture.output); | ||
}); | ||
}); | ||
}); |
@@ -17,3 +17,3 @@ jest.unmock('../../../src/fns/formatTagsTypes'); | ||
it('should apply all the transformations', () => { | ||
it('should apply all the transformations', async () => { | ||
// Given | ||
@@ -62,3 +62,3 @@ const input = [ | ||
// When | ||
result = formatTagsTypes(input, options, 0); | ||
result = await formatTagsTypes(input, options, 0); | ||
// Then | ||
@@ -88,3 +88,3 @@ expect(result).toEqual(output); | ||
it('should only format objects', () => { | ||
it('should only format objects', async () => { | ||
// Given | ||
@@ -132,3 +132,3 @@ const input = [ | ||
// When | ||
result = formatTagsTypes(input, options, 2); | ||
result = await formatTagsTypes(input, options, 2); | ||
// Then | ||
@@ -138,3 +138,3 @@ expect(result).toEqual(output); | ||
it('should only format arrays', () => { | ||
it('should only format arrays', async () => { | ||
// Given | ||
@@ -183,3 +183,3 @@ const input = [ | ||
// When | ||
result = formatTagsTypes(input, options, 4); | ||
result = await formatTagsTypes(input, options, 4); | ||
// Then | ||
@@ -189,3 +189,3 @@ expect(result).toEqual(output); | ||
it("shouldn't format anything", () => { | ||
it("shouldn't format anything", async () => { | ||
// Given | ||
@@ -233,3 +233,3 @@ const input = [ | ||
// When | ||
result = formatTagsTypes(input, options, 2); | ||
result = await formatTagsTypes(input, options, 2); | ||
// Then | ||
@@ -236,0 +236,0 @@ expect(result).toEqual(output); |
@@ -12,3 +12,3 @@ jest.unmock('../../../src/fns/formatTypeAsCode'); | ||
it('should ignore a basic type', () => { | ||
it('should ignore a basic type', async () => { | ||
// Given | ||
@@ -19,3 +19,3 @@ const input = 'string'; | ||
// When | ||
result = formatTypeAsCode(input, {}, 0); | ||
result = await formatTypeAsCode(input, {}, 0); | ||
// Then | ||
@@ -26,3 +26,3 @@ expect(result).toEqual(output); | ||
it('should call prettier for a complex type', () => { | ||
it('should call prettier for a complex type', async () => { | ||
// Given | ||
@@ -42,3 +42,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = formatTypeAsCode(input, options, 0); | ||
result = await formatTypeAsCode(input, options, 0); | ||
// Then | ||
@@ -54,3 +54,3 @@ expect(result).toEqual(output); | ||
it('should return the original type if prettier throws an error', () => { | ||
it('should return the original type if prettier throws an error', async () => { | ||
// Given | ||
@@ -69,3 +69,3 @@ format.mockImplementationOnce(() => { | ||
// When | ||
result = formatTypeAsCode(input, options, 2); | ||
result = await formatTypeAsCode(input, options, 2); | ||
// Then | ||
@@ -72,0 +72,0 @@ expect(result).toEqual(output); |
jest.mock('comment-parser'); | ||
jest.mock('prettier/parser-babel'); | ||
jest.mock('prettier/parser-flow'); | ||
jest.mock('prettier/parser-typescript'); | ||
jest.mock('prettier/parser-babel', () => ({ | ||
parsers: { | ||
babel: { | ||
parse: jest.fn(), | ||
}, | ||
'babel-flow': { | ||
parse: jest.fn(), | ||
}, | ||
'babel-ts': { | ||
parse: jest.fn(), | ||
}, | ||
}, | ||
})); | ||
jest.mock('prettier/parser-flow', () => ({ | ||
parsers: { | ||
flow: { | ||
parse: jest.fn(), | ||
}, | ||
}, | ||
})); | ||
jest.mock('prettier/parser-typescript', () => ({ | ||
parsers: { | ||
typescript: { | ||
parse: jest.fn(), | ||
}, | ||
}, | ||
})); | ||
jest.unmock('../../../src/fns/getParsers'); | ||
@@ -35,3 +59,3 @@ | ||
it("shouldn't do anything if there are no comments on the AST", () => { | ||
it("shouldn't do anything if there are no comments on the AST", async () => { | ||
// Given | ||
@@ -80,9 +104,11 @@ const astBase = { | ||
sut = getParsers(); | ||
parsersToTest.forEach((info) => { | ||
sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}); | ||
await Promise.all( | ||
parsersToTest.map(async (info) => { | ||
await sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}), | ||
); | ||
}); | ||
it("shouldn't do anything if the plugin is disabled", () => { | ||
it("shouldn't do anything if the plugin is disabled", async () => { | ||
// Given | ||
@@ -143,9 +169,11 @@ const commentStr = '*\n * @typedef {string} MyStr\n '; | ||
sut = getParsers(); | ||
parsersToTest.forEach((info) => { | ||
sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}); | ||
await Promise.all( | ||
parsersToTest.map(async (info) => { | ||
await sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}), | ||
); | ||
}); | ||
it("shouldn't do anything if the plugin is being extended", () => { | ||
it("shouldn't do anything if the plugin is being extended", async () => { | ||
// Given | ||
@@ -207,9 +235,11 @@ const commentStr = '*\n * @typedef {string} MyStr\n '; | ||
sut = getParsers(true); | ||
parsersToTest.forEach((info) => { | ||
sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}); | ||
await Promise.all( | ||
parsersToTest.map(async (info) => { | ||
await sut[info.name].parse(text, parsers, options); | ||
expect(info.ast).toEqual(astBase); | ||
}), | ||
); | ||
}); | ||
it('should render a comment', () => { | ||
it('should ignore comment with @prettierignore', async () => { | ||
// Given | ||
@@ -267,3 +297,3 @@ const commentStr = '*\n * @typedef {string} MyStr\n '; | ||
sut = getParsers(); | ||
sut.typescript.parse(text, parsers, options); | ||
await sut.typescript.parse(text, parsers, options); | ||
// Then | ||
@@ -306,4 +336,64 @@ expect(ast).toEqual({ | ||
it('should render an inline comment', () => { | ||
it('should render a comment', async () => { | ||
// Given | ||
const commentStr = '*\n * @typedef {string} MyStr\n * @prettierignore\n '; | ||
const column = 2; | ||
const astBase = { | ||
comments: [ | ||
{ | ||
type: 'CommentBlock', | ||
value: commentStr, | ||
loc: { | ||
start: { | ||
column, | ||
}, | ||
}, | ||
}, | ||
], | ||
}; | ||
const ast = R.clone(astBase); | ||
const tagsList = [ | ||
{ | ||
tag: 'typedef', | ||
type: 'string', | ||
name: 'MyStr', | ||
description: '', | ||
}, | ||
{ | ||
tag: 'prettierignore', | ||
description: '', | ||
}, | ||
]; | ||
const parsed = [ | ||
{ | ||
description: '', | ||
tags: tagsList, | ||
}, | ||
]; | ||
commentParser.mockImplementationOnce(() => parsed); | ||
const formatTagsTypesRest = jest.fn((tags) => tags); | ||
formatTagsTypes.mockImplementationOnce(() => formatTagsTypesRest); | ||
const formatTagsRest = jest.fn((tags) => tags); | ||
formatTags.mockImplementationOnce(() => formatTagsRest); | ||
const formatDescriptionRest = jest.fn((tags) => tags); | ||
formatDescription.mockImplementationOnce(() => formatDescriptionRest); | ||
const prepareTagsRest = jest.fn((tags) => tags); | ||
prepareTags.mockImplementationOnce(() => prepareTagsRest); | ||
tsParser.parsers.typescript.parse.mockImplementationOnce(() => ast); | ||
const text = 'lorem ipsum'; | ||
const parsers = ['ts']; | ||
const options = { | ||
jsdocPluginEnabled: true, | ||
printWidth: 80, | ||
}; | ||
let sut = null; | ||
// When | ||
sut = getParsers(); | ||
await sut.typescript.parse(text, parsers, options); | ||
// Then | ||
expect(ast).toEqual(astBase); | ||
}); | ||
it('should render an inline comment', async () => { | ||
// Given | ||
const commentStr = '*\n * @type {MyStr}\n '; | ||
@@ -362,3 +452,3 @@ const column = 2; | ||
sut = getParsers(); | ||
sut['babel-flow'].parse(text, parsers, options); | ||
await sut['babel-flow'].parse(text, parsers, options); | ||
// Then | ||
@@ -380,3 +470,3 @@ expect(ast).toEqual({ | ||
it('should fix a tag without a space between name and type', () => { | ||
it('should fix a tag without a space between name and type', async () => { | ||
// Given | ||
@@ -434,3 +524,3 @@ const commentStr = '*\n * @typedef{string} MyStr\n '; | ||
sut = getParsers(); | ||
sut.typescript.parse(text, parsers, options); | ||
await sut.typescript.parse(text, parsers, options); | ||
// Then | ||
@@ -437,0 +527,0 @@ expect(ast).toEqual({ |
@@ -1,4 +0,1 @@ | ||
jest.mock('../../../src/fns/getLanguages', () => ({ | ||
getLanguages: () => 'languages', | ||
})); | ||
jest.mock('../../../src/fns/getParsers', () => ({ | ||
@@ -16,6 +13,24 @@ getParsers: () => 'parsers', | ||
describe('getPlugin', () => { | ||
it('should generate the plugin main exports', () => { | ||
// Given/When/Then | ||
expect(getPlugin()).toEqual({ | ||
languages: 'languages', | ||
it('should generate the plugin main exports', async () => { | ||
// Given/When | ||
const result = await getPlugin(); | ||
// Then | ||
expect(result).toEqual({ | ||
languages: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
name: 'JavaScript', | ||
}), | ||
expect.objectContaining({ | ||
name: 'JSX', | ||
}), | ||
expect.objectContaining({ | ||
name: 'TypeScript', | ||
}), | ||
expect.objectContaining({ | ||
name: 'TSX', | ||
}), | ||
expect.objectContaining({ | ||
name: 'Flow', | ||
}), | ||
]), | ||
options: 'options', | ||
@@ -22,0 +37,0 @@ defaultOptions: 'defaultOptions', |
@@ -12,3 +12,3 @@ jest.unmock('../../../src/fns/prepareExampleTag'); | ||
it("should ignore a tag that's not @example", () => { | ||
it("should ignore a tag that's not @example", async () => { | ||
// Given | ||
@@ -23,3 +23,3 @@ const input = { | ||
// When | ||
result = prepareExampleTag(input, {}, 0); | ||
result = await prepareExampleTag(input, {}, 0); | ||
// Then | ||
@@ -30,3 +30,3 @@ expect(result).toEqual(output); | ||
it('should call prettier for an example tag', () => { | ||
it('should call prettier for an example tag', async () => { | ||
// Given | ||
@@ -55,3 +55,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = prepareExampleTag(input, options, 2); | ||
result = await prepareExampleTag(input, options, 2); | ||
// Then | ||
@@ -66,3 +66,3 @@ expect(result).toEqual(output); | ||
it('should indent formatted text', () => { | ||
it('should indent formatted text', async () => { | ||
// Given | ||
@@ -91,3 +91,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = prepareExampleTag(input, options, 2); | ||
result = await prepareExampleTag(input, options, 2); | ||
// Then | ||
@@ -102,3 +102,3 @@ expect(result).toEqual(output); | ||
it('should indent unformatted text', () => { | ||
it('should indent unformatted text', async () => { | ||
// Given | ||
@@ -128,3 +128,3 @@ format.mockImplementationOnce(() => { | ||
// When | ||
result = prepareExampleTag(input, options, 0); | ||
result = await prepareExampleTag(input, options, 0); | ||
// Then | ||
@@ -139,3 +139,3 @@ expect(result).toEqual(output); | ||
it('should detect an example caption', () => { | ||
it('should detect an example caption', async () => { | ||
// Given | ||
@@ -165,3 +165,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = prepareExampleTag(input, options, 0); | ||
result = await prepareExampleTag(input, options, 0); | ||
// Then | ||
@@ -176,3 +176,3 @@ expect(result).toEqual(output); | ||
it('should detect multiple captions', () => { | ||
it('should detect multiple captions', async () => { | ||
// Given | ||
@@ -210,3 +210,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = prepareExampleTag(input, options, 0); | ||
result = await prepareExampleTag(input, options, 0); | ||
// Then | ||
@@ -225,3 +225,3 @@ expect(result).toEqual(output); | ||
it('should detect an empty example tag', () => { | ||
it('should detect an empty example tag', async () => { | ||
// Given | ||
@@ -242,3 +242,3 @@ const input = { | ||
// When | ||
result = prepareExampleTag(input, options, 0); | ||
result = await prepareExampleTag(input, options, 0); | ||
// Then | ||
@@ -245,0 +245,0 @@ expect(result).toEqual(output); |
@@ -15,3 +15,3 @@ jest.unmock('../../../src/fns/prepareTags'); | ||
it('should prepare types and tags names on a tags list', () => { | ||
it('should prepare types and tags names on a tags list', async () => { | ||
// Given | ||
@@ -52,3 +52,3 @@ const input = [ | ||
// When | ||
result = prepareTags(input, options, 0); | ||
result = await prepareTags(input, options, 0); | ||
// Then | ||
@@ -58,3 +58,3 @@ expect(result).toEqual(output); | ||
it('should prepare examples', () => { | ||
it('should prepare examples', async () => { | ||
// Given | ||
@@ -116,3 +116,3 @@ const prettierResponse = 'prettier-response'; | ||
// When | ||
result = prepareTags(input, options, 2); | ||
result = await prepareTags(input, options, 2); | ||
// Then | ||
@@ -127,3 +127,3 @@ expect(result).toEqual(output); | ||
it('should prepare descriptions', () => { | ||
it('should prepare descriptions', async () => { | ||
// Given | ||
@@ -156,3 +156,3 @@ const input = [ | ||
// When | ||
result = prepareTags(input, options, 0); | ||
result = await prepareTags(input, options, 0); | ||
// Then | ||
@@ -159,0 +159,0 @@ expect(result).toEqual(output); |
342223
2.59%9177
3.21%105
-0.94%+ Added
- Removed
Updated