# normalize-see-links
Normalizes labeled links in `@see` tags to a canonical `{@link}` form.
Set `wrapBareUrls` to `true` to also wrap an `@see` description that contains
only a lowercase `http:` or `https:` URL in a plain, no-label `{@link}` tag.
This option defaults to `false`, and its output is independent of
`canonicalForm` because there is no label to position.
## Options
A single options object has the following properties.
### canonicalForm
The canonical `{@link}` form: `"pipe"` produces `{@link url|label}`, while `"prefix"` produces `[label]{@link url}`. Defaults to `"pipe"`.
### enableFixer
Whether to enable the fixer. Defaults to `true`.
### wrapBareUrls
Whether to wrap an `@see` description containing only a lowercase `http:` or `https:` URL (for example, `@see https://example.com`) in a plain `{@link https://example.com}`. Defaults to `false`.
|||
|---|---|
|Context|everywhere|
|Tags|`see`|
|Recommended|false|
|Settings||
|Options|`canonicalForm`, `enableFixer`, `wrapBareUrls`|
## Failing examples
The following patterns are considered problems:
````ts
/**
* @see [Docs](https://api.example.com/v1?ids=1|2|3)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [See {options}](https://example.com/api)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [a}b](https://example.com)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [Foo](https://example.com/a|b)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see [ ](https://example.com)
*/
// Message: @see link cannot be safely normalized.
/**
* @see {@link https://example.com|A]B}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: @see link cannot be safely normalized.
/**
* @see [ ]{@link https://example.com}
*/
// Message: @see link cannot be safely normalized.
/**
* @see [Foo](https://example.com/a}b)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see [Foo](https://example.com/a{b)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see [Braces](https://example.com/a{b}c)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Existing](https://example.com/%7C?x=1&y=2#frag)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Percent](https://example.com/100%)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [A{B](https://example.com)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [a}b](https://example.com)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see {@link https://example.com|A|B}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see {@link https://example.com|A`B}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see [a\}b](https://example.com)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [See {{one} and {two}}](https://example.com)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [A}B|C](https://example.com)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [Read the guide](https://example.com/read)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Browse the API]{@link https://example.com/api}
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [A](https://a.com) and [B](https://b.com)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [A](https://a.com)
* @see [B](https://b.com)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Unsafe](https://example.com/a|b?x=1&y=2#frag) and [Safe](https://example.com/safe)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [JSDoc Markdown](https://example.com/jsdoc|markdown)
*/
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: Expected @see link to use the pipe form.
/**
* @see [Package](@scope/pkg)
*/
// Message: @see link cannot be safely normalized.
/**
* @see [First](https://example.com/first)
* and [Second](https://example.com/second)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Example](https://example.com)
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [Guide]{@link https://example.com/guide}
*/
// Message: Expected @see link to use the pipe form.
/**
* @see [API](https://example.com/api)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see {@link https://example.com/reference|Reference}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
// Message: Expected @see link to use the prefix form.
/**
* @see [No fix](https://example.com/no-fix)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"enableFixer":false}]
// Message: Expected @see link to use the pipe form.
/**
* @see [Incomplete](https://example.com/incomplete
*/
// Message: @see link cannot be safely normalized.
/**
* @see [Incomplete]{@link}
*/
// Message: @see link cannot be safely normalized.
/**
* @see {@link https://example.com|}
*/
// Message: @see link cannot be safely normalized.
/**
* @see `[Code](https://example.com/code)`
*/
// Message: @see link cannot be safely normalized.
/**
* @see [Package]{@link @scope/pkg}
*/
// Message: @see link cannot be safely normalized.
/**
* @see {@link https://example.com Space label}
*/
// Message: @see link cannot be safely normalized.
/**
* @see [JSDoc]{@link https://example.com/jsdoc}
*/
// Settings: {"jsdoc":{"mode":"jsdoc"}}
// Message: Expected @see link to use the pipe form.
/**
* @see [TypeScript](https://example.com/type{script})
*/
const value: string = 'value';
// Message: Expected @see link to use the pipe form.
/**
* @see [Complex](https://example.com/a_(b))
*/
// Message: @see link cannot be safely normalized.
/**
* @see https://example.com/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see http://example.com/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see https://example.com/%7C?ids=1|2&brace={ok}#part}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see https://example.com/prefix
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix","wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see https://example.com/report-only
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"enableFixer":false,"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see [Docs](https://example.com/labeled)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected @see link to use the pipe form.
/**
* @see [Docs]{@link https://example.com/labeled}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected @see link to use the pipe form.
/**
* @see {@link https://example.com/labeled|Docs}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix","wrapBareUrls":true}]
// Message: Expected @see link to use the prefix form.
/**
* @see [See {options}](https://example.com/labeled)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: @see link cannot be safely normalized.
/**
* @see [No fix](https://example.com/labeled)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"enableFixer":false,"wrapBareUrls":true}]
// Message: Expected @see link to use the pipe form.
/**
* @see https://example.com/period.
* @see https://example.com/comma,
* @see https://example.com/paren)
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see
* https://example.com/continued
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
/**
* @see http:MyClass#method
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
// Message: Expected bare @see URL to use a {@link} tag.
````
## Passing examples
The following patterns are not considered problems:
````ts
/**
* @see {@link https://api.example.com/v1?ids=1%7C2%7C3|Docs}
*/
/**
* @see [Foo]{@link https://example.com/a%7Cb}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see [Foo]{@link https://example.com/a%7Db}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see [Foo]{@link https://example.com/a%7Bb}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see {@link https://example.com/a%7Bb%7Dc|Braces}
*/
/**
* @see {@link https://example.com/%7C?x=1&y=2#frag|Existing}
*/
/**
* @see {@link https://example.com/100%25|Percent}
*/
/**
* @see {@link https://example.com|A{B}
*/
/**
* @see [a}b]{@link https://example.com}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see {@link https://example.com|A|B}
*/
/**
* @see [A|B]{@link https://example.com}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see [A`B]{@link https://example.com}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see {@link https://example.com/a%7Cb?x=1&y=2#frag|Unsafe} and {@link https://example.com/safe|Safe}
*/
/**
* @see {@link https://example.com/read|Read the guide}
*/
/**
* @see {@link https://example.com/api|Browse the API}
*/
/**
* @see {@link https://a.com|A} and {@link https://b.com|B}
*/
/**
* @see {@link https://a.com|A}
* @see {@link https://b.com|B}
*/
/**
* @see {@link https://example.com/jsdoc%7Cmarkdown|JSDoc Markdown}
*/
// Settings: {"jsdoc":{"mode":"jsdoc"}}
/**
* @see {@link https://example.com/first|First}
* and {@link https://example.com/second|Second}
*/
/**
* @see {@link https://example.com|Example}
*/
/**
* @see {@link https://example.com/guide|Guide}
*/
/**
* @see [API]{@link https://example.com/api}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see [Reference]{@link https://example.com/reference}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"canonicalForm":"prefix"}]
/**
* @see {@link https://example.com/jsdoc|JSDoc}
*/
// Settings: {"jsdoc":{"mode":"jsdoc"}}
/**
* @see {@link https://example.com/type%7Bscript%7D|TypeScript}
*/
const value: string = 'value';
/**
* @see https://example.com
*/
/**
* @see MyClass#method
*/
/**
* @see some text
*/
/**
* @see {@link https://example.com}
*/
/**
* @see {@link @scope/pkg|Package}
*/
/**
* @see @scope/pkg
*/
/**
* @returns [Example](https://example.com)
*/
/**
* @see {@code foo|bar}
*/
/**
* @see \[Escaped](https://example.com)
*/
/**
* @see {@link https://example.com/idempotent}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see Read https://example.com/docs
*/
/**
* @see Read https://example.com/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see MyClass#method
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see ftp://example.com/file
*/
/**
* @see ftp://example.com/file
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see mailto:docs@example.com
*/
/**
* @see mailto:docs@example.com
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see file:///tmp/docs
*/
/**
* @see file:///tmp/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see //example.com/docs
*/
/**
* @see //example.com/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see `https://example.com/docs`
*/
/**
* @see `https://example.com/docs`
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see {@link https://example.com/docs}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see
*/
/**
* @see
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see https://example.com/one two
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see HTTP://example.com/docs
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see https://example.com/one https://example.com/two
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
/**
* @see {@link https://example.com/%7C}
*/
// "jsdoc/normalize-see-links": ["error"|"warn", {"wrapBareUrls":true}]
````