Files
bun.sh/test/js/bun/css/dedent.ts
Zack Radisic 274e5a2022 CSS Parser (#14122)
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
2024-09-26 13:39:26 -07:00

86 lines
2.5 KiB
TypeScript

/// Copied from https://github.com/dmnd/dedent/blob/main/src/dedent.ts
export interface DedentOptions {
escapeSpecialCharacters?: boolean;
}
export interface Dedent {
(literals: string): string;
(strings: TemplateStringsArray, ...values: unknown[]): string;
withOptions: CreateDedent;
}
export type CreateDedent = (options: DedentOptions) => Dedent;
const dedent: Dedent = createDedent({});
export default dedent;
function createDedent(options: DedentOptions) {
dedent.withOptions = (newOptions: DedentOptions): Dedent => createDedent({ ...options, ...newOptions });
return dedent;
function dedent(literals: string): string;
function dedent(strings: TemplateStringsArray, ...values: unknown[]): string;
function dedent(strings: TemplateStringsArray | string, ...values: unknown[]) {
const raw = typeof strings === "string" ? [strings] : strings.raw;
const { escapeSpecialCharacters = Array.isArray(strings) } = options;
// first, perform interpolation
let result = "";
for (let i = 0; i < raw.length; i++) {
let next = raw[i];
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) {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
result += values[i];
}
}
// now strip indentation
const lines = result.split("\n");
let mindent: null | number = null;
for (const l of lines) {
const m = l.match(/^(\s+)\S+/);
if (m) {
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; // appease TypeScript
result = lines
// https://github.com/typescript-eslint/typescript-eslint/issues/7140
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
.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;
}
}