From 77ffb34fda24858729b5df2aa6bee54e2abbd222 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Sun, 31 May 2020 21:01:08 -0400 Subject: [PATCH 1/4] Better support for typedef @property Given the following JSDoc ```js /** * @typedef {Object} BillboardGraphics.ConstructorOptions * * Initialization options for the BillboardGraphics constructor * * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the billboard. */ ``` tsd-jsdoc was producing the following TS code ```ts /** * Initialization options for the BillboardGraphics constructor * @property [show = true] - A boolean Property specifying the visibility of the billboard. */ type ConstructorOptions = { show?: Property | boolean; }; ``` `@property` is not valid TS markup and the actual property, show, does not include it's description or default value. After this change the same JSDoc markup produces much nicer code that handles both of these: ```ts /** * Initialization options for the BillboardGraphics constructor */ type ConstructorOptions = { /** * A boolean property specifying the visibility of the billboard. * @defaultValue true */ show?: Property | boolean; }; ``` I updated the tests, to match the new output and manually verified its what I would expect. --- src/create_helpers.ts | 6 +- src/type_resolve_helpers.ts | 19 +++++- test/expected/typedef_all.d.ts | 119 ++++++++++++++++++++------------- 3 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/create_helpers.ts b/src/create_helpers.ts index 8cdca7b..60b9ce7 100644 --- a/src/create_helpers.ts +++ b/src/create_helpers.ts @@ -234,9 +234,13 @@ function handleComment(doclet: TDoclet, node: T): T { let comment = `*${description}${examples}${properties}${params}${returns} `; + if(doclet.kind === 'typedef') { + // typedef properties are written out at the member. + comment = `*${description}${examples}${params}${returns} + `; + } const kind = ts.SyntaxKind.MultiLineCommentTrivia; - ts.addSyntheticLeadingComment(node, kind, comment, true); } } diff --git a/src/type_resolve_helpers.ts b/src/type_resolve_helpers.ts index d0fd717..f9a204e 100644 --- a/src/type_resolve_helpers.ts +++ b/src/type_resolve_helpers.ts @@ -740,13 +740,28 @@ export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts const opt = node.prop.optional ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined; const t = node.children.length ? createTypeLiteral(node.children, node) : resolveType(node.prop.type); - members.push(ts.createPropertySignature( + const property = ts.createPropertySignature( undefined, // modifiers node.name, // name opt, // questionToken t, // type undefined // initializer - )); + ); + + // !parent ensures we are dealing with a top-level typedef. + // So that the tsd-doc is added at the property level. + if(!parent && (node.prop.description || node.prop.defaultvalue)) { + let comment = `*\n `; + if(node.prop.description){ + comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n ` + } + if(node.prop.defaultvalue){ + comment += `* @defaultValue ${node.prop.defaultvalue}\n ` + } + ts.addSyntheticLeadingComment(property, ts.SyntaxKind.MultiLineCommentTrivia, comment, true); + } + + members.push(property); } let node: ts.TypeNode = ts.createTypeLiteralNode(members); diff --git a/test/expected/typedef_all.d.ts b/test/expected/typedef_all.d.ts index 08827ce..81cd087 100644 --- a/test/expected/typedef_all.d.ts +++ b/test/expected/typedef_all.d.ts @@ -1,24 +1,36 @@ declare module "typedefs" { /** * The complete Triforce, or one or more components of the Triforce. - * @property hasCourage - Indicates whether the Courage component is present. - * @property hasPower - Indicates whether the Power component is present. - * @property hasWisdom - Indicates whether the Wisdom component is present. */ type Triforce = { + /** + * Indicates whether the Courage component is present. + */ hasCourage: boolean; + /** + * Indicates whether the Power component is present. + */ hasPower: boolean; + /** + * Indicates whether the Wisdom component is present. + */ hasWisdom: boolean; }; /** * The complete Triforce, or one or more components of the Triforce. - * @property hasCourage - Indicates whether the Courage component is present. - * @property hasPower - Indicates whether the Power component is present. - * @property hasWisdom - Indicates whether the Wisdom component is present. */ type Anon = { + /** + * Indicates whether the Courage component is present. + */ hasCourage: boolean; + /** + * Indicates whether the Power component is present. + */ hasPower: boolean; + /** + * Indicates whether the Wisdom component is present. + */ hasWisdom: boolean; thing: { a: { @@ -30,27 +42,52 @@ declare module "typedefs" { }; }; /** - * @property [elementId = "gitGraph"] - Id of the canvas container - * @property [template] - Template of the graph - * @property [author = "Sergio Flores "] - Default author for commits - * @property [mode = (null|"compact")] - Display mode - * @property [canvas] - DOM canvas (ex: document.getElementById("id")) - * @property [orientation = ("vertical-reverse"|"horizontal"|"horizontal-reverse")] - Graph orientation - * @property [reverseArrow = false] - Make arrows point to ancestors if true - * @property [initCommitOffsetX = 0] - Add custom offsetX to initial commit. - * @property [initCommitOffsetY = 0] - Add custom offsetY to initial commit. - * @property [tooltipContainer = document.body] - HTML Element containing tooltips in compact mode. */ type GitGraphOptions = { + /** + * Id of the canvas container + * @defaultValue "gitGraph" + */ elementId?: string; + /** + * Template of the graph + */ template?: Template | string | any; + /** + * Default author for commits + * @defaultValue "Sergio Flores " + */ author?: string; + /** + * Display mode + * @defaultValue (null|"compact") + */ mode?: string; + /** + * DOM canvas (ex: document.getElementById("id")) + */ canvas?: HTMLElement; + /** + * Graph orientation + * @defaultValue ("vertical-reverse"|"horizontal"|"horizontal-reverse") + */ orientation?: string; + /** + * Make arrows point to ancestors if true + */ reverseArrow?: boolean; + /** + * Add custom offsetX to initial commit. + */ initCommitOffsetX?: number; + /** + * Add custom offsetY to initial commit. + */ initCommitOffsetY?: number; + /** + * HTML Element containing tooltips in compact mode. + * @defaultValue document.body + */ tooltipContainer?: HTMLElement; }; /** @@ -58,40 +95,11 @@ declare module "typedefs" { */ type NumberLike = number | string; /** - * @property pattern - Holds a pattern definition. - * @property pattern.image - URL to an image to use as the pattern. - * @property pattern.width - Width of the pattern. For images this is - * automatically set to the width of the element bounding box if not supplied. - * For non-image patterns the default is 32px. Note that automatic resizing of - * image patterns to fill a bounding box dynamically is only supported for - * patterns with an automatically calculated ID. - * @property pattern.height - Analogous to pattern.width. - * @property pattern.aspectRatio - For automatically calculated width and - * height on images, it is possible to set an aspect ratio. The image will be - * zoomed to fill the bounding box, maintaining the aspect ratio defined. - * @property pattern.x - Horizontal offset of the pattern. Defaults to 0. - * @property pattern.y - Vertical offset of the pattern. Defaults to 0. - * @property pattern.path - Either an SVG path as string, or an - * object. As an object, supply the path string in the `path.d` property. Other - * supported properties are standard SVG attributes like `path.stroke` and - * `path.fill`. If a path is supplied for the pattern, the `image` property is - * ignored. - * @property pattern.color - Pattern color, used as default path stroke. - * @property pattern.opacity - Opacity of the pattern as a float value - * from 0 to 1. - * @property pattern.id - ID to assign to the pattern. This is - * automatically computed if not added, and identical patterns are reused. To - * refer to an existing pattern for a Highcharts color, use - * `color: "url(#pattern-id)"`. - * @property animation - Animation options for the image pattern - * loading. - * Note: doesn't matter what I put, a @property only gets "FUNCTION" from jsdoc - * @property rotate - Rotates the pattern by degrees - * @property wiggle - Wiggles the pattern (default function) - * @property wobble - Wobbles the pattern - * (complex function) */ type PatternOptions = { + /** + * Holds a pattern definition. + */ pattern: { image: string; width: number; @@ -104,9 +112,24 @@ declare module "typedefs" { opacity: number; id: string; }; + /** + * Animation options for the image pattern + loading. + Note: doesn't matter what I put, a @property only gets "FUNCTION" from jsdoc + */ animation: any | boolean; + /** + * Rotates the pattern by degrees + */ rotate: (...params: any[]) => any; + /** + * Wiggles the pattern (default function) + */ wiggle: (...params: any[]) => any; + /** + * Wobbles the pattern + (complex function) + */ wobble: (...params: any[]) => any; }; } From 7ab662e9e0ecf74b661d2ddc11717264fe721f49 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 3 Jun 2020 10:00:10 -0400 Subject: [PATCH 2/4] Update src/type_resolve_helpers.ts Co-authored-by: Chad Engler --- src/type_resolve_helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/type_resolve_helpers.ts b/src/type_resolve_helpers.ts index f9a204e..a59e7a9 100644 --- a/src/type_resolve_helpers.ts +++ b/src/type_resolve_helpers.ts @@ -752,9 +752,9 @@ export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts // So that the tsd-doc is added at the property level. if(!parent && (node.prop.description || node.prop.defaultvalue)) { let comment = `*\n `; - if(node.prop.description){ - comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n ` - } + if (node.prop.description) + comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n `; + if(node.prop.defaultvalue){ comment += `* @defaultValue ${node.prop.defaultvalue}\n ` } From e0bdaaab48f3db7074d7c33ca2b51c4b2fd37776 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 3 Jun 2020 10:00:16 -0400 Subject: [PATCH 3/4] Update src/type_resolve_helpers.ts Co-authored-by: Chad Engler --- src/type_resolve_helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/type_resolve_helpers.ts b/src/type_resolve_helpers.ts index a59e7a9..7a851d9 100644 --- a/src/type_resolve_helpers.ts +++ b/src/type_resolve_helpers.ts @@ -755,9 +755,9 @@ export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts if (node.prop.description) comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n `; - if(node.prop.defaultvalue){ - comment += `* @defaultValue ${node.prop.defaultvalue}\n ` - } + if (node.prop.defaultvalue) + comment += `* @defaultValue ${node.prop.defaultvalue}\n `; + ts.addSyntheticLeadingComment(property, ts.SyntaxKind.MultiLineCommentTrivia, comment, true); } From f197e45885e989e9205df4fd40aa0c42bbcd583f Mon Sep 17 00:00:00 2001 From: Chad Engler Date: Wed, 3 Jun 2020 07:13:14 -0700 Subject: [PATCH 4/4] Style fixes --- src/create_helpers.ts | 3 ++- src/type_resolve_helpers.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/create_helpers.ts b/src/create_helpers.ts index 60b9ce7..5b691a0 100644 --- a/src/create_helpers.ts +++ b/src/create_helpers.ts @@ -234,7 +234,8 @@ function handleComment(doclet: TDoclet, node: T): T { let comment = `*${description}${examples}${properties}${params}${returns} `; - if(doclet.kind === 'typedef') { + if (doclet.kind === 'typedef') + { // typedef properties are written out at the member. comment = `*${description}${examples}${params}${returns} `; diff --git a/src/type_resolve_helpers.ts b/src/type_resolve_helpers.ts index 7a851d9..85d37e5 100644 --- a/src/type_resolve_helpers.ts +++ b/src/type_resolve_helpers.ts @@ -750,7 +750,8 @@ export function createTypeLiteral(children: IPropDesc[], parent?: IPropDesc): ts // !parent ensures we are dealing with a top-level typedef. // So that the tsd-doc is added at the property level. - if(!parent && (node.prop.description || node.prop.defaultvalue)) { + if (!parent && (node.prop.description || node.prop.defaultvalue)) + { let comment = `*\n `; if (node.prop.description) comment += `* ${node.prop.description.split(/\r\s*/).join("\n * ")}\n `;