{"id":42222301,"url":"https://github.com/homer0/prettier-plugin-jsdoc","last_synced_at":"2026-05-18T05:17:16.698Z","repository":{"id":181995785,"uuid":"667732459","full_name":"homer0/prettier-plugin-jsdoc","owner":"homer0","description":"A Prettier plugin to format JSDoc blocks.","archived":false,"fork":false,"pushed_at":"2026-01-27T00:46:13.000Z","size":853,"stargazers_count":15,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-10T06:24:18.615Z","etag":null,"topics":["hacktoberfest","jsdoc","prettier"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/homer0.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-07-18T07:22:16.000Z","updated_at":"2026-01-27T00:46:15.000Z","dependencies_parsed_at":"2025-12-04T07:04:52.657Z","dependency_job_id":null,"html_url":"https://github.com/homer0/prettier-plugin-jsdoc","commit_stats":null,"previous_names":["homer0/prettier-plugin-jsdoc"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/homer0/prettier-plugin-jsdoc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/homer0%2Fprettier-plugin-jsdoc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/homer0%2Fprettier-plugin-jsdoc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/homer0%2Fprettier-plugin-jsdoc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/homer0%2Fprettier-plugin-jsdoc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/homer0","download_url":"https://codeload.github.com/homer0/prettier-plugin-jsdoc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/homer0%2Fprettier-plugin-jsdoc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31704584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T21:17:31.016Z","status":"online","status_checked_at":"2026-04-12T02:00:06.763Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","jsdoc","prettier"],"created_at":"2026-01-27T02:12:28.475Z","updated_at":"2026-05-18T05:17:16.689Z","avatar_url":"https://github.com/homer0.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 𝍌 JSDoc plugin for Prettier\n\n[![GitHub Workflow Status (main)](https://img.shields.io/github/actions/workflow/status/homer0/prettier-plugin-jsdoc/test.yml?branch=main\u0026style=flat-square)](https://github.com/homer0/prettier-plugin-jsdoc/actions?query=workflow%3ATest)\n[![Coveralls github](https://img.shields.io/coveralls/github/homer0/prettier-plugin-jsdoc.svg?style=flat-square)](https://coveralls.io/github/homer0/prettier-plugin-jsdoc?branch=main)\n![Dependencies status](https://img.shields.io/librariesio/release/npm/%40homer0/prettier-plugin-jsdoc/latest?style=flat-square)\n\nA [Prettier](https://prettier.io) plugin to format [JSDoc](https://jsdoc.app) blocks.\n\n## 🍿 Usage\n\n\u003e If you are wondering why I built this, go to the [Motivation](#motivation) section.\n\n- 📦 [Installation](#-Installation)\n- ⚙️ [Options](#%EF%B8%8F-options)\n- 🚫 [Ignoring blocks and ignored tags](#-ignoring-blocks-and-ignored-tags)\n- ⚡️ [Modifying the functionality](#%EF%B8%8F-modifying-the-functionality)\n- 📖 [Troubleshooting](#-troubleshooting)\n- 🤘 [Development](#-development)\n- 🐞 [Validating bugs](#-validating-bugs)\n\n### 📦 Installation\n\nFirst, please check the [official documentation](https://prettier.io/docs/plugins#using-plugins) on how plugins are used.\n\nJust to recap, and focusing in the configuration file approach, there are two ways in which you are probably going to be using this plugin:\n\n#### 1. Adding it to your existing configuration\n\nThe simplest use case: you have a configuration with your rules, and you want to add the plugin. You'd need to define the `plugins` array, if you don't have it already, and add the plugin name to it:\n\n```json\n{\n  \"tabWidth\": 90,\n  \"plugins\": [\"@homer0/prettier-plugin-jsdoc\"]\n}\n```\n\n#### 2. Extending an existing configuration and adding the plugin\n\nThis is kind of confusing in the official docs, because it's not linked in the \"using plugins\" section, but rather in the [\"using a shareable config\"](https://prettier.io/docs/sharing-configurations#using-a-shareable-config) section.\n\nUnfortunately, Prettier doesn't have a way to use and extend an existing configuration with a JSON syntax, so you have to change to a JavaScript file:\n\n```js\nimport config from '@homer0/prettier-config';\n// You may need to add the type attribute, depending on your env and the config being imported:\n//\n// import config from '@homer0/prettier-config' with { type: 'json' };\n//\n\nexport default {\n  ...config,\n  plugins: [\n    ...(config.plugins || []),\n    '@homer0/prettier-plugin-jsdoc'\n  ],\n}\n```\n\n### ⚙️ Options\n\n- [`@description` tag](#description-tag)\n  - [Allow the `@description` tag](#allow-the-description-tag)\n  - [Use the `@description` tag](#use-the-description-tag)\n- [`@example` tag](#example-tag)\n  - [Format @example tags](#format-example-tags)\n  - [Add lines around @example tags' content](#add-lines-around-example-tags-content)\n  - [Manage indentation on formatted examples](#manage-indentation-on-formatted-examples)\n  - [Manage indentation for pseudo code examples](#manage-indentation-for-pseudo-code-examples)\n- [`@access` tag](#access-tag)\n  - [Allow @access tag](#allow-access-tag)\n  - [Enforce the use of the @access tag](#enfore-the-use-of-the-access-tag)\n- [Types with string literals](#types-with-string-literals)\n  - [Format types with string literals](#format-types-with-string-literals)\n  - [Specify quotes types for string literals](#specify-quotes-types-for-string-literals)\n  - [Specify space around string literals](#specify-space-around-string-literals)\n- [TypeScript types](#typescript-types)\n  - [Use TypeScript casing for basic types](#use-typescript-casing-for-basic-types)\n  - [Format complex types with Prettier as TypeScript](#format-complex-types-with-prettier-as-typescript)\n- [Arrays and objects](#arrays-and-objects)\n  - [Transform arrays into their shorter form](#transform-arrays-into-their-shorter-form)\n  - [Modify the dot used for the generics of arrays and objects](#modify-the-dot-used-for-the-generics-of-arrays-and-objects)\n  - [Ensure the use or not of the dot for the generics of arrays and objects](#ensure-the-use-or-not-of-the-dot-for-the-generics-of-arrays-and-objects)\n- [Tags](#tags)\n  - [Replace tags synonyms](#replace-tags-synonyms)\n  - [Sort tags](#sort-tags)\n  - [Tags order](#tags-order)\n- [Rendering](#rendering)\n  - [Use columns](#use-columns)\n  - [Group columns](#group-columns)\n  - [Consistent columns](#consistent-columns)\n  - [Keep description in the same line when columns are disabled](#keep-description-in-the-same-line-when-columns-are-disabled)\n  - [Avoid small columns for descriptions](#avoid-small-columns-for-descriptions)\n  - [Tag spacing: Between tag and type](#tag-spacing-between-tag-and-type)\n  - [Tag spacing: Between type and name](#tag-spacing-between-type-and-name)\n  - [Tag spacing: Between name and description](#tag-spacing-between-name-and-description)\n  - [Space between description body and tags](#space-between-description-body-and-tags)\n  - [Make sure descriptions are valid sentences](#make-sure-descriptions-are-valid-sentences)\n  - [Allow descriptions to be on different lines](#allow-descriptions-to-be-on-different-lines)\n  - [Ignore tags for consistent columns](#ignore-tags-for-consistent-columns)\n  - [Use an inline block for a single tag](#use-an-inline-block-for-a-single-tag)\n  - [Ignore specific tags](#ignore-specific-tags)\n  - [Ignore typedef import tags](#ignore-typedef-import-tags)\n- [Extras](#extras)\n  - [Custom width](#custom-width)\n  - [Turn the plugin on and off](#turn-the-plugin-on-and-off)\n  - [Let the plugin know that it's being extended](#let-the-plugin-know-that-its-being-extended)\n- [⚠️ Experimental](#%EF%B8%8F-experimental)\n  - [Parse comments without tags](#parse-comments-without-tags)\n\n#### @description tag\n\n##### Allow the @description tag\n\n| Option                     | Type    | Default |\n| -------------------------- | ------- | ------- |\n| `jsdocAllowDescriptionTag` | boolean | `false` |\n\nWhether or not the `@description` tag can be used on JSDoc blocks. When disabled, if a `@description` tag is found, its contents will be moved to the block body:\n\n```js\n// jsdocAllowDescriptionTag: false\n\n/**\n * @typedef {Object} MyType\n * @description Lorem ipsum description.\n */\n\n// -\u003e\n\n/**\n * Lorem ipsum description.\n *\n * @typedef {Object} MyType\n */\n```\n\n##### Use the @description tag\n\n| Option                   | Type    | Default |\n| ------------------------ | ------- | ------- |\n| `jsdocUseDescriptionTag` | boolean | `false` |\n\nWhether or not to use the `@description` tag when a description is found on the block body or following a type/callback definition.\n\n```js\n// jsdocUseDescriptionTag: true\n\n/**\n * Lorem ipsum description.\n *\n * @typedef {Object} MyType\n */\n\n// -\u003e\n\n/**\n * @typedef {Object} MyType\n * @description Lorem ipsum description.\n */\n```\n\n#### @example tag\n\n##### Format @example tags\n\n| Option                | Type    | Default |\n| --------------------- | ------- | ------- |\n| `jsdocFormatExamples` | boolean | `true`  |\n\nWhether or not to attempt to format the `@example` tags using Prettier itself.\n\n```js\n// jsdocFormatExamples: true\n\n/**\n * @example\n * ensureArray([\n * 'x', 'y',\n * ])\n */\n\n// -\u003e\n\n/**\n * @example\n *\n *   ensureArray(['x', 'y'])\n */\n```\n\n##### Add lines around @example tags' content\n\n| Option                               | Type | Default |\n| ------------------------------------ | ---- | ------- |\n| `jsdocLinesBetweenExampleTagAndCode` | int  | `1`     |\n\nHow many lines should there be between an `@example` tag and its code.\n\n```js\n// jsdocLinesBetweenExampleTagAndCode: 0\n\n/**\n * @example\n * ensureArray([\n * 'x', 'y',\n * ])\n */\n\n// -\u003e\n\n/**\n * @example\n *   ensureArray(['x', 'y'])\n */\n```\n\n##### Manage indentation on formatted examples\n\n| Option                         | Type    | Default |\n| ------------------------------ | ------- | ------- |\n| `jsdocIndentFormattedExamples` | boolean | `true`  |\n\nWhether or not to add an indentation level to the code snippets of `@example` tags. The indentation space will be taken from the `tabWidth` option.\n\n```js\n// jsdocIndentFormattedExamples: false\n\n/**\n * @example\n * ensureArray([\n * 'x', 'y',\n * ])\n */\n\n// -\u003e\n\n/**\n * @example\n *\n * ensureArray(['x', 'y'])\n */\n```\n\n##### Manage indentation for pseudo code examples\n\n| Option                           | Type    | Default |\n| -------------------------------- | ------- | ------- |\n| `jsdocIndentUnformattedExamples` | boolean | `false` |\n\nWhether or not to add an indentation level to the code snippets of `@example` tags that couldn't be formatted with Prettier. This is only valid if `jsdocFormatExamples` is `true`.\n\n```js\n// jsdocIndentUnformattedExamples: true\n\n/**\n * @example\n * instance -\u003e handler -\u003e middlewares\n */\n\n// -\u003e\n\n/**\n * @example\n *\n *   instance -\u003e handler -\u003e middlewares\n */\n```\n\n#### @access tag\n\n##### Allow @access tag\n\n| Option                | Type    | Default |\n| --------------------- | ------- | ------- |\n| `jsdocAllowAccessTag` | boolean | `true`  |\n\nWhether or not the `@access` tag can be used; if `false`, when a tag is found, it will replaced with a tag of its value:\n\n```js\n// jsdocAllowAccessTag: false\n\n/**\n * @access public\n */\n\n// -\u003e\n\n/**\n * @public\n */\n```\n\n##### Enforce the use of the @access tag\n\n| Option                  | Type    | Default |\n| ----------------------- | ------- | ------- |\n| `jsdocEnforceAccessTag` | boolean | `true`  |\n\nWhether or not to transform the tags `@private`, `@public` and `@protected` into `@access [type]` tags:\n\n```js\n// jsdocEnforceAccessTag: true\n\n/**\n * @private\n */\n\n// -\u003e\n\n/**\n * @access private\n */\n```\n\n#### Types with string literals\n\n##### Format types with string literals\n\n| Option                      | Type    | Default |\n| --------------------------- | ------- | ------- |\n| `jsdocFormatStringLiterals` | boolean | `true`  |\n\nWhether or not to apply transformations to string literal types.\n\n```js\n// jsdocFormatStringLiterals: true\n\n/**\n * @type {'a'| \"b\"  |  'c'} MyType\n */\n\n// -\u003e\n\n/**\n * @type {'a' | 'b' | 'c'} MyType\n */\n```\n\n##### Specify quotes types for string literals\n\n| Option                                  | Type    | Default |\n| --------------------------------------- | ------- | ------- |\n| `jsdocUseSingleQuotesForStringLiterals` | boolean | `true`  |\n\nWhether or not to use single quotes for string literals' types.\n\n```js\n// jsdocUseSingleQuotesForStringLiterals: false\n\n/**\n * @type {'a'| \"b\"  |  'c'} MyType\n */\n\n// -\u003e\n\n/**\n * @type {\"a\" | \"b\" | \"c\"} MyType\n */\n```\n\n##### Specify space around string literals\n\n| Option                             | Type | Default |\n| ---------------------------------- | ---- | ------- |\n| `jsdocSpacesBetweenStringLiterals` | int  | `1`     |\n\nHow many spaces should there be between string literals on a type.\n\n```js\n// jsdocSpacesBetweenStringLiterals: 0\n\n/**\n * @type {'a'| \"b\"  |  'c'} MyType\n */\n\n// -\u003e\n\n/**\n * @type {'a'|'b'|'c'} MyType\n */\n```\n\n#### TypeScript types\n\n##### Use TypeScript casing for basic types\n\n| Option                          | Type    | Default |\n| ------------------------------- | ------- | ------- |\n| `jsdocUseTypeScriptTypesCasing` | boolean | `true`  |\n\nWhether or not to transform the casing of the basic types to make them compatible with TypeScript. This applies to `string`, `number`, `boolean`, `Object` and `Array`.\n\n```js\n// jsdocUseTypeScriptTypesCasing: true\n\n/**\n * @typedef {object} Person\n * @property {String}        name    ...\n * @property {Number}        age     ...\n * @property {Boolean}       single  ...\n * @property {array\u003cString\u003e} pets    ...\n */\n\n// -\u003e\n\n/**\n * @typedef {Object} Person\n * @property {string}        name    ...\n * @property {number}        age     ...\n * @property {boolean}       single  ...\n * @property {Array\u003cstring\u003e} pets    ...\n */\n```\n\n##### Format complex types with Prettier as TypeScript\n\n| Option                                | Type    | Default |\n| ------------------------------------- | ------- | ------- |\n| `jsdocFormatComplexTypesWithPrettier` | boolean | `true`  |\n\nWhether or not to format complex type definitions (compatibles with TypeScript) using Prettier.\n\n```js\n// jsdocFormatComplexTypesWithPrettier: true\n\n/**\n * @typedef {{ name:string,age:number,pets:Array\u003cstring\u003e}} Person\n */\n\n// -\u003e\n\n/**\n * @typedef {{\n *   name: string,\n *   age: number,\n *   pets: string[],\n * }} Person\n */\n```\n\n#### Arrays and objects\n\n##### Transform arrays into their shorter form\n\n| Option                | Type    | Default |\n| --------------------- | ------- | ------- |\n| `jsdocUseShortArrays` | boolean | `true`  |\n\nWhether or not to transform the type `Array\u003ctype\u003e` into `type[]` when possible. If inside the symbols there's more than a type, the transformation won't happen:\n\n```js\n// jsdocUseShortArrays: true\n\n/**\n * @typedef {Array\u003cArray\u003cstring\u003e\u003e} ListOfLists\n * @typedef {Array\u003cListOfLists\u003e} ListOfListsOfLists\n */\n\n// -\u003e\n\n/**\n * @typedef {Array\u003cstring[]\u003e} ListOfLists\n * @typedef {ListOfLists[]} ListOfListsOfLists\n */\n```\n\n##### Modify the dot used for the generics of arrays and objects\n\n| Option                              | Type    | Default |\n| ----------------------------------- | ------- | ------- |\n| `jsdocFormatDotForArraysAndObjects` | boolean | `true`  |\n\nWhether or not to apply transformations regarding the dot `Array` and `Object` types can have before their generics (`Array.\u003c...`):\n\n```js\n// jsdocFormatDotForArraysAndObjects: true\n\n/**\n * @typedef {Array\u003cArray\u003cstring\u003e\u003e} ListOfLists\n */\n\n// -\u003e\n\n/**\n * @typedef {Array.\u003cstring[]\u003e} ListOfLists\n */\n```\n\n##### Ensure the use or not of the dot for the generics of arrays and objects\n\n| Option                           | Type    | Default |\n| -------------------------------- | ------- | ------- |\n| `jsdocUseDotForArraysAndObjects` | boolean | `true`  |\n\nIf the formatting for dots is enabled, this options will specify whether the dot is added or removed.\n\n```js\n// jsdocUseDotForArraysAndObjects: false\n\n/**\n * @typedef {Array.\u003cArray.\u003cstring\u003e\u003e} ListOfLists\n */\n\n// -\u003e\n\n/**\n * @typedef {Array\u003cstring[]\u003e} ListOfLists\n */\n```\n\n#### Tags\n\n##### Replace tags synonyms\n\n| Option                     | Type    | Default |\n| -------------------------- | ------- | ------- |\n| `jsdocReplaceTagsSynonyms` | boolean | `true`  |\n\nWhether or not to replace tags synonyms with their _official_ tag.\n\n```js\n// jsdocReplaceTagsSynonyms: true\n\n/**\n * @extends Something\n * @arg {string} name  ...\n * @virtual\n * ...\n */\n\n// -\u003e\n\n/**\n * @augments Something\n * @param {string} name  ...\n * @abstract\n * ...\n */\n```\n\n##### Sort tags\n\n| Option          | Type    | Default |\n| --------------- | ------- | ------- |\n| `jsdocSortTags` | boolean | `true`  |\n\nWhether or not to sort the tags of a JSDoc block.\n\n```js\n// jsdocSortTags: true\n\n/**\n * @param {string} name  ...\n * @throws {Error} if ...\n * @callback CreatePerson\n * @returns {Person}\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string} name  ...\n * @returns {Person}\n * @throws {Error} if ...\n */\n```\n\n##### Tags order\n\n| Option           | Type  | Default                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |\n| ---------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `jsdocTagsOrder` | array | \u003cul\u003e\u003cli\u003e`type`\u003c/li\u003e\u003cli\u003e`typedef`\u003c/li\u003e\u003cli\u003e`callback`\u003c/li\u003e\u003cli\u003e`function`\u003c/li\u003e\u003cli\u003e`method`\u003c/li\u003e\u003cli\u003e`class`\u003c/li\u003e\u003cli\u003e`file`\u003c/li\u003e\u003cli\u003e`constant`\u003c/li\u003e\u003cli\u003e`description`\u003c/li\u003e\u003cli\u003e`classdesc`\u003c/li\u003e\u003cli\u003e`example`\u003c/li\u003e\u003cli\u003e`param`\u003c/li\u003e\u003cli\u003e`property`\u003c/li\u003e\u003cli\u003e`returns`\u003c/li\u003e\u003cli\u003e`template`\u003c/li\u003e\u003cli\u003e`augments`\u003c/li\u003e\u003cli\u003e`extends`\u003c/li\u003e\u003cli\u003e`throws`\u003c/li\u003e\u003cli\u003e`yields`\u003c/li\u003e\u003cli\u003e`fires`\u003c/li\u003e\u003cli\u003e`listens`\u003c/li\u003e\u003cli\u003e`async`\u003c/li\u003e\u003cli\u003e`abstract`\u003c/li\u003e\u003cli\u003e`override`\u003c/li\u003e\u003cli\u003e`private`\u003c/li\u003e\u003cli\u003e`protected`\u003c/li\u003e\u003cli\u003e`public`\u003c/li\u003e\u003cli\u003e`access`\u003c/li\u003e\u003cli\u003e`deprecated`\u003c/li\u003e\u003cli\u003e`author`\u003c/li\u003e\u003cli\u003e`version`\u003c/li\u003e\u003cli\u003e`since`\u003c/li\u003e\u003cli\u003e`member`\u003c/li\u003e\u003cli\u003e`memberof`\u003c/li\u003e\u003cli\u003e`category`\u003c/li\u003e\u003cli\u003e`external`\u003c/li\u003e\u003cli\u003e`see`\u003c/li\u003e\u003cli\u003e`other`\u003c/li\u003e\u003cli\u003e`todo`\u003c/li\u003e\u003c/ul\u003e |\n\nA list specifying the order in which the the tags of a JSDoc block should be sorted. It supports an `other` item to place tags that are not on the list.\n\n#### Rendering\n\n##### Use columns\n\n| Option            | Type    | Default |\n| ----------------- | ------- | ------- |\n| `jsdocUseColumns` | boolean | `true`  |\n\nWhether or not to try to use columns for type, name and description when possible; if `false`, the descriptions will be moved to a new line.\n\n```js\n// jsdocUseColumns: true\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} age The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @throws {Error} if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string}   name  The name of the person.\n * @param {number}   age   The age of the person.\n * @param {string[]} pets  A list of the person's pets.\n * @returns {Person}\n * @throws {Error}              if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n```\n\nThe alternative:\n\n```js\n// jsdocUseColumns: false\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} age The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @throws {Error} if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string} name\n * The name of the person.\n * @param {number} age\n * The age of the person.\n * @param {string[]} pets\n * A list of the person's pets.\n * @returns {Person}\n * @throws {Error}\n * if something goes wrong\n * @throws {AnotherTypeOfError}\n * If something else goes wrong.\n */\n```\n\n##### Group columns\n\n| Option                   | Type    | Default |\n| ------------------------ | ------- | ------- |\n| `jsdocGroupColumnsByTag` | boolean | `true`  |\n\nWhether to respect column alignment within the same tag. For example: all `@param` tags are aligned with each other, but not with all the `@throws` tags.\n\n```js\n// jsdocGroupColumnsByTag: false\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} age The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @throws {Error} if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param   {string}             name  The name of the person.\n * @param   {number}             age   The age of the person.\n * @param   {string[]}           pets  A list of the person's pets.\n * @returns {Person}\n * @throws  {Error}              if something goes wrong\n * @throws  {AnotherTypeOfError} If something else goes wrong.\n */\n```\n\n##### Consistent columns\n\n| Option                   | Type    | Default |\n| ------------------------ | ------- | ------- |\n| `jsdocConsistentColumns` | boolean | `true`  |\n\nThis is for when the columns are aligned by tags; if `true` and one tag can't use columns, no other tag will use them either.\n\n```js\n// jsdocConsistentColumns: true\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} extraLongTypeThatWillTakeTheMinSpaceForADescription The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @throws {Error} if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string} name\n * The name of the person.\n * @param {number} extraLongTypeThatWillTakeTheMinSpaceForADescription\n * The age of the person.\n * @param {string[]} pets\n * A list of the person's pets.\n * @returns {Person}\n * @throws {Error}              if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n```\n\n##### Keep description in the same line when columns are disabled\n\n| Option                          | Type    | Default |\n| ------------------------------- | ------- | ------- |\n| `jsdocDescriptionInTheSameLine` | boolean | `false` |\n\nWhether or not to try to keep the description in the same line when columns are disabled (`jsdocUseColumns: false`).\n\n```js\n// jsdocDescriptionInTheSameLine: true\n\n/**\n * @callback CreatePerson\n * @param {string} name\n * The name of the person.\n * @param {number} age\n * The age of the person.\n * @param {string[]} pets\n * A list of the person's pets.\n * @returns {Person}\n * @throws {Error}\n * if something goes wrong\n * @throws {AnotherTypeOfError}\n * If something else goes wrong.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} age The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @throws {Error} if something goes wrong\n * @throws {AnotherTypeOfError} If something else goes wrong.\n */\n```\n\n##### Avoid small columns for descriptions\n\nWhen `jsdocUseColumns: true`:\n\n| Option                            | Type | Default |\n| --------------------------------- | ---- | ------- |\n| `jsdocDescriptionColumnMinLength` | int  | `35`    |\n\nWhen `jsdocUseColumns: false` and `jsdocDescriptionInTheSameLine: true`:\n\n| Option                            | Type | Default |\n| --------------------------------- | ---- | ------- |\n| `jsdocInlineDescriptionMinLength` | int  | `35`    |\n\nWhen using columns, or when `jsdocDescriptionInTheSameLine` is enabled, this is the minimum available space the description column must have; if it's less, the description will be moved to a new line.\n\n**When columns are enabled** when a description is moved, columns will be disabled for the tag, and if consistent columns are enabled, for the entire block.\n\n\u003e Why two options for the same thing? Columns have a lot of different options and possible configurations, and I wanted the new behavior to not be attached to any of that: if columns have to be disabled, but you still need to configure a \"columns option\", it would be confusing.\n\n##### Tag spacing: Between tag and type\n\n| Option                            | Type | Default |\n| --------------------------------- | ---- | ------- |\n| `jsdocMinSpacesBetweenTagAndType` | int  | `1`     |\n\nHow many spaces should there be between a tag and a type:\n\n```\n * @[tag][\u003c--this--\u003e]{[type]} [name] [description]\n```\n\n##### Tag spacing: Between type and name\n\n| Option                             | Type | Default |\n| ---------------------------------- | ---- | ------- |\n| `jsdocMinSpacesBetweenTypeAndName` | int  | `1`     |\n\nHow many spaces should there be between a type and a name:\n\n```\n * @[tag] {[type]}[\u003c--this--\u003e][name] [description]\n```\n\n##### Tag spacing: Between name and description\n\n| Option                                    | Type | Default |\n| ----------------------------------------- | ---- | ------- |\n| `jsdocMinSpacesBetweenNameAndDescription` | int  | `2`     |\n\nHow many spaces should there be between a name and a description column.\n\n```\n * @[tag] {[type]} [name][\u003c--this--\u003e][description]\n```\n\n##### Space between description body and tags\n\n| Option                                | Type | Default |\n| ------------------------------------- | ---- | ------- |\n| `jsdocLinesBetweenDescriptionAndTags` | int  | `1`     |\n\nHow many lines should there be between a description body and the tags.\n\n```js\n// jsdocLinesBetweenDescriptionAndTags: 1\n\n/**\n * My type description.\n * @typedef {Object} MyType\n */\n\n// -\u003e\n\n/**\n * My type description.\n *\n * @typedef {Object} MyType\n */\n```\n\n##### Make sure descriptions are valid sentences\n\n| Option                                | Type    | Default |\n| ------------------------------------- | ------- | ------- |\n| `jsdocEnsureDescriptionsAreSentences` | boolean | `true`  |\n\nIf enabled, it will make sure descriptions start with an upper case letter and end with a period.\n\n```js\n// jsdocEnsureDescriptionsAreSentences: true\n\n/**\n * my type description\n *\n * @typedef {Object} MyType\n */\n\n// -\u003e\n\n/**\n * My type description.\n *\n * @typedef {Object} MyType\n */\n```\n\n##### Allow descriptions to be on different lines\n\n| Option                                   | Type  | Default                                                                                                                                                         |\n| ---------------------------------------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `jsdocAllowDescriptionOnNewLinesForTags` | array | \u003cul\u003e\u003cli\u003e`classdesc`\u003c/li\u003e\u003cli\u003e`license`\u003c/li\u003e\u003cli\u003e`desc`\u003c/li\u003e\u003cli\u003e`description`\u003c/li\u003e\u003cli\u003e`file`\u003c/li\u003e\u003cli\u003e`fileoverview`\u003c/li\u003e\u003cli\u003e`overview`\u003c/li\u003e\u003cli\u003e`summary`\u003c/li\u003e\u003c/ul\u003e |\n\nA list of tags that are allowed to have their description on a new line.\n\n```js\n// jsdocUseColumns: true\n\n/**\n * @callback CreatePerson\n * @param {string} name The name of the person.\n * @param {number} age The age of the person.\n * @param {string[]} pets A list of the person's pets.\n * @returns {Person}\n * @license\n * Some license.\n */\n\n// -\u003e\n\n/**\n * @callback CreatePerson\n * @param {string}   name  The name of the person.\n * @param {number}   age   The age of the person.\n * @param {string[]} pets  A list of the person's pets.\n * @returns {Person}\n * @license\n * Some license.\n */\n```\n\n##### Ignore tags for consistent columns\n\n| Option                                               | Type    | Default |\n| ---------------------------------------------------- | ------- | ------- |\n| `jsdocIgnoreNewLineDescriptionsForConsistentColumns` | boolean | `true`  |\n\nIf enabled, when evaluating the rule for consistent columns, tags with description on a new line, allowed by `jsdocAllowDescriptionOnNewLinesForTags`, will be ignored.\n\n##### Use an inline block for a single tag\n\n| Option                                    | Type    | Default |\n| ----------------------------------------- | ------- | ------- |\n| `jsdocUseInlineCommentForASingleTagBlock` | boolean | `false` |\n\nWhether or not to use a single line JSDoc block when there\\'s only one tag.\n\n```js\n// jsdocUseInlineCommentForASingleTagBlock: true\n\n/**\n * @type {string}\n */\n\n// -\u003e\n\n/** @type {string} */\n```\n\n##### Ignore specific tags\n\n| Option            | Type  | Default |\n| ----------------- | ----- | ------- |\n| `jsdocIgnoreTags` | array | _empty_ |\n\nA list of tags that should be ignored when formatting JSDoc comments.\n\n#### Ignore typedef import tags\n\n| Option                           | Type    | Default |\n| -------------------------------- | ------- | ------- |\n| `jsdocIgnoreTypedefImports`      | boolean | `false`  |\n\nUnder certain environments, changing the rendering of `@typedef` tags that use `import(...)` can cause types to break, and adding `typedef` to `jsdocIgnoreTags` is not a great solution, as it would take away formatting for ALL `@typedef` tags.\n\n#### Extras\n\n##### Custom width\n\n| Option            | Type | Default                 |\n| ----------------- | ---- | ----------------------- |\n| `jsdocPrintWidth` | int  | `0` (uses `printWidth`) |\n\nThis is an override for the `printWidth` option, in case the length of the documentation lines needs to be different.\n\n##### Turn the plugin on and off\n\n| Option               | Type    | Default |\n| -------------------- | ------- | ------- |\n| `jsdocPluginEnabled` | boolean | `true`  |\n\nWhether or not the plugin will parse and transform JSDoc blocks.\n\n##### Let the plugin know that it's being extended\n\n| Option                | Type    | Default |\n| --------------------- | ------- | ------- |\n| `jsdocPluginExtended` | boolean | `false` |\n\nThis will prevent the plugin from running from the original package. The idea is for it to be enabled when the plugin is being extended on the implementation.\n\n#### ⚠️ Experimental\n\n##### Parse comments without tags\n\n| Option                                       | Type    | Default |\n| -------------------------------------------- | ------- | ------- |\n| `jsdocExperimentalFormatCommentsWithoutTags` | boolean | `false` |\n\nBy default, the plugin will only parse comments with tags. Use this option, at your own risk, if you want to format blocks without tags.\n\n##### Ignore inline blocks for comments without tags\n\n| Option                                                | Type    | Default |\n| ----------------------------------------------------- | ------- | ------- |\n| `jsdocExperimentalIgnoreInlineForCommentsWithoutTags` | boolean | `false` |\n\nWhether or not to ignore the `jsdocUseInlineCommentForASingleTagBlock` option for comments without tags (when `jsdocExperimentalFormatCommentsWithoutTags` is enabled).\n\n### 🚫 Ignoring blocks and ignored tags\n\nIf you have some blocks where you don't the plugin to make any modification, you can add the `@prettierignore` tag and it/they will be skipped:\n\n```js\n/**\n * @type {Array\u003cSomething\u003e}\n * @prettierignore\n */\n```\n\nAnd while there's an option to ignore specific tags ([`jsdocIgnoreTags`](#ignore-specific-tags)), the plugin also ignores some _non-standard_ tags by default, as changing in their formatting could affect things outside styling.\n\nHere's the list of tags that are ignored by default:\n\n- [`@import`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#the-jsdoc-import-tag)\n\n### ⚡️ Modifying the functionality\n\nWhile the plugin has enough options to cover most of the common cases, if you find that it doesn't handle some edge case and you don't think it would be a good idea to send a PR, you can easily modify the plugin functionality without having to fork/clone the original repository.\n\nThe entire plugin is (mostly) built around tiny functions inside a dependency injection container, so you could take the container and replace the function you want to modify.\n\nFirst, we have to enable the option `jsdocPluginExtended`, as it will prevent it from running from the original package, and create a JS file to work:\n\n`.prettierrc`:\n\n```json\n{\n  \"jsdocPluginExtended\": true,\n  \"plugins\": [\"./my-jsdoc-plugin.js\"]\n}\n```\n\nNow, on our JS file, we'll add the following snippet:\n\n```js\nimport { get, override } from '@homer0/prettier-plugin-jsdoc/src/fns/app.js';\nimport { loadFns } from '@homer0/prettier-plugin-jsdoc/src/loader.js';\nimport { getPlugin } from '@homer0/prettier-plugin-jsdoc/src/fns/getPlugin.js';\n\nloadFns();\n\nexport default get(getPlugin)();\n```\n\nThat's all that's needed in order to setup the plugin:\n\n1. `get` is the access to the dependency injection container, you pass the reference of an original function and it will return either the function or an override.\n2. `loadFns` is a utility function that `import`s all the functions of the plugin and loads them on the dependency injection container.\n3. `getPlugin` basically connects all the functions and returns the plugin definition.\n\nAfter that, to modify a function, we need to import the original and use `override` before the call to `getPlugin`.\n\nLet's say you want to add the synonym `params` to `param` (if the plugin finds `@params` it will be converted to `@param`):\n\n```js\nimport { get, override } from '@homer0/prettier-plugin-jsdoc/src/fns/app.js';\nimport { loadFns } from '@homer0/prettier-plugin-jsdoc/src/loader.js';\nimport { getPlugin } from '@homer0/prettier-plugin-jsdoc/src/fns/getPlugin.js';\n// + We add the `require` for the original function.\nimport { getTagsSynonyms } from '@homer0/prettier-plugin-jsdoc/src/fns/constants.js';\n\nloadFns();\n\n// + We create a custom `getTagsSynonyms`.\nconst customGetTagsSynonyms = () =\u003e ({\n  ...getTagsSynonyms(),\n  params: 'param',\n});\n\n// + We override the function on the container.\noverride(getTagsSynonyms, customGetTagsSynonyms);\n\nexport default get(getPlugin)();\n```\n\nThat's all, the plugin was successfully extended 🎉!\n\n### 📖 Troubleshooting\n\n#### Forcing new lines in paragraphs and lists\n\nWhen writing multiple paragraphs or markdown lists, you might want to force new lines to be respected, for example:\n\n```js\n/**\n * First paragraph\n * Second paragraph\n *\n * @type {Something}\n */\n\n/**\n * A list:\n *\n * - First item\n * - Second item\n *\n * @type {Something}\n */\n```\n\nThe problem is that the plugin will end up putting those lines together, as it will assume that they are all part of the same paragraph:\n\n```js\n/**\n * First paragraph Second paragraph\n *\n * @type {Something}\n */\n\n/**\n * A list:\n *\n * - First item - Second item\n *\n * @type {Something}\n */\n```\n\nIt may look like a bug, but this is actually the functionality that formats the the descriptions in order to respect the [`printWidth`/`jsdocPrintWidth`](#custom-width) option.\n\nThe way you can solve this is by adding a period at the end of the line, which will tell the plugin that you ended the sentence and that it should respect the line break\n\n```js\n/**\n * First paragraph.\n * Second paragraph.\n *\n * @type {Something}\n */\n\n/**\n * A list:\n *\n * - First item.\n * - Second item.\n *\n * @type {Something}\n */\n```\n\n### 🤘 Development\n\n#### Tasks\n\n| Task        | Description                    |\n| ----------- | ------------------------------ |\n| `test:unit` | Runs the unit tests.           |\n| `test:e2e`  | Runs the functional tests.     |\n| `test`      | Runs all tests.                |\n| `lint`      | Lint the modified files.       |\n| `lint:all`  | Lint the entire project code.  |\n| `todo`      | List all the pending to-do's.  |\n\n### Repository hooks\n\nI use [`husky`](https://www.npmjs.com/package/husky) to automatically install the repository hooks so...\n\n1. The code will be formatted and linted before any commit.\n2. The dependencies will be updated after every merge.\n3. The tests will run before pushing.\n\n\u003e ⚠️ 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 `pnpm run lint:all` and commit with `-n`.\n\n#### Commits convention\n\nI 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.\n\nThe configuration is on the `commitlint` property of the `package.json`.\n\n### Releases\n\nI 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.\n\nThe configuration for `semantic-release` is on `./releaserc` and the workflow for the release is on `./.github/workflow/release.yml`.\n\n\u003e ⚠️ `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.\n\n#### Testing\n\nI use [Vitest](https://vitest.dev/) to test the project, both with unit tests and functional tests.\n\nThe configurations files are `vitest.e2e.config` and `vitest.unit.config`, and the test files are located on `/tests`.\n\nIn 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`.\n\n\n### Linting \u0026\u0026 Formatting\n\nI 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 `./eslint.config.js`. The script that runs it is on `./utils/scripts/lint-all`.\n\nFor formatting I use [Prettier](https://prettier.io) with [my custom configuration](https://www.npmjs.com/package/@homer0/prettier-config), and this plugin. The configuration file for the project code is on `./.prettierrc.js`.\n\n### To-Dos\n\nI 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`.\n\n### 🐞 Validating bugs\n\nYou can use the functional tests to validate a scenario in which the plugin is not behaving as you would expect.\n\nCreate a file `issue.fixture.js` in `./tests/e2e/fixtures` and add the following code:\n\n```js\nmodule.exports = { only: true, jsdocPrintWidth: 70 };\n\n//# input\n\n/**\n * @template{Something} [something]\n */\n\n//# output\n\n/**\n * @template {Something} [something]\n */\n```\n\n- The `module.exports` defines the plugin options for that specific case. And yes, even though this is now an ESM only project, the fixtures still use `module.exports` for the options, and that's fine, because they are not modules.\n- `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.\n- Below `//# input` you can put any number of comment blocks, in the state you would expect the plugin to pick them.\n- Below `//# output` you have to put the expected output after formatting the input with the plugin.\n- 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.\n\nThen, you can just run run the test for the fixture with `pnpm run test:e2e`.\n\n## Motivation\n\nLet's start with the fact that I really like the functionality of Prettier, but I really dislike their philosophy. I understand what they are trying to achieve, and it makes sense, but \"just use it the way I tell you to\" doesn't seem like a valid solution to me.\n\nOk, they won't accept options requests? that's perfect, it doesn't make sense to just add _\"one more\"_... but it would be great if it could be open to be extended, but the only way to do that is with a plugin, which means an extra parsing.\n\nEnough rant; I started using Prettier a couple of weeks ago and being a huge fan of JSDoc, I wanted to use it to format JSDoc blocks too, something I've doing using a Node script that I was trying to make into a VSCode plugin :P.\n\nI found [prettier-plugin-jsdoc](https://github.com/hosseinmd/prettier-plugin-jsdoc/) by [@hosseinmd](https://github.com/hosseinmd), but it (currently) doesn't cover most of the cases I wanted (like columns creations), it's written in TypeScript (which I don't like very much) and if I were to fork and send PRs, it could've taken forever (you can see the commits for this package), also, it seemed like the perfect opportunity to try [Ramda](https://ramdajs.com) and functional programming... so I started a new one.\n\n\u003e 5 years later...\n\u003e\n\u003e - HUGE fan of TypeScript, for a couple of years now.\n\u003e - I hate reading the Ramda code in here.\n\u003e - Still hate Prettier philosophy.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhomer0%2Fprettier-plugin-jsdoc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhomer0%2Fprettier-plugin-jsdoc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhomer0%2Fprettier-plugin-jsdoc/lists"}