Commit 3c697cfb authored by gumen's avatar gumen 🐢

Add prettier and format all JS files

parent 6019e7f5
{
"printWidth": 120,
"useTabs": false,
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"bracketSpacing": true,
"arrowParens": "avoid",
"endOfLine": "lf",
"plugins": ["."],
"parser": "jsdoc-parser",
"jsdocSpaces": 1,
"jsdocPrintWidth": 80,
"jsdocDescriptionWithDot": false,
"jsdocDescriptionTag": false,
"jsdocVerticalAlignment": true,
"jsdocUnionTypeParentheses": false,
"jsdocKeepUnparseableExampleIndent": true
}
......@@ -6,7 +6,6 @@ Contributor: @VectorW
TODO
Fill README file with useful informations like description of options
Add prettier
Release first version
Mention plugin in https://github.com/prettier/prettier/issues/5659
Investigate sorting of over 10 tags - failing test in ./tests/main.js:209
......@@ -253,3 +253,12 @@ sob, 25 sty 2020, 09:05:37 CET
Udało się zrobić forka, poprawkę i nawet dopisać nowe testy projektu
Doctrine. Teraz mamy wsparcie dla tagu @yields.
czw, 30 sty 2020, 15:13:00 CET
Kolejne dwa fajne PR od Wiktora. Wreszcie mam też trochę czasu żeby
zająć się tematami wypisanymi w README.
czw, 30 sty 2020, 15:53:28 CET
Mergowałem PR. Dodałem prettiera do tego projektu.
......@@ -7,25 +7,25 @@ const tagSynonyms = {
// to avoid different titles in the same tag so here is map with
// synonyms as keys and tag type as value that we want to have in
// final jsDoc.
'virtual' : 'abstract',
'extends' : 'augments',
'constructor' : 'class',
'const' : 'constant',
'defaultvalue' : 'default',
'desc' : 'description',
'host' : 'external',
'fileoverview' : 'file',
'overview' : 'file',
'emits' : 'fires',
'func' : 'function',
'method' : 'function',
'var' : 'member',
'arg' : 'param',
'argument' : 'param',
'prop' : 'property',
'returns' : 'return',
'exception' : 'throws',
'yield' : 'yields',
virtual: 'abstract',
extends: 'augments',
constructor: 'class',
const: 'constant',
defaultvalue: 'default',
desc: 'description',
host: 'external',
fileoverview: 'file',
overview: 'file',
emits: 'fires',
func: 'function',
method: 'function',
var: 'member',
arg: 'param',
argument: 'param',
prop: 'property',
returns: 'return',
exception: 'throws',
yield: 'yields',
// {@link} (synonyms: {@linkcode}, {@linkplain})
// TODO I'm not sure how @link is parsed. I will have to look up
......@@ -34,36 +34,30 @@ const tagSynonyms = {
// It looks like sometimes someone use incorrect tag title. Its
// close to correct title but not quite. We want to map that too.
'examples' : 'example',
'params' : 'param',
examples: 'example',
params: 'param',
}
const vertiacallyAlignableTags = [
'param',
'property',
'return',
'throws',
'yields',
]
const vertiacallyAlignableTags = ['param', 'property', 'return', 'throws', 'yields']
const typePrefixMap = {
'NullableType': '?',
'NonNullableType': '!',
NullableType: '?',
NonNullableType: '!',
}
/**
* Return properly formatted tag type name. Call itself recursively for complex
* inner types
*
* @param {Object} tagType Tag type object from parsed jsdoc
* @param {Boolean} unionTypeParentheses flag for parentheses around union type
* @returns {String} Formatted tag type
* @param {Object} tagType Tag type object from parsed jsdoc
* @param {Boolean} unionTypeParentheses Flag for parentheses around union type
* @return {String} Formatted tag type
*/
function getTagTypeName(tagType, unionTypeParentheses) {
let { name } = tagType
if (name) return name
let { type, expression, applications, elements, prefix } = tagType
switch (type) {
......@@ -83,9 +77,7 @@ function getTagTypeName(tagType, unionTypeParentheses) {
case 'OptionalType':
return getTagTypeName(expression)
case 'UnionType':
return `${
unionTypeParentheses ? '(' : ''
}${elements.map(e => getTagTypeName(e)).join('|')}${
return `${unionTypeParentheses ? '(' : ''}${elements.map(e => getTagTypeName(e)).join('|')}${
unionTypeParentheses ? ')' : ''
}`
default:
......@@ -93,25 +85,27 @@ function getTagTypeName(tagType, unionTypeParentheses) {
}
}
/**
* Trim, make single line with capitalized text. Insert dot if flag for it is
* set to true and last character is a word character
* @param {String} text
* @param {Boolean} insertDot flag for dot at the end of text
* @return {String}
*
* @param {String} text TODO
* @param {Boolean} insertDot Flag for dot at the end of text
* @return {String} TODO
*/
function formatDescription(text, insertDot) {
text = text ? text.trim() : ''
if (!text) return ''
text = text.replace(/\s\s+/g, ' ') // Avoid multiple spaces
text = text.replace(/\n/g, ' ') // Make single line
if (insertDot) text = text.replace(/(\w)(?=$)/g, '$1.') // Insert dot if needed
text = text[0].toUpperCase() + text.slice(1) // Capitalize
text = text.replace(/\s\s+/g, ' ') // Avoid multiple spaces
text = text.replace(/\n/g, ' ') // Make single line
if (insertDot) text = text.replace(/(\w)(?=$)/g, '$1.') // Insert dot if needed
text = text[0].toUpperCase() + text.slice(1) // Capitalize
return text || ''
}
/** {@link https://prettier.io/docs/en/api.html#custom-parser-api} */
/**
* {@link https://prettier.io/docs/en/api.html#custom-parser-api}
*/
function jsdocParser(text, parsers, options) {
const ast = parsers['babel-flow'](text)
......@@ -120,13 +114,14 @@ function jsdocParser(text, parsers, options) {
const printWidth = options.jsdocPrintWidth
/**
* Control order of tags by weights. Smaller value brings tag higher.
* @param {String} tagTitle
* @return {Number} Tag weight
* Control order of tags by weights. Smaller value brings tag higher.
*
* @param {String} tagTitle TODO
* @return {Number} Tag weight
*/
function getTagOrderWeight(tagTitle) {
const index = options.jsdocTagsOrder.indexOf(tagTitle)
return index === -1 ? (options.jsdocTagsOrder.indexOf('other') || 0) : index
return index === -1 ? options.jsdocTagsOrder.indexOf('other') || 0 : index
}
ast.comments.forEach(comment => {
......@@ -183,8 +178,11 @@ function jsdocParser(text, parsers, options) {
if (['description', 'param', 'property', 'return', 'yields', 'throws', 'todo'].includes(tag.title))
tag.description = formatDescription(tag.description, options.jsdocDescriptionWithDot)
if (!tag.description && ['description', 'param', 'property', 'return', 'yields', 'throws', 'todo', 'memberof'].includes(tag.title) &&
(!tag.type || !['Undefined', 'undefined', 'Null', 'null', 'Void', 'void'].includes(tag.type.name)))
if (
!tag.description &&
['description', 'param', 'property', 'return', 'yields', 'throws', 'todo', 'memberof'].includes(tag.title) &&
(!tag.type || !['Undefined', 'undefined', 'Null', 'null', 'Void', 'void'].includes(tag.type.name))
)
tag.description = formatDescription('TODO', options.jsdocDescriptionWithDot)
return tag
......@@ -207,11 +205,11 @@ function jsdocParser(text, parsers, options) {
if (tag.type && tag.type.name) tagTypeGapAdj += maxTagTypeNameLength - tag.type.name.length
else if (maxTagTypeNameLength) descGapAdj += maxTagTypeNameLength + gap.length
if (tag.name) tagNameGapAdj += maxTagNameLength - tag.name.length
if (tag.name) tagNameGapAdj += maxTagNameLength - tag.name.length
else if (maxTagNameLength) descGapAdj = maxTagNameLength + gap.length
}
let useTagTitle = (tag.title !== 'description' || options.jsdocDescriptionTag)
let useTagTitle = tag.title !== 'description' || options.jsdocDescriptionTag
let tagString = ` * `
if (useTagTitle) tagString += `@${tag.title}` + ' '.repeat(tagTitleGapAdj)
......@@ -221,9 +219,11 @@ function jsdocParser(text, parsers, options) {
// Add description (complicated because of text wrap)
if (tag.description && tag.title !== 'example') {
if (useTagTitle) tagString += gap + ' '.repeat(descGapAdj)
if (['memberof', 'see'].includes(tag.title)) { // Avoid wrapping
if (['memberof', 'see'].includes(tag.title)) {
// Avoid wrapping
tagString += tag.description
} else { // Wrap tag description
} else {
// Wrap tag description
const marginLength = tagString.length
let maxWidth = printWidth
if (marginLength >= maxWidth) maxWidth = marginLength + 40
......@@ -249,8 +249,11 @@ function jsdocParser(text, parsers, options) {
tagString += formatedDescription.replace(/(^|\n)/g, '\n * ')
tagString = tagString.slice(0, tagString.length - 6)
} catch (err) {
tagString += '\n' + tag.description
.split('\n').map(l => ` * ${options.jsdocKeepUnparseableExampleIndent ? l : l.trim()}`).join('\n')
tagString += '\n'
tagString += tag.description
.split('\n')
.map(l => ` * ${options.jsdocKeepUnparseableExampleIndent ? l : l.trim()}`)
.join('\n')
}
}
......@@ -271,12 +274,14 @@ function jsdocParser(text, parsers, options) {
// jsdoc-parser
module.exports = {
languages: [{
name: 'JavaScript',
parsers: ['jsdoc-parser'],
}],
languages: [
{
name: 'JavaScript',
parsers: ['jsdoc-parser'],
},
],
parsers: {
'jsdoc-parser': Object.assign({}, babelFlow, { parse: jsdocParser })
'jsdoc-parser': Object.assign({}, babelFlow, { parse: jsdocParser }),
},
// How to define options: https://github.com/prettier/prettier/blob/master/src/cli/constant.js#L16
// Issue with string type: https://github.com/prettier/prettier/issues/6151
......@@ -297,30 +302,34 @@ module.exports = {
type: 'path',
category: 'jsdoc',
array: true, // Fancy way to get option in array form
default: [{ value: [
'private',
'global',
'class',
'memberof',
'namespace',
'callback',
'description',
'see',
'todo',
'examples',
'other',
'param',
'throws',
'yields',
'return',
]}],
default: [
{
value: [
'private',
'global',
'class',
'memberof',
'namespace',
'callback',
'description',
'see',
'todo',
'examples',
'other',
'param',
'throws',
'yields',
'return',
],
},
],
description: 'Define order of tags.',
},
jsdocDescriptionWithDot: {
type: 'boolean',
category: 'jsdoc',
default: false,
description: 'Should dot be inserted at the end of description'
description: 'Should dot be inserted at the end of description',
},
jsdocDescriptionTag: {
type: 'boolean',
......@@ -345,7 +354,7 @@ module.exports = {
category: 'jsdoc',
default: false,
description: 'Should unparseable esample (pseudo code or no js code) keep its indentation',
}
},
},
defaultOptions: {
jsdocSpaces: 1,
......@@ -355,5 +364,5 @@ module.exports = {
jsdocVerticalAlignment: false,
jsdocUnionTypeParentheses: false,
jsdocKeepUnparseableExampleIndent: false,
}
},
}
......@@ -1564,7 +1564,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
......@@ -1585,12 +1586,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
......@@ -1605,17 +1608,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
......@@ -1732,7 +1738,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
......@@ -1744,6 +1751,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
......@@ -1758,6 +1766,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
......@@ -1765,12 +1774,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
......@@ -1789,6 +1800,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
......@@ -1869,7 +1881,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
......@@ -1881,6 +1894,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
......@@ -1966,7 +1980,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
......@@ -2002,6 +2017,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
......@@ -2021,6 +2037,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
......@@ -2064,12 +2081,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
......
......@@ -4,7 +4,8 @@
"description": "",
"main": "jsdoc_parser.js",
"scripts": {
"test": "jest"
"test": "jest",
"prettier": "prettier --write \"**/*.js\""
},
"keywords": [
"prettier",
......
......@@ -9,8 +9,8 @@ function subject(code, options = {}) {
plugins: ['.'],
jsdocSpaces: 1,
jsdocPrintWidth: 80,
...options
});
...options,
})
}
test('JS code should be formatted as usuall', () => {
......@@ -286,9 +286,12 @@ test('Should add parentheses to union type if option set to true', () => {
const options = {
jsdocUnionTypeParentheses: true,
}
const Result1 = subject(`/**
const Result1 = subject(
`/**
* @param {Number|String} test Test param
*/`, options)
*/`,
options
)
const Expected1 = `/**
* @param {(Number|String)} test Test param
*/
......@@ -299,14 +302,17 @@ test('Should add parentheses to union type if option set to true', () => {
test('Should align vertically param|property|return|yields|throws if option set to true', () => {
const options = {
jsdocVerticalAlignment: true
jsdocVerticalAlignment: true,
}
const Result1 = subject(`/**
const Result1 = subject(
`/**
* @property {Object} unalginedProp unaligned property descriptin
* @param {String} unalginedParam unaligned param description
* @yields {Number} yields description
* @returns {undefined}
*/`, options)
*/`,
options
)
const Expected1 = `/**
* @property {Object} unalginedProp Unaligned property descriptin
* @param {String} unalginedParam Unaligned param description
......@@ -315,11 +321,14 @@ test('Should align vertically param|property|return|yields|throws if option set
*/
`
const Result2 = subject(`/**
const Result2 = subject(
`/**
* @throws {CustomExceptio} unaligned throws description
* @yields {Number} yields description
* @returns {String} unaligned returns description
*/`, options)
*/`,
options
)
const Expected2 = `/**
* @throws {CustomExceptio} Unaligned throws description
* @yields {Number} Yields description
......@@ -334,7 +343,7 @@ test('Should align vertically param|property|return|yields|throws if option set
test('Should align vertically param|property|return|yields|throws if option set to true, and amount of spaces is different than default', () => {
const options1 = {
jsdocVerticalAlignment: true,
jsdocSpaces: 2
jsdocSpaces: 2,
}
const unformattedJsdoc = `/**
* @property {Object} unalginedProp unaligned property descriptin
......@@ -355,15 +364,18 @@ test('Should align vertically param|property|return|yields|throws if option set
const options2 = {
jsdocVerticalAlignment: true,
jsdocSpaces: 4
jsdocSpaces: 4,
}
const Result2 = subject(`/**
const Result2 = subject(
`/**
* @property {Object} unalginedProp unaligned property descriptin
* @param {String} unalginedParam unaligned param description
* @throws {CustomExceptio} unaligned throws description
* @yields {Number} yields description
* @returns {String} unaligned returns description
*/`, options2)
*/`,
options2
)
const Expected2 = `/**
* @property {Object} unalginedProp Unaligned property
* descriptin
......@@ -383,12 +395,15 @@ test('Should align vertically param|property|return|yields|throws if option set
test('Should insert proper amount of spaces based on option', () => {
const options1 = {
jsdocSpaces: 2
jsdocSpaces: 2,
}
const Result1 = subject(`/**
const Result1 = subject(
`/**
* @param {Object} paramName param description that goes on and on and on utill it will need to be wrapped
* @returns {Number} return description
*/`, options1)