RFC: Support for custom TSDoc tags
See original GitHub issueIn RFC: Core set of tags for TSDoc, @karol-majewski brought up the topic of custom tags. Extensiblity is a primary goal of TSDoc. The challenge is that JSDoc’s tags have inconsistent tag-specific syntaxes, whereas a custom tag needs to be safely skippable by parsers that are unaware of the tag.
Kinds of tags
Here’s some proposed core tags that we already discussed supporting, grouped by their type of syntax:
Standalone tags
These act as simple on/off switches. In terms of parser ambiguity, it doesn’t matter too much where they appear inside the doc comment:
@readonly
@public
@internal
@alpha
@beta
@ignore
Section-starter tags
These probably will act as delimiters that start blocks of rich text content (which possibly may include inline tags). Probably they should appear at the start of their line. Their captured content will probably terminate with the first TSDoc tag that is not an inline tag:
@remarks
@returns
@deprecated
Tags with unusual syntax
These are like section starter tags, but with special meaning for the “-” delimiter:
@param variable.member - description
@template TThing - description
These act like bullet items, so they must appear at the start of the line and must appear as a group. Otherwise they are like section-starter tags:
@see {@link <https://domain.com>} and other resources
Inline tags
These use curly braces to delimit their content. Within the curly braces, highly specialized parsing rules apply:
{@inheritdoc @scope/my-package/components:Foo.member}
{@link @scope/my-package/components:Foo.member | the thing}
{@link http://blarg | the thing}
Custom tag syntaxes
Custom inline tags should be fairly easy to support. Some interesting design questions:
-
Should we assume that unrecognized tags are standalone tags by default?
-
If we want to support custom section-starter tags, what would the notation look like?
-
For an unrecognized tag, should its content be included in the API documentation? Or should it be omitted? Is the answer different for different custom tag kinds?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:7
- Comments:6 (1 by maintainers)
Top GitHub Comments
@raymondfeng’s PR #1296 for API Extractor got me thinking some more about how a documentation tool should handle unrecognized TSDoc tags.
In the current implementation, the TSDoc parser can interpret the
@myExampleTag
syntax three ways, according to how it is defined in the TSDoc configuration:@remarks
or@privateRemarks
.) Introduces a documentation block. In the AST, it creates aDocBlock
object that becomes the parent of the following paragraph objects.@public
or@eventProperty
.) Its presence acts as a flag to communicate some attribute of the API. A modifier tag does NOT start a new block, and the tag is “invisible” to the surrounding text (although the attribute itself may be indicated in the generated docs somehow). In the AST, theDocBlockTag
appears inline without anyDocBlock
.Why are modifier tags parsed differently from block tags? Suppose someone meant to write this:
…but they actually wrote it like this:
In the above example, we don’t want
@public
(a modifier tag) to consume up the “Adds two numbers” text the way the@remarks
(a block tag) would. That would produce an empty summary block, and in that case a documentation tool should probably discard the “Adds two numbers” text entirely (since modifier tags don’t use it).If you try it in the TSDoc Playground, you will see that our special parsing of modifier tags causes this input to get rendered as intended:
And if you misspell
@public
(e.g. as@xublic
), it is also parsed like a modifier, so you will see it rendered like this, which is pretty good:But this approach has some downsides. Consider an input like this:
Here, the person has misspelled the
@privateRemarks
tag, and they also used a custom block tag@svgIcon
that is undefined in our TSDoc configuration (perhaps because it’s intended for some other tool).The Playground renders it like this:
This is bad:
@svgIcon
block tag, and instead treated its content as being part of the@remarks
tagI’m thinking these problems may be worse than the original problems we were trying to solve when we introduced the special parsing for modifiers. Also, this special parsing rule is harder to understand, since it requires developers to memorize which names are “modifier tags” versus “block tags”.
What if we changed the parser as follows:
DocBlock
AST node, and always consume any content up until the next such tag.Do you see any problems with this change?
The first two bullet points sound like an ideal solution to me. The lax mode change makes sense, but if I wrote a comment after a tag (that I didn’t know/forgot that was a modifier tag), I would be surprised to see the content appear under another tag… Unfortunately I don’t think I have a better solution. Just dropping the text isn’t any better.