@timhall/dedent
Version:
Remove extra indentation from template strings
55 lines (53 loc) • 2.07 kB
JavaScript
const placeholder = `{${String.fromCharCode(32)}}`;
function dedent(strings, ...values) {
const raw = typeof strings === 'string'
? [strings]
: isTemplateStringsArray(strings)
? strings.raw
: strings;
// Handle template string formatting (backticks, \ line endings)
const formatted = raw.map((part) => pipeline(part, unescapeBackticks, joinSuppressedNewline));
// Find minimum indentation of template strings
const lines = formatted.join(placeholder).split(/\r?\n/);
const minimumIndentation = Math.min(...lines.map((line) => {
const leadingSpaces = line.match(/^(\s+)\S+/);
return leadingSpaces ? leadingSpaces[1].length : Infinity;
}));
// Rejoin formatted lines with unindentation and placeholders
const shouldDedent = minimumIndentation > 0 && minimumIndentation < Infinity;
const joined = !shouldDedent
? lines.join('\n')
: lines
.map((line, lineIndex) => {
const isFirstLine = lineIndex === 0;
const hasLeadingSpaces = !!line.match(/^(\s+)\S+/);
const isUnindented = isFirstLine && !hasLeadingSpaces;
return !isUnindented ? line.slice(minimumIndentation) : line;
})
.join('\n');
// Replace placeholders with values
const replaced = joined.split(placeholder).reduce((memo, part, partIndex) => {
return memo + part + (values[partIndex] || '');
}, '');
return pipeline(replaced, trim, unescapeNewlines);
}
function isTemplateStringsArray(value) {
return value && Array.isArray(value.raw);
}
function joinSuppressedNewline(value) {
return value.replace(/\\\n[ \t]*/g, '');
}
function unescapeBackticks(value) {
return value.replace(/\\`/g, '`');
}
function trim(value) {
return value.trim();
}
function unescapeNewlines(value) {
return value.replace(/\\n/g, '\n');
}
function pipeline(value, ...functions) {
return functions.reduce((value, fn) => fn(value), value);
}
export default dedent;
//# sourceMappingURL=dedent.es.js.map