From 12dfebb4ca3e201daabebc0bccd3bff9ec65f2eb Mon Sep 17 00:00:00 2001 From: Alina Sireneva Date: Tue, 31 Oct 2023 16:23:15 +0300 Subject: [PATCH] build(docs): updated typedoc --- package.json | 2 +- pnpm-lock.yaml | 21 +- scripts/totally-great-typedoc-plugin.js | 527 ------------------------ typedoc.base.cjs | 2 +- 4 files changed, 16 insertions(+), 536 deletions(-) delete mode 100644 scripts/totally-great-typedoc-plugin.js diff --git a/package.json b/package.json index 9583f3f9..b266cc14 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "semver": "7.5.1", "ts-node": "10.9.1", "tsconfig-paths": "^4.2.0", - "typedoc": "0.24.7", + "typedoc": "0.25.3", "typescript": "5.0.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5482f010..7d4bac00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,8 +106,8 @@ importers: specifier: ^4.2.0 version: 4.2.0 typedoc: - specifier: 0.24.7 - version: 0.24.7(typescript@5.0.4) + specifier: 0.25.3 + version: 0.25.3(typescript@5.0.4) typescript: specifier: 5.0.4 version: 5.0.4 @@ -3859,6 +3859,13 @@ packages: dependencies: brace-expansion: 2.0.1 + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -5309,16 +5316,16 @@ packages: is-typedarray: 1.0.0 dev: true - /typedoc@0.24.7(typescript@5.0.4): - resolution: {integrity: sha512-zzfKDFIZADA+XRIp2rMzLe9xZ6pt12yQOhCr7cD7/PBTjhPmMyMvGrkZ2lPNJitg3Hj1SeiYFNzCsSDrlpxpKw==} - engines: {node: '>= 14.14'} + /typedoc@0.25.3(typescript@5.0.4): + resolution: {integrity: sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==} + engines: {node: '>= 16'} hasBin: true peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x dependencies: lunr: 2.3.9 marked: 4.3.0 - minimatch: 9.0.1 + minimatch: 9.0.3 shiki: 0.14.2 typescript: 5.0.4 dev: true diff --git a/scripts/totally-great-typedoc-plugin.js b/scripts/totally-great-typedoc-plugin.js deleted file mode 100644 index 5f3bd1e2..00000000 --- a/scripts/totally-great-typedoc-plugin.js +++ /dev/null @@ -1,527 +0,0 @@ -// typedoc plugin to fix up references to other packages, and also some other stuff -// based on https://github.com/nlepage/typedoc-plugin-resolve-crossmodule-references/blob/main/src/index.ts - -const path = require('path') -const { - Converter, - Renderer, - DeclarationReflection, - SignatureReflection, - ParameterReflection, - TypeParameterReflection, - makeRecursiveVisitor, - ReferenceType, - TypeScript: ts, - ReflectionKind, - DefaultTheme, - Application, -} = require('typedoc') -const fs = require('fs') - -const PACKAGES_DIR = path.join(__dirname, '..', 'packages') - -function isReferenceType(type) { - return type.type === 'reference' -} - -function isReferenceTypeBroken(type) { - return type.reflection == null && type.getSymbol() != null -} - -function isTypedReflection(reflection) { - return ( - reflection instanceof DeclarationReflection || - reflection instanceof SignatureReflection || - reflection instanceof ParameterReflection || - reflection instanceof TypeParameterReflection - ) -} - -const defaultTheme = new DefaultTheme(new Renderer(new Application())) - -function packageNameFromPath(path) { - return path - .slice(PACKAGES_DIR.length + 1) - .split(/[/\\]/)[0] -} - -function load(app) { - // app.converter.on(Converter.EVENT_BEGIN, (ctx) => { - // const program = ctx.programs[0] - // const basePath = path.join(PACKAGES_DIR, packageNameFromPath(program.getRootFileNames()[0])) - // - // for (const file of program.getSourceFiles()) { - // if (file.fileName.startsWith(basePath)) { - // let stmtsToRemove = [] - // for (const stmt of file.statements) { - // if (stmt.kind === ts.SyntaxKind.ExportDeclaration && - // stmt.moduleSpecifier && - // // we only want to remove re-exports from other packages - // !stmt.moduleSpecifier.text.startsWith('.') - // ) { - // stmtsToRemove.push(stmt) - // } - // } - // file.statements = file.statements.filter((stmt) => !stmtsToRemove.includes(stmt)) - // } - // } - // }) - - app.converter.on(Converter.EVENT_RESOLVE, (ctx, reflection) => { - recursivelyVisit(ctx, reflection, fixType) - }) -} - -function recursivelyVisit(ctx, reflection, callback) { - const project = ctx.project - - if (isTypedReflection(reflection)) { - recursivelyVisitTypes(project, reflection, 'type', callback) - } - - if (reflection instanceof DeclarationReflection) { - recursivelyVisitTypes(project, reflection, 'extendedTypes', callback) - recursivelyVisitTypes(project, reflection, 'implementedTypes', callback) - } - - if (reflection.comment) { - // maybe fix links in the comment - let idx = 0 - - for (const it of reflection.comment.summary) { - if (it.tag === '@link') { - const name = it.text - // unlike normal references, here we don't have a symbol, - // so we can only manually hardcode some known references - let link = '' - - if (name.startsWith('tl.')) { - // todo link to tl reference - link = 'https://google.com' - } else { - const [base, path] = name.split('.') - - const knownClasses = { - TelegramClient: 'client', - ChosenInlineResult: 'client', - CallbackQuery: 'client', - Chat: 'client', - ChatMember: 'client', - ChatMemberUpdate: 'client', - Message: 'client', - UserStatusUpdate: 'client', - UserTypingUpdate: 'client', - PollVoteUpdate: 'client', - PollUpdate: 'client', - HistoryReadUpdate: 'client', - DeleteMessageUpdate: 'client', - ChatJoinRequestUpdate: 'client', - BotChatJoinRequestUpdate: 'client', - SessionConnection: 'core', - } - - if (knownClasses[base]) { - // yay we know where that is - link = `/packages/client/${knownClasses[base]}/${base}.html` - } - if (path) link += `#${path}` - } - - if (link) { - reflection.comment.summary[idx] = { - kind: 'text', - text: `[${name}](${link})`, - } - } - } - - idx += 1 - } - } -} - -function recursivelyVisitTypes(project, typed, field, callback) { - fixTyped(project, typed, field, callback) - - const typedField = typed[field] - if (!typedField) return - - const visitor = makeRecursiveVisitor({ - array(type) { - fixTyped(project, type, 'elementType', callback) - }, - conditional(type) { - fixTyped(project, type, 'checkType', callback) - fixTyped(project, type, 'trueType', callback) - fixTyped(project, type, 'falseType', callback) - fixTyped(project, type, 'extendsType', callback) - }, - indexedAccess(type) { - fixTyped(project, type, 'indexType', callback) - fixTyped(project, type, 'objectType', callback) - }, - intersection(type) { - fixTyped(project, type, 'types', callback) - }, - mapped(type) { - fixTyped(project, type, 'nameType', callback) - fixTyped(project, type, 'parameterType', callback) - fixTyped(project, type, 'templateType', callback) - }, - 'named-tuple-member'(type) { - fixTyped(project, type, 'element', callback) - }, - optional(type) { - fixTyped(project, type, 'elementType', callback) - }, - predicate(type) { - fixTyped(project, type, 'targetType', callback) - }, - query(type) { - fixTyped(project, type, 'queryType', callback) - }, - reference(type) { - fixTyped(project, type, 'typeArguments', callback) - }, - reflection(type) { - fixTyped(project, type.declaration, 'type', callback) - }, - rest(type) { - fixTyped(project, type, 'elementType', callback) - }, - tuple(type) { - fixTyped(project, type, 'elements', callback) - }, - // FIXME template-literal? - typeOperator(type) { - fixTyped(project, type, 'target', callback) - }, - union(type) { - fixTyped(project, type, 'types', callback) - }, - }) - - if (Array.isArray(typedField)) { - typedField.forEach((type) => type.visit && type.visit(visitor)) - } else { - typedField.visit(visitor) - } -} - -function fixTyped(project, typed, field, callback) { - const typedField = typed[field] - if (!typedField) return - - if (Array.isArray(typedField)) { - typedField.forEach((iType, i) => { - typedField[i] = callback(project, iType) - }) - } else { - typed[field] = callback(project, typedField) - } -} - -function fixType(project, type) { - if (isReferenceType(type) && isReferenceTypeBroken(type)) { return findReferenceType(type, project) } - - return type -} - -function getNamespacedName(symbol) { - if (!symbol.parent) return symbol.name.text - - let parts = [symbol.name.text] - - while (symbol.parent) { - symbol = symbol.parent - - if (symbol.kind === ts.SyntaxKind.ModuleDeclaration) { - parts.push(symbol.name.text) - } - } - - return parts.reverse().join('.') -} - -findReferenceType._reflections = {} - -function findReferenceType(type, project) { - const symbol = type.getSymbol()?.getDeclarations()?.[0] - const pkgFileName = symbol.getSourceFile().fileName - if (!pkgFileName) return type - - if (pkgFileName.startsWith(PACKAGES_DIR)) { - const pkgName = packageNameFromPath(pkgFileName) - - const namespacedName = getNamespacedName(symbol) - const qualifiedName = `${pkgName}:${namespacedName}` - let reflection = findReferenceType._reflections[qualifiedName] - - if (!reflection && pkgName === 'tl') { - reflection = new DeclarationReflection(namespacedName, ReflectionKind.Reference, project) - reflection.$tl = true - project.registerReflection(reflection) - - // todo link to TL reference - // reflection.url = '...' - } - - if (!reflection) { - let kind = { - [ts.SyntaxKind.TypeAliasDeclaration]: ReflectionKind.TypeAlias, - [ts.SyntaxKind.InterfaceDeclaration]: ReflectionKind.Interface, - [ts.SyntaxKind.ClassDeclaration]: ReflectionKind.Class, - [ts.SyntaxKind.EnumDeclaration]: ReflectionKind.Enum, - [ts.SyntaxKind.FunctionDeclaration]: ReflectionKind.Function, - [ts.SyntaxKind.ModuleDeclaration]: ReflectionKind.Namespace, - }[symbol.kind] - - if (!kind) { - return type - } - - reflection = new DeclarationReflection(qualifiedName, kind, project) - project.registerReflection(reflection) - - // awesome hack - reflection.name = namespacedName - const urls = defaultTheme.buildUrls(reflection, []) - - if (!urls[0]) { - throw new Error(`No url for ${qualifiedName}`) - } - - reflection.name = qualifiedName - // reflection.url = path.join(`../${pkgName}/index.html`) - - const prefix = determineUrlPrefix(pkgFileName, symbol) - if (prefix === null) return type - - reflection.url = path.join(`../${pkgName}/${urls[0].url}`) - - if (prefix) { - reflection.url = reflection.url.replace( - /\/([^/]+?)\.html$/, - `/${prefix}$1.html`, - ) - } - } - - findReferenceType._reflections[qualifiedName] = reflection - - const newType = ReferenceType.createResolvedReference( - qualifiedName, - reflection, - project, - ) - - if (type.typeArguments) { - newType.typeArguments = type.typeArguments - } - - return newType - } - - return type -} - -function* walkDirectory(dir) { - const dirents = fs.readdirSync(dir, { withFileTypes: true }) - - for (const dirent of dirents) { - const res = path.resolve(dir, dirent.name) - - if (dirent.isDirectory()) { - yield* walkDirectory(res) - } else { - yield res - } - } -} - -function getModuleExports(module, filename, prefix = '') { - let exports = [] - - for (const statement of module.statements) { - if (statement.kind === ts.SyntaxKind.ExportDeclaration) { - const exportDeclaration = statement - - if ( - exportDeclaration.exportClause && - exportDeclaration.exportClause.kind === - ts.SyntaxKind.NamedExports - ) { - // export default sucks and we don't use it here - for (const specifier of exportDeclaration.exportClause - .elements) { - exports.push(specifier.name.getText()) - } - } else if ( - !exportDeclaration.exportClause && - exportDeclaration.moduleSpecifier - ) { - // export * from ... - exports.push( - ...getFileExports( - path.resolve( - path.dirname(filename), - exportDeclaration.moduleSpecifier.text, - ), - ), - ) - } - } - - if ( - Array.isArray(statement.modifiers) && - statement.modifiers.some( - (m) => m.kind === ts.SyntaxKind.ExportKeyword, - ) - ) { - if (statement.declarationList) { - for (const decl of statement.declarationList.declarations) { - exports.push(decl.name.getText()) - } - } else if (statement.name) { - exports.push(statement.name.getText()) - } - } - - if (statement.kind === ts.SyntaxKind.ModuleDeclaration) { - exports.push( - ...getModuleExports(statement.body, filename, `${statement.name.text}.`), - ) - } - } - - if (prefix) exports = exports.map((e) => `${prefix}${e}`) - - return exports -} - -getFileExports._cache = {} - -function getFileExports(filename) { - if (!filename.endsWith('.ts')) { - // could either be a .ts file or a directory with index.ts file - const indexFilename = path.join(filename, 'index.ts') - - if (fs.existsSync(indexFilename)) { - filename = indexFilename - } else if (fs.existsSync(filename + '.ts')) { - filename += '.ts' - } else { - return [] - } - } - - if (getFileExports._cache[filename]) return getFileExports._cache[filename] - - const sourceFile = ts.createSourceFile( - filename, - fs.readFileSync(filename, 'utf8'), - ts.ScriptTarget.ES2015, - true, - ) - - const exports = getModuleExports(sourceFile, filename) - - getFileExports._cache[filename] = exports - - return exports -} - -determineUrlPrefix._cache = {} - -function determineUrlPrefix(pkgFileName, symbol) { - const cacheKey = `${pkgFileName}!${symbol.getSourceFile().fileName}@${ - symbol.pos - }` - - if (cacheKey in determineUrlPrefix._cache) { - return determineUrlPrefix._cache[cacheKey] - } - - const pkgName = packageNameFromPath(pkgFileName) - - const packageJsonFile = path.join(PACKAGES_DIR, pkgName, 'package.json') - const packageJson = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')) - - if (packageJson.name !== '@mtcute/' + pkgName) { - throw new Error(`could not find package.json for ${pkgName}`) - } - - const tdConfig = require(path.join(PACKAGES_DIR, pkgName, 'typedoc.js')) - - const symbolName = getNamespacedName(symbol) - - let entryPoint - - switch (tdConfig.entryPointStrategy) { - case 'expand': { - const possiblePoints = [] - - for (const dir of tdConfig.entryPoints) { - const fullDir = path.join(PACKAGES_DIR, pkgName, dir) - - for (const file of walkDirectory(fullDir)) { - const exports = getFileExports(file) - - if (exports.includes(symbolName)) { - possiblePoints.push(path.relative(fullDir, file)) - break - } - } - } - - if (possiblePoints.length) { - // shortest one wins - entryPoint = possiblePoints.sort((a, b) => { - return a.match(/[/\\]/g).length - b.match(/[/\\]/g).length - })[0] - } - - break - } - case undefined: - case 'resolve': - for (const file of tdConfig.entryPoints) { - const exports = getFileExports( - path.join(PACKAGES_DIR, pkgName, file), - ) - - if (exports.includes(symbolName)) { - entryPoint = file - break - } - } - break - default: - throw new Error( - `Unsupported entryPointStrategy: ${tdConfig.entryPointStrategy}`, - ) - } - - if (!entryPoint) { - console.warn( - `warning: could not find entry point for ${symbolName}`, - ) - - return null - } - - let prefix - - if (entryPoint.endsWith('index.ts')) { - // exported from root namespace, no prefix thus - prefix = '' - } else { - prefix = entryPoint.replace(/\.ts$/, '').replace(/[/\\]/g, '') + '.' - } - - determineUrlPrefix._cache[cacheKey] = prefix - - return prefix -} - -module.exports = { load } diff --git a/typedoc.base.cjs b/typedoc.base.cjs index 92eb1c15..0632647c 100644 --- a/typedoc.base.cjs +++ b/typedoc.base.cjs @@ -9,10 +9,10 @@ module.exports = { excludeExternals: true, excludeInternal: true, exclude: [ - '**/*/dist', '**/*/node_modules', './packages/tl/**/*', ], + externalPattern: ['**/dist/**'], plugin: [ './scripts/typedoc-external-links.cjs', ],