From b69e532da079dce29c347349ae75db58edcb14e9 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 3 Jan 2021 17:28:52 -0700 Subject: [PATCH] Added custom linkRenderer --- .eslintignore | 5 ++- .eslintrc | 5 ++- README.md | 71 +++++++++++++++++++++++----------- bin/generateReadme.js | 4 +- bin/readme.ejs | 25 ++++++++++++ dist/README.md | 71 +++++++++++++++++++++++----------- src/_private/types.ts | 4 +- src/_private/utils.ts | 82 +++++++++++++++++++--------------------- src/getTag/index.test.js | 43 +++++++++++++++++++++ src/getTag/index.ts | 9 +++-- src/parse/index.ts | 6 ++- src/parseTags/index.ts | 6 ++- 12 files changed, 227 insertions(+), 104 deletions(-) diff --git a/.eslintignore b/.eslintignore index 76add87..5de02b1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ -node_modules -dist \ No newline at end of file +coverage +dist +node_modules \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index 794767b..f708ad0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,7 +10,8 @@ "plugin:@typescript-eslint/recommended" ], "rules": { - "no-console": 1, - "semi": 2 + "comma-dangle": [1, "always-multiline"], + "no-console": "warn", + "semi": "error" } } \ No newline at end of file diff --git a/README.md b/README.md index a0fd85b..11818e7 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,31 @@ export type GetCommentsFromFileConfig = { keepIndent?: boolean }; export type ToCommentStringConfig = { indentChars?: number }; ``` +

Using a custom linkRenderer

+

+ Some functions have an optional linkRenderer which is used to convert inline + {@link} and {@tutorial} tags to clickable links. +

+

+ By default, the output will be a basic link like: +

+ +``` +text +``` + +

However, you can override that by providing your own linkRenderer. For example:

+ +``` +const myLinkRenderer = (link: InlineLink) => `${link.text} + +// outputs => +text +``` + +

Without further ado, the utils...

+
+ @@ -150,9 +175,9 @@ getCommentsFromFile(file); Param - Type + TypeDefault -

jsdoc

The entire jsdoc stringstring +

jsdoc

The entire jsdoc stringstring

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {(tag: string) => ITag | Array<ITag | ITag[]>} Function to get the tag or array of all tags that go by that name

Import

@@ -275,7 +300,7 @@ tag('@customTag'); Param TypeDefault -

jsdoc

The entire jsdoc comment stringstring

customTags (optional)

Optional array of custom tags parsestring[][] +

jsdoc

The entire jsdoc comment stringstring

customTags (optional)

Optional array of custom tags parsestring[][]

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {object} Object with keys of each parsed tag

Import

@@ -417,9 +442,9 @@ parse(jsdoc, ['customTag', 'docgen_types']); Param - Type + TypeDefault -

jsdoc

The entire jsdoc comment stringstring

tags

The tags to parsestring[] +

jsdoc

The entire jsdoc comment stringstring

tags

The tags to parsestring[]

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {object} Object with keys of each parsed tag

Import

