mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
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
43 lines
1.1 KiB
TypeScript
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
|
|
}
|