enso/app/gui/scripts/ci/dedent.js

65 lines
1.5 KiB
JavaScript
Raw Normal View History

2024-11-21 13:52:20 +03:00
/**
* @param {string | TemplateStringsArray} strings
* @param {...unknown[]} values
* @returns {string}
*/
export function dedent(strings, ...values) {
const raw = typeof strings === 'string' ? [strings] : strings.raw
const escapeSpecialCharacters = Array.isArray(strings)
// first, perform interpolation
let result = ''
for (let i = 0; i < raw.length; i++) {
let next = raw[i]
if (next === undefined) {
continue
}
if (escapeSpecialCharacters) {
// handle escaped newlines, backticks, and interpolation characters
next = next
.replace(/\\\n[ \t]*/g, '')
.replace(/\\`/g, '`')
.replace(/\\\$/g, '$')
.replace(/\\\{/g, '{')
}
result += next
if (i < values.length) {
result += values[i]
}
}
// now strip indentation
const lines = result.split('\n')
let mindent = null
for (const l of lines) {
const m = l.match(/^(\s+)\S+/)
if (m && m[1]) {
const indent = m[1].length
if (!mindent) {
// this is the first indented line
mindent = indent
} else {
mindent = Math.min(mindent, indent)
}
}
}
if (mindent !== null) {
const m = mindent
result = lines.map((l) => (l[0] === ' ' || l[0] === '\t' ? l.slice(m) : l)).join('\n')
}
// dedent eats leading and trailing whitespace too
result = result.trim()
if (escapeSpecialCharacters) {
// handle escaped newlines at the end to ensure they don't get stripped too
result = result.replace(/\\n/g, '\n')
}
return result
}