diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts
index e08de24265e24a..75c0e57952db24 100644
--- a/packages/playground/assets/__tests__/assets.spec.ts
+++ b/packages/playground/assets/__tests__/assets.spec.ts
@@ -307,3 +307,10 @@ if (!isBuild) {
await untilUpdated(() => getColor('.import-css'), 'rgb(0, 255, 136)')
})
}
+
+test('html import word boundary', async () => {
+ expect(await page.textContent('.obj-import-express')).toMatch(
+ 'ignore object import prop'
+ )
+ expect(await page.textContent('.string-import-express')).toMatch('no load')
+})
diff --git a/packages/playground/assets/index.html b/packages/playground/assets/index.html
index b0ec76f5483b6f..6678a2da7c2106 100644
--- a/packages/playground/assets/index.html
+++ b/packages/playground/assets/index.html
@@ -176,9 +176,28 @@
new URL(`non-existent`, import.meta.url)
simple script tag import-expression
+
+
url in style tag
url
diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts
index 25ad91582140c3..5c86b6c0ac6073 100644
--- a/packages/vite/src/node/plugins/html.ts
+++ b/packages/vite/src/node/plugins/html.ts
@@ -35,6 +35,7 @@ import type {
TextNode
} from '@vue/compiler-dom'
import { NodeTypes } from '@vue/compiler-dom'
+import { emptyString } from '../cleanString'
interface ScriptAssetsUrl {
start: number
@@ -44,8 +45,9 @@ interface ScriptAssetsUrl {
const htmlProxyRE = /\?html-proxy=?[&inline\-css]*&index=(\d+)\.(js|css)$/
const inlineCSSRE = /__VITE_INLINE_CSS__([^_]+_\d+)__/g
+// Do not allow preceding '.', but do allow preceding '...' for spread operations
+const inlineImportRE = /(? htmlProxyRE.test(id)
@@ -303,14 +305,19 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
}
} else if (node.children.length) {
const scriptNode = node.children.pop()! as TextNode
- const code = scriptNode.content
+ const cleanCode = emptyString(scriptNode.content)
+
let match: RegExpExecArray | null
- while ((match = inlineImportRE.exec(code))) {
- const { 0: full, 1: url, index } = match
- const startUrl = full.indexOf(url)
- const start = scriptNode.loc.start.offset + index + startUrl + 1
+ while ((match = inlineImportRE.exec(cleanCode))) {
+ const { 1: url, index } = match
+ const startUrl = cleanCode.indexOf(url, index)
+ const start = startUrl + 1
const end = start + url.length - 2
- scriptUrls.push({ start, end, url: url.slice(1, -1) })
+ scriptUrls.push({
+ start: start + scriptNode.loc.start.offset,
+ end: end + scriptNode.loc.start.offset,
+ url: scriptNode.content.slice(start, end)
+ })
}
}
}