Skip to content

Commit

Permalink
feat: format indented code block
Browse files Browse the repository at this point in the history
issue: #32
  • Loading branch information
hosseinmd committed Feb 26, 2021
1 parent f755db1 commit b5d8c9f
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 64 deletions.
28 changes: 27 additions & 1 deletion src/descriptionFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { format } from "prettier";
import { DESCRIPTION, EXAMPLE, TODO } from "./tags";
import { AllOptions } from "./types";
import { capitalizer } from "./utils";
import { capitalizer, formatCode } from "./utils";

const EMPTY_LINE_SIGNATURE = "2@^5!~#sdE!_EMPTY_LINE_SIGNATURE";
const NEW_LINE_START_WITH_DASH = "2@^5!~#sdE!_NEW_LINE_START_WITH_DASH";
Expand All @@ -12,6 +12,7 @@ const NEW_PARAGRAPH_START_WITH_DASH =
const NEW_PARAGRAPH_START_THREE_SPACE_SIGNATURE =
"2@^5!~#sdE!_NEW_PARAGRAPH_START_THREE_SPACE_SIGNATURE";
const CODE = "2@^5!~#sdE!_CODE";
const CODE_INDENTED = "2@^5!~#sdE!_CODE_INDENTED";

interface DescriptionEndLineParams {
description: string;
Expand Down Expand Up @@ -63,6 +64,17 @@ function formatDescription(
text = text.replace(code, `\n\n${CODE}\n\n`);
});
}
const intendedCodes: string[] = [];
text = text.replace(
/(\n\n[^\S\r\n]{4}[\s\S]*?)((\n[\S])|$)/g,
(code, _1, _2, _3) => {
code = _3 ? code.slice(0, -1) : code;

intendedCodes.push(code);
return `\n\n${CODE_INDENTED}\n\n${_3 ? _3.slice(1) : ""}`;
},
);

