UNPKG

@wc-toolkit/jsdoc-tags

Version:

A set of tools for retrieving and transforming data from the Custom Elements Manifest

509 lines (493 loc) 16.1 kB
// node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/primitives.js var Markers; (function(Markers2) { Markers2["start"] = "/**"; Markers2["nostart"] = "/***"; Markers2["delim"] = "*"; Markers2["end"] = "*/"; })(Markers = Markers || (Markers = {})); // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/util.js function isSpace(source) { return /^\s+$/.test(source); } function splitCR(source) { const matches = source.match(/\r+$/); return matches == null ? ["", source] : [source.slice(-matches[0].length), source.slice(0, -matches[0].length)]; } function splitSpace(source) { const matches = source.match(/^\s+/); return matches == null ? ["", source] : [source.slice(0, matches[0].length), source.slice(matches[0].length)]; } function splitLines(source) { return source.split(/\n/); } function seedSpec(spec = {}) { return Object.assign({ tag: "", name: "", type: "", optional: false, description: "", problems: [], source: [] }, spec); } function seedTokens(tokens = {}) { return Object.assign({ start: "", delimiter: "", postDelimiter: "", tag: "", postTag: "", name: "", postName: "", type: "", postType: "", description: "", end: "", lineEnd: "" }, tokens); } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/block-parser.js var reTag = /^@\S+/; function getParser({ fence = "```" } = {}) { const fencer = getFencer(fence); const toggleFence = (source, isFenced) => fencer(source) ? !isFenced : isFenced; return function parseBlock(source) { const sections = [[]]; let isFenced = false; for (const line of source) { if (reTag.test(line.tokens.description) && !isFenced) { sections.push([line]); } else { sections[sections.length - 1].push(line); } isFenced = toggleFence(line.tokens.description, isFenced); } return sections; }; } function getFencer(fence) { if (typeof fence === "string") return (source) => source.split(fence).length % 2 === 0; return fence; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/source-parser.js function getParser2({ startLine = 0, markers = Markers } = {}) { let block = null; let num = startLine; return function parseSource(source) { let rest = source; const tokens = seedTokens(); [tokens.lineEnd, rest] = splitCR(rest); [tokens.start, rest] = splitSpace(rest); if (block === null && rest.startsWith(markers.start) && !rest.startsWith(markers.nostart)) { block = []; tokens.delimiter = rest.slice(0, markers.start.length); rest = rest.slice(markers.start.length); [tokens.postDelimiter, rest] = splitSpace(rest); } if (block === null) { num++; return null; } const isClosed = rest.trimRight().endsWith(markers.end); if (tokens.delimiter === "" && rest.startsWith(markers.delim) && !rest.startsWith(markers.end)) { tokens.delimiter = markers.delim; rest = rest.slice(markers.delim.length); [tokens.postDelimiter, rest] = splitSpace(rest); } if (isClosed) { const trimmed = rest.trimRight(); tokens.end = rest.slice(trimmed.length - markers.end.length); rest = trimmed.slice(0, -markers.end.length); } tokens.description = rest; block.push({ number: num, source, tokens }); num++; if (isClosed) { const result = block.slice(); block = null; return result; } return null; }; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/spec-parser.js function getParser3({ tokenizers }) { return function parseSpec(source) { var _a; let spec = seedSpec({ source }); for (const tokenize of tokenizers) { spec = tokenize(spec); if ((_a = spec.problems[spec.problems.length - 1]) === null || _a === void 0 ? void 0 : _a.critical) break; } return spec; }; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/tag.js function tagTokenizer() { return (spec) => { const { tokens } = spec.source[0]; const match = tokens.description.match(/\s*(@(\S+))(\s*)/); if (match === null) { spec.problems.push({ code: "spec:tag:prefix", message: 'tag should start with "@" symbol', line: spec.source[0].number, critical: true }); return spec; } tokens.tag = match[1]; tokens.postTag = match[3]; tokens.description = tokens.description.slice(match[0].length); spec.tag = match[2]; return spec; }; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/type.js function typeTokenizer(spacing = "compact") { const join2 = getJoiner(spacing); return (spec) => { let curlies = 0; let lines = []; for (const [i, { tokens }] of spec.source.entries()) { let type = ""; if (i === 0 && tokens.description[0] !== "{") return spec; for (const ch of tokens.description) { if (ch === "{") curlies++; if (ch === "}") curlies--; type += ch; if (curlies === 0) break; } lines.push([tokens, type]); if (curlies === 0) break; } if (curlies !== 0) { spec.problems.push({ code: "spec:type:unpaired-curlies", message: "unpaired curlies", line: spec.source[0].number, critical: true }); return spec; } const parts = []; const offset = lines[0][0].postDelimiter.length; for (const [i, [tokens, type]] of lines.entries()) { tokens.type = type; if (i > 0) { tokens.type = tokens.postDelimiter.slice(offset) + type; tokens.postDelimiter = tokens.postDelimiter.slice(0, offset); } [tokens.postType, tokens.description] = splitSpace(tokens.description.slice(type.length)); parts.push(tokens.type); } parts[0] = parts[0].slice(1); parts[parts.length - 1] = parts[parts.length - 1].slice(0, -1); spec.type = join2(parts); return spec; }; } var trim = (x) => x.trim(); function getJoiner(spacing) { if (spacing === "compact") return (t) => t.map(trim).join(""); else if (spacing === "preserve") return (t) => t.join("\n"); else return spacing; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/name.js var isQuoted = (s) => s && s.startsWith('"') && s.endsWith('"'); function nameTokenizer() { const typeEnd = (num, { tokens }, i) => tokens.type === "" ? num : i; return (spec) => { const { tokens } = spec.source[spec.source.reduce(typeEnd, 0)]; const source = tokens.description.trimLeft(); const quotedGroups = source.split('"'); if (quotedGroups.length > 1 && quotedGroups[0] === "" && quotedGroups.length % 2 === 1) { spec.name = quotedGroups[1]; tokens.name = `"${quotedGroups[1]}"`; [tokens.postName, tokens.description] = splitSpace(source.slice(tokens.name.length)); return spec; } let brackets = 0; let name = ""; let optional = false; let defaultValue; for (const ch of source) { if (brackets === 0 && isSpace(ch)) break; if (ch === "[") brackets++; if (ch === "]") brackets--; name += ch; } if (brackets !== 0) { spec.problems.push({ code: "spec:name:unpaired-brackets", message: "unpaired brackets", line: spec.source[0].number, critical: true }); return spec; } const nameToken = name; if (name[0] === "[" && name[name.length - 1] === "]") { optional = true; name = name.slice(1, -1); const parts = name.split("="); name = parts[0].trim(); if (parts[1] !== void 0) defaultValue = parts.slice(1).join("=").trim(); if (name === "") { spec.problems.push({ code: "spec:name:empty-name", message: "empty name", line: spec.source[0].number, critical: true }); return spec; } if (defaultValue === "") { spec.problems.push({ code: "spec:name:empty-default", message: "empty default value", line: spec.source[0].number, critical: true }); return spec; } if (!isQuoted(defaultValue) && /=(?!>)/.test(defaultValue)) { spec.problems.push({ code: "spec:name:invalid-default", message: "invalid default value syntax", line: spec.source[0].number, critical: true }); return spec; } } spec.optional = optional; spec.name = name; tokens.name = nameToken; if (defaultValue !== void 0) spec.default = defaultValue; [tokens.postName, tokens.description] = splitSpace(source.slice(tokens.name.length)); return spec; }; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/tokenizers/description.js function descriptionTokenizer(spacing = "compact", markers = Markers) { const join2 = getJoiner2(spacing); return (spec) => { spec.description = join2(spec.source, markers); return spec; }; } function getJoiner2(spacing) { if (spacing === "compact") return compactJoiner; if (spacing === "preserve") return preserveJoiner; return spacing; } function compactJoiner(lines, markers = Markers) { return lines.map(({ tokens: { description } }) => description.trim()).filter((description) => description !== "").join(" "); } var lineNo = (num, { tokens }, i) => tokens.type === "" ? num : i; var getDescription = ({ tokens }) => (tokens.delimiter === "" ? tokens.start : tokens.postDelimiter.slice(1)) + tokens.description; function preserveJoiner(lines, markers = Markers) { if (lines.length === 0) return ""; if (lines[0].tokens.description === "" && lines[0].tokens.delimiter === markers.start) lines = lines.slice(1); const lastLine = lines[lines.length - 1]; if (lastLine !== void 0 && lastLine.tokens.description === "" && lastLine.tokens.end.endsWith(markers.end)) lines = lines.slice(0, -1); lines = lines.slice(lines.reduce(lineNo, 0)); return lines.map(getDescription).join("\n"); } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/parser/index.js function getParser4({ startLine = 0, fence = "```", spacing = "compact", markers = Markers, tokenizers = [ tagTokenizer(), typeTokenizer(spacing), nameTokenizer(), descriptionTokenizer(spacing) ] } = {}) { if (startLine < 0 || startLine % 1 > 0) throw new Error("Invalid startLine"); const parseSource = getParser2({ startLine, markers }); const parseBlock = getParser({ fence }); const parseSpec = getParser3({ tokenizers }); const joinDescription = getJoiner2(spacing); return function(source) { const blocks = []; for (const line of splitLines(source)) { const lines = parseSource(line); if (lines === null) continue; const sections = parseBlock(lines); const specs = sections.slice(1).map(parseSpec); blocks.push({ description: joinDescription(sections[0], markers), tags: specs, source: lines, problems: specs.reduce((acc, spec) => acc.concat(spec.problems), []) }); } return blocks; }; } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/index.js function join(tokens) { return tokens.start + tokens.delimiter + tokens.postDelimiter + tokens.tag + tokens.postTag + tokens.type + tokens.postType + tokens.name + tokens.postName + tokens.description + tokens.end + tokens.lineEnd; } function getStringifier() { return (block) => block.source.map(({ tokens }) => join(tokens)).join("\n"); } // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/stringifier/inspect.js var zeroWidth = { line: 0, start: 0, delimiter: 0, postDelimiter: 0, tag: 0, postTag: 0, name: 0, postName: 0, type: 0, postType: 0, description: 0, end: 0, lineEnd: 0 }; var fields = Object.keys(zeroWidth); // node_modules/.pnpm/comment-parser@1.4.1/node_modules/comment-parser/es6/index.js function parse(source, options = {}) { return getParser4(options)(source); } var stringify = getStringifier(); // src/logger.ts var Logger = class { #debug; constructor(debug = false) { this.#debug = debug; } log(message, color = "\x1B[30m%s\x1B[0m") { if (!this.#debug) { return; } console.log(color, message); } red(message) { this.log(message, "\x1B[31m%s\x1B[0m"); } green(message) { this.log(message, "\x1B[32m%s\x1B[0m"); } yellow(message) { this.log(message, "\x1B[33m%s\x1B[0m"); } blue(message) { this.log(message, "\x1B[34m%s\x1B[0m"); } magenta(message) { this.log(message, "\x1B[35m%s\x1B[0m"); } cyan(message) { this.log(message, "\x1B[36m%s\x1B[0m"); } }; // node_modules/.pnpm/@wc-toolkit+cem-utilities@1.0.0/node_modules/@wc-toolkit/cem-utilities/dist/index.js function deepMerge(target, source) { if (typeof target !== "object" || target === null) { return source; } if (typeof source !== "object" || source === null) { return target; } const targetObj = target; const sourceObj = source; for (const key of Object.keys(source)) { if (sourceObj[key] instanceof Array) { if (!targetObj[key]) { targetObj[key] = []; } targetObj[key] = targetObj[key].concat(sourceObj[key]); } else if (sourceObj[key] instanceof Object) { if (!targetObj[key]) { targetObj[key] = {}; } targetObj[key] = deepMerge(targetObj[key], sourceObj[key]); } else { targetObj[key] = sourceObj[key]; } } return targetObj; } // src/cem-plugin.ts var userOptions = { tags: {} }; function jsDocTagsPlugin(options = {}) { userOptions = deepMerge(userOptions, options); const log = new Logger(userOptions.debug); if (options.skip) { log.yellow("[jsdoc-tags] - Skipped"); return; } log.log("[jsdoc-tags] - Updating Custom Elements Manifest..."); return { name: "jsdoc-tags-plugin", analyzePhase(params) { parseJsDocTags(params, userOptions.tags || {}); }, packageLinkPhase: () => { log.green("[cem-expanded-types] - Custom Elements Manifest updated."); } }; } function parseJsDocTags(params, tags) { if (params.node.kind !== params.ts.SyntaxKind.ClassDeclaration) { return; } const className = params.node.name.getText(); const component = params.moduleDoc?.declarations?.find( (declaration) => declaration.name === className ); const customTags = Object.keys(tags || {}); let customComments = "/**"; params.node.jsDoc?.forEach((jsDoc) => { jsDoc?.tags?.forEach( (tag) => { const tagName = tag.tagName.getText(); if (customTags.includes(tagName)) { customComments += ` * @${tagName} ${tag.comment}`; } } ); }); const parsed = parse(`${customComments} */`); parsed[0]?.tags?.forEach((tagMeta) => { const tagOptions = tags[tagMeta.tag]; if (!tagOptions) { return; } const propName = tagOptions.mappedName || tagMeta.tag; if (!component) { return; } const existingProp = component[propName]; const cemTag = { name: tagMeta.name === "-" ? "" : tagMeta.name, default: tagMeta.default, description: tagMeta.description.replace(/^\s?-/, "").trim(), // removes leading dash type: tagMeta.type ? { text: tagMeta.type } : void 0 }; if (!existingProp && tagOptions.isArray) { component[propName] = [cemTag]; } else if (Array.isArray(component[propName])) { component[propName].push(cemTag); } else if (existingProp && !Array.isArray(component[propName])) { component[propName] = [component[propName], cemTag]; } else { component[propName] = cemTag; } }); } export { jsDocTagsPlugin, parseJsDocTags };