123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _commentParser = require("comment-parser");
- /**
- * Transform based on https://github.com/syavorsky/comment-parser/blob/master/src/transforms/align.ts
- *
- * It contains some customizations to align based on the tags, and some custom options.
- */
- /**
- * @typedef {{
- * hasNoTypes: boolean,
- * maxNamedTagLength: import('./iterateJsdoc.js').Integer,
- * maxUnnamedTagLength: import('./iterateJsdoc.js').Integer
- * }} TypelessInfo
- */
- const {
- rewireSource
- } = _commentParser.util;
- /**
- * @typedef {{
- * name: import('./iterateJsdoc.js').Integer,
- * start: import('./iterateJsdoc.js').Integer,
- * tag: import('./iterateJsdoc.js').Integer,
- * type: import('./iterateJsdoc.js').Integer
- * }} Width
- */
- /** @type {Width} */
- const zeroWidth = {
- name: 0,
- start: 0,
- tag: 0,
- type: 0
- };
- /**
- * @param {string[]} tags
- * @param {import('./iterateJsdoc.js').Integer} index
- * @param {import('comment-parser').Line[]} source
- * @returns {boolean}
- */
- const shouldAlign = (tags, index, source) => {
- const tag = source[index].tokens.tag.replace('@', '');
- const includesTag = tags.includes(tag);
- if (includesTag) {
- return true;
- }
- if (tag !== '') {
- return false;
- }
- for (let iterator = index; iterator >= 0; iterator--) {
- const previousTag = source[iterator].tokens.tag.replace('@', '');
- if (previousTag !== '') {
- if (tags.includes(previousTag)) {
- return true;
- }
- return false;
- }
- }
- return true;
- };
- /**
- * @param {string[]} tags
- * @returns {(
- * width: Width,
- * line: {
- * tokens: import('comment-parser').Tokens
- * },
- * index: import('./iterateJsdoc.js').Integer,
- * source: import('comment-parser').Line[]
- * ) => Width}
- */
- const getWidth = tags => {
- return (width, {
- tokens
- }, index, source) => {
- if (!shouldAlign(tags, index, source)) {
- return width;
- }
- return {
- name: Math.max(width.name, tokens.name.length),
- start: tokens.delimiter === '/**' ? tokens.start.length : width.start,
- tag: Math.max(width.tag, tokens.tag.length),
- type: Math.max(width.type, tokens.type.length)
- };
- };
- };
- /**
- * @param {{
- * description: string;
- * tags: import('comment-parser').Spec[];
- * problems: import('comment-parser').Problem[];
- * }} fields
- * @returns {TypelessInfo}
- */
- const getTypelessInfo = fields => {
- const hasNoTypes = fields.tags.every(({
- type
- }) => {
- return !type;
- });
- const maxNamedTagLength = Math.max(...fields.tags.map(({
- tag,
- name
- }) => {
- return name.length === 0 ? -1 : tag.length;
- }).filter(length => {
- return length !== -1;
- })) + 1;
- const maxUnnamedTagLength = Math.max(...fields.tags.map(({
- tag,
- name
- }) => {
- return name.length === 0 ? tag.length : -1;
- }).filter(length => {
- return length !== -1;
- })) + 1;
- return {
- hasNoTypes,
- maxNamedTagLength,
- maxUnnamedTagLength
- };
- };
- /**
- * @param {import('./iterateJsdoc.js').Integer} len
- * @returns {string}
- */
- const space = len => {
- return ''.padStart(len, ' ');
- };
- /**
- * @param {{
- * customSpacings: import('../src/rules/checkLineAlignment.js').CustomSpacings,
- * tags: string[],
- * indent: string,
- * preserveMainDescriptionPostDelimiter: boolean,
- * wrapIndent: string,
- * }} cfg
- * @returns {(
- * block: import('comment-parser').Block
- * ) => import('comment-parser').Block}
- */
- const alignTransform = ({
- customSpacings,
- tags,
- indent,
- preserveMainDescriptionPostDelimiter,
- wrapIndent
- }) => {
- let intoTags = false;
- /** @type {Width} */
- let width;
- /**
- * @param {import('comment-parser').Tokens} tokens
- * @param {TypelessInfo} typelessInfo
- * @returns {import('comment-parser').Tokens}
- */
- const alignTokens = (tokens, typelessInfo) => {
- const nothingAfter = {
- delim: false,
- name: false,
- tag: false,
- type: false
- };
- if (tokens.description === '') {
- nothingAfter.name = true;
- tokens.postName = '';
- if (tokens.name === '') {
- nothingAfter.type = true;
- tokens.postType = '';
- if (tokens.type === '') {
- nothingAfter.tag = true;
- tokens.postTag = '';
- /* istanbul ignore next: Never happens because the !intoTags return. But it's here for consistency with the original align transform */
- if (tokens.tag === '') {
- nothingAfter.delim = true;
- }
- }
- }
- }
- let untypedNameAdjustment = 0;
- let untypedTypeAdjustment = 0;
- if (typelessInfo.hasNoTypes) {
- nothingAfter.tag = true;
- tokens.postTag = '';
- if (tokens.name === '') {
- untypedNameAdjustment = typelessInfo.maxNamedTagLength - tokens.tag.length;
- } else {
- untypedNameAdjustment = typelessInfo.maxNamedTagLength > typelessInfo.maxUnnamedTagLength ? 0 : Math.max(0, typelessInfo.maxUnnamedTagLength - (tokens.tag.length + tokens.name.length + 1));
- untypedTypeAdjustment = typelessInfo.maxNamedTagLength - tokens.tag.length;
- }
- }
- // Todo: Avoid fixing alignment of blocks with multiline wrapping of type
- if (tokens.tag === '' && tokens.type) {
- return tokens;
- }
- const spacings = {
- postDelimiter: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postDelimiter) || 1,
- postName: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postName) || 1,
- postTag: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postTag) || 1,
- postType: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postType) || 1
- };
- tokens.postDelimiter = nothingAfter.delim ? '' : space(spacings.postDelimiter);
- if (!nothingAfter.tag) {
- tokens.postTag = space(width.tag - tokens.tag.length + spacings.postTag);
- }
- if (!nothingAfter.type) {
- tokens.postType = space(width.type - tokens.type.length + spacings.postType + untypedTypeAdjustment);
- }
- if (!nothingAfter.name) {
- // If post name is empty for all lines (name width 0), don't add post name spacing.
- tokens.postName = width.name === 0 ? '' : space(width.name - tokens.name.length + spacings.postName + untypedNameAdjustment);
- }
- return tokens;
- };
- /**
- * @param {import('comment-parser').Line} line
- * @param {import('./iterateJsdoc.js').Integer} index
- * @param {import('comment-parser').Line[]} source
- * @param {TypelessInfo} typelessInfo
- * @param {string|false} indentTag
- * @returns {import('comment-parser').Line}
- */
- const update = (line, index, source, typelessInfo, indentTag) => {
- /** @type {import('comment-parser').Tokens} */
- const tokens = {
- ...line.tokens
- };
- if (tokens.tag !== '') {
- intoTags = true;
- }
- const isEmpty = tokens.tag === '' && tokens.name === '' && tokens.type === '' && tokens.description === '';
- // dangling '*/'
- if (tokens.end === '*/' && isEmpty) {
- tokens.start = indent + ' ';
- return {
- ...line,
- tokens
- };
- }
- switch (tokens.delimiter) {
- case '/**':
- tokens.start = indent;
- break;
- case '*':
- tokens.start = indent + ' ';
- break;
- default:
- tokens.delimiter = '';
- // compensate delimiter
- tokens.start = indent + ' ';
- }
- if (!intoTags) {
- if (tokens.description === '') {
- tokens.postDelimiter = '';
- } else if (!preserveMainDescriptionPostDelimiter) {
- tokens.postDelimiter = ' ';
- }
- return {
- ...line,
- tokens
- };
- }
- const postHyphenSpacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postHyphen) ?? 1;
- const hyphenSpacing = /^\s*-\s+/u;
- tokens.description = tokens.description.replace(hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '));
- // Not align.
- if (shouldAlign(tags, index, source)) {
- alignTokens(tokens, typelessInfo);
- if (indentTag) {
- tokens.postDelimiter += wrapIndent;
- }
- }
- return {
- ...line,
- tokens
- };
- };
- return ({
- source,
- ...fields
- }) => {
- width = source.reduce(getWidth(tags), {
- ...zeroWidth
- });
- const typelessInfo = getTypelessInfo(fields);
- let tagIndentMode = false;
- return rewireSource({
- ...fields,
- source: source.map((line, index) => {
- const indentTag = tagIndentMode && !line.tokens.tag && line.tokens.description;
- const ret = update(line, index, source, typelessInfo, indentTag);
- if (line.tokens.tag) {
- tagIndentMode = true;
- }
- return ret;
- })
- });
- };
- };
- var _default = exports.default = alignTransform;
- module.exports = exports.default;
- //# sourceMappingURL=alignTransform.js.map
|