maticzav-tydoc

The TypeScript documenter that meets you where you are

Usage no npm install needed!

<script type="module">
  import maticzavTydoc from 'https://cdn.skypack.dev/maticzav-tydoc';
</script>

README

Work in progress 👷‍

tydoc

API

renderMarkdown

(docs: DocPackage, opts: Options) => string

fromProject

(opts: Options) => DocPackage

fromModule

(manager: Manager, sourceFile: SourceFile) => DocPackage

Exported Types

I RenderMarkdownOptions

typeIndexRef

Type Index

I Options

export interface Options {
  /**
   * Whether or not the API terms section should have a title and nest its term
   * entries under it. If false, term entry titles are de-nested by one level.
   */
  flatTermsSection: boolean
}

T DocPackage

//
// Package node
//

export type DocPackage = {
  modules: DocModule[]
  typeIndex: TypeIndex
}

& DocModule

//
// Module Node
//

export type DocModule = TSDocFrag & {
  kind: 'module'
  name: string
  /**
   * The path to this module from package root. If this module is the root
   * module then the path will be `/`.
   *
   * @remarks
   *
   * This is what a user would place in their import `from `string _following_ the
   * package name. For example:
   *
   * ```ts
   * import foo from "@foo/bar/quux/toto"
   * //                       ^^^^^^^^^^
   * ```
   */
  path: string
  isMain: boolean
  mainExport: null | Node
  namedExports: Expor[]
  location: {
    absoluteFilePath: string
  }
}

T TSDocFrag

//
// Node Features
//

export type TSDocFrag = {
  tsdoc: null | TSDoc
}

I TSDoc

export interface TSDoc {
  raw: string
  summary: string
  examples: { text: string }[]
  customTags: { name: string; text: string }[]
}

& DocTypeUnion

//
// Union Node
//

export type DocTypeUnion = {
  kind: 'union'
  isDiscriminated: boolean
  discriminantProperties: null | string[]
  types: Node[]
} & RawFrag

| Node

export type Node =
  | DocTypeUnion
  | DocTypePrimitive
  | DocTypeLiteral
  | DocTypeAlias
  | DocTypeInterface
  | DocTypeCallable
  | DocTypeArray
  | DocTypeObject
  | DocTypeIndexRef
  | DocUnsupported
  | DocTypeIntersection
  // todo unused?
  | { kind: 'function'; signatures: DocSig[] }
  | ({
      kind: 'callable_object'
      signatures: DocSig[]
      properties: DocProp[]
    } & RawFrag)
  | ({
      kind: 'callable_interface'
      properties: DocProp[]
      signatures: DocSig[]
    } & RawFrag)

T DocTypePrimitive

export type DocTypePrimitive = { kind: 'primitive'; type: string }

T DocTypeLiteral

export type DocTypeLiteral = { kind: 'literal'; base: string }

& DocTypeAlias

export type DocTypeAlias = {
  kind: 'alias'
  name: string
  type: Node
} & RawFrag &
  TSDocFrag

T RawFrag

export type RawFrag = {
  raw: {
    typeText: string
    nodeText: string
    nodeFullText: string
  }
}

& DocTypeInterface

export type DocTypeInterface = {
  kind: 'interface'
  name: string
  props: DocProp[]
} & RawFrag &
  TSDocFrag

T DocProp

export type DocProp = { kind: 'prop'; name: string; type: Node }

& DocTypeCallable

export type DocTypeCallable = {
  kind: 'callable'
  isOverloaded: boolean
  hasProps: boolean
  sigs: DocSig[]
  props: DocProp[]
} & RawFrag

T DocSig

export type DocSig = { kind: 'sig'; params: DocSigParam[]; return: Node }

T DocSigParam

export type DocSigParam = { kind: 'sigParam'; name: string; type: Node }

T DocTypeArray

export type DocTypeArray = { kind: 'array'; innerType: Node }

& DocTypeObject

export type DocTypeObject = { kind: 'object'; props: DocProp[] } & RawFrag

T DocTypeIndexRef

/**
 * A link to the type index. All named types go into the type index. When a type
 * or export includes a named type, rather than documenting it inline, a
 * reference to the type index is created.
 *
 */
export type DocTypeIndexRef = {
  kind: 'typeIndexRef'
  /**
   * An identifier that can be used to lookup the type in the type index.
   *
   * @example
   *
   * ```ts
   * docs.typeIndex[typeIndexRef.link]
   * ```
   */
  link: string
}

& DocUnsupported

export type DocUnsupported = { kind: 'unsupported' } & RawFrag

& DocTypeIntersection

//
// Intersection Node
//

export type DocTypeIntersection = {
  kind: 'intersection'
  types: Node[]
} & RawFrag

T Expor

//
// Export Node
//

export type Expor = {
  kind: 'export'
  name: string
  isTerm: boolean
  isType: boolean
  type: Node
}

I Options

interface Options {
  /**
   * Paths to modules in project, relative to project root or absolute.
   */
  entrypoints: string[]
  project?: tsm.Project
  /**
   * Specify the path to the package's entrypoint file.
   *
   * @defualt Read from package.json main field
   * @remarks This is useful for tests to avoid mocks or environment setup
   */
  packageMainEntrypoint?: string
  /**
   * Specify the root of the project.
   *
   * @default The current working directory
   * @remarks This is useful for tests to avoid having to mock process.cwd
   */
  prjDir?: string
  readSettingsFromJSON: boolean
  /**
   * Sometimes a source entrypoint is fronted by a facade module that allows
   * package consumers to do e.g. `import foo from "bar/toto"` _instead of_
   * `import foo from "bar/dist/toto". Use this mapping to force tydoc to view
   * the given source modules (keys) at the given package path (values).
   *
   * @example
   *
   * Given project layout:
   *
   * ```
   * /src/foo/bar/toto.ts
   * ```
   *
   * The setting:
   *
   * ```ts
   * sourceModuleToPackagePathMappings: {
   *    "foo/bar/toto": "toto"
   * }
   * ```
   *
   * Will cause the `toto` module to be documented as being available at path:
   *
   * ```ts
   * import some from "thing/toto"
   * ```
   */
  sourceModuleToPackagePathMappings?: Record<string, string>
}

I Settings

export interface Settings {
  /**
   * Absolute path to the source root. This should match the path that rootDir
   * resolves to from the project's tsconfig.json.
   */
  srcDir: string
  prjDir: string
  mainModuleFilePathAbs: string
  sourceModuleToPackagePathMappings?: Record<string, string>
}

F Thunk

export type Thunk<T> = () => T

Internal Development

  • yarn -s dev:test gives fast feedback with many simple unit tests.

  • https://ts-ast-viewer.com can be extremely help when trying to get a birds eye view of the AST. Sometimes you see data that you wish you were shown the API navigation calls to get it. But even without that it is still very handy to at least get a sense.

  • Amazing use-case for Quokka.js if you have it. Set yourself up a test module using techniques like those seen in test/setup.ts and get the best possible feedback loop going!

  • Very little information about the TS AST seems available. There is the Wiki and a bit of information here https://sandersn.github.io/manual/Typescript-compiler-implementation.html.