chore(docs): Updated UI Reference (automated) (#13968)
* chore(docs): Generated + Updated UI Reference (automated) * fix react-docs-generator not resolving external types * sort undefined --------- Co-authored-by: olivermrbl <olivermrbl@users.noreply.github.com> Co-authored-by: Shahed Nasser <shahednasser@gmail.com>
This commit is contained in:
committed by
GitHub
parent
924d651188
commit
423b6d94dc
@@ -6,7 +6,7 @@ import {
|
||||
TSFunctionSignatureType,
|
||||
TypeDescriptor,
|
||||
} from "react-docgen/dist/Documentation.js"
|
||||
import { Comment, ReferenceReflection, ReferenceType } from "typedoc"
|
||||
import { Comment, ReferenceReflection } from "typedoc"
|
||||
import {
|
||||
Application,
|
||||
Context,
|
||||
@@ -18,12 +18,14 @@ import {
|
||||
SomeType,
|
||||
SourceReference,
|
||||
} from "typedoc"
|
||||
import ts from "typescript"
|
||||
import {
|
||||
getFunctionType,
|
||||
getProjectChild,
|
||||
getType,
|
||||
getTypeChildren,
|
||||
} from "utils"
|
||||
import { getTypescriptTsType } from "../utils/get-typescript-ts-type.js"
|
||||
|
||||
type MappedReflectionSignature = {
|
||||
source: SourceReference
|
||||
@@ -36,7 +38,7 @@ type Options = {
|
||||
verbose?: boolean
|
||||
}
|
||||
|
||||
type TsType = TypeDescriptor<TSFunctionSignatureType>
|
||||
export type TsType = TypeDescriptor<TSFunctionSignatureType>
|
||||
|
||||
type ExcludeExternalOptions = {
|
||||
parentReflection: DeclarationReflection
|
||||
@@ -121,17 +123,14 @@ export default class TypedocManager {
|
||||
return spec
|
||||
}
|
||||
|
||||
const doesReflectionHaveSignature =
|
||||
reflection.type?.type === "reference" &&
|
||||
reflection.type.reflection instanceof DeclarationReflection &&
|
||||
reflection.type.reflection.signatures?.length
|
||||
if (reflection.type?.type === "reference") {
|
||||
reflection = reflection.type.reflection as DeclarationReflection
|
||||
}
|
||||
|
||||
let signature: SignatureReflection | undefined
|
||||
let props: DeclarationReflection[] = []
|
||||
if (doesReflectionHaveSignature) {
|
||||
signature = (
|
||||
(reflection.type! as ReferenceType).reflection as DeclarationReflection
|
||||
).signatures![0]
|
||||
if (reflection.signatures?.length) {
|
||||
signature = reflection.signatures![0]
|
||||
props =
|
||||
signature?.parameters?.length && signature.parameters[0].type
|
||||
? getTypeChildren({
|
||||
@@ -282,7 +281,7 @@ export default class TypedocManager {
|
||||
|
||||
// Retrieves the `tsType` stored in a spec's prop
|
||||
// The format is based on the expected format of React Docgen.
|
||||
getTsType(reflectionType: SomeType, level = 1): TsType {
|
||||
getTsType(reflectionType: SomeType, symbol?: ts.Symbol, level = 1): TsType {
|
||||
const rawValue = getType({
|
||||
reflectionType,
|
||||
...this.getTypeOptions,
|
||||
@@ -294,7 +293,11 @@ export default class TypedocManager {
|
||||
}
|
||||
switch (reflectionType.type) {
|
||||
case "array": {
|
||||
const elements = this.getTsType(reflectionType.elementType, level + 1)
|
||||
const elements = this.getTsType(
|
||||
reflectionType.elementType,
|
||||
symbol,
|
||||
level + 1
|
||||
)
|
||||
return {
|
||||
name: "Array",
|
||||
elements: [elements],
|
||||
@@ -306,16 +309,27 @@ export default class TypedocManager {
|
||||
(reflectionType.reflection as DeclarationReflection) ||
|
||||
getProjectChild(this.project!, reflectionType.name)
|
||||
const elements: TsType[] = []
|
||||
if (!referenceReflection && symbol) {
|
||||
return (
|
||||
getTypescriptTsType(symbol) || {
|
||||
name: reflectionType.name,
|
||||
raw: rawValue,
|
||||
elements,
|
||||
}
|
||||
)
|
||||
}
|
||||
if (referenceReflection?.children) {
|
||||
referenceReflection.children?.forEach((child) => {
|
||||
if (!child.type) {
|
||||
return
|
||||
}
|
||||
|
||||
elements.push(this.getTsType(child.type, level + 1))
|
||||
elements.push(this.getTsType(child.type, symbol, level + 1))
|
||||
})
|
||||
} else if (referenceReflection?.type) {
|
||||
elements.push(this.getTsType(referenceReflection.type, level + 1))
|
||||
elements.push(
|
||||
this.getTsType(referenceReflection.type, symbol, level + 1)
|
||||
)
|
||||
}
|
||||
return {
|
||||
name: reflectionType.name,
|
||||
@@ -344,7 +358,7 @@ export default class TypedocManager {
|
||||
typeData.signature.properties.push({
|
||||
key: property.name,
|
||||
value: property.type
|
||||
? this.getTsType(property.type, level + 1)
|
||||
? this.getTsType(property.type, symbol, level + 1)
|
||||
: {
|
||||
name: "unknown",
|
||||
},
|
||||
@@ -390,7 +404,7 @@ export default class TypedocManager {
|
||||
const elementData: TsType[] = []
|
||||
|
||||
elements.forEach((element) => {
|
||||
elementData.push(this.getTsType(element, level + 1))
|
||||
elementData.push(this.getTsType(element, undefined, level + 1))
|
||||
})
|
||||
|
||||
return elementData
|
||||
@@ -462,10 +476,12 @@ export default class TypedocManager {
|
||||
return: undefined,
|
||||
},
|
||||
}
|
||||
const signatureSymbol = this.getReflectionSymbol(signature)
|
||||
|
||||
signature.parameters?.forEach((parameter) => {
|
||||
const parameterSymbol = this.getReflectionSymbol(parameter)
|
||||
const parameterType = parameter.type
|
||||
? this.getTsType(parameter.type, level + 1)
|
||||
? this.getTsType(parameter.type, parameterSymbol, level + 1)
|
||||
: undefined
|
||||
typeData.signature.arguments.push({
|
||||
name: parameter.name,
|
||||
@@ -475,14 +491,14 @@ export default class TypedocManager {
|
||||
})
|
||||
|
||||
typeData.signature.return = signature.type
|
||||
? this.getTsType(signature.type, level + 1)
|
||||
? this.getTsType(signature.type, signatureSymbol, level + 1)
|
||||
: undefined
|
||||
|
||||
return typeData
|
||||
}
|
||||
|
||||
// Checks if a TsType only has a `name` field.
|
||||
doesOnlyHaveName(obj: TsType): boolean {
|
||||
onlyHasName(obj: TsType): boolean {
|
||||
const primitiveTypes = ["string", "number", "object", "boolean", "function"]
|
||||
const keys = Object.keys(obj)
|
||||
|
||||
@@ -493,6 +509,34 @@ export default class TypedocManager {
|
||||
)
|
||||
}
|
||||
|
||||
isRawTypeEmpty(tsType: TsType): boolean {
|
||||
if (!("raw" in tsType)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if ("elements" in tsType && tsType.elements.length > 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if ("signature" in tsType && tsType.signature) {
|
||||
if (
|
||||
"arguments" in tsType.signature &&
|
||||
tsType.signature.arguments.length > 0
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (
|
||||
"properties" in tsType.signature &&
|
||||
tsType.signature.properties.length > 0
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// retrieves a reflection by the provided name
|
||||
// and check if its type is ReactNode
|
||||
// this is useful for the CustomResolver to check
|
||||
@@ -559,7 +603,10 @@ export default class TypedocManager {
|
||||
return null
|
||||
}
|
||||
|
||||
return this.getTsType(childReflection.type as SomeType)
|
||||
return this.getTsType(
|
||||
childReflection.type as SomeType,
|
||||
this.getReflectionSymbol(childReflection)
|
||||
)
|
||||
}
|
||||
|
||||
// used to check if a reflection (typically of a prop)
|
||||
@@ -686,4 +733,8 @@ export default class TypedocManager {
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
|
||||
getReflectionSymbol(reflection: Reflection): ts.Symbol | undefined {
|
||||
return this.project?.getSymbolFromReflection(reflection)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ function resolveDocumentation(
|
||||
utils.setPropDescription(documentation, propertyPath)
|
||||
|
||||
// set type if missing
|
||||
if (!propDescriptor.tsType && typedocManager) {
|
||||
if (typedocManager && !propDescriptor.tsType) {
|
||||
const typeAnnotation = utils.getTypeAnnotation(path)
|
||||
if (typeAnnotation?.isTSTypeReference()) {
|
||||
const typeName = typeAnnotation.get("typeName")
|
||||
@@ -71,7 +71,8 @@ function resolveDocumentation(
|
||||
}
|
||||
} else if (
|
||||
propDescriptor.tsType &&
|
||||
typedocManager?.doesOnlyHaveName(propDescriptor.tsType)
|
||||
(typedocManager?.onlyHasName(propDescriptor.tsType) ||
|
||||
typedocManager?.isRawTypeEmpty(propDescriptor.tsType))
|
||||
) {
|
||||
// see if the type needs to be resolved.
|
||||
const typeReflection = typedocManager?.getReflectionByName(
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
import ts from "typescript"
|
||||
import { TsType } from "../classes/typedoc-manager.js"
|
||||
|
||||
const MAX_LEVEL = 3
|
||||
|
||||
export function getTypescriptTsType(
|
||||
symbol: ts.Symbol | undefined
|
||||
): TsType | null {
|
||||
if (!symbol) {
|
||||
return null
|
||||
}
|
||||
let convertedType: TsType | null = null
|
||||
if ("type" in symbol) {
|
||||
convertedType = convertTypeToTsType(symbol.type as ts.Type, 1)
|
||||
}
|
||||
if (
|
||||
!convertedType &&
|
||||
"links" in symbol &&
|
||||
"type" in (symbol.links as Record<string, unknown>)
|
||||
) {
|
||||
const symbolTypeLink = (symbol.links as Record<string, unknown>)
|
||||
.type as ts.Type
|
||||
|
||||
convertedType = convertTypeToTsType(symbolTypeLink, 1)
|
||||
}
|
||||
|
||||
return convertedType
|
||||
}
|
||||
|
||||
function convertTypeToTsType(type: ts.Type, level = 1): TsType | null {
|
||||
if (level > MAX_LEVEL) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Handle union types
|
||||
if (type.isUnion()) {
|
||||
const elements: TsType[] = type.types
|
||||
.map((unionedType) => convertTypeToTsType(unionedType, level + 1))
|
||||
.filter((element): element is TsType => element !== null)
|
||||
|
||||
// If all elements were filtered out, return null
|
||||
if (elements.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Sort elements to put undefined at the end
|
||||
elements.sort((a, b) => {
|
||||
const aIsUndefined = a.name === "undefined"
|
||||
const bIsUndefined = b.name === "undefined"
|
||||
|
||||
if (aIsUndefined && !bIsUndefined) {
|
||||
return 1
|
||||
}
|
||||
if (!aIsUndefined && bIsUndefined) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
return {
|
||||
name: "union",
|
||||
raw: undefined,
|
||||
elements,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle intersection types
|
||||
if (type.isIntersection()) {
|
||||
const elements: TsType[] = type.types
|
||||
.map((intersectedType) => convertTypeToTsType(intersectedType, level + 1))
|
||||
.filter((element): element is TsType => element !== null)
|
||||
|
||||
// If all elements were filtered out, return null
|
||||
if (elements.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
name: "intersection",
|
||||
raw: undefined,
|
||||
elements,
|
||||
}
|
||||
}
|
||||
|
||||
const typeFlags = type.flags
|
||||
|
||||
// Handle string literal
|
||||
if (typeFlags & ts.TypeFlags.StringLiteral) {
|
||||
const literalType = type as ts.StringLiteralType
|
||||
return {
|
||||
name: "literal",
|
||||
value: `"${literalType.value}"`,
|
||||
}
|
||||
}
|
||||
|
||||
// Handle number literal
|
||||
if (typeFlags & ts.TypeFlags.NumberLiteral) {
|
||||
const literalType = type as ts.NumberLiteralType
|
||||
return {
|
||||
name: "literal",
|
||||
value: literalType.value.toString(),
|
||||
}
|
||||
}
|
||||
|
||||
// Handle boolean literal
|
||||
if (typeFlags & ts.TypeFlags.BooleanLiteral) {
|
||||
const literalType = type as ts.Type & { intrinsicName?: string }
|
||||
return {
|
||||
name: "literal",
|
||||
value: literalType.intrinsicName || "boolean",
|
||||
}
|
||||
}
|
||||
|
||||
// Handle null
|
||||
if (typeFlags & ts.TypeFlags.Null) {
|
||||
return {
|
||||
name: "null",
|
||||
}
|
||||
}
|
||||
|
||||
// Handle undefined
|
||||
if (typeFlags & ts.TypeFlags.Undefined) {
|
||||
return {
|
||||
name: "undefined",
|
||||
}
|
||||
}
|
||||
|
||||
// Handle primitive types
|
||||
if (typeFlags & ts.TypeFlags.String) {
|
||||
return { name: "string" }
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Number) {
|
||||
return { name: "number" }
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Boolean) {
|
||||
return { name: "boolean" }
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Void) {
|
||||
return { name: "void" }
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Any) {
|
||||
return { name: "any" }
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Unknown) {
|
||||
return null
|
||||
}
|
||||
if (typeFlags & ts.TypeFlags.Never) {
|
||||
return { name: "never" }
|
||||
}
|
||||
|
||||
// Handle object types
|
||||
if (typeFlags & ts.TypeFlags.Object) {
|
||||
const objectType = type as ts.ObjectType
|
||||
|
||||
// Handle reference types (named types)
|
||||
if (objectType.objectFlags & ts.ObjectFlags.Reference) {
|
||||
const typeRef = type as ts.TypeReference
|
||||
const typeName = typeRef.symbol?.name || "unknown"
|
||||
|
||||
const elements: TsType[] = []
|
||||
if (typeRef.typeArguments) {
|
||||
typeRef.typeArguments.forEach((typeArg) => {
|
||||
const convertedType = convertTypeToTsType(typeArg, level + 1)
|
||||
if (convertedType) {
|
||||
elements.push(convertedType)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
name: typeRef.symbol?.name || typeName,
|
||||
elements: elements.length > 0 ? elements : undefined,
|
||||
raw: undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: return the string representation of the type
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user