build(docs): updated typedoc

This commit is contained in:
alina 🌸 2023-10-31 16:23:15 +03:00
parent e3682058df
commit 12dfebb4ca
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
4 changed files with 16 additions and 536 deletions

View file

@ -56,7 +56,7 @@
"semver": "7.5.1", "semver": "7.5.1",
"ts-node": "10.9.1", "ts-node": "10.9.1",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"typedoc": "0.24.7", "typedoc": "0.25.3",
"typescript": "5.0.4" "typescript": "5.0.4"
} }
} }

View file

@ -106,8 +106,8 @@ importers:
specifier: ^4.2.0 specifier: ^4.2.0
version: 4.2.0 version: 4.2.0
typedoc: typedoc:
specifier: 0.24.7 specifier: 0.25.3
version: 0.24.7(typescript@5.0.4) version: 0.25.3(typescript@5.0.4)
typescript: typescript:
specifier: 5.0.4 specifier: 5.0.4
version: 5.0.4 version: 5.0.4
@ -3859,6 +3859,13 @@ packages:
dependencies: dependencies:
brace-expansion: 2.0.1 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: /minimist-options@4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -5309,16 +5316,16 @@ packages:
is-typedarray: 1.0.0 is-typedarray: 1.0.0
dev: true dev: true
/typedoc@0.24.7(typescript@5.0.4): /typedoc@0.25.3(typescript@5.0.4):
resolution: {integrity: sha512-zzfKDFIZADA+XRIp2rMzLe9xZ6pt12yQOhCr7cD7/PBTjhPmMyMvGrkZ2lPNJitg3Hj1SeiYFNzCsSDrlpxpKw==} resolution: {integrity: sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==}
engines: {node: '>= 14.14'} engines: {node: '>= 16'}
hasBin: true hasBin: true
peerDependencies: 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: dependencies:
lunr: 2.3.9 lunr: 2.3.9
marked: 4.3.0 marked: 4.3.0
minimatch: 9.0.1 minimatch: 9.0.3
shiki: 0.14.2 shiki: 0.14.2
typescript: 5.0.4 typescript: 5.0.4
dev: true dev: true

View file

@ -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 }

View file

@ -9,10 +9,10 @@ module.exports = {
excludeExternals: true, excludeExternals: true,
excludeInternal: true, excludeInternal: true,
exclude: [ exclude: [
'**/*/dist',
'**/*/node_modules', '**/*/node_modules',
'./packages/tl/**/*', './packages/tl/**/*',
], ],
externalPattern: ['**/dist/**'],
plugin: [ plugin: [
'./scripts/typedoc-external-links.cjs', './scripts/typedoc-external-links.cjs',
], ],