diff --git a/src/bin/tools/trimIndent.ts b/src/bin/tools/trimIndent.ts index 33c195ba..1c826cd7 100644 --- a/src/bin/tools/trimIndent.ts +++ b/src/bin/tools/trimIndent.ts @@ -21,13 +21,18 @@ function populateTemplate(strings: TemplateStringsArray, ...args: unknown[]) { return chunks.join(""); } -function trimIndentPrivate(removeEmptyLeadingAndTrailingLines: boolean, strings: TemplateStringsArray, ...args: any[]) { +/** + * Shift all lines left by the *smallest* indentation level, + * and remove initial newline and all trailing spaces. + */ +export default function trimIndent(strings: TemplateStringsArray, ...args: any[]) { // Remove initial and final newlines - let string = populateTemplate(strings, ...args); - if (removeEmptyLeadingAndTrailingLines) { - string = string.replace(/^[\r\n]/, "").replace(/[^\S\r\n]*[\r\n]$/, ""); - } - const dents = string.match(/^([ \t])+/gm)?.map(s => s.length) ?? []; + let string = populateTemplate(strings, ...args) + .replace(/^[\r\n]/, "") + .replace(/\r?\n *$/, ""); + const dents = string.match(/^([ \t])+/gm) + ?.filter(s => /^\s+$/.test(s)) + ?.map(s => s.length) ?? []; // No dents? no change required if (!dents || dents.length == 0) return string; const minDent = Math.min(...dents); @@ -37,19 +42,3 @@ function trimIndentPrivate(removeEmptyLeadingAndTrailingLines: boolean, strings: const dedented = string.replace(re, ""); return dedented; } - -/** - * Shift all lines left by the *smallest* indentation level, - * and remove initial newline and all trailing spaces. - */ -export default function trimIndent(strings: TemplateStringsArray, ...args: unknown[]) { - return trimIndentPrivate(true, strings, ...args); -} - -/** - * Shift all lines left by the *smallest* indentation level, - * and _keep_ initial newline and all trailing spaces. - */ -trimIndent.keepLeadingAndTrailingNewlines = function (strings: TemplateStringsArray, ...args: unknown[]) { - return trimIndentPrivate(false, strings, ...args); -}; diff --git a/test/bin/tools/trimIndet.spec.ts b/test/bin/tools/trimIndet.spec.ts new file mode 100644 index 00000000..b25c33e9 --- /dev/null +++ b/test/bin/tools/trimIndet.spec.ts @@ -0,0 +1,57 @@ +import trimIndent from "keycloakify/bin/tools/trimIndent"; +import { it, describe, assert } from "vitest"; + +describe("trimIndent", () => { + + it("does not change a left-aligned string as expected", () => { + const txt = trimIndent`lorem +ipsum` + assert.equal(txt, ['lorem', 'ipsum'].join('\n')) + }) + + it("removes leading and trailing empty lines from a left-aligned string", () => { + const txt = trimIndent` +lorem +ipsum +` + assert.equal(txt, ['lorem', 'ipsum'].join('\n')) + }) + + it("removes indent from an aligned string", () => { + const txt = trimIndent` + lorem + ipsum + ` + assert.equal(txt, ['lorem', 'ipsum'].join('\n')) + }) + + it("removes indent from unaligned string", () => { + const txt = trimIndent` + lorem + ipsum + ` + assert.equal(txt, ['lorem', ' ipsum'].join('\n')) + }) + + it("removes only first and last empty line", () => { + const txt = trimIndent` + + lorem + ipsum + + ` + + assert.equal(txt, ['', 'lorem', 'ipsum', ''].join('\n')) + }) + + + it("interpolates non-strings", () => { + const d = new Date() + const txt = trimIndent` + lorem + ${d} + ipsum` + + assert.equal(txt, ['lorem', String(d), 'ipsum'].join('\n')) + }) +}) \ No newline at end of file