UNPKG

prettier-plugin-jsdoc

Version:

Prettier plugin for format comment blocks and convert to standard Match with Visual studio and other IDE which support jsdoc and comments as markdown.

230 lines (229 loc) 9.48 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatDescription = exports.descriptionEndLine = void 0; const prettier_1 = require("prettier"); const tags_1 = require("./tags"); const utils_1 = require("./utils"); const mdast_util_from_markdown_1 = __importDefault(require("mdast-util-from-markdown")); const TABLE = "2@^5!~#sdE!_TABLE"; const parserSynonyms = { js: ["babel", "babel-flow", "vue"], javascript: ["babel", "babel-flow", "vue"], ts: ["typescript", "babel-ts", "angular"], typescript: ["typescript", "babel-ts", "angular"], json: ["json", "json5", "json-stringify"], }; function descriptionEndLine({ tag, isEndTag, }) { if ([tags_1.DESCRIPTION, tags_1.EXAMPLE, tags_1.TODO].includes(tag) && !isEndTag) { return "\n"; } return ""; } exports.descriptionEndLine = descriptionEndLine; /** * Trim, make single line with capitalized text. Insert dot if flag for it is * set to true and last character is a word character * * @private */ function formatDescription(tag, text, options, formatOptions) { if (!text) return text; const { printWidth } = options; const { tagStringLength = 0, beginningSpace } = formatOptions; /** * change list with dash to dot for example: * 1- a thing * * to * * 1. a thing */ text = text.replace(/^(\d+)[-][\s|]+/g, "$1. "); // Start text = text.replace(/\n+(\s*\d+)[-][\s]+/g, "\n$1. "); const tables = []; text = text.replace(/((\n|^)\|[\s\S]*?)((\n[^|])|$)/g, (code, _1, _2, _3) => { code = _3 ? code.slice(0, -1) : code; tables.push(code); return `\n\n${TABLE}\n\n${_3 ? _3.slice(1) : ""}`; }); text = utils_1.capitalizer(text); text = `${"!".repeat(tagStringLength)}${text.startsWith("```") ? "\n" : ""}${text}`; let tableIndex = 0; const rootAst = mdast_util_from_markdown_1.default(text); function stringifyASTWithoutChildren(mdAst, intention, parent) { if (mdAst.type === "inlineCode") { return `\`${mdAst.value}\``; } if (mdAst.type === "code") { let result = mdAst.value || ""; let _intention = intention; if (result) { // Remove two space from lines, maybe added previous format if (mdAst.lang) { const supportParsers = parserSynonyms[mdAst.lang.toLowerCase()]; const parser = (supportParsers === null || supportParsers === void 0 ? void 0 : supportParsers.includes(options.parser)) ? options.parser : (supportParsers === null || supportParsers === void 0 ? void 0 : supportParsers[0]) || mdAst.lang; result = utils_1.formatCode(result, intention, { ...options, parser, jsdocKeepUnParseAbleExampleIndent: true, }); } else { _intention = intention + " ".repeat(4); result = utils_1.formatCode(result, _intention, { ...options, jsdocKeepUnParseAbleExampleIndent: true, }); } } result = mdAst.lang ? result : result.trimEnd(); return result ? mdAst.lang ? `\n\n${_intention}\`\`\`${mdAst.lang}${result}\`\`\`` : `\n${result}` : ""; } if (mdAst.value === TABLE) { if (parent) { parent.costumeType = TABLE; } if (tables.length > 0) { let result = (tables === null || tables === void 0 ? void 0 : tables[tableIndex]) || ""; tableIndex++; if (result) { result = prettier_1.format(result, { ...options, parser: "markdown", }).trim(); } return `${result ? `\n\n${intention}${result.split("\n").join(`\n${intention}`)}` : mdAst.value}`; } } if (mdAst.type === "break") { return `\\\n`; } return (mdAst.value || ""); } function stringyfy(mdAst, intention, parent) { if (!Array.isArray(mdAst.children)) { return stringifyASTWithoutChildren(mdAst, intention, parent); } return mdAst.children .map((ast, index) => { var _a; if (ast.type === "listItem") { let _listCount = `\n${intention}- `; // .replace(/((?!(^))\n)/g, "\n" + _intention); if (typeof mdAst.start === "number") { const count = index + ((_a = mdAst.start) !== null && _a !== void 0 ? _a : 1); _listCount = `\n${intention}${count}. `; } const _intention = intention + " ".repeat(_listCount.length - 1); const result = stringyfy(ast, _intention, mdAst).trim(); return `${_listCount}${result}`; } if (ast.type === "list") { let end = ""; /** * Add empty line after list if that is end of description * issue: {@link https://github.com/hosseinmd/prettier-plugin-jsdoc/issues/98} */ if (tag !== tags_1.DESCRIPTION && mdAst.type === "root" && index === mdAst.children.length - 1) { end = "\n"; } return `\n${stringyfy(ast, intention, mdAst)}${end}`; } if (ast.type === "paragraph") { const paragraph = stringyfy(ast, intention, parent); if (ast.costumeType === TABLE) { return paragraph; } return `\n\n${paragraph /** * Break by backslash\ * issue: https://github.com/hosseinmd/prettier-plugin-jsdoc/issues/102 */ .split("\\\n") .map((_paragraph) => { const links = []; // Find jsdoc links and remove spaces _paragraph = _paragraph.replace(/{@link[\s](([^{}])*)}/g, (_, link) => { links.push(link); return `{@link${"_".repeat(link.length)}}`; }); _paragraph = _paragraph.replace(/\s+/g, " "); // Make single line _paragraph = utils_1.capitalizer(_paragraph); if (options.jsdocDescriptionWithDot) _paragraph = _paragraph.replace(/([\w\p{L}])$/u, "$1."); // Insert dot if needed let result = breakDescriptionToLines(_paragraph, printWidth, intention); // Replace links result = result.replace(/{@link([_]+)}/g, (original, underline) => { const link = links[0]; if (link.length === underline.length) { links.shift(); return `{@link ${link}}`; } return original; }); return result; }) .join("\\\n")}`; } if (ast.type === "strong") { return `**${stringyfy(ast, intention, mdAst)}**`; } if (ast.type === "emphasis") { return `*${stringyfy(ast, intention, mdAst)}*`; } if (ast.type === "heading") { return `\n\n${intention}${"#".repeat(ast.depth)} ${stringyfy(ast, intention, mdAst)}`; } if (ast.type === "link") { return `[${stringyfy(ast, intention, mdAst)}](${ast.url})`; } return stringyfy(ast, intention, mdAst); }) .join(""); } let result = stringyfy(rootAst, beginningSpace, null); result = result.trimStart().slice(tagStringLength); return result; } exports.formatDescription = formatDescription; function breakDescriptionToLines(desContent, maxWidth, beginningSpace) { let str = desContent.trim(); if (!str) { return str; } const extraLastLineWidth = 10; let result = ""; while (str.length > maxWidth + extraLastLineWidth) { let sliceIndex = str.lastIndexOf(" ", str.startsWith("\n") ? maxWidth + 1 : maxWidth); /** * When a str is a long word lastIndexOf will gives 4 every time loop * running unlimited time */ if (sliceIndex <= beginningSpace.length) sliceIndex = str.indexOf(" ", beginningSpace.length + 1); if (sliceIndex === -1) sliceIndex = str.length; result += str.substring(0, sliceIndex); str = str.substring(sliceIndex + 1); if (str) { str = `${beginningSpace}${str}`; str = `\n${str}`; } } result += str; return `${beginningSpace}${result}`; }