/**
* Description
*
Expand Down Expand Up @@ -194,6 +206,19 @@ function formatDescription(
}, "");
}

if (intendedCodes.length > 0) {
text = text.split(CODE_INDENTED).reduce((pre, cur, index) => {
let result = intendedCodes?.[index] || "";
const beginningSpace = " ".repeat(4);

if (result) {
// Remove two space from lines, maybe added previous format
result = formatCode(result, beginningSpace, options).trim();
}
return `${pre}${cur.trim()}${result ? `\n\n ${result}\n\n` : ""}`;
}, "");
}

text = text.trim().slice(tagStringLength);

return text;
Expand All @@ -209,6 +234,7 @@ function breakDescriptionToLines(
if (!str) {
return str;
}

const extraLastLineWidth = 10;
let result = "";
while (str.length > maxWidth + extraLastLineWidth) {
Expand Down
48 changes: 5 additions & 43 deletions src/stringify.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Spec } from "comment-parser/src/primitives";
import { format } from "prettier";
import { formatDescription, descriptionEndLine } from "./descriptionFormatter";
import { DESCRIPTION, EXAMPLE, SPACE_TAG_DATA } from "./tags";
import {
Expand All @@ -8,6 +7,7 @@ import {
TAGS_VERTICALLY_ALIGN_ABLE,
} from "./roles";
import { AllOptions } from "./types";
import { formatCode } from "./utils";

const stringify = (
{ name, description, type, tag }: Spec,
Expand All @@ -29,7 +29,6 @@ const stringify = (
jsdocSpaces,
jsdocVerticalAlignment,
jsdocDescriptionTag,
jsdocKeepUnParseAbleExampleIndent,
useTabs,
tabWidth,
} = options;
Expand Down Expand Up @@ -96,47 +95,10 @@ const stringify = (
}

const beginningSpace = useTabs ? "\t" : " ".repeat(tabWidth);

// Remove two space from lines, maybe added previous format
if (
description
.split("\n")
.slice(1)
.every((v) => !v.trim() || v.startsWith(beginningSpace))
) {
description = description.replace(
new RegExp(`\n${useTabs ? "[\t]" : `[^S\r\n]{${tabWidth}}`}`, "g"),
"\n",
);
}

try {
let formattedExample = "";
const examplePrintWith = printWidth - tabWidth;

// If example is a json
if (description.trim().startsWith("{")) {
formattedExample = format(description || "", {
...options,
parser: "json",
printWidth: examplePrintWith,
});
} else {
formattedExample = format(description || "", {
...options,
printWidth: examplePrintWith,
});
}

tagString += formattedExample.replace(/(^|\n)/g, "\n" + beginningSpace); // Add tow space to start of lines
tagString = tagString.slice(0, tagString.length - 3);
} catch (err) {
tagString += "\n";
tagString += description
.split("\n")
.map((l) => ` ${jsdocKeepUnParseAbleExampleIndent ? l : l.trim()}`)
.join("\n");
}
const formattedExample = formatCode(description, beginningSpace, options);
tagString += formattedExample.startsWith("\n")
? formattedExample.trimEnd()
: "\n" + formattedExample;
}

// Add empty line after some tags if there is something below
Expand Down
59 changes: 59 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,70 @@ function findTokenIndex(tokens: Token[], token: Token): number {
});
}

function formatCode(
result: string,
beginningSpace: string,
options: AllOptions,
): string {
const { printWidth, jsdocKeepUnParseAbleExampleIndent } = options;

if (
result
.split("\n")
.slice(1)
.every((v) => !v.trim() || v.startsWith(beginningSpace))
) {
result = result.replace(
new RegExp(
`\n${beginningSpace
.replace(/[\t]/g, "[\\t]")
.replace(/[^S\r\n]/g, "[^S\\r\\n]")}`,
"g",
),
"\n",
);
}

try {
let formattedExample = "";
const examplePrintWith = printWidth - 4;

// If example is a json
if (result.trim().startsWith("{")) {
formattedExample = format(result || "", {
...options,
parser: "json",
printWidth: examplePrintWith,
});
} else {
formattedExample = format(result || "", {
...options,
printWidth: examplePrintWith,
});
}

result = formattedExample.replace(/(^|\n)/g, "\n" + beginningSpace); // Add spaces to start of lines
} catch (err) {
result = result
.split("\n")
.map(
(l) =>
`${beginningSpace}${
jsdocKeepUnParseAbleExampleIndent ? l : l.trim()
}`,
)
.join("\n");
}

return result;
}

export {
convertToModernType,
formatType,
addStarsToTheBeginningOfTheLines,
capitalizer,
detectEndOfLine,
findTokenIndex,
formatCode,
};
20 changes: 10 additions & 10 deletions tests/__snapshots__/files/prism-core.js.shot
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ var Prism = (function (_self) {
* type([1, 2]) === 'Array';
* type({}) === 'Object';
* type(String) === 'Function';
* type(/abc+/) === 'RegExp'
* type(/abc+/) === 'RegExp';
*
* @param {any} o
* @returns {string}
Expand Down Expand Up @@ -275,13 +275,13 @@ var Prism = (function (_self) {
* Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
*
* @example
* Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
* // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
* // at its original position
* 'comment': { ... },
* // CSS doesn't have a 'color' token, so this token will be appended
* 'color': /\\\\b(?:red|green|blue)\\\\b/
* });
* Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
* // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
* // at its original position
* 'comment': { ... },
* // CSS doesn't have a 'color' token, so this token will be appended
* 'color': /\\\\b(?:red|green|blue)\\\\b/
* });
*
* @param {string} id The id of the language to extend. This has to be a key in \`Prism.languages\`.
* @param {Grammar} redef The new tokens to append.
Expand Down Expand Up @@ -593,7 +593,7 @@ var Prism = (function (_self) {
*
* @memberof Prism
* @example
* Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript')
* Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
*
* @param {string} text A string with the code to be highlighted.
* @param {Grammar} grammar An object containing the tokens to use.
Expand Down Expand Up @@ -631,7 +631,7 @@ var Prism = (function (_self) {
* if (token instanceof Prism.Token && token.type === 'number') {
* console.log(\`Found numeric literal: \${token.content}\`);
* }
* })
* });
*
* @param {string} text A string with the code to be highlighted.
* @param {Grammar} grammar An object containing the tokens to use.
Expand Down
46 changes: 46 additions & 0 deletions tests/__snapshots__/files/types.ts.shot
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,51 @@
exports[`File: types.ts Options: {} 1`] = `
"/** @type {((element: HTMLElement) => boolean)[]} */
var filters = [];

