tailwindcss/packages/@tailwindcss-upgrade/src/template/splice-changes-into-string.ts
Jordan Pittman 92a43d6904
Speed up template migrations (#14679)
This PR does two things:
- Computes UTF-16 string positions in Rust rather than in JS —
eliminating a significant number of traversals of the input string
- Applies replacements to the content in ascending order so we only ever
move forward through the source string — this lets v8 optimize string
concatenation
2024-10-16 13:13:48 +02:00

43 lines
1.1 KiB
TypeScript

export interface StringChange {
start: number
end: number
replacement: string
}
/**
* Apply the changes to the string such that a change in the length
* of the string does not break the indexes of the subsequent changes.
*/
export function spliceChangesIntoString(str: string, changes: StringChange[]) {
// If there are no changes, return the original string
if (!changes[0]) return str
// Sort all changes in order to make it easier to apply them
changes.sort((a, b) => {
return a.end - b.end || a.start - b.start
})
// Append original string between each chunk, and then the chunk itself
// This is sort of a String Builder pattern, thus creating less memory pressure
let result = ''
let previous = changes[0]
result += str.slice(0, previous.start)
result += previous.replacement
for (let i = 1; i < changes.length; ++i) {
let change = changes[i]
result += str.slice(previous.end, change.start)
result += change.replacement
previous = change
}
// Add leftover string from last chunk to end
result += str.slice(previous.end)
return result
}