Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support description/example indentation #407

Merged
merged 1 commit into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/__tests__/description/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
27 changes: 20 additions & 7 deletions src/__tests__/description/schemas/OneSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -51,9 +64,9 @@ export const exampleNewLineSchema = Joi.object({
})
.example(
`
I have many
lines!
`
I have many
lines!
`
)
.meta({ className: 'ExampleNewLine' });

Expand Down
46 changes: 41 additions & 5 deletions src/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
Expand All @@ -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}`);
}
}

Expand All @@ -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
};
}