rushstack icon indicating copy to clipboard operation
rushstack copied to clipboard

[api-documenter] How to define custom tags behavior?

Open markus-incisive opened this issue 1 year ago • 5 comments

Summary

The tsdoc.json file allows adding custom tags. This allows them to be parsed, but how do I get them to be eventually emitted by api-documenter?

To be more specific, I want to add the inline @linkcode tag and have it behave exactly the same as the @link tag.

Repro steps

tsdoc.json:

{
  "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
  "tagDefinitions": [
    {
      "tagName": "@linkcode",
      "syntaxKind": "inline"
    }
  ]
}

Source code:

/**
 * This is a {@linkcode http://example.com/ | link}.
 *
 * @public
 */
export class MyClass {}

Actual result:

The documentation is created without any errors, but the custom @linkcode tag is simply ignored.

{9EE9877D-C12C-4F13-A349-6F2FA143C016}

Details

I noticed there's a seemingly undocumented api-documenter.json config file, but it mentions nothing of custom tags. If I need to create a plugin to add here, that's fine, but a how-to would be nice.

Standard questions

Please answer these questions to help us investigate your issue more quickly:

Question Answer
@microsoft/api-documenter version? 7.25.14
Operating system? Windows
Documentation target? Markdown
Would you consider contributing a PR? No
TypeScript compiler version? 5.4.2
Node.js version (node -v)? 22.7.0

markus-incisive avatar Oct 01 '24 19:10 markus-incisive

I have the same issue. I created a tsdoc.json next to api-extractor.json where I define my custom tags and enable them

ahnpnl avatar Oct 14 '24 08:10 ahnpnl

@octogonz - Can you provide some info on how to do this? This would be via a TSDoc plugin I think.

iclanton avatar Nov 04 '24 19:11 iclanton

The best I can do right now is an intermediate script between api-extractor and api-documenter that replaces custom tags in the .api.json file with tags that api-documenter can understand. For example, this is what I'm doing to get @linkcode to work:

const apiPath = path.resolve(__dirname, '../temp/PACKAGE.api.json')
const apiJson = JSON.parse(fs.readFileSync(apiPath, 'utf-8'))

function jsonCrawler (obj, handler, context = { parent: null }) {
  handler(obj, context)

  if (typeof obj === 'object') {
    if (obj === null) {
      // nothing
    } else if (Array.isArray(obj)) {
      for (let index = 0; index < obj.length; ++index) {
        jsonCrawler(obj[index], handler, { parent: { parent: context, _: obj }, key: index })
      }
    } else {
      for (const key in obj) {
        jsonCrawler(obj[key], handler, { parent: { parent: context, _: obj }, key })
      }
    }
  }
}

jsonCrawler(apiJson, (value, { parent, key }) => {
  if (key === 'docComment' && typeof value === 'string') {
    value = value.replaceAll(/{@linkcode ([^|}]*) \| ([^}]*)}/g, '{@link $1 | <code>$2</code>}')
    value = value.replaceAll(/{@linkcode ([^|}]*)}/g, '{@link $1 | <code>$1</code>}')
    value = value.replaceAll(/@linkcode/g, '@link')

    parent._[key] = value
  }
})

fs.writeFileSync(apiPath, JSON.stringify(apiJson, null, 2))

pillowfication avatar Nov 04 '24 20:11 pillowfication

The intend design is that API Extractor would accept these tags (because they are valid according to your config definition). And then an API Documenter plugin would implement any special processing.

The plugin system is in early/experimental stages, but if you are interested to contribute to API Documenter, I can help to design a solution for your problem. I've been really busy lately, so the best way would be to arrange a Rush Stack community call.

octogonz avatar Nov 05 '24 20:11 octogonz

Hi @octogonz , me and my team working on https://github.com/iTwin/itwinjs-core are interested in contributing if it'd help move this along. We'd like to create new jsdoc tags to use, as well as override existing tags such as the @preapproved tag to match some custom behavior. Please let us know how we can help!

aruniverse avatar Feb 11 '25 23:02 aruniverse