diff --git a/crates/oxide/src/scanner/mod.rs b/crates/oxide/src/scanner/mod.rs
index ec6aea642481..ea914cb6f5b9 100644
--- a/crates/oxide/src/scanner/mod.rs
+++ b/crates/oxide/src/scanner/mod.rs
@@ -553,11 +553,17 @@ where
a
})
.into_iter()
- .map(|s| unsafe { String::from_utf8_unchecked(s.to_vec()) })
+ .filter_map(|s| match String::from_utf8(s.to_vec()) {
+ Ok(s) => Some(s),
+ Err(_e) => {
+ // Optionally log or handle invalid UTF-8 here
+ // eprintln!("Skipped invalid UTF-8 candidate, error: {:?}", _e);
+ None
+ }
+ })
.collect();
- // SAFETY: Unstable sort is faster and in this scenario it's also safe because we are
- // guaranteed to have unique candidates.
+ // Unstable sort is performant & remains correct with unique candidates
result.par_sort_unstable();
result
diff --git a/packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts b/packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
index fa7ee7f4a1c5..6f57358e3836 100644
--- a/packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
+++ b/packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
@@ -1,4 +1,5 @@
import { parseCandidate } from '../../../../tailwindcss/src/candidate'
+import { parse as parseHtml } from 'node-html-parser'
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
import { DefaultMap } from '../../../../tailwindcss/src/utils/default-map'
import * as version from '../../utils/version'
@@ -187,31 +188,24 @@ export function isSafeMigration(
return true
}
-// Assumptions:
-// - All ``
-// - No nested `', offset)
- if (endTag === -1) return ranges
- offset = endTag + 1
-
- ranges.push(startTag, endTag)
+ const ranges: number[] = []
+ try {
+ const root = parseHtml(source, { lowerCaseTagName: false, comment: false, blockTextElements: { style: true } })
+ const styleNodes = root.querySelectorAll('style')
+ styleNodes.forEach(node => {
+ const nodeHtml = node.toString()
+ const start = typeof node.range === 'object' && node.range !== null
+ ? node.range[0]
+ : source.indexOf(nodeHtml)
+ const end = start + nodeHtml.length
+ ranges.push(start, end)
+ })
+ } catch (_) {
+ // fallback: do nothing if parser fails
}
+ return ranges
})
const BACKSLASH = 0x5c