UNPKG

@compodoc/compodoc

Version:

The missing documentation tool for your Angular application

1,417 lines 2.28 MB
const require_logger = require("./logger-BY80-2wN.js"); let fs_extra = require("fs-extra"); fs_extra = require_logger.__toESM(fs_extra); let node_path = require("node:path"); node_path = require_logger.__toESM(node_path); let path = require("path"); path = require_logger.__toESM(path); let ts_morph = require("ts-morph"); let typescript = require("typescript"); typescript = require_logger.__toESM(typescript); let semver = require("semver"); semver = require_logger.__toESM(semver); let json5 = require("json5"); json5 = require_logger.__toESM(json5); let html_entities = require("html-entities"); let cheerio = require("cheerio"); cheerio = require_logger.__toESM(cheerio); let uuid = require("uuid"); let child_process = require("child_process"); let node_os = require("node:os"); node_os = require_logger.__toESM(node_os); let fs = require("fs"); fs = require_logger.__toESM(fs); let os = require("os"); os = require_logger.__toESM(os); let cosmiconfig = require("cosmiconfig"); //#region src/utils/collection.util.ts function getByPath(source, path) { if (source == null) return; return String(path).split(".").reduce((value, key) => value == null ? void 0 : value[key], source); } function toIteratee(iteratee) { if (typeof iteratee === "function") return iteratee; return (item) => getByPath(item, iteratee); } function toPredicate(predicate) { if (typeof predicate === "function") return predicate; if (Array.isArray(predicate)) { const [key, value] = predicate; return (item) => isEqual(getByPath(item, key), value); } return (item) => { for (const key of Object.keys(predicate)) if (!isEqual(item[key], predicate[key])) return false; return true; }; } function compareValues(a, b) { if (a === b) return 0; if (a == null) return 1; if (b == null) return -1; return a > b ? 1 : -1; } function hasOwn(source, key) { return Object.keys(source).indexOf(key) !== -1; } function isArrayLike(collection) { return collection && typeof collection !== "function" && typeof collection.length === "number"; } function toArray(collection) { if (!collection) return []; if (Array.isArray(collection)) return collection; if (isArrayLike(collection)) return Array.prototype.slice.call(collection); return Object.keys(collection).map((key) => collection[key]); } function forEach(collection, iteratee) { if (!collection) return; if (isArrayLike(collection)) { for (let index = 0; index < collection.length; index++) iteratee(collection[index], index, collection); return; } for (const key of Object.keys(collection)) iteratee(collection[key], key, collection); } function sortBy(collection, iteratees) { const selectors = (Array.isArray(iteratees) ? iteratees : [iteratees]).map(toIteratee); return toArray(collection).map((item, index) => ({ item, index })).sort((a, b) => { for (const selector of selectors) { const comparison = compareValues(selector(a.item), selector(b.item)); if (comparison !== 0) return comparison; } return a.index - b.index; }).map((entry) => entry.item); } function find(collection, predicate) { return toArray(collection).find(toPredicate(predicate)); } function findIndex(collection, predicate) { return toArray(collection).findIndex(toPredicate(predicate)); } function filter(collection, predicate) { return toArray(collection).filter(toPredicate(predicate)); } function map(collection, iteratee) { return toArray(collection).map(iteratee); } function includes(collection, value) { return collection == null ? false : collection.includes(value); } function indexOf(collection, value) { return collection == null ? -1 : collection.indexOf(value); } function concat(...arrays) { return [].concat(...arrays.filter((array) => array != null)); } function slice(collection, start, end) { return Array.prototype.slice.call(collection, start, end); } function flatMap(collection, iteratee) { return concat(...toArray(collection).map(iteratee)); } function clone(value) { if (Array.isArray(value)) return value.slice(); if (value && typeof value === "object") return Object.assign(Object.create(Object.getPrototypeOf(value)), value); return value; } function cloneDeep(value, seen = /* @__PURE__ */ new WeakMap()) { if (value == null || typeof value !== "object") return value; if (seen.has(value)) return seen.get(value); if (value instanceof Date) return new Date(value.getTime()); if (value instanceof RegExp) return new RegExp(value.source, value.flags); if (Array.isArray(value)) { const result = []; seen.set(value, result); value.forEach((item, index) => { result[index] = cloneDeep(item, seen); }); return result; } const result = Object.create(Object.getPrototypeOf(value)); seen.set(value, result); for (const key of Object.keys(value)) result[key] = cloneDeep(value[key], seen); return result; } function isEqual(a, b, seen = /* @__PURE__ */ new WeakMap()) { if (Object.is(a, b)) return true; if (a == null || b == null || typeof a !== "object" || typeof b !== "object") return false; const knownMatches = seen.get(a); if (knownMatches?.has(b)) return true; if (knownMatches) knownMatches.add(b); else seen.set(a, new WeakSet([b])); if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime(); if (a instanceof RegExp || b instanceof RegExp) return a instanceof RegExp && b instanceof RegExp && String(a) === String(b); if (Array.isArray(a) || Array.isArray(b)) { if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false; return a.every((item, index) => isEqual(item, b[index], seen)); } const keysA = Object.keys(a); const keysB = Object.keys(b); if (keysA.length !== keysB.length) return false; for (const key of keysA) if (!hasOwn(b, key) || !isEqual(a[key], b[key], seen)) return false; return true; } function uniq(collection) { return Array.from(new Set(toArray(collection))); } function uniqWith(collection, comparator) { const result = []; for (const item of toArray(collection)) if (!result.some((existing) => comparator(item, existing))) result.push(item); return result; } function groupBy(collection, iteratee) { const selector = toIteratee(iteratee); return toArray(collection).reduce((groups, item) => { const key = String(selector(item)); groups[key] = groups[key] || []; groups[key].push(item); return groups; }, {}); } var Chain = class { constructor(collection) { this.collection = collection; } filter(predicate) { this.collection = filter(this.collection, predicate); return this; } groupBy(iteratee) { this.collection = groupBy(this.collection, iteratee); return this; } values() { const source = this.collection || {}; this.collection = Object.keys(source).map((key) => source[key]); return this; } map(iteratee) { this.collection = map(this.collection, iteratee); return this; } value() { return this.collection; } }; function chain(collection) { return new Chain(collection || []); } //#endregion //#region src/utils/defaults.ts const COMPODOC_DEFAULTS = { title: "Application documentation", additionalEntryName: "Additional documentation", additionalEntryPath: "additional-documentation", folder: "./documentation/", hostname: "127.0.0.1", port: 8080, theme: "gitbook", exportFormat: "html", exportFormatsSupported: [ "html", "json", "llm-md" ], base: "/", defaultCoverageThreshold: 70, defaultCoverageMinimumPerFile: 0, coverageTestThresholdFail: true, toggleMenuItems: ["all"], navTabConfig: [], disableSearch: false, disableSourceCode: false, disableDomTree: false, disableTemplateTab: false, disableStyleTab: false, disableGraph: false, disableMainGraph: false, disableCoverage: false, disablePrivate: false, disableProtected: false, disableInternal: false, disableLifeCycleHooks: false, disableConstructors: false, disableRoutesGraph: false, disableDependencies: false, disableProperties: false, disableFilePath: false, disableOverview: false, hideGenerator: false, hideDarkModeToggle: false, minimal: false, silent: false, serve: false, watch: false, PAGE_TYPES: { ROOT: "root", INTERNAL: "internal" }, gaSite: "auto", coverageTestShowOnlyFailed: false, language: "en-US", maxSearchResults: 15 }; var configuration_default = class Configuration { constructor() { this._pages = []; this._mainData = { output: COMPODOC_DEFAULTS.folder, theme: COMPODOC_DEFAULTS.theme, extTheme: "", serve: false, templatePlayground: false, hostname: COMPODOC_DEFAULTS.hostname, host: "", port: COMPODOC_DEFAULTS.port, open: false, assetsFolder: "", documentationMainName: COMPODOC_DEFAULTS.title, documentationMainDescription: "", base: COMPODOC_DEFAULTS.base, hideGenerator: false, hideDarkModeToggle: false, hasFilesToCoverage: false, modules: [], readme: false, changelog: "", contributing: "", license: "", todo: "", markdowns: [], additionalPages: [], pipes: [], classes: [], interfaces: [], components: [], controllers: [], entities: [], directives: [], injectables: [], interceptors: [], guards: [], miscellaneous: [], routes: [], tsconfig: "", toggleMenuItems: COMPODOC_DEFAULTS.toggleMenuItems, navTabConfig: [], templates: "", includes: "", includesName: COMPODOC_DEFAULTS.additionalEntryName, includesFolder: COMPODOC_DEFAULTS.additionalEntryPath, disableSourceCode: COMPODOC_DEFAULTS.disableSourceCode, disableDomTree: COMPODOC_DEFAULTS.disableDomTree, disableTemplateTab: COMPODOC_DEFAULTS.disableTemplateTab, disableStyleTab: COMPODOC_DEFAULTS.disableStyleTab, disableGraph: COMPODOC_DEFAULTS.disableGraph, disableMainGraph: COMPODOC_DEFAULTS.disableMainGraph, disableCoverage: COMPODOC_DEFAULTS.disableCoverage, disablePrivate: COMPODOC_DEFAULTS.disablePrivate, disableInternal: COMPODOC_DEFAULTS.disableInternal, disableProtected: COMPODOC_DEFAULTS.disableProtected, disableLifeCycleHooks: COMPODOC_DEFAULTS.disableLifeCycleHooks, disableConstructors: COMPODOC_DEFAULTS.disableConstructors, disableRoutesGraph: COMPODOC_DEFAULTS.disableRoutesGraph, disableSearch: false, disableDependencies: COMPODOC_DEFAULTS.disableDependencies, disableProperties: COMPODOC_DEFAULTS.disableProperties, disableFilePath: COMPODOC_DEFAULTS.disableFilePath, disableOverview: COMPODOC_DEFAULTS.disableOverview, watch: false, mainGraph: "", dependencyGraph: { nodes: [], edges: [] }, dependencyGraphSerialized: "{\"nodes\":[],\"edges\":[]}", coverageTest: false, coverageTestThreshold: COMPODOC_DEFAULTS.defaultCoverageThreshold, coverageTestThresholdFail: COMPODOC_DEFAULTS.coverageTestThresholdFail, coverageTestPerFile: false, coverageMinimumPerFile: COMPODOC_DEFAULTS.defaultCoverageMinimumPerFile, coverageExclude: [], unitTestCoverage: "", unitTestData: void 0, coverageTestShowOnlyFailed: COMPODOC_DEFAULTS.coverageTestShowOnlyFailed, routesLength: 0, angularVersion: "", exportFormat: COMPODOC_DEFAULTS.exportFormat, coverageData: {}, customFavicon: "", customLogo: "", packageDependencies: [], packagePeerDependencies: [], packageProperties: {}, gaID: "", gaSite: "", angularProject: false, angularJSProject: false, language: COMPODOC_DEFAULTS.language, maxSearchResults: 15, publicApiOnly: "", publicApiExports: /* @__PURE__ */ new Map(), outputProvided: false }; } static getInstance() { if (!Configuration.instance) Configuration.instance = new Configuration(); return Configuration.instance; } addPage(page) { if (findIndex(this._pages, { name: page.name, path: page.path }) === -1) this._pages.push(page); } hasPage(name) { return findIndex(this._pages, { name }) !== -1; } addAdditionalPage(page) { this._mainData.additionalPages.push(page); } getAdditionalPageById(id) { return this._mainData.additionalPages.find((page) => page.id === id); } resetPages() { this._pages = []; } resetAdditionalPages() { this._mainData.additionalPages = []; } resetRootMarkdownPages() { let indexPage = findIndex(this._pages, { name: "index" }); this._pages.splice(indexPage, 1); indexPage = findIndex(this._pages, { name: "changelog" }); this._pages.splice(indexPage, 1); indexPage = findIndex(this._pages, { name: "contributing" }); this._pages.splice(indexPage, 1); indexPage = findIndex(this._pages, { name: "license" }); this._pages.splice(indexPage, 1); indexPage = findIndex(this._pages, { name: "todo" }); this._pages.splice(indexPage, 1); this._mainData.markdowns = []; } get pages() { return this._pages; } set pages(pages) { this._pages = []; } get markDownPages() { return this._pages.filter((page) => page.markdown); } get mainData() { return this._mainData; } set mainData(data) { Object.assign(this._mainData, data); } }.getInstance(); //#endregion //#region src/utils/angular-api.util.ts let apiListPath = "../src/data/api-list.json"; try { require.resolve(apiListPath); } catch (e) { apiListPath = path.join(process.cwd(), "src/data/api-list.json"); } const AngularAPIs = require(apiListPath); var angular_api_util_default = class AngularApiUtil { constructor() {} static getInstance() { if (!AngularApiUtil.instance) AngularApiUtil.instance = new AngularApiUtil(); return AngularApiUtil.instance; } findApi(type) { let foundedApi; forEach(AngularAPIs, (mainApi) => { forEach(mainApi.items, (api) => { if (api.title === type) foundedApi = api; }); }); return { source: "external", data: foundedApi, score: foundedApi ? 1 : 0 }; } }.getInstance(); //#endregion //#region src/utils/link-parser.ts function extractLeadingText(string, completeTag) { let tagIndex = string.indexOf(completeTag); let leadingText = void 0; let leadingTextRegExp = /\[(.+?)\]/g; let leadingTextInfo = leadingTextRegExp.exec(string); while (leadingTextInfo && leadingTextInfo.length) { if (leadingTextInfo.index + leadingTextInfo[0].length === tagIndex) { string = string.replace(leadingTextInfo[0], ""); leadingText = leadingTextInfo[1]; break; } leadingTextInfo = leadingTextRegExp.exec(string); } return { leadingText, string }; } function splitLinkText(text) { let linkText; let target; let splitIndex; splitIndex = text.indexOf("|"); if (splitIndex === -1) splitIndex = text.search(/\s/); if (splitIndex !== -1) { linkText = text.substr(splitIndex + 1); linkText = linkText.replace(/\n+/, " "); target = text.substr(0, splitIndex); } return { linkText, target: target || text }; } let LinkParser = (function() { let processTheLink = function(string, tagInfo, leadingText) { let leading = extractLeadingText(string, tagInfo.completeTag), linkText, split, target, stringtoReplace; linkText = leadingText ? leadingText : leading.leadingText || ""; split = splitLinkText(tagInfo.text); target = split.target; if (leading.leadingText !== void 0) stringtoReplace = "[" + leading.leadingText + "]" + tagInfo.completeTag; else if (typeof split.linkText !== "undefined") { stringtoReplace = tagInfo.completeTag; linkText = split.linkText; } if (linkText === "" || linkText == null || target == null) return string; return string.replace(stringtoReplace, "[" + linkText + "](" + target + ")"); }; /** * Convert * {@link http://www.google.com|Google} or {@link https://github.com GitHub} or [Github]{@link https://github.com} to [Github](https://github.com) */ let replaceLinkTag = function(str) { if (typeof str === "undefined") return { newString: "" }; let tagRegExpLight = /* @__PURE__ */ new RegExp("\\{@link\\s+((?:.|\n)+?)\\}", "i"), tagRegExpFull = /* @__PURE__ */ new RegExp("\\{@link\\s+((?:.|\n)+?)\\}", "i"), tagRegExp, matches, previousString, tagInfo = []; tagRegExp = str.indexOf("]{") !== -1 ? tagRegExpFull : tagRegExpLight; function replaceMatch(replacer, tag, match, text, linkText) { let matchedTag = { completeTag: match, tag, text }; tagInfo.push(matchedTag); if (linkText) return replacer(str, matchedTag, linkText); else return replacer(str, matchedTag); } do { matches = tagRegExp.exec(str); if (matches) { previousString = str; if (matches.length === 2) str = replaceMatch(processTheLink, "link", matches[0], matches[1]); if (matches.length === 3) str = replaceMatch(processTheLink, "link", matches[0], matches[2], matches[1]); } } while (matches && previousString !== str); return { newString: str }; }; let _resolveLinks = function(str) { return replaceLinkTag(str).newString; }; return { resolveLinks: _resolveLinks }; })(); //#endregion //#region src/utils/angular-lifecycles-hooks.ts let AngularLifecycleHooks = /* @__PURE__ */ function(AngularLifecycleHooks) { AngularLifecycleHooks[AngularLifecycleHooks["ngOnChanges"] = 0] = "ngOnChanges"; AngularLifecycleHooks[AngularLifecycleHooks["ngOnInit"] = 1] = "ngOnInit"; AngularLifecycleHooks[AngularLifecycleHooks["ngDoCheck"] = 2] = "ngDoCheck"; AngularLifecycleHooks[AngularLifecycleHooks["ngAfterContentInit"] = 3] = "ngAfterContentInit"; AngularLifecycleHooks[AngularLifecycleHooks["ngAfterContentChecked"] = 4] = "ngAfterContentChecked"; AngularLifecycleHooks[AngularLifecycleHooks["ngAfterViewInit"] = 5] = "ngAfterViewInit"; AngularLifecycleHooks[AngularLifecycleHooks["ngAfterViewChecked"] = 6] = "ngAfterViewChecked"; AngularLifecycleHooks[AngularLifecycleHooks["ngOnDestroy"] = 7] = "ngOnDestroy"; return AngularLifecycleHooks; }({}); //#endregion //#region src/utils/kind-to-type.ts const IsKindType = { ANY(kind) { return kindToType(kind) === "any"; }, ARRAY(kind) { return kindToType(kind) === "[]"; }, BOOLEAN(kind) { return kindToType(kind) === "boolean"; }, FUNCTION(kind) { return kindToType(kind) === "function"; }, LITERAL(kind) { return kindToType(kind) === "literal type"; }, NEVER(kind) { return kindToType(kind) === "never"; }, NULL(kind) { return kindToType(kind) === "null"; }, NUMBER(kind) { return kindToType(kind) === "number"; }, OBJECT(kind) { return kindToType(kind) === "object"; }, STRING(kind) { return kindToType(kind) === "string"; }, SYMBOL(kind) { return kindToType(kind) === "symbol"; }, TEMPLATE_LITERAL(kind) { return kindToType(kind) === "template literal type"; }, UNDEFINED(kind) { return kindToType(kind) === "undefined"; }, UNKNOWN(kind) { return kindToType(kind) === "unknown"; }, VOID(kind) { return kindToType(kind) === "void"; } }; function kindToType(kind) { let _type = "unknown"; switch (kind) { case ts_morph.SyntaxKind.StringKeyword: case ts_morph.SyntaxKind.StringLiteral: _type = "string"; break; case ts_morph.SyntaxKind.NumberKeyword: case ts_morph.SyntaxKind.NumericLiteral: _type = "number"; break; case ts_morph.SyntaxKind.ArrayType: case ts_morph.SyntaxKind.ArrayLiteralExpression: _type = "[]"; break; case ts_morph.SyntaxKind.VoidKeyword: _type = "void"; break; case ts_morph.SyntaxKind.FunctionType: _type = "function"; break; case ts_morph.SyntaxKind.TemplateLiteralType: _type = "template literal type"; break; case ts_morph.SyntaxKind.TypeLiteral: _type = "literal type"; break; case ts_morph.SyntaxKind.BooleanKeyword: _type = "boolean"; break; case ts_morph.SyntaxKind.AnyKeyword: _type = "any"; break; case ts_morph.SyntaxKind.NullKeyword: _type = "null"; break; case ts_morph.SyntaxKind.SymbolKeyword: _type = "symbol"; break; case ts_morph.SyntaxKind.NeverKeyword: _type = "never"; break; case ts_morph.SyntaxKind.UnknownKeyword: _type = "unknown"; break; case ts_morph.SyntaxKind.UndefinedKeyword: _type = "undefined"; break; case ts_morph.SyntaxKind.ObjectKeyword: case ts_morph.SyntaxKind.ObjectLiteralExpression: _type = "object"; break; } return _type; } //#endregion //#region src/utils/ts-internal.ts const tsany = typescript; function getJSDocCommentRanges(node, text) { return tsany.getJSDocCommentRanges.apply(this, arguments); } //#endregion //#region src/utils/jsdoc-parser.util.ts /** * Standard JSDoc tags whose inline text should NOT be folded into the description. * For any other (custom) tag, text on the same line as the tag is included. */ const SKIP_TAG_INLINE_CONTENT = /* @__PURE__ */ new Set([ "param", "arg", "argument", "parameter", "returns", "return", "throws", "exception", "throw", "type", "typedef", "template", "deprecated", "example", "see", "ignore", "internal" ]); var JsdocParserUtil = class { isVariableLike(node) { if (node) switch (node.kind) { case ts_morph.SyntaxKind.BindingElement: case ts_morph.SyntaxKind.EnumMember: case ts_morph.SyntaxKind.Parameter: case ts_morph.SyntaxKind.PropertyAssignment: case ts_morph.SyntaxKind.PropertyDeclaration: case ts_morph.SyntaxKind.PropertySignature: case ts_morph.SyntaxKind.ShorthandPropertyAssignment: case ts_morph.SyntaxKind.VariableDeclaration: return true; } return false; } isTopmostModuleDeclaration(node) { if (node.nextContainer && node.nextContainer.kind === ts_morph.ts.SyntaxKind.ModuleDeclaration) { const next = node.nextContainer; if (node.name.end + 1 === next.name.pos) return false; } return true; } getRootModuleDeclaration(node) { while (node.parent && node.parent.kind === ts_morph.ts.SyntaxKind.ModuleDeclaration) { let parent = node.parent; if (node.name.pos === parent.name.end + 1) node = parent; else break; } return node; } getMainCommentOfNode(node, sourceFile) { let description = ""; if (node.parent && node.parent.kind === ts_morph.ts.SyntaxKind.VariableDeclarationList) node = node.parent.parent; else if (node.kind === ts_morph.ts.SyntaxKind.ModuleDeclaration) if (!this.isTopmostModuleDeclaration(node)) return null; else node = this.getRootModuleDeclaration(node); const comments = getJSDocCommentRanges(node, sourceFile.text); if (comments && comments.length) { let comment; if (node.kind === ts_morph.ts.SyntaxKind.SourceFile) { if (comments.length === 1) return null; comment = comments[0]; } else comment = comments[comments.length - 1]; description = sourceFile.text.substring(comment.pos, comment.end); } return description; } parseComment(text) { let comment = ""; let shortText = 0; function readBareLine(line) { comment += "\n" + line; if (line === "" && shortText === 0) {} else if (line === "" && shortText === 1) shortText = 2; else if (shortText === 2) comment += (comment === "" ? "" : "\n") + line; } const CODE_FENCE = /^\s*```(?!.*```)/; let inCode = false; let inExample = false; let exampleHasCodeFence = false; function readLine(line, index) { line = line.replace(/^\s*\*? ?/, ""); line = line.replace(/\s*$/, ""); if (CODE_FENCE.test(line)) { inCode = !inCode; if (inExample) exampleHasCodeFence = true; } if (line.indexOf("@example") !== -1) { inExample = true; exampleHasCodeFence = false; const lines = text.split(/\r\n?|\n/); for (let i = index + 1; i < lines.length; i++) { const nextLine = lines[i].replace(/^\s*\*? ?/, "").replace(/\s*$/, ""); if (nextLine === "") continue; if (CODE_FENCE.test(nextLine)) exampleHasCodeFence = true; break; } if (!exampleHasCodeFence) line = "```html"; else return; } if (inCode && inExample && exampleHasCodeFence && line === "") line = "___COMPODOC_EMPTY_LINE___"; if (inExample && line === "") { inExample = false; if (!exampleHasCodeFence) line = "```"; else return; } if (!inCode) { const tag = /^@(\S+)/.exec(line); const SeeTag = /^@see/.exec(line); if (SeeTag) line = line.replace(/^@see/, "See"); if (tag && !SeeTag) { const tagName = tag[1].toLowerCase(); if (!SKIP_TAG_INLINE_CONTENT.has(tagName)) { const textAfterTag = line.slice(tag[0].length).trim(); if (textAfterTag) readBareLine(textAfterTag); } return; } } readBareLine(line); } text = text.replace(/^\s*\/\*+/, ""); text = text.replace(/\*+\/\s*$/, ""); text.split(/\r\n?|\n/).forEach((line, index) => readLine(line, index)); return comment; } getJSDocTags(node, kind) { const docs = this.getJSDocs(node); if (docs) { const result = []; for (const doc of docs) if (ts_morph.ts.isJSDocParameterTag(doc)) { if (doc.kind === kind) result.push(doc); } else if (ts_morph.ts.isJSDoc(doc)) result.push(...filter(doc.tags, (tag) => tag.kind === kind)); else if (doc && doc.kind === kind) result.push(doc); else if (doc && typeof doc.kind === "number") continue; else throw new Error("Unexpected type"); return result; } } getJSDocs(node) { let cache = node.jsDocCache; if (!cache) { cache = this.getJSDocsWorker(node, []).filter((x) => x); node.jsDocCache = cache; } return cache; } getJSDocsWorker(node, cache) { const parent = node.parent; const isInitializerOfVariableDeclarationInStatement = this.isVariableLike(parent) && parent.initializer === node && ts_morph.ts.isVariableStatement(parent.parent.parent); const isVariableOfVariableDeclarationStatement = this.isVariableLike(node) && ts_morph.ts.isVariableStatement(parent.parent); const variableStatementNode = isInitializerOfVariableDeclarationInStatement ? parent.parent.parent : isVariableOfVariableDeclarationStatement ? parent.parent : void 0; if (variableStatementNode) cache = this.getJSDocsWorker(variableStatementNode, cache); if (parent && parent.parent && ts_morph.ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts_morph.SyntaxKind.EqualsToken && ts_morph.ts.isExpressionStatement(parent.parent)) cache = this.getJSDocsWorker(parent.parent, cache); const isModuleDeclaration = ts_morph.ts.isModuleDeclaration(node) && parent && ts_morph.ts.isModuleDeclaration(parent); const isPropertyAssignmentExpression = parent && ts_morph.ts.isPropertyAssignment(parent); if (isModuleDeclaration || isPropertyAssignmentExpression) cache = this.getJSDocsWorker(parent, cache); if (ts_morph.ts.isParameter(node)) cache = concat(cache, this.getJSDocParameterTags(node)); if (this.isVariableLike(node) && node.initializer) { const initializerJsDoc = node.initializer.jsDoc; if (initializerJsDoc) cache = concat(cache, initializerJsDoc); } const nodeJsDoc = node.jsDoc; if (nodeJsDoc) cache = concat(cache, nodeJsDoc); return cache; } getJSDocParameterTags(param) { const func = param.parent; const tags = this.getJSDocTags(func, ts_morph.SyntaxKind.JSDocParameterTag); if (!param.name) { const i = func.parameters.indexOf(param); const paramTags = filter(tags, (tag) => ts_morph.ts.isJSDocParameterTag(tag)); if (paramTags && 0 <= i && i < paramTags.length) return [paramTags[i]]; } else if (ts_morph.ts.isIdentifier(param.name)) { const name = param.name.text; return filter(tags, (tag) => { if (ts_morph.ts && ts_morph.ts.isJSDocParameterTag(tag)) { const t = tag; if (typeof t.parameterName !== "undefined") return t.parameterName.text === name; else if (typeof t.name !== "undefined") { if (typeof t.name.escapedText !== "undefined") return t.name.escapedText === name; } } }); } else return; } parseJSDocNode(node) { let rawDescription = ""; if (typeof node.comment === "string") rawDescription += node.comment; else if (node.comment) { const len = node.comment.length; for (let i = 0; i < len; i++) { const JSDocNode = node.comment[i]; switch (JSDocNode.kind) { case ts_morph.SyntaxKind.JSDocComment: rawDescription += JSDocNode.comment; break; case ts_morph.SyntaxKind.JSDocText: rawDescription += JSDocNode.text; break; case ts_morph.SyntaxKind.JSDocLink: if (JSDocNode.name) { let text = JSDocNode.name.escapedText; if (text === void 0 && JSDocNode.name.left && JSDocNode.name.right) text = JSDocNode.name.left.escapedText + "." + JSDocNode.name.right.escapedText; rawDescription += JSDocNode.text + "{@link " + text + "}"; } break; default: break; } } } return rawDescription; } }; //#endregion //#region src/utils/marked.acl.ts const { marked } = require("marked"); const markedAcl = marked; //#endregion //#region src/utils/utils.ts const getCurrentDirectory = ts_morph.ts.sys.getCurrentDirectory; const useCaseSensitiveFileNames = ts_morph.ts.sys.useCaseSensitiveFileNames; const newLine = ts_morph.ts.sys.newLine; function getNewLine() { return newLine; } function cleanNameWithoutSpaceAndToLowerCase(name) { return name.toLowerCase().replace(/ /g, "-"); } function getCanonicalFileName(fileName) { return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } const formatDiagnosticsHost = { getCurrentDirectory, getCanonicalFileName, getNewLine }; function markedtags(tags) { const jsdocParserUtil = new JsdocParserUtil(); let mtags = tags; forEach(mtags, (tag) => { const rawComment = jsdocParserUtil.parseJSDocNode(tag); tag.comment = markedAcl(LinkParser.resolveLinks(rawComment)); }); return mtags; } function mergeTagsAndArgs(args, jsdoctags) { let margs = cloneDeep(args); forEach(margs, (arg) => { arg.tagName = { text: "param" }; if (jsdoctags) forEach(jsdoctags, (jsdoctag) => { if (jsdoctag.name && jsdoctag.name.text === arg.name) { arg.tagName = jsdoctag.tagName; arg.name = jsdoctag.name; arg.comment = jsdoctag.comment; arg.typeExpression = jsdoctag.typeExpression; } }); }); if (jsdoctags) forEach(jsdoctags, (jsdoctag) => { if (jsdoctag.tagName && (jsdoctag.tagName.text === "example" || jsdoctag.tagName.text === "private")) margs.push({ tagName: jsdoctag.tagName, comment: jsdoctag.comment }); if (jsdoctag.tagName && (jsdoctag.tagName.text === "returns" || jsdoctag.tagName.text === "return")) { const ret = { tagName: jsdoctag.tagName, comment: jsdoctag.comment }; if (jsdoctag.typeExpression?.type) ret.returnType = kindToType(jsdoctag.typeExpression.type.kind); margs.push(ret); } if (jsdoctag.tagName && [ "throws", "throw", "exception" ].includes(jsdoctag.tagName.text)) margs.push({ tagName: jsdoctag.tagName, comment: jsdoctag.comment }); }); return margs; } function readConfig(configFile) { let result = ts_morph.ts.readConfigFile(configFile, ts_morph.ts.sys.readFile); if (result.error) { let message = ts_morph.ts.formatDiagnostics([result.error], formatDiagnosticsHost); throw new Error(message); } return result.config; } function stripBom(source) { if (source.charCodeAt(0) === 65279) return source.slice(1); return source; } function hasBom(source) { return source.charCodeAt(0) === 65279; } function cleanLifecycleHooksFromMethods(methods) { let result = []; if (typeof methods !== "undefined") { let i = 0; let len = methods.length; for (; i < len; i++) if (!(methods[i].name in AngularLifecycleHooks)) result.push(methods[i]); } return result; } function cleanSourcesForWatch(list) { return list.filter((element) => { const normalizedPath = isAbsoluteFilePath(element) ? path.normalize(element) : path.resolve(process.cwd(), element); return fs_extra.existsSync(normalizedPath); }); } function isAbsoluteFilePath(filePath) { return path.isAbsolute(filePath) || /^[A-Za-z]:[\\/]/.test(filePath); } function normalizeWatchFilePath(filePath, basePath) { if (isAbsoluteFilePath(filePath)) return path.normalize(filePath); return path.resolve(basePath, filePath); } function getNamesCompareFn(name) { /** * Copyright https://github.com/ng-bootstrap/ng-bootstrap */ name = name || "name"; const t = (a, b) => { if (a[name]) return a[name].localeCompare(b[name]); else return 0; }; return t; } function hasJSDocTag(member, searchedTag) { if (!member || !member.jsDoc) return false; const normalizedTag = searchedTag.toLowerCase(); for (const doc of member.jsDoc) { if (!doc.tags) continue; for (const tag of doc.tags) { const tagName = tag.tagName && (tag.tagName.text || tag.tagName.escapedText) || ""; if (!tagName) continue; const normalizedTagName = String(tagName).toLowerCase(); if (normalizedTagName === normalizedTag || normalizedTagName.indexOf(normalizedTag) > -1) return true; } } return false; } function isIgnore(member) { return hasJSDocTag(member, "ignore"); } function isCoverageIgnore(member) { return hasJSDocTag(member, "coverageIgnore"); } if (!Array.prototype.includes) Object.defineProperty(Array.prototype, "includes", { value: function(searchElement, fromIndex) { if (this == null) throw new TypeError("\"this\" is null or not defined"); let o = Object(this); let len = o.length >>> 0; if (len === 0) return false; let n = fromIndex | 0; let k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); function sameValueZero(x, y) { return x === y || typeof x === "number" && typeof y === "number" && isNaN(x) && isNaN(y); } while (k < len) { if (sameValueZero(o[k], searchElement)) return true; k++; } return false; } }); function findMainSourceFolder(files) { let mainFolder = ""; let mainFolderCount = 0; let rawFolders = files.map((filepath) => { let shortPath = filepath.replace(process.cwd() + path.sep, ""); return path.dirname(shortPath); }); let folders = {}; rawFolders = uniq(rawFolders); for (let i = 0; i < rawFolders.length; i++) rawFolders[i].split(path.sep).forEach((folder) => { if (folders[folder]) folders[folder] += 1; else folders[folder] = 1; }); for (let f in folders) if (folders[f] > mainFolderCount) { mainFolderCount = folders[f]; mainFolder = f; } return mainFolder; } function compilerHost(transpileOptions) { const inputFileName = transpileOptions.fileName || (transpileOptions.jsx ? "module.tsx" : "module.ts"); return { getSourceFile: (fileName) => { if (fileName.lastIndexOf(".ts") !== -1 || fileName.lastIndexOf(".js") !== -1) { if (fileName === "lib.d.ts") return; if (fileName.substr(-5) === ".d.ts") return; if (path.isAbsolute(fileName) === false) fileName = path.join(transpileOptions.tsconfigDirectory, fileName); if (!fs_extra.existsSync(fileName)) return; let libSource = ""; try { libSource = fs_extra.readFileSync(fileName).toString(); if (hasBom(libSource)) libSource = stripBom(libSource); } catch (e) { require_logger.logger.debug(e, fileName); } return ts_morph.ts.createSourceFile(fileName, libSource, transpileOptions.target, false); } }, writeFile: (name, text) => {}, getDefaultLibFileName: () => "lib.d.ts", useCaseSensitiveFileNames: () => false, getCanonicalFileName: (fileName) => fileName, getCurrentDirectory: () => "", getNewLine: () => "\n", fileExists: (fileName) => fileName === inputFileName, readFile: () => "", directoryExists: () => true, getDirectories: () => [] }; } function detectIndent(str, count) { let stripIndent = (stripedString) => { const match = stripedString.match(/^[ \t]*(?=\S)/gm); if (!match) return stripedString; const indent = Math.min(...match.map((x) => x.length)); const re = new RegExp(`^[ \\t]{${indent}}`, "gm"); return indent > 0 ? stripedString.replace(re, "") : stripedString; }; let repeating = (n, repeatString) => { repeatString = repeatString === void 0 ? " " : repeatString; if (typeof repeatString !== "string") throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof repeatString}\``); if (n < 0) throw new TypeError(`Expected \`count\` to be a positive finite number, got \`${n}\``); let ret = ""; do { if (n & 1) ret += repeatString; repeatString += repeatString; } while (n >>= 1); return ret; }; let indentString = (indentedString, indentCount) => { let indent = " "; indentCount = indentCount === void 0 ? 1 : indentCount; if (typeof indentedString !== "string") throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof indentedString}\``); if (typeof indentCount !== "number") throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof indentCount}\``); if (typeof indent !== "string") throw new TypeError(`Expected \`indent\` to be a \`string\`, got \`${typeof indent}\``); if (indentCount === 0) return indentedString; indent = indentCount > 1 ? repeating(indentCount, indent) : indent; return indentedString.replace(/^(?!\s*$)/gm, indent); }; return indentString(stripIndent(str), count || 0); } const INCLUDE_PATTERNS = ["**/*.ts", "**/*.tsx"]; const EXCLUDE_PATTERNS = [ "**/.git", "**/node_modules", "**/*.d.ts", "**/*.spec.ts" ]; //#endregion //#region src/app/engines/dependencies/interface-declaration-merger.ts var InterfaceDeclarationMerger = class { merge(interfaces) { if (!interfaces || interfaces.length === 0) return []; const mergedInterfaces = chain(interfaces).filter((interf) => !!interf.declarationMergeId).groupBy((interf) => interf.declarationMergeId).values().map((group) => this.mergeGroup(group)).value(); return concat(interfaces.filter((interf) => !interf.declarationMergeId), mergedInterfaces); } mergeGroup(group) { const merged = { ...group[0] }; const properties = this.mergeUniqueArrayValues(group.map((interf) => interf.properties)); if (properties) merged.properties = properties; const methods = this.mergeUniqueArrayValues(group.map((interf) => interf.methods)); if (methods) merged.methods = methods; const indexSignatures = this.mergeUniqueArrayValues(group.map((interf) => interf.indexSignatures)); if (indexSignatures) merged.indexSignatures = indexSignatures; const extendsList = this.mergeUniqueArrayValues(group.map((interf) => interf.extends)); if (extendsList) merged.extends = extendsList; merged.deprecated = group.some((interf) => !!interf.deprecated); merged.deprecationMessage = this.mergeDeprecationMessages(group); return merged; } mergeDeprecationMessages(group) { const deprecationMessages = uniq(group.map((interf) => interf.deprecationMessage).filter(Boolean)); return deprecationMessages.length > 0 ? deprecationMessages.join("\n\n") : ""; } mergeUniqueArrayValues(arrays) { const merged = []; const cache = /* @__PURE__ */ new Set(); for (const arr of arrays) { if (!arr || arr.length === 0) continue; for (const item of arr) { const key = typeof item === "object" && item !== null ? JSON.stringify(item) : String(item); if (cache.has(key)) continue; cache.add(key); merged.push(item); } } return merged.length > 0 ? merged : void 0; } }; //#endregion //#region src/app/engines/dependencies.engine.ts const traverse$4 = require("neotraverse/legacy"); var dependencies_engine_default = class DependenciesEngine { static { this.angularApiAliases = { NgFor: ["NgForOf"] }; } constructor() { this.miscellaneous = { variables: [], functions: [], typealiases: [], enumerations: [], groupedVariables: [], groupedFunctions: [], groupedEnumerations: [], groupedTypeAliases: [] }; this.relationshipsCache = {}; this.interfaceDeclarationMerger = new InterfaceDeclarationMerger(); } static getInstance() { if (!DependenciesEngine.instance) DependenciesEngine.instance = new DependenciesEngine(); return DependenciesEngine.instance; } updateModulesDeclarationsExportsTypes() { const mergeTypes = (entry) => { const directive = this.findInCompodocDependencies(entry.name, this.directives, entry.file); if (typeof directive.data !== "undefined") { entry.type = "directive"; entry.id = directive.data.id; } const component = this.findInCompodocDependencies(entry.name, this.components, entry.file); if (typeof component.data !== "undefined") { entry.type = "component"; entry.id = component.data.id; } const pipe = this.findInCompodocDependencies(entry.name, this.pipes, entry.file); if (typeof pipe.data !== "undefined") { entry.type = "pipe"; entry.id = pipe.data.id; } }; this.modules.forEach((module) => { module.declarations.forEach((declaration) => { mergeTypes(declaration); }); module.exports.forEach((expt) => { mergeTypes(expt); }); module.entryComponents.forEach((ent) => { mergeTypes(ent); }); }); } init(data) { traverse$4(data).forEach(function(node) { if (node) { if (node.parent) delete node.parent; if (node.initializer) delete node.initializer; } }); this.rawData = data; this.modules = sortBy(this.rawData.modules, [(el) => el.name.toLowerCase()]); this.rawModulesForOverview = sortBy(data.modulesForGraph, [(el) => el.name.toLowerCase()]); this.rawModules = sortBy(data.modulesForGraph, [(el) => el.name.toLowerCase()]); this.components = sortBy(this.rawData.components, [(el) => el.name.toLowerCase()]); this.controllers = sortBy(this.rawData.controllers, [(el) => el.name.toLowerCase()]); this.entities = sortBy(this.rawData.entities, [(el) => el.name.toLowerCase()]); this.directives = sortBy(this.rawData.directives, [(el) => el.name.toLowerCase()]); this.injectables = sortBy(this.rawData.injectables, [(el) => el.name.toLowerCase()]); this.interceptors = sortBy(this.rawData.interceptors, [(el) => el.name.toLowerCase()]); this.guards = sortBy(this.rawData.guards, [(el) => el.name.toLowerCase()]); this.interfaces = this.interfaceDeclarationMerger.merge(this.rawData.interfaces); this.interfaces = sortBy(this.interfaces, [(el) => el.name.toLowerCase()]); this.pipes = sortBy(this.rawData.pipes, [(el) => el.name.toLowerCase()]); this.classes = sortBy(this.rawData.classes, [(el) => el.name.toLowerCase()]); this.miscellaneous = this.rawData.miscellaneous; this.prepareMiscellaneous(); this.updateModulesDeclarationsExportsTypes(); this.routes = this.rawData.routesTree; this.manageDuplicatesName(); this.cleanRawModulesNames(); this.relationshipsCache = {}; } cleanRawModulesNames() { this.rawModulesForOverview = this.rawModulesForOverview.map((module) => { module.name = module.name.replace("$", ""); return module; }); } findInCompodocDependencies(name, data, file) { let _result = { source: "internal", data: void 0, score: 0 }; let nameFoundCounter = 0; if (data && data.length > 0) { for (let i = 0; i < data.length; i++) if (typeof name !== "undefined") { if (typeof file !== "undefined") { if (name === data[i].name && file.replace(/\\/g, "/").indexOf(data[i].file) !== -1) { nameFoundCounter += 1; _result.data = data[i]; _result.score = 2; } else if (name.indexOf(data[i].name) !== -1 && file.replace(/\\/g, "/").indexOf(data[i].file) !== -1) { nameFoundCounter += 1; _result.data = data[i]; _result.score = 1; } } else if (name === data[i].name) { nameFoundCounter += 1; _result.data = data[i]; _result.score = 2; } else if (name.indexOf(data[i].name) !== -1) { nameFoundCounter += 1; _result.data = data[i]; _result.score = 1; } } if (nameFoundCounter > 1) { let found = false; for (let i = 0; i < data.length; i++) if (typeof name !== "undefined") { if (typeof file !== "undefined") { if (name === data[i].name) { found = true; _result.data = data[i]; _result.score = 2; } } else if (name === data[i].name) { found = true; _result.data = data[i]; _result.score = 2; } } if (!found) _result = { source: "internal", data: void 0, score: 0 }; } } return _result; } manageDuplicatesName() { const processDuplicates = (element, index, array) => { const elementsWithSameName = filter(array, { name: element.name }); if (elementsWithSameName.length > 1) for (let i = 1; i < elementsWithSameName.length; i++) { let elementToEdit = elementsWithSameName[i]; if (typeof elementToEdit.isDuplicate === "undefined") { elementToEdit.isDuplicate = true; elementToEdit.duplicateId = i; elementToEdit.duplicateName = elementToEdit.name + "-" + elementToEdit.duplicateId; elementToEdit.id = elementToEdit.id + "-" + elementToEdit.duplicateId; } } return element; }; this.classes = this.classes.map(processDuplicates); this.interfaces = this.interfaces.map(processDuplicates); this.injectables = this.injectables.map(processDuplicates); this.pipes = this.pipes.map(processDuplicates); this.interceptors = this.interceptors.map(processDuplicates); this.guards = this.guards.map(processDuplicates); this.modules = this.modules.map(processDuplicates); this.components = this.components.map(processDuplicates); this.controllers = this.controllers.map(processDuplicates); this.entities = this.entities.map(processDuplicates); this.directives = this.directives.map(processDuplicates); } find(name) { const normalizedName = typeof name === "string" ? name.trim() : name; const namesToResolve = [normalizedName]; if (DependenciesEngine.angularApiAliases[normalizedName]) namesToResolve.push(...DependenciesEngine.angularApiAliases[normalizedName]); let bestScore = 0; let bestResult = void 0; for (const resolvedName of namesToResolve) { const searchFunctions = [ () => this.findInCompodocDependencies(resolvedName, this.modules), () => this.findInCompodocDependencies(resolvedName, this.injectables), () => this.findInCompodocDependencies(resolvedName, this.interceptors), () => this.findInCompodocDependencies(resolvedName, this.guards), () => this.findInCompodocDependencies(resolvedName, this.interfaces), () => this.findInCompodocDependencies(resolvedName, this.classes), () => this.findInCompodocDependencies(resolvedName, this.components), () => this.findInCompodocDependencies(resolvedName, this.controllers), () => this.findInCompodocDependencies(resolvedName, this.entities), () => this.findInCompodocDependencies(resolvedName, this.directives), () => this.findInCompodocDependencies(resolvedName, this.miscellaneous.variables), () => this.findInCompodocDependencies(resolvedName, this.miscellaneous.functions), () => this.findInCompodocDependencies(resolvedName, this.miscellaneous.typealiases), () => this.findInCompodocDependencies(resolvedName, this.miscellaneous.enumerations), () => angular_api_util_default.findApi(resolvedName) ]; for (let searchFunction of searchFunctions) { const result = searchFunction(); if (result.data && result.score > bestScore) { bestScore = result.score; bestResult = result; } } } return bestResult; } update(updatedData) { if (updatedData.modules.length > 0) forEach(updatedData.modules, (module) => { const _index = findIndex(this.modules, { name: module.name }); this.modules[_index] = module; }); if (updatedData.components.length > 0) forEach(updatedData.components, (component) => { const _index = findIndex(this.components, { name: component.name }); this.components[_index] = component; }); if (updatedData.controllers.length > 0) forEach(updatedData.controllers, (controller) => { const _index = findIndex(this.controllers, { name: controller.name }); this.controllers[_index] = controller; }); if (updatedData.entities.length > 0) forEach(updatedData.entities, (entity) => { const _index = findIndex(this.entities, { name: entity.name }); this.entities[_index] = entity; }); if (updatedData.directives.length > 0) forEach(updatedData.directives, (directive) => { const _index = findIndex(this.directives, { name: directive.name }); this.directives[_index] = directive; }); if (updatedData.injectables.length > 0) forEach(updatedData.injectables, (injectable) => { const _index = findIndex(this.injectables, { name: injectable.name }); this.injectables[_index] = injectable; }); if (updatedData.interceptors.length > 0) forEach(updatedData.interceptors, (interceptor) => { const _index = findIndex(this.interceptors, { name: interceptor.name }); this.interceptors[_index] = interceptor; }); if (updatedData.guards.length > 0) forEach(updatedData.guards, (guard) => { const _index = findIndex(this.guards, { name: guard.name }); this.guards[_index] = guard; }); if (updatedData.interfaces.length > 0) forEach(updatedData.interfaces, (int) => { const _index = findIndex(this.interfaces, { name: int.name }); this.interfaces[_index] = int; }); if (updatedData.pipes.length > 0) forEach(updatedData.pipes, (pipe) => { const _index = findIndex(this.pipes, { name: pipe.name }); this.pipes[_index] = pipe; }); if (updatedData.classes.length > 0) forEach(updatedData.classes, (classe) => { const _index = findIndex(this.classes, { name: classe.name }); this.classes[_index] = classe; }); /** * Miscellaneous update */ if (updatedData.miscellaneous.variables.length > 0) forEach(updatedData.miscellaneous.variables, (variable) => { const _index = findIndex(this.miscellaneous.variables, { name: variable.name, file: variable.file }); this.miscellaneous.variables[_index] = variable; }); if (updatedData.miscellaneous.functions.length > 0) forEach(updatedData.miscellaneous.functions, (func) => { const _index = findIndex(this.miscellaneous.functions, { name: func.name, file: func.file }); this.miscellaneous.functions[_index] = func; }); if (updatedData.miscellaneous.typealiases.length > 0) forEach(updatedData.miscellaneous.typealiases, (typealias) => { const _index = findIndex(this.miscellaneous.typealiases, { name: typealias.name, file: typealias.file }); this.miscellaneous.typealiases[_index] = typealias; }); if (updatedData.miscellaneous.enumerations.length > 0) forEach(updatedData.miscellaneous.enumerations, (enumeration) => { const _index = findIndex(this.miscellaneous.enumerations