@@ -612,16 +637,16 @@ README.md -- this file └───index.d.ts - 784 Bytes └───index.js - 2.29 KB └───/getTag - └───index.d.ts - 431 Bytes - └───index.js - 951 Bytes + └───index.d.ts - 628 Bytes + └───index.js - 1.11 KB └───index.d.ts - 388 Bytes └───index.js - 1.22 KB └───/parse - └───index.d.ts - 413 Bytes - └───index.js - 1.44 KB + └───index.d.ts - 638 Bytes + └───index.js - 1.6 KB └───/parseTags - └───index.d.ts - 380 Bytes - └───index.js - 750 Bytes + └───index.d.ts - 605 Bytes + └───index.js - 918 Bytes └───/removeTags └───index.d.ts - 306 Bytes └───index.js - 1.58 KB @@ -632,25 +657,25 @@ README.md -- this file └───index.d.ts - 627 Bytes └───index.js - 79 Bytes └───/_private - └───types.d.ts - 120 Bytes + └───types.d.ts - 177 Bytes └───types.js - 79 Bytes - └───utils.d.ts - 1.89 KB - └───utils.js - 13.42 KB + └───utils.d.ts - 2.12 KB + └───utils.js - 13.47 KB └───/es6 └───/getCommentsFromFile └───index.d.ts - 784 Bytes └───index.js - 2.13 KB └───/getTag - └───index.d.ts - 431 Bytes - └───index.js - 823 Bytes + └───index.d.ts - 628 Bytes + └───index.js - 1005 Bytes └───index.d.ts - 388 Bytes └───index.js - 272 Bytes └───/parse - └───index.d.ts - 413 Bytes - └───index.js - 1.3 KB + └───index.d.ts - 638 Bytes + └───index.js - 1.47 KB └───/parseTags - └───index.d.ts - 380 Bytes - └───index.js - 607 Bytes + └───index.d.ts - 605 Bytes + └───index.js - 775 Bytes └───/removeTags └───index.d.ts - 306 Bytes └───index.js - 1.45 KB @@ -661,10 +686,10 @@ README.md -- this file └───index.d.ts - 627 Bytes └───index.js - 12 Bytes └───/_private - └───types.d.ts - 120 Bytes + └───types.d.ts - 177 Bytes └───types.js - 12 Bytes - └───utils.d.ts - 1.89 KB - └───utils.js - 11.88 KB + └───utils.d.ts - 2.12 KB + └───utils.js - 11.94 KB ``` diff --git a/bin/generateReadme.js b/bin/generateReadme.js index f551e74..32f4329 100644 --- a/bin/generateReadme.js +++ b/bin/generateReadme.js @@ -1,3 +1,5 @@ +/* eslint-disable no-undef */ +/* eslint-disable @typescript-eslint/no-var-requires */ const ejs = require('ejs'); const { copyFileSync, existsSync, readdirSync, readFileSync, writeFileSync, exists } = require('fs'); const { join, resolve } = require('path'); @@ -139,7 +141,7 @@ ${util.example.map(x => x.value).join('\n')} } if (isNotNullOrEmpty(examples)) { - examples = '

Examples

\n\n' + examples + examples = '

Examples

\n\n' + examples; } const _import = ` diff --git a/bin/readme.ejs b/bin/readme.ejs index c0c04d5..aa02b01 100644 --- a/bin/readme.ejs +++ b/bin/readme.ejs @@ -27,6 +27,31 @@ <%= interfaces %> ``` +

Using a custom linkRenderer

+

+ Some functions have an optional linkRenderer which is used to convert inline + {@link} and {@tutorial} tags to clickable links. +

+

+ By default, the output will be a basic link like: +

+ +``` +text +``` + +

However, you can override that by providing your own linkRenderer. For example:

+ +``` +const myLinkRenderer = (link: InlineLink) => `${link.text} + +// outputs => +text +``` + +

Without further ado, the utils...

