Commit 1c638bd1 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Convert trimAndDedent in a tag function

parent 7db92f0c
......@@ -2,10 +2,10 @@ import { trimAndDedent } from '../trim-and-dedent';
describe('trimAndDedent', () => {
[
['Foo', 'Foo'],
[' Foo', 'Foo'],
[() => trimAndDedent`Foo`, 'Foo'],
[() => trimAndDedent` Foo`, 'Foo'],
[
`First line
() => trimAndDedent`First line
Second line
Third line`,
`First line
......@@ -13,7 +13,7 @@ describe('trimAndDedent', () => {
Third line`,
],
[
`
() => trimAndDedent`
Hello, Jane!
Indented line
......@@ -24,10 +24,38 @@ describe('trimAndDedent', () => {
Indented line
Goodbye, John!`,
],
].forEach(([str, expectedResult]) => {
[
() => {
const firstVar = ` very indented`;
const secondVar = `
multiple
lines
with no indentation
`;
return trimAndDedent`
Hello, Jane!
${firstVar}
Indented line
Goodbye, John!
${secondVar}
`;
},
`Hello, Jane!
very indented
Indented line
Goodbye, John!
multiple
lines
with no indentation
`,
],
].forEach(([getResult, expectedResult]) => {
it('normalizes strings with multiple lines', () => {
const result = trimAndDedent(str);
assert.equal(result, expectedResult);
assert.equal(getResult(), expectedResult);
});
});
});
function trimLeadingEmptyLines(str: string): string {
return str.replace(/^\s*\n/g, '');
}
function trimTrailingEmptyLines(str: string): string {
return str.replace(/\n\s*$/g, '');
}
/**
* Remove leading and trailing empty lines from a string.
* Remove specified indentation from each line of a string.
*/
function trimEmptyLines(str: string): string {
return str.replace(/^\s*\n|\n\s*$/g, '');
function dedentStr(str: string, indent: number) {
const indentRegexp = new RegExp(`^ {${indent}}`, 'gm');
return str.replace(indentRegexp, '');
}
/**
* Remove common indentation from each line of a string.
* Remove common indentation from each line of every string, then interpolate
* params verbatim.
*/
function dedent(str: string) {
// Match the smallest indentation
function dedent(strings: string[], ...params: any[]) {
// Match the smallest indentation among all strings
const indents = strings
.map(str => {
const match = str.match(/^[ \t]*(?=\S)/gm);
const indent = match && Math.min(...match.map(el => el.length));
return match ? Math.min(...match.map(el => el.length)) : -1;
})
// Exclude lines where indentation could not be matched
.filter(num => num > -1);
const smallestIndent = indents.length > 0 ? Math.min(...indents) : 0;
if (indent) {
const regexp = new RegExp(`^ {${indent}}`, 'gm');
return str.replace(regexp, '');
let result = '';
for (const [i, param] of params.entries()) {
result += dedentStr(strings[i], smallestIndent);
result += param;
}
return str;
return result + dedentStr(strings[strings.length - 1], smallestIndent);
}
/**
......@@ -35,21 +52,45 @@ function dedent(str: string) {
* if (arg === 3) {
* console.log(`First line
* Second line
* Third line`);
* ${var}
* Fourth line`);
* }
* }
*
* to this:
* function foo(arg) {
* if (arg === 3) {
* console.log(trimAndDedent(`
* console.log(trimAndDedent`
* First line
* Second line
* Third line
* `));
* ${var}
* Fourth line
* `);
* }
* }
*/
export function trimAndDedent(str: string): string {
return dedent(trimEmptyLines(str));
export function trimAndDedent(
strings: TemplateStringsArray,
...params: any[]
): string {
if (strings.length < 2) {
// Trim leading and trailing empty lines from first (and only) string
const trimmedLines = [
trimLeadingEmptyLines(trimTrailingEmptyLines(strings[0])),
];
return dedent(trimmedLines, ...params);
}
const firstString = strings[0];
const lastString = strings[strings.length - 1];
const middle = strings.slice(1, strings.length - 1);
// Trim empty leading lines from first string, and empty trailing lines from last one
const trimmedLines = [
trimLeadingEmptyLines(firstString),
...middle,
trimTrailingEmptyLines(lastString),
];
return dedent(trimmedLines, ...params);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment