From 1dc8632a0f3d434cf3a60805f05a848124c0c509 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:05:39 -0300 Subject: [PATCH 01/11] fix: move return tag to tags with desc as name Before moving the return tag to the new group, even on inline mode, it was rendering the description in a column format. Now, it will correctly move it to a new line in inline mode, and in column mode, it will align it with the name property, instead of the description, so the white space will be reduced. --- src/fns/constants.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fns/constants.js b/src/fns/constants.js index 225fe14..89945d1 100644 --- a/src/fns/constants.js +++ b/src/fns/constants.js @@ -58,6 +58,8 @@ const getTagsWithDescriptionAsName = () => [ 'summary', 'throws', 'todo', + 'returns', + 'return', ]; /** * Gets a list of tags that need to be in column format. @@ -79,8 +81,6 @@ const getTagsWithNameAsDescription = () => [ 'see', 'borrows', 'yields', - 'returns', - 'return', ]; /** * Gets the list of languages the plugin supports. From f33eaf3aedcbfb9fdbeecf84887ce67601d6c71e Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:09:12 -0300 Subject: [PATCH 02/11] test: update the fixtures and a new one for the return change --- tests/e2e/fixtures/columns-02.fixture.js | 4 ++-- tests/e2e/fixtures/issue-03.fixture.js | 25 ++++++++++++++++++++++++ tests/e2e/fixtures/random-01.fixture.js | 9 +++++---- 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 tests/e2e/fixtures/issue-03.fixture.js diff --git a/tests/e2e/fixtures/columns-02.fixture.js b/tests/e2e/fixtures/columns-02.fixture.js index b3b35b2..aeb7389 100644 --- a/tests/e2e/fixtures/columns-02.fixture.js +++ b/tests/e2e/fixtures/columns-02.fixture.js @@ -12,7 +12,7 @@ module.exports = { /** * @callback IsAvailable * @param {"blue"|"red"|"purple"|"orange"} color Something. - * @returns {boolean} + * @returns {boolean} Some flag property. * @throws {Error} If something goes wrong * @see Something. */ @@ -28,7 +28,7 @@ module.exports = { /** * @callback IsAvailable * @param {'blue' | 'red' | 'purple' | 'orange'} color Something. - * @returns {boolean} + * @returns {boolean} Some flag property. * @throws {Error} If something goes wrong. * @see Something. */ diff --git a/tests/e2e/fixtures/issue-03.fixture.js b/tests/e2e/fixtures/issue-03.fixture.js new file mode 100644 index 0000000..f4f707a --- /dev/null +++ b/tests/e2e/fixtures/issue-03.fixture.js @@ -0,0 +1,25 @@ +module.exports = { + jsdocPrintWidth: 95, + jsdocUseColumns: false, +}; + +//# input + +/** + * @param {foo} bar baz + * @returns {number} Returns how the node is positioned relatively to the reference node + * according to the bitmask. 0 if reference node and given node are the same. + * @todo Refactor how the multiline names are handled. And some extra text to make the line longer. + */ + +//# output + +/** + * @param {foo} bar + * Baz. + * @returns {number} + * Returns how the node is positioned relatively to the reference node according to the + * bitmask. 0 if reference node and given node are the same. + * @todo Refactor how the multiline names are handled. And some extra text to make the line + * longer. + */ diff --git a/tests/e2e/fixtures/random-01.fixture.js b/tests/e2e/fixtures/random-01.fixture.js index fb120b6..f2d8507 100644 --- a/tests/e2e/fixtures/random-01.fixture.js +++ b/tests/e2e/fixtures/random-01.fixture.js @@ -112,7 +112,8 @@ export function log(name = 'batman', logger) {} * }; * }} newUser * Something else. - * @returns {User} Some description for the return value. + * @returns {User} + * Some description for the return value. * @summary * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec malesuada fermentum nibh, sed * aliquet ante porta a. Nullam blandit posuere fringilla. Nullam vel risus vitae lectus luctus @@ -136,9 +137,9 @@ export function log(name = 'batman', logger) {} /** * @returns A function that is used to analyze the value and the index and determine whether or - * not to increment the count. Return `true` to increment the count, and return `false` - * to keep the count the same. If the predicate is not provided, every value will be - * counted. + * not to increment the count. Return `true` to increment the count, and return + * `false` to keep the count the same. If the predicate is not provided, every value + * will be counted. */ export function foo(predicate) { console.log(predicate); From 6805ba093994e614e8ad587ada2053ed2b899da1 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:09:49 -0300 Subject: [PATCH 03/11] fix: move todo to the tags without desc Some editors require the todo tag to be in the same line as the description, that's why the tag needed to be moved. This will ensure that even on inline mode, todo and its description get rendered as columns. --- src/fns/constants.js | 2 +- tests/e2e/fixtures/inline-01.fixture.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fns/constants.js b/src/fns/constants.js index 89945d1..1ebefc7 100644 --- a/src/fns/constants.js +++ b/src/fns/constants.js @@ -57,7 +57,6 @@ const getTagsWithDescriptionAsName = () => [ 'remarks', 'summary', 'throws', - 'todo', 'returns', 'return', ]; @@ -81,6 +80,7 @@ const getTagsWithNameAsDescription = () => [ 'see', 'borrows', 'yields', + 'todo', ]; /** * Gets the list of languages the plugin supports. diff --git a/tests/e2e/fixtures/inline-01.fixture.js b/tests/e2e/fixtures/inline-01.fixture.js index c9e3025..5f712e5 100644 --- a/tests/e2e/fixtures/inline-01.fixture.js +++ b/tests/e2e/fixtures/inline-01.fixture.js @@ -19,6 +19,7 @@ module.exports = { * @see Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla facilisis enim sed mattis vulputate. Fusce velit dui, commodo eget ex sed, rutrum finibus ipsum. Vivamus dapibus sollicitudin lobortis. * @throws {Error} If something goes wrong * @yields {Object} Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla facilisis enim sed mattis vulputate. Fusce velit dui, commodo eget ex sed, rutrum finibus ipsum. Vivamus dapibus sollicitudin lobortis. + * @todo Refactor how the multiline names are handled. And some extra text to make the line a bit more longer. */ //# output @@ -44,4 +45,6 @@ module.exports = { * @see Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla facilisis enim sed mattis * vulputate. Fusce velit dui, commodo eget ex sed, rutrum finibus ipsum. Vivamus dapibus * sollicitudin lobortis. + * @todo Refactor how the multiline names are handled. And some extra text to make the line a bit + * more longer. */ From f1a26c0390aaf93b029288d9b24ea246800e5409 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:45:11 -0300 Subject: [PATCH 04/11] chore: fix Prettier setup --- .prettierrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.prettierrc.js b/.prettierrc.js index 3101e7e..a2a5061 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -2,5 +2,5 @@ const base = require('@homer0/prettier-config'); module.exports = { ...base, - plugins: ['./src'], + plugins: ['./src/index.js'], }; From 1d4167b8ff48b8166e05b63004d199c77b55d43e Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:45:45 -0300 Subject: [PATCH 05/11] fix: track tags that cannot be converted into sentences --- src/fns/constants.js | 16 +++++++++----- src/fns/prepareTagDescription.js | 38 ++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/fns/constants.js b/src/fns/constants.js index 1ebefc7..45c1442 100644 --- a/src/fns/constants.js +++ b/src/fns/constants.js @@ -76,12 +76,14 @@ const getTagsThatRequireColumns = () => ['template']; * * @returns {string[]} */ -const getTagsWithNameAsDescription = () => [ - 'see', - 'borrows', - 'yields', - 'todo', -]; +const getTagsWithNameAsDescription = () => ['see', 'borrows', 'yields', 'todo', 'since']; +/** + * There are certain tags which description cannot be converted into sentences (upper case + * and period at the end). + * + * @returns {string[]} + */ +const getTagsWithDescriptionThatCannotBeSentences = () => ['since']; /** * Gets the list of languages the plugin supports. * @@ -237,6 +239,8 @@ const getSupportedLanguages = () => [ module.exports.getTagsSynonyms = getTagsSynonyms; module.exports.getTagsWithDescriptionAsName = getTagsWithDescriptionAsName; module.exports.getTagsThatRequireColumns = getTagsThatRequireColumns; +module.exports.getTagsWithDescriptionThatCannotBeSentences = + getTagsWithDescriptionThatCannotBeSentences; module.exports.getTagsWithNameAsDescription = getTagsWithNameAsDescription; module.exports.getSupportedLanguages = getSupportedLanguages; module.exports.provider = provider('constants', module.exports); diff --git a/src/fns/prepareTagDescription.js b/src/fns/prepareTagDescription.js index 433264c..d637484 100644 --- a/src/fns/prepareTagDescription.js +++ b/src/fns/prepareTagDescription.js @@ -1,6 +1,9 @@ const R = require('ramda'); const { ensureSentence, hasValidProperty, isTag } = require('./utils'); -const { getTagsWithNameAsDescription } = require('./constants'); +const { + getTagsWithNameAsDescription, + getTagsWithDescriptionThatCannotBeSentences, +} = require('./constants'); const { get, provider } = require('./app'); /** @@ -33,23 +36,26 @@ const prepareTagDescription = (tag) => { const useHasValidProperty = get(hasValidProperty); const useIsStag = get(isTag); const useMakePropertyInstoSentence = get(makePropertyIntoSentence); - return R.when( - R.complement(useIsStag(['example', 'examples'])), - R.compose( - R.when( - useHasValidProperty('description'), - useMakePropertyInstoSentence('description'), - ), - R.when( - R.allPass([ - useIsStag(get(getTagsWithNameAsDescription)()), - useHasValidProperty('name'), - ]), - useMakePropertyInstoSentence('name'), + const useCannotBeSentence = get(getTagsWithDescriptionThatCannotBeSentences)(); + return R.unless( + useIsStag(useCannotBeSentence), + R.when( + R.complement(useIsStag(['example', 'examples'])), + R.compose( + R.when( + useHasValidProperty('description'), + useMakePropertyInstoSentence('description'), + ), + R.when( + R.allPass([ + useIsStag(get(getTagsWithNameAsDescription)()), + useHasValidProperty('name'), + ]), + useMakePropertyInstoSentence('name'), + ), ), ), - tag, - ); + )(tag); }; module.exports.prepareTagDescription = prepareTagDescription; From 4d46b3dfe4f04776d3258a70ab9ed1f4a81753cc Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:48:33 -0300 Subject: [PATCH 06/11] chore: allow extra args to the test command --- utils/scripts/test-unit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/test-unit b/utils/scripts/test-unit index 23c8367..ba22c8d 100755 --- a/utils/scripts/test-unit +++ b/utils/scripts/test-unit @@ -1,2 +1,2 @@ #!/bin/bash -e -NODE_OPTIONS=--experimental-vm-modules jest -c ./.jestrc-unit.js +NODE_OPTIONS=--experimental-vm-modules jest -c ./.jestrc-unit.js $@ From b322bb2666a82027a5de7e1a9e2958a8bda1e91c Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:49:26 -0300 Subject: [PATCH 07/11] test: add new cases for the 'since' change --- tests/e2e/fixtures/columns-02.fixture.js | 2 ++ tests/unit/fns/prepareTagDescription.test.js | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/tests/e2e/fixtures/columns-02.fixture.js b/tests/e2e/fixtures/columns-02.fixture.js index aeb7389..451befd 100644 --- a/tests/e2e/fixtures/columns-02.fixture.js +++ b/tests/e2e/fixtures/columns-02.fixture.js @@ -15,6 +15,7 @@ module.exports = { * @returns {boolean} Some flag property. * @throws {Error} If something goes wrong * @see Something. + * @since 1.0.0 RC1 */ /** @@ -30,6 +31,7 @@ module.exports = { * @param {'blue' | 'red' | 'purple' | 'orange'} color Something. * @returns {boolean} Some flag property. * @throws {Error} If something goes wrong. + * @since 1.0.0 RC1 * @see Something. */ diff --git a/tests/unit/fns/prepareTagDescription.test.js b/tests/unit/fns/prepareTagDescription.test.js index e91b9a4..c97807f 100644 --- a/tests/unit/fns/prepareTagDescription.test.js +++ b/tests/unit/fns/prepareTagDescription.test.js @@ -13,6 +13,17 @@ describe('prepareTagDescription', () => { name: 'something', }, }, + { + it: 'should ignore a tag that cannot be a sentence', + input: { + tag: 'since', + name: 'something', + }, + output: { + tag: 'since', + name: 'something', + }, + }, { it: 'should transform a tag description', input: { From bec8801d455ec35575717643927165718e9a3143 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 20:59:35 -0300 Subject: [PATCH 08/11] docs: update README --- README.md | 56 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4a4a40a..53a2ff9 100644 --- a/README.md +++ b/README.md @@ -1004,15 +1004,40 @@ The way you can solve this is by adding a period at the end of the line, which w ### 🤘 Development -As this project is part of the `packages` monorepo, some of the tooling, like ESLint and Husky, are installed on the root's `package.json`. - #### Tasks -| Task | Description | -| ----------- | -------------------------- | -| `test:unit` | Runs the unit tests. | -| `test:e2e` | Runs the functional tests. | -| `test` | Runs all tests. | +| Task | Description | +| ----------- | ------------------------------ | +| `test:unit` | Runs the unit tests. | +| `test:e2e` | Runs the functional tests. | +| `test` | Runs all tests. | +| `lint` | Lint the modified files. | +| `lint:all` | Lint the entire project code. | +| `todo` | List all the pending to-do's. | + +### Repository hooks + +I use [`husky`](https://www.npmjs.com/package/husky) to automatically install the repository hooks so... + +1. The code will be formatted and linted before any commit. +2. The dependencies will be updated after every merge. +3. The tests will run before pushing. + +> ⚠️ When the linter and formatter runs for staged files, if the file is importing Prettier, it may fail due to Prettier being ESM. This is temporary, and the workaround for now is to run `npm run lint:all` and commit with `-n`. + +#### Commits convention + +I use [conventional commits](https://www.conventionalcommits.org) with [`commitlint`](https://commitlint.js.org) in order to support semantic releases. The one that sets it up is actually husky, that installs a script that runs `commitlint` on the `git commit` command. + +The configuration is on the `commitlint` property of the `package.json`. + +### Releases + +I use [`semantic-release`](https://www.npmjs.com/package/semantic-release) and a GitHub action to automatically release on NPM everything that gets merged to main. + +The configuration for `semantic-release` is on `./releaserc` and the workflow for the release is on `./.github/workflow/release.yml`. + +> ⚠️ `semantic-release` requires Node 18 to be installed, so I temporarily removed it form the `package.json` and it's only installed in the GitHub action, before being used. #### Testing @@ -1022,9 +1047,18 @@ The configurations files are `.jestrc-e2e` and `.jestrc-unit`, and the test file In the case of the functional tests, there's a special environment on `./tests/utils` that loads and parses a list of fixture files in order to save them on the global object. In reality, there's only one test file for the functional tests, the one that reads the global object and dynamically generates the `it(...)`: `index.e2e.js`. -### 🐞 Validating bugs -> Yes, since this is in a monorepo (for now), I can't put this on the issue template. +### Linting && Formatting + +I use [ESlint](https://eslint.org) with [my own custom configuration](https://www.npmjs.com/package/@homer0/eslint-plugin) to validate all the JS code. The configuration file for the project code is on `./.eslintrc` and the one for the tests is on `./tests/.eslintrc`. There's also an `./.eslintignore` to exclude some files on the process. The script that runs it is on `./utils/scripts/lint-all`. + +For formatting I use [Prettier](https://prettier.io) with [my custom configuration](https://www.npmjs.com/package/@homer0/prettier-config) and this same plugin. The configuration file for the project code is on `./.prettierrc`. + +### To-Dos + +I use `@todo` comments to write all the pending improvements and fixes, and [Leasot](https://www.npmjs.com/package/leasot) to generate a report. The script that runs it is on `./utils/scripts/todo`. + +### 🐞 Validating bugs You can use the functional tests to validate a scenario in which the plugin is not behaving as you would expect. @@ -1050,7 +1084,9 @@ module.exports = { only: true, jsdocPrintWidth: 70 }; - `only: true` is not a plugin option, but will make the test runner ignore all the other tests, and only run the one you specify. - Below `//# input` you can put any number of comment blocks, in the state you would expect the plugin to pick them. - Below `//# output` you have to put the expected output after formatting the input with the plugin. -- The "input" and "output" are handled as if they were different files, so you can even put functions and real code, it won't be executed though, just formatted. +- The "input" and "output" are handled as if they were different files, so you can even put functions and real code, they won't be executed though, just formatted. + +Then, you can just run run the test for the fixture with `npm run test:e2e`. ## Motivation From 378ea6918b6b03af03a4ec39acb918e8a4de2ffb Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 21:00:50 -0300 Subject: [PATCH 09/11] style: run Prettier in the whole project --- .eslintrc | 5 +---- .github/workflows/test.yml | 2 +- src/fns/formatDescription.js | 10 +++++----- src/fns/render.js | 3 ++- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.eslintrc b/.eslintrc index 7cec6b7..6865141 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,5 @@ { "root": true, "plugins": ["@homer0"], - "extends": [ - "plugin:@homer0/node-with-prettier", - "plugin:@homer0/jsdoc" - ] + "extends": ["plugin:@homer0/node-with-prettier", "plugin:@homer0/jsdoc"] } diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1ab600e..3bfcb95 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [ '16', '18' ] + node: ['16', '18'] name: Run jest and ESLint (Node ${{ matrix.node }}) steps: - uses: actions/checkout@v3 diff --git a/src/fns/formatDescription.js b/src/fns/formatDescription.js index 8660af6..23ffe05 100644 --- a/src/fns/formatDescription.js +++ b/src/fns/formatDescription.js @@ -61,11 +61,11 @@ const findTag = R.curry((targetTag, matchHandlerFn, unmatchHandlerFn, step) => { /** * Generates a reducer handler for specific tags. * - * @param {string | string[]} descriptionProperty The property or properties that make - * the description of a tag. - * @param {boolean} saveIndex Whether or not the tag index should be - * saved as the accumulator `tagIndex` - * property. + * @param {string | string[]} descriptionProperty + * The property or properties that make the description of a tag. + * @param {boolean} saveIndex + * Whether or not the tag index should be saved as the accumulator `tagIndex` + * property. * @returns {FindTagHandlerFn} */ const processTag = (descriptionProperty, saveIndex = false) => { diff --git a/src/fns/render.js b/src/fns/render.js index a7add44..4ff2891 100644 --- a/src/fns/render.js +++ b/src/fns/render.js @@ -127,7 +127,8 @@ const renderTagsInColumns = (columnsWidth, fullWidth, options, tags) => * The options sent to the plugin. * @param {CommentTag[]} tags * The list of tags to render. - * @returns {string[]} The list of lines. + * @returns {string[]} + * The list of lines. */ const tryToRenderTagsInColums = (tagsData, width, options, tags) => R.compose( From 852caa4401dc89780b3b0b7abb6ab56bbe96fd4a Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 21:01:15 -0300 Subject: [PATCH 10/11] chore: ignore formatting on README and CHANGELOG --- .prettierignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.prettierignore b/.prettierignore index 333ac01..c0a0dac 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,3 @@ **/tests/**/fixtures +CHANGELOG.md +README.md From 4bf90e56b58c55fd74a89b87a4ebee595faf4c16 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 21 Jul 2023 21:01:46 -0300 Subject: [PATCH 11/11] chore: format everything from the lint:all script --- tests/.eslintrc | 4 +--- utils/scripts/lint-all | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/.eslintrc b/tests/.eslintrc index 59321cc..1aabab3 100644 --- a/tests/.eslintrc +++ b/tests/.eslintrc @@ -1,9 +1,7 @@ { "root": true, "plugins": ["@homer0"], - "extends": [ - "plugin:@homer0/jest-with-prettier" - ], + "extends": ["plugin:@homer0/jest-with-prettier"], "globals": { "global": true, "__dirname": true diff --git a/utils/scripts/lint-all b/utils/scripts/lint-all index 81e490e..ea6ec3d 100755 --- a/utils/scripts/lint-all +++ b/utils/scripts/lint-all @@ -1,2 +1,3 @@ #!/bin/bash -e -eslint ./ --ext .js +eslint ./ --ext .js && \ +prettier --write .