From a9cdde0a6db374e13fd882d6b072ae68c666043a Mon Sep 17 00:00:00 2001 From: Alberto Marchetti Date: Sun, 17 Dec 2023 08:32:52 +0200 Subject: [PATCH] Support description/example indentation --- src/__tests__/description/index.ts | 18 +++++++- .../description/schemas/OneSchema.ts | 27 ++++++++--- src/write.ts | 46 +++++++++++++++++-- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/__tests__/description/index.ts b/src/__tests__/description/index.ts index 9cf3ac03..fe341e47 100644 --- a/src/__tests__/description/index.ts +++ b/src/__tests__/description/index.ts @@ -114,16 +114,30 @@ export interface Example { } /** - * This is a long description. + * This is a long indented description. * There are many lines! * * And more here! */ export interface ExampleLong { /** - * another + * Another description */ another: string; + /** + * Not indented description + */ + noIndent?: string; + /** + * Badly indented description + * What a line + */ + badIndent?: string; + /** + * Another badly indented description + * What a line + */ + badIndent2?: string; } /** diff --git a/src/__tests__/description/schemas/OneSchema.ts b/src/__tests__/description/schemas/OneSchema.ts index 6425a507..d5a00e56 100644 --- a/src/__tests__/description/schemas/OneSchema.ts +++ b/src/__tests__/description/schemas/OneSchema.ts @@ -7,12 +7,25 @@ export const exampleSchema = Joi.object({ .description('A simple description'); export const exampleLongSchema = Joi.object({ - another: Joi.string().required() + another: Joi.string().required().description(` + Another description + `), + noIndent: Joi.string().description(` +Not indented description +`), + badIndent: Joi.string().description(` +Badly indented description + What a line +`), + badIndent2: Joi.string().description(` + Another badly indented description + What a line +`) }).meta({ className: 'ExampleLong' }).description(` -This is a long description. -There are many lines! + This is a long indented description. + There are many lines! -And more here! + And more here! `); export const noCommentSchema = Joi.object({ @@ -51,9 +64,9 @@ export const exampleNewLineSchema = Joi.object({ }) .example( ` -I have many -lines! -` + I have many + lines! + ` ) .meta({ className: 'ExampleNewLine' }); diff --git a/src/write.ts b/src/write.ts index 964f9485..6833adb0 100644 --- a/src/write.ts +++ b/src/write.ts @@ -56,7 +56,7 @@ export function getJsDocString(settings: Settings, name: string, jsDoc?: JsDoc, if (settings.commentEverything || (jsDoc && jsDoc.description)) { let description = name; if (jsDoc?.description) { - description = jsDoc.description.trim(); + description = getStringIndentation(jsDoc.description).deIndentedString; } lines.push(...description.split('\n').map(line => ` * ${line}`.trimEnd())); } @@ -67,13 +67,13 @@ export function getJsDocString(settings: Settings, name: string, jsDoc?: JsDoc, } for (const example of jsDoc?.examples ?? []) { - const trimmed = example.trim(); + const deIndented = getStringIndentation(example).deIndentedString; - if (trimmed.includes('\n')) { + if (deIndented.includes('\n')) { lines.push(` * @example`); - lines.push(...trimmed.split('\n').map(line => ` * ${line}`.trimEnd())); + lines.push(...deIndented.split('\n').map(line => ` * ${line}`.trimEnd())); } else { - lines.push(` * @example ${trimmed}`); + lines.push(` * @example ${deIndented}`); } } @@ -83,3 +83,39 @@ export function getJsDocString(settings: Settings, name: string, jsDoc?: JsDoc, return lines.map(line => `${getIndentStr(settings, indentLevel)}${line}`).join('\n') + '\n'; } + +interface GetStringIndentationResult { + deIndentedString: string; + indent: string; +} + +/** + * Given an indented string, uses the first line's indentation as base to de-indent + * the rest of the string, and returns both the de-indented string and the + * indentation found as prefix. + */ +function getStringIndentation(value: string): GetStringIndentationResult { + const lines = value.split('\n'); + let indent = ''; + for (const line of lines) { + // Skip initial newlines + if (line.trim() == '') { + continue; + } + const match = /^(\s+)\b/.exec(line); + if (match) { + indent = match[1]; + } + break; + } + + const deIndentedString = lines + .map(line => (line.startsWith(indent) ? line.substring(indent.length) : line)) + .join('\n') + .trim(); + + return { + deIndentedString, + indent + }; +}