Docblock Abstract Syntax Tree.
docast is a specification for representing docblock comments as abstract syntax trees.
It implements the unist spec.
- Introduction
- Types
- Nodes (abstract)
- Nodes
- Mixins
- Content model
- Glossary
- List of utilities
- Contribute
This document defines a format for representing docblock comments as abstract syntax trees. Development of docast started in October 2022. This specification is written in a TypeScript-like grammar.
docast extends unist, a format for syntax trees, to benefit from its ecosystem of utilities. It also integrates with mdast, a specification for representing markdown.
docast relates to JavaScript and TypeScript in that both languages support docblock comments. docast is language-agnostic, however, and can be used with any programming language that supports docblock comments.
docast relates to JSDoc, TSDoc, and typedoc in that these tools parse docblock comments.
These tools also have a limited set of tags that developers are allowed to use. If developers already have a set of tags
they're using, they must spend additional time re-configuring those tags for their chosen tool. docast does not
enforce any tag semantics — the user does. Tag specifications can be left to an ESLint rule, or a
setting akin to jsdoc/check-tag-names
or jsdoc.structuredTags
.
TypeScript users can integrate docast
type definitions into their project by installing the appropriate packages:
yarn add @flex-development/docast
interface Node extends unist.Node {}
Node (unist.Node) is a syntactic unit in docast syntax trees.
interface Literal extends Node {
value: bigint | boolean | number | string | null | undefined
}
Literal represents an abstract interface in docast containing the smallest possible value.
interface Parent extends unist.Parent {
children: Child[]
}
Parent (unist.Parent) represents an abstract interface in docast containing other nodes (said to be children).
Its content is limited to docast content and mdast content.
interface BlockTag extends Parent, Tag {
children:
| Exclude<BlockTagContent, TypeMetadata>[]
| [TypeMetadata, ...Exclude<BlockTagContent, TypeMetadata>[]]
data?: BlockTagData | undefined
type: 'blockTag'
}
BlockTag (Parent) represents top-level metadata.
Block tags should be the only element on their line, except in cases where special meaning is assigned to succeeding
text. All text following a block tag name, up until the start of the next block tag name, or comment closer
(*/
), is considered to be the block tag's tag content.
BlockTag can be used in comment nodes. Its content model is block tag content.
interface Comment extends Parent {
children:
| Exclude<FlowContent, Description>[]
| [summary: Description, ...Exclude<FlowContent, Description>[]]
code?: CodeSegment | null | undefined
data?: CommentData | undefined
type: 'comment'
}
Comment (Parent) represents a docblock comment in a source file.
The code
field represents the segment of code documented by a comment. The value of the code
field may be null
,
undefined
, or implement the CodeSegment
interface. The code
field must not be present if a comment
is used only to provide additional information.
Comment can be used in root nodes. Its content model is flow content.
interface CodeSegment {
position: unist.Position
type: string
}
CodeSegment represents the code segment in a file that is documented by a comment.
The value of the type
field is the node type of the code segment.
interface Description extends Parent {
children: DescriptionContent[]
data?: DescriptionData | undefined
type: 'description'
}
Description (Parent) represents the text of a comment. It is located at the start of a comment, before any block tags, and may contain Markdown content.
Description can be used in comment nodes. Its content model is description.
interface InlineTag extends Literal, Tag {
data?: InlineTagData | undefined
type: 'inlineTag'
value: string
}
InlineTag (Literal) represents inline metadata.
Inline tags are denoted by wrapping a tag name and any tag content in angle brackets ({
and }
).
InlineTag can be used in block tag and description nodes. It cannot contain any children — it is a leaf.
interface Root extends Parent {
children: Comment[]
data?: RootData | undefined
type: 'root'
}
Root (Parent) represents a document.
Root can be used as the root of a tree, never as a child. It can contain comment nodes.
interface TypeMetadata extends Parent {
children: TypeExpression[]
data?: TypeMetadataData | undefined
raw: string
type: 'typeMetadata'
}
TypeMetadata (Parent) represents an inlined type expression (e.g. {number}
).
TypeMetadata can be used in block tag nodes. Its content model is type expresssion.
A raw
field must be present. Its value is the raw type expression (e.g. number
).
interface Tag {
name: TagName
}
Tag represents metadata associated with a comment.
The name
field represents the tag name. Tag names start with an at-sign (@
) and may contain any ASCII letter after
the at-sign.
type TagName<T extends string = string> = `@${T}`
type Content = BlockTagContent | DescriptionContent | FlowContent | PhrasingContent
Nodes are grouped by content type, if applicable. Each node in docast, with the exception of Comment
,
falls into one or more categories of Content
.
type BlockTagContent = PhrasingContent | TypeMetadata
Block content represents block tag text, and its markup.
type DescriptionContent =
| mdast.Blockquote
| mdast.Definition
| mdast.FootnoteDefinition
| mdast.List
| mdast.ListItem
| mdast.Paragraph
| mdast.Table
| mdast.ThematicBreak
| PhrasingContent
Description content represents description text, and its markup.
type FlowContent = BlockTag | Description
Flow content represents the sections of comment.
type PhrasingContent = InlineTag | mdast.Code | mdast.PhrasingContent
Phrasing content represents comment text, and its markup.
type TypeExpression = TypeExpressionMap[keyof TypeExpressionMap]
TypeExpression content is a type expression.
When developing type expression parsers compatible with docast, the TypeExpressionMap
map should be augmented (and
exported! 😉) to register custom nodes:
declare module '@flex-development/docast' {
interface TypeExpressionMap {
arrayType: ArrayType
assertionPredicate: AssertionPredicate
bigint: BigIntLiteral
boolean: BooleanLiteral
conditionalType: ConditionalType
constructorType: ConstructorType
functionType: FunctionType
genericType: GenericType
identifier: Identifier
inferType: InferType
intersectionType: IntersectionType
nonNullableType: NonNullableType
null: NullLiteral
nullableType: NullableType
number: NumberLiteral
objectLiteralType: ObjectLiteralType
optionalType: OptionalType
parenthesizedType: ParenthesizedType
propertyAccessType: PropertyAccessType
string: StringLiteral
super: Super
templateLiteral: TemplateLiteral
this: This
tupleType: TupleType
typeOperation: TypeOperation
typePredicate: TypePredicate
typeSymbol: TypeSymbol
undefined: UndefinedLiteral
unionType: UnionType
variadicType: VariadicType
}
}
See the unist glossary for more terms.
A specially formatted comment in a source file used to document a segment of code or provide additional information.
Any text following a block tag name (e.g. @example
, @param
), up until the start of the next block tag
or comment closer (*/
), or any text following an inline tag name, up until the closing punctuator (}
).
See the unist list of utilities for more utilities.
docast-util-from-docs
- parse docblocks
See CONTRIBUTING.md
.
Ideas for new utilities and tools can be posted in docast/ideas.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.