Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Dedenting Template Strings
function dedent(callSite, ...args) {
function format(str) {
let size = -1;
return str.replace(/\n(\s+)/g, (m, m1) => {
if (size < 0)
size = m1.replace(/\t/g, " ").length;
return "\n" + m1.slice(Math.min(m1.length, size));
});
}
if (typeof callSite === "string")
return format(callSite);
if (typeof callSite === "function")
return (...args) => format(callSite(...args));
let output = callSite
.slice(0, args.length + 1)
.map((text, i) => (i === 0 ? "" : args[i - 1]) + text)
.join("");
return format(output);
}
let output;
console.log("=== As a string function ===");
output = dedent(`
this
is
the ${ "end" }
my only
friend
the end
`);
console.log(output);
console.log("=== As a template tag ===");
output = dedent`
this
is
the ${ "end" }
my only
friend
the end
`;
console.log(output);
console.log("=== As a higher-order template tag ===");
output = dedent(String.raw)`
this
is
the ${ "end" }
my only
friend
the \end
`;
console.log(output);
@simevidas

This comment has been minimized.

Copy link

commented Sep 19, 2014

Could you explain the backslash in line 66 (the \end)?

@mathiasbynens

This comment has been minimized.

Copy link

commented Mar 23, 2015

@simevidas It’s there to demonstrate that String.raw still works as expected.

@jedwards1211

This comment has been minimized.

Copy link

commented Sep 6, 2018

Now we need to make a babel plugin to do the dedent at compile time...

@jedwards1211

This comment has been minimized.

Copy link

commented Sep 6, 2018

@rimiti

This comment has been minimized.

Copy link

commented Apr 25, 2019

@mathiasbynens Thanks !

@leonardochaia

This comment has been minimized.

Copy link

commented Sep 2, 2019

+1 for Jim Morrison

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.