Skip to content

Commit a761dc0

Browse files
committed
feat(compiler): add normalizeCssUrlValue function to standardize URL handling in styles and update tests accordingly
1 parent 6d97ef4 commit a761dc0

2 files changed

Lines changed: 40 additions & 19 deletions

File tree

fe/packages/compiler/__tests__/style-compiler.spec.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import { ensureImportSemicolons, normalizeRootStyleImports, removeBaseComponentScope, resolveStyleImportPath } from '../src/core/style-compiler'
2+
import { ensureImportSemicolons, normalizeCssUrlValue, normalizeRootStyleImports, removeBaseComponentScope, resolveStyleImportPath } from '../src/core/style-compiler'
33

44
describe('ensureImportSemicolons', () => {
55
it('should add semicolons to @import statements that do not have them', () => {
@@ -234,3 +234,15 @@ describe('style import path helpers', () => {
234234
expect(result).not.toContain('@import "/variable.less";')
235235
})
236236
})
237+
238+
describe('normalizeCssUrlValue', () => {
239+
it('应该将协议相对 URL 规范化为 https', () => {
240+
const input = 'url(//at.alicdn.com/iconfont.woff2?t=1)'
241+
expect(normalizeCssUrlValue(input, '/tmp/app/pages/index.wxss')).toBe('url(https://at.alicdn.com/iconfont.woff2?t=1)')
242+
})
243+
244+
it('应该保留 https URL 不变', () => {
245+
const input = 'url("https://example.com/a.png")'
246+
expect(normalizeCssUrlValue(input, '/tmp/app/pages/index.wxss')).toBe(input)
247+
})
248+
})

fe/packages/compiler/src/core/style-compiler.js

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -204,30 +204,18 @@ async function enhanceCSS(module) {
204204
}
205205
})
206206
}).processSync(node.selector)
207-
208-
// 处理样式声明
209-
node.walkDecls((decl) => {
210-
const match = decl.value.match(/url\("([^"]*)"\)/)
211-
if (match) {
212-
const imgSrc = match[1].trim()
213-
// Skip processing if it's a data:image resource
214-
if (imgSrc.startsWith('data:image')) {
215-
return
216-
}
217-
const realSrc = collectAssets(getWorkPath(), absolutePath, imgSrc, getTargetPath(), getAppId())
218-
decl.value = `url(${realSrc})`
219-
}
220-
else {
221-
decl.value = transformRpx(decl.value)
222-
}
223-
})
224207
}
225208
else if (node.type === 'comment') {
226209
// 移除注释
227210
node.remove()
228211
}
229212
})
230213

214+
ast.walkDecls((decl) => {
215+
decl.value = normalizeCssUrlValue(decl.value, absolutePath)
216+
decl.value = transformRpx(decl.value)
217+
})
218+
231219
const cssCode = ast.toResult().css
232220

233221
// 样式隔离
@@ -259,6 +247,27 @@ async function enhanceCSS(module) {
259247
return result
260248
}
261249

250+
function normalizeCssUrlValue(value, absolutePath) {
251+
return value.replace(/url\(([^)]+)\)/g, (fullMatch, rawUrl) => {
252+
const cleanedUrl = rawUrl.trim().replace(/^['"]|['"]$/g, '')
253+
254+
if (!cleanedUrl || cleanedUrl.startsWith('data:image')) {
255+
return fullMatch
256+
}
257+
258+
if (cleanedUrl.startsWith('//')) {
259+
return `url(https:${cleanedUrl})`
260+
}
261+
262+
if (/^(https?:|blob:|data:)/.test(cleanedUrl)) {
263+
return fullMatch
264+
}
265+
266+
const realSrc = collectAssets(getWorkPath(), absolutePath, cleanedUrl, getTargetPath(), getAppId())
267+
return `url(${realSrc})`
268+
})
269+
}
270+
262271
function getAbsolutePath(modulePath) {
263272
const workPath = getWorkPath()
264273
const src = modulePath.startsWith('/') ? modulePath : `/${modulePath}`
@@ -354,4 +363,4 @@ function processHostSelector(selector, moduleId) {
354363
.replace(/:host(?=\.|#|:)/g, `[data-v-${moduleId}]`)
355364
}
356365

357-
export { compileSS, ensureImportSemicolons, normalizeRootStyleImports, processHostSelector, removeBaseComponentScope, resolveStyleImportPath }
366+
export { compileSS, ensureImportSemicolons, normalizeCssUrlValue, normalizeRootStyleImports, processHostSelector, removeBaseComponentScope, resolveStyleImportPath }

0 commit comments

Comments
 (0)