+
+ <% for(var f=0; f < utils.length; f++) { %> <%- generateTable(utils[f], package.name) %> diff --git a/dist/README.md b/dist/README.md index a0fd85b..11818e7 100644 --- a/dist/README.md +++ b/dist/README.md @@ -73,6 +73,31 @@ export type GetCommentsFromFileConfig = { keepIndent?: boolean }; export type ToCommentStringConfig = { indentChars?: number }; ``` +

Using a custom linkRenderer

+

+ Some functions have an optional linkRenderer which is used to convert inline + {@link} and {@tutorial} tags to clickable links. +

+

+ By default, the output will be a basic link like: +

+ +``` +text +``` + +

However, you can override that by providing your own linkRenderer. For example:

+ +``` +const myLinkRenderer = (link: InlineLink) => `${link.text} + +// outputs => +text +``` + +

Without further ado, the utils...

+
+ @@ -150,9 +175,9 @@ getCommentsFromFile(file); Param - Type + TypeDefault -

jsdoc

The entire jsdoc stringstring +

jsdoc

The entire jsdoc stringstring

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {(tag: string) => ITag | Array<ITag | ITag[]>} Function to get the tag or array of all tags that go by that name

Import

@@ -275,7 +300,7 @@ tag('@customTag'); Param TypeDefault -

jsdoc

The entire jsdoc comment stringstring

customTags (optional)

Optional array of custom tags parsestring[][] +

jsdoc

The entire jsdoc comment stringstring

customTags (optional)

Optional array of custom tags parsestring[][]

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {object} Object with keys of each parsed tag

Import

@@ -417,9 +442,9 @@ parse(jsdoc, ['customTag', 'docgen_types']); Param - Type + TypeDefault -

jsdoc

The entire jsdoc comment stringstring

tags

The tags to parsestring[] +

jsdoc

The entire jsdoc comment stringstring

tags

The tags to parsestring[]

linkRenderer (optional)

Optional function to override default rendering of inline link and tutorial tags(link: InlineLink) => stringlinkRenderer

Returns: {object} Object with keys of each parsed tag

Import

@@ -612,16 +637,16 @@ README.md -- this file └───index.d.ts - 784 Bytes └───index.js - 2.29 KB └───/getTag - └───index.d.ts - 431 Bytes - └───index.js - 951 Bytes + └───index.d.ts - 628 Bytes + └───index.js - 1.11 KB └───index.d.ts - 388 Bytes └───index.js - 1.22 KB └───/parse - └───index.d.ts - 413 Bytes - └───index.js - 1.44 KB + └───index.d.ts - 638 Bytes + └───index.js - 1.6 KB └───/parseTags - └───index.d.ts - 380 Bytes - └───index.js - 750 Bytes + └───index.d.ts - 605 Bytes + └───index.js - 918 Bytes └───/removeTags └───index.d.ts - 306 Bytes └───index.js - 1.58 KB @@ -632,25 +657,25 @@ README.md -- this file └───index.d.ts - 627 Bytes └───index.js - 79 Bytes └───/_private - └───types.d.ts - 120 Bytes + └───types.d.ts - 177 Bytes └───types.js - 79 Bytes - └───utils.d.ts - 1.89 KB - └───utils.js - 13.42 KB + └───utils.d.ts - 2.12 KB + └───utils.js - 13.47 KB └───/es6 └───/getCommentsFromFile └───index.d.ts - 784 Bytes └───index.js - 2.13 KB └───/getTag - └───index.d.ts - 431 Bytes - └───index.js - 823 Bytes + └───index.d.ts - 628 Bytes + └───index.js - 1005 Bytes └───index.d.ts - 388 Bytes └───index.js - 272 Bytes └───/parse - └───index.d.ts - 413 Bytes - └───index.js - 1.3 KB + └───index.d.ts - 638 Bytes + └───index.js - 1.47 KB └───/parseTags - └───index.d.ts - 380 Bytes - └───index.js - 607 Bytes + └───index.d.ts - 605 Bytes + └───index.js - 775 Bytes └───/removeTags └───index.d.ts - 306 Bytes └───index.js - 1.45 KB @@ -661,10 +686,10 @@ README.md -- this file └───index.d.ts - 627 Bytes └───index.js - 12 Bytes └───/_private - └───types.d.ts - 120 Bytes + └───types.d.ts - 177 Bytes └───types.js - 12 Bytes - └───utils.d.ts - 1.89 KB - └───utils.js - 11.88 KB + └───utils.d.ts - 2.12 KB + └───utils.js - 11.94 KB ``` diff --git a/src/_private/types.ts b/src/_private/types.ts index 457aff1..2ec8950 100644 --- a/src/_private/types.ts +++ b/src/_private/types.ts @@ -1,3 +1,3 @@ -import { ITag } from '../types'; +import { InlineLink, ITag } from '../types'; -export type TagMapFunction = (jsdoc: string) => ITag | Array; \ No newline at end of file +export type TagMapFunction = (jsdoc: string, linkRenderer?: (link: InlineLink) => string) => ITag | Array; \ No newline at end of file diff --git a/src/_private/utils.ts b/src/_private/utils.ts index 2a6d4c8..f565178 100644 --- a/src/_private/utils.ts +++ b/src/_private/utils.ts @@ -1,4 +1,4 @@ -import { ITag, IDescriptive, IParam, IType } from '../types'; +import { ITag, IDescriptive, IParam, IType, InlineLink } from '../types'; import { TagMapFunction } from '../_private/types'; export const first = (array: T[], defaultValue?: TDefault) : T | TDefault => array && array[0] || defaultValue; @@ -23,32 +23,32 @@ const removeJsDocCommentStars = (jsdoc: string) => jsdoc.replace(/(?: *?\*\/|^ * * @param {string} jsdoc The entire jsdoc string * @returns {ITag} */ -export const getDescription = (jsdoc: string) : ITag => { +export const getDescription = (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : ITag => { // from tag - const description = getTag('@description')(jsdoc); + const description = getTag('@description')(jsdoc, linkRenderer); if (isNotNullOrEmpty(description)) return description as ITag; // no tag - single line - const text = first(jsdoc.match(/\/\*\*( *)(.*)( *)\*\//), ''); + const text = first(jsdoc.match(/\/\*\*((?:(?! @).)*)(?: *)\*\//), ''); if (isNotNullOrEmpty(text)) { const raw = removeJsDocCommentStars(text); return { tag: '@description', - value: processInlineLinks(raw), + value: processInlineLinks(raw, linkRenderer), raw, }; } // no tag - multiline - const raw = first(jsdoc.match(/\/\*\*( *)(.*)(\r\n|\r|\n)*((?:(?:(?! @).)(?:\{@link|\{@tutorial))*(?:(?!( @)).)*(\r\n|\r|\n)?)*/), '').replace(/^(?:\/\*\*| *\*\/? *)/gm, '').trim(); + const raw = first(jsdoc.match(/\/\*\*((?:(?! @).)*)(\r\n|\r|\n)*((?:(?:(?! @).)(?:\{@link|\{@tutorial))*(?:(?!( @)).)*(\r\n|\r|\n)?)*/), '').replace(/^(?:\/\*\*| *\*\/? *)/gm, '').trim(); if (isNotNullOrEmpty(raw)) { return { tag: '@description', - value: processInlineLinks(raw), + value: processInlineLinks(raw, linkRenderer), raw, }; } @@ -60,8 +60,8 @@ export const getDescription = (jsdoc: string) : ITag => { * @param {string} jsdoc - The entire jsdoc string * @returns {IParam[]} */ -export const getTemplate = () => (jsdoc: string) : IDescriptive[] => { - const rawParams = getTags('@template')(jsdoc) as ITag[]; +export const getTemplate = () => (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : IDescriptive[] => { + const rawParams = getTags('@template')(jsdoc, linkRenderer) as ITag[]; if (isNullOrEmpty(rawParams)) return []; @@ -74,9 +74,9 @@ export const getTemplate = () => (jsdoc: string) : IDescriptive[] => { { tag: '@template', value: match[1].trim(), - description: processInlineLinks(match[2].trim()), + description: processInlineLinks(match[2].trim(), linkRenderer), raw: match[0].trim(), - } + }, ]; } @@ -86,21 +86,18 @@ export const getTemplate = () => (jsdoc: string) : IDescriptive[] => { { tag: '@template', raw: match[0].trim(), - } + }, ]; } - - const value = match[2].trim(); - const description = isNotNullOrEmpty(match[3]) && processInlineLinks(match[3].trim()) || undefined; return [ ...accumulator, { tag: '@template', - value, - description, + value: processInlineLinks(match[2].trim(), linkRenderer), + description: undefined, raw: match[0].trim(), - } + }, ]; }, []); }; @@ -111,8 +108,8 @@ export const getTemplate = () => (jsdoc: string) : IDescriptive[] => { * @param {string} jsdoc - The entire jsdoc string * @returns {IParam[]} */ -export const getParam = (tag: '@param' | '@property' | '@prop' | '@arg' | '@argument') => (jsdoc: string) : IParam[] => { - const rawParams = getTags(tag)(jsdoc) as ITag[]; +export const getParam = (tag: '@param' | '@property' | '@prop' | '@arg' | '@argument') => (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : IParam[] => { + const rawParams = getTags(tag)(jsdoc, linkRenderer) as ITag[]; if (isNullOrEmpty(rawParams)) return []; @@ -124,7 +121,7 @@ export const getParam = (tag: '@param' | '@property' | '@prop' | '@arg' | '@argu const type = match[1]; const optional = match[2].startsWith('[') && match[2].endsWith(']'); let name = optional ? match[2].substring(1, match[2].length - 1) : match[2]; - const description = processInlineLinks(match[3].trim()); + const description = processInlineLinks(match[3].trim(), linkRenderer); let defaultValue: string; if (optional && !name.startsWith('{')) { @@ -142,7 +139,7 @@ export const getParam = (tag: '@param' | '@property' | '@prop' | '@arg' | '@argu optional, defaultValue, raw: `${tag} ${match[0].trim()}`, - } + }, ]; }, []); }; @@ -154,17 +151,16 @@ export const getParam = (tag: '@param' | '@property' | '@prop' | '@arg' | '@argu * @returns {IType} */ export const getTyped = (tag: string) => (jsdoc: string) : IType => { - const _tag = tag.startsWith('@') ? tag : '@' + tag; - const regex = new RegExp(`${_tag} *(?:(?![A-Za-z]))(?:{(.*?)} *)?(?:- )?(.*)`, 'g'); + const regex = new RegExp(`${tag} *(?:(?![A-Za-z]))(?:{(.*?)} *)?(?:- )?(.*)`, 'g'); const match = first(Array.from(jsdoc.matchAll(regex))); if (isNullOrEmpty(match)) return; return { - tag: _tag, + tag: tag, type: match[1]?.trim(), description: isNotNullOrEmpty(match[2]) ? match[2].trim() : undefined, - raw: match[0]?.trim(), + raw: match[0].trim(), }; }; @@ -175,9 +171,8 @@ export const getTyped = (tag: string) => (jsdoc: string) : IType => { * @param {string} jsdoc - The entire jsdoc string * @returns {(ITag | ITag[])} */ -export const getTag = (tag: string) => (jsdoc: string) : ITag | ITag[] => { - const _tag = tag.startsWith('@') ? tag : '@' + tag; - const matches = jsdoc.match(getTagRegExp(_tag)); +export const getTag = (tag: string) => (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : ITag | ITag[] => { + const matches = jsdoc.match(getTagRegExp(tag)); if (isNullOrEmpty(matches)) { return; @@ -188,8 +183,8 @@ export const getTag = (tag: string) => (jsdoc: string) : ITag | ITag[] => { if (isNotNullOrEmpty(match) && match.length <= 1) { const raw = removeJsDocCommentStars(first(matches, '')); return { - tag: _tag, - value: processInlineLinks(raw.replace(_tag, '').trim()), + tag, + value: processInlineLinks(raw.replace(tag, '').trim(), linkRenderer), raw, }; } @@ -197,8 +192,8 @@ export const getTag = (tag: string) => (jsdoc: string) : ITag | ITag[] => { const raw = removeJsDocCommentStars(first(matches, '')); return { - tag: _tag, - value: processInlineLinks(raw.replace(_tag, '').trim()), + tag, + value: processInlineLinks(raw.replace(tag, '').trim(), linkRenderer), raw, }; }; @@ -210,9 +205,8 @@ export const getTag = (tag: string) => (jsdoc: string) : ITag | ITag[] => { * @param {string} jsdoc - The entire jsdoc string * @returns {string[]} Array of string values for each matching tag */ -export const getTags = (tag: string) => (jsdoc: string) : Array => { - const _tag = tag.startsWith('@') ? tag : '@' + tag; - const regex = getTagRegExp(_tag); +export const getTags = (tag: string) => (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : Array => { + const regex = getTagRegExp(tag); const matches = [...Array.from(jsdoc.matchAll(regex))]; if (isNullOrEmpty(matches)) { @@ -224,14 +218,14 @@ export const getTags = (tag: string) => (jsdoc: string) : Array = const raw = removeJsDocCommentStars(first(x, '')); return { - tag: _tag, - value: processInlineLinks(raw.replace(_tag, '').trim()), + tag, + value: processInlineLinks(raw.replace(tag, '').trim(), linkRenderer), raw, }; }); } - return [getTag(_tag)(jsdoc)]; + return [getTag(tag)(jsdoc, linkRenderer)]; }; /** @@ -239,15 +233,17 @@ export const getTags = (tag: string) => (jsdoc: string) : Array = * @param jsdoc - Any jsdoc string * @returns {string} The updated string with anchor tags */ -const processInlineLinks = (jsdoc: string) : string => { +const processInlineLinks = (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : string => { if (isNullOrEmpty(jsdoc)) return jsdoc; + const renderLink = linkRenderer || ((link: InlineLink) => `${link.text}`); + const matches = Array.from(jsdoc.matchAll(/(?:\[(.*?)\])?{@(link|tutorial) (.*?)(?:(?:\|| +)(.*?))?}/gm)); if (isNullOrEmpty(matches)) return jsdoc; for (const match of matches) { - // const tag = match[2].trim(); + const tag = match[2].trim(); const url = match[3].trim(); let text = url; @@ -257,7 +253,7 @@ const processInlineLinks = (jsdoc: string) : string => { text = match[1].trim(); } - jsdoc = jsdoc.replace(match[0], `${text}`); + jsdoc = jsdoc.replace(match[0], renderLink({ tag, url, text, raw: match[0] })); } return jsdoc; @@ -352,5 +348,5 @@ export const getTagMap = () : Map => new Map { }); }); + test('getTag => @description => no description', () => { + expect(getTag(`/** @readonly */`)('@description')).toBe(undefined); + }); + test('getTag => @since', () => { expect(getTag(jsdoc)('@since')).toStrictEqual({ tag: '@since', @@ -327,6 +333,28 @@ describe('getTag', () => { }]); }); + test('getTag => inline => {@link} => linkRenderer', () => { + const jsdoc = ` + /** + * See {@link MyClass} and [MyClass's foo property]{@link MyClass#foo}. + * Also, check out {@link http://www.google.com|Google} and + * {@link https://github.com GitHub}. + * @see {@link MyClass} and [MyClass's foo property]{@link MyClass#foo}. + * Also, check out {@link http://www.google.com|Google} and + * {@link https://github.com GitHub}. + */`; + expect(getTag(jsdoc, link => `${link.text}`)('@description')).toStrictEqual({ + tag: '@description', + value: 'See MyClass and MyClass\'s foo property.\nAlso, check out Google and\nGitHub.', + raw: 'See {@link MyClass} and [MyClass\'s foo property]{@link MyClass#foo}.\nAlso, check out {@link http://www.google.com|Google} and\n{@link https://github.com GitHub}.', + }); + expect(getTag(jsdoc, link => `${link.text}`)('@see')).toStrictEqual([{ + tag: '@see', + value: 'MyClass and MyClass\'s foo property.\nAlso, check out Google and\nGitHub.', + raw: '@see {@link MyClass} and [MyClass\'s foo property]{@link MyClass#foo}.\nAlso, check out {@link http://www.google.com|Google} and\n{@link https://github.com GitHub}.', + }]); + }); + test('getTag => typed', () => { let jsdoc = ` /** @@ -458,4 +486,19 @@ describe('getTag', () => { }, ]); }); + + test('getTag => @type', () => { + expect(getTag('/**\n * @type {string} description\n */')('@type')).toStrictEqual({ + tag: '@type', + type: 'string', + description: 'description', + raw: '@type {string} description', + }); + }); + expect(getTag('/**\n * @type {string}\n */')('@type')).toStrictEqual({ + tag: '@type', + type: 'string', + description: undefined, + raw: '@type {string}', + }); }); \ No newline at end of file diff --git a/src/getTag/index.ts b/src/getTag/index.ts index 10b3d50..d7a1ebd 100644 --- a/src/getTag/index.ts +++ b/src/getTag/index.ts @@ -1,22 +1,23 @@ -import { ITag } from '../types'; +import { InlineLink, ITag } from '../types'; import { getTagMap, getTags } from './../_private/utils'; /** * Gets a jsdoc tag's data; if the tag type supports multiple entries, an array of the tags will be returned * * @param {string} jsdoc - The entire jsdoc string + * @param {(link: InlineLink) => string} [linkRenderer] - Optional function to override default rendering of inline link and tutorial tags * @returns {(tag: string) => ITag | Array} Function to get the tag or array of all tags that go by that name */ -export const getTag = (jsdoc: string) : (tag: string) => ITag | Array => { +export const getTag = (jsdoc: string, linkRenderer?: (link: InlineLink) => string) : (tag: string) => ITag | Array => { const tagMap = getTagMap(); return (tag: string) : ITag | Array => { const _tag = tag.startsWith('@') ? tag : '@' + tag; const func = tagMap.get(_tag); - if (func) return func(jsdoc); + if (func) return func(jsdoc, linkRenderer); // Custom tag - const tags = getTags(_tag)(jsdoc); + const tags = getTags(_tag)(jsdoc, linkRenderer); if (tags.length === 0) return; if (tags.length === 1) return tags[0]; diff --git a/src/parse/index.ts b/src/parse/index.ts index acaddc8..8467b62 100644 --- a/src/parse/index.ts +++ b/src/parse/index.ts @@ -1,5 +1,6 @@ import { getTagMap } from '../_private/utils'; import { getTag } from '../getTag'; +import { InlineLink } from '../types'; /** * Parse a jsdoc comment string against all potential jsdoc tags and optional custom tags @@ -7,10 +8,11 @@ import { getTag } from '../getTag'; * @since v1.0.0 * @param {string} jsdoc - The entire jsdoc comment string * @param {string[]} [customTags=[]] - Optional array of custom tags parse + * @param {(link: InlineLink) => string} [linkRenderer] - Optional function to override default rendering of inline link and tutorial tags * @returns {object} Object with keys of each parsed tag */ -export const parse = (jsdoc: string, customTags: string[] = []) : Record => { - const tag = getTag(jsdoc); +export const parse = (jsdoc: string, customTags: string[] = [], linkRenderer?: (link: InlineLink) => string) : Record => { + const tag = getTag(jsdoc, linkRenderer); const allTags = [...Array.from(getTagMap().keys()), ...customTags]; const output = allTags.reduce((accumulator, item) => { diff --git a/src/parseTags/index.ts b/src/parseTags/index.ts index 8c4c849..22d213a 100644 --- a/src/parseTags/index.ts +++ b/src/parseTags/index.ts @@ -1,4 +1,5 @@ import { getTag } from '../getTag'; +import { InlineLink } from '../types'; /** * Parse a jsdoc comment string against specified tags only; custom tags may be included @@ -6,10 +7,11 @@ import { getTag } from '../getTag'; * @since v1.0.0 * @param {string} jsdoc - The entire jsdoc comment string * @param {string[]} tags - The tags to parse + * @param {(link: InlineLink) => string} [linkRenderer] - Optional function to override default rendering of inline link and tutorial tags * @returns {object} Object with keys of each parsed tag */ -export const parseTags = (jsdoc: string, tags: string[]) : Record => { - const tag = getTag(jsdoc); +export const parseTags = (jsdoc: string, tags: string[], linkRenderer?: (link: InlineLink) => string) : Record => { + const tag = getTag(jsdoc, linkRenderer); return tags.reduce((accumulator, x) => Object.assign(accumulator, { [x.replace('@', '')]: tag(x),