build(docs): updated typedoc
This commit is contained in:
parent
e3682058df
commit
12dfebb4ca
4 changed files with 16 additions and 536 deletions
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
|
@ -9,10 +9,10 @@ module.exports = {
|
|||
excludeExternals: true,
|
||||
excludeInternal: true,
|
||||
exclude: [
|
||||
'**/*/dist',
|
||||
'**/*/node_modules',
|
||||
'./packages/tl/**/*',
|
||||
],
|
||||
externalPattern: ['**/dist/**'],
|
||||
plugin: [
|
||||
'./scripts/typedoc-external-links.cjs',
|
||||
],
|
||||
|
|
Loading…
Reference in a new issue