/**
* Returns a slice of the first array that doesn't contain the leading and
* trailing elements the both arrays have in common.
*
* Examples:
*
* trimCommon([1,2,3,4], [1,3,2,4]) => [2,3]
* trimCommon([1,2,3,4], [1,2,3,4]) => []
* trimCommon([1,2,0,0,3,4], [1,2,3,4]) => [0,0]
* trimCommon([1,2,3,4], [1,2,0,0,3,4]) => []
*
*
*
* trimCommon([1,2,3,4],[1,3,2,4])
* trimCommon([1,2,3,4 ], [1,2,3,4])
* trimCommon([1,2,0,0, 3,4], [1,2,3,4])
* trimCommon([1,2,3,4],[1,2,0,0,3,4])
*
* @template T
* @param {readonly T[]} a1
* @param {readonly T[]} a2
* @returns {T[]}
*/

/**
* Returns a slice of the first array that doesn't contain the leading and
* trailing elements the both arrays have in common.
*
* Examples:
*
* trimCommon([1,2,3,4], [1,3,2,4]) => [2,3]
* trimCommon([1,2,3,4], [1,2,3,4]) => []
* trimCommon([1,2,0,0,3,4], [1,2,3,4]) => [0,0]
* trimCommon([1,2,3,4], [1,2,0,0,3,4]) => []
*
* trimCommon([1,2,3,4],[1,3,2,4])
* trimCommon([1,2,3,4 ], [1,2,3,4])
* trimCommon([1,2,0,0, 3,4], [1,2,3,4])
* trimCommon([1,2,3,4],[1,2,0,0,3,4])
*
* @template T
* @param {readonly T[]} a1
* @param {readonly T[]} a2
* @returns {T[]}
*/
"
`;
13 changes: 6 additions & 7 deletions tests/__snapshots__/paragraph.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -354,17 +354,16 @@ exports[`description new line with dash 3`] = `
*
* The test case file can either consist of two parts:
*
* {source code}
* -------------------------------------
* {expected token stream}
* const a = \\"\\";
* const b = { c: [] };
*
* Or of three parts:
*
* {source code}
* -------------------------------------
* {expected token stream}
* -------------------------------------
* {text comment explaining the test case}
* ----
* {expected token stream}
* ----
* {text comment explaining the test case}
*
* If the file contains more than three parts, the remaining parts are just
* ignored. If the file however does not contain at least two parts (so no
Expand Down
47 changes: 47 additions & 0 deletions tests/files/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,50 @@
* @type {Array<(element: HTMLElement) => boolean>}
*/
var filters = [];

/**
* Returns a slice of the first array that doesn't contain the leading and trailing elements the both arrays have in
* common.
*
* Examples:
*
* trimCommon([1,2,3,4], [1,3,2,4]) => [2,3]
* trimCommon([1,2,3,4], [1,2,3,4]) => []
* trimCommon([1,2,0,0,3,4], [1,2,3,4]) => [0,0]
* trimCommon([1,2,3,4], [1,2,0,0,3,4]) => []
*
*
*
* trimCommon([1,2,3,4],[1,3,2,4])
* trimCommon([1,2,3,4 ], [1,2,3,4])
* trimCommon([1,2,0,0, 3,4], [1,2,3,4])
* trimCommon([1,2,3,4],[1,2,0,0,3,4])
*
* @param {readonly T[]} a1
* @param {readonly T[]} a2
* @returns {T[]}
* @template T
*/


/**
* Returns a slice of the first array that doesn't contain the leading and trailing elements the both arrays have in
* common.
*
* Examples:
*
* trimCommon([1,2,3,4], [1,3,2,4]) => [2,3]
* trimCommon([1,2,3,4], [1,2,3,4]) => []
* trimCommon([1,2,0,0,3,4], [1,2,3,4]) => [0,0]
* trimCommon([1,2,3,4], [1,2,0,0,3,4]) => []
*
* trimCommon([1,2,3,4],[1,3,2,4])
* trimCommon([1,2,3,4 ], [1,2,3,4])
* trimCommon([1,2,0,0, 3,4], [1,2,3,4])
* trimCommon([1,2,3,4],[1,2,0,0,3,4])
*
* @param {readonly T[]} a1
* @param {readonly T[]} a2
* @returns {T[]}
* @template T
*/
5 changes: 2 additions & 3 deletions tests/paragraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,8 @@ test("description new line with dash", () => {
*
* The test case file can either consist of two parts:
*
* {source code}
* ----
* {expected token stream}
* const a=''
* const b={c:[]}
*
*
* or of three parts:
Expand Down

0 comments on commit b5d8c9f

Please sign in to comment.