Skip to content

Commit e4df30e

Browse files
committed
fix: resolve mpx v4 relative config paths
1 parent fc1920a commit e4df30e

3 files changed

Lines changed: 88 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"weapp-tailwindcss": patch
3+
---
4+
5+
修复 Mpx + Tailwind CSS v4 子包 CSS 中相对 `@config` 路径在构建时被错误按项目根解析的问题,保持源码相对当前文件的写法可用。

packages/weapp-tailwindcss/src/bundlers/webpack/loaders/weapp-tw-css-import-rewrite-loader.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { TailwindV4CssSource } from 'tailwindcss-patch'
22
import type webpack from 'webpack'
33
import type { AppType } from '@/types'
44
import { Buffer } from 'node:buffer'
5+
import path from 'node:path'
56
import process from 'node:process'
67
import { inspect } from 'node:util'
78
import { ensurePosix } from '@weapp-tailwindcss/shared'
@@ -45,6 +46,32 @@ function applyCssImportRewrite(source: string, options: CssImportRewriteLoaderOp
4546
return rewritten ?? source
4647
}
4748

49+
function isPackageJsonImportRequest(request: string) {
50+
return request.startsWith('#')
51+
}
52+
53+
function toRootRelativeConfigPath(configPath: string, rootContext: string | undefined) {
54+
if (!rootContext) {
55+
return ensurePosix(configPath)
56+
}
57+
const relative = ensurePosix(path.relative(rootContext, configPath))
58+
return relative.startsWith('.') ? relative : `./${relative}`
59+
}
60+
61+
function normalizeCssConfigDirectives(source: string, resourcePath?: string, rootContext?: string) {
62+
if (!resourcePath) {
63+
return source
64+
}
65+
const base = path.dirname(resourcePath)
66+
return source.replace(/@config\s+(["'])(.+?)\1\s*;?/g, (full, quote: string, request: string) => {
67+
if (path.isAbsolute(request) || isPackageJsonImportRequest(request)) {
68+
return full
69+
}
70+
const resolved = path.resolve(base, request)
71+
return `@config ${quote}${toRootRelativeConfigPath(resolved, rootContext)}${quote};`
72+
})
73+
}
74+
4875
export function transformCssImportRewriteSource(
4976
source: string | Buffer,
5077
options: CssImportRewriteLoaderOptions | undefined,
@@ -77,10 +104,20 @@ const WeappTwCssImportRewriteLoader: webpack.LoaderDefinitionFunction<CssImportR
77104
const registerTask = typeof input === 'string' && hasTailwindRootDirectives(input, { importFallback: true })
78105
? opt?.tailwindcssImportRewrite?.registerCssSource?.({
79106
file: this.resourcePath,
80-
css: normalizeTailwindSourceForGenerator(input, { importFallback: true }),
107+
css: normalizeCssConfigDirectives(
108+
normalizeTailwindSourceForGenerator(input, { importFallback: true }),
109+
this.resourcePath,
110+
this.rootContext,
111+
),
81112
})
82113
: undefined
83-
const transform = () => transformCssImportRewriteSource(source, opt)
114+
const transform = () => {
115+
const transformed = transformCssImportRewriteSource(source, opt)
116+
if (typeof transformed === 'string') {
117+
return normalizeCssConfigDirectives(transformed, this.resourcePath, this.rootContext)
118+
}
119+
return transformed
120+
}
84121
if (registerTask && typeof (registerTask as PromiseLike<void>).then === 'function') {
85122
return Promise.resolve(registerTask).then(transform)
86123
}

packages/weapp-tailwindcss/test/bundlers/css-imports.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,50 @@ describe('bundlers/shared css-imports', () => {
4949
expect(rewritten).toBe(`@import "${pkgDir}/index.css";`)
5050
})
5151

52+
it('normalizes registered relative @config paths against the webpack loader resource file', async () => {
53+
const registerCssSource = vi.fn()
54+
const result = loader.call({
55+
query: {
56+
tailwindcssImportRewrite: {
57+
pkgDir,
58+
appType: 'mpx',
59+
registerCssSource,
60+
},
61+
},
62+
resourcePath: '/repo/demo/mpx-tailwindcss-v4/src/sub-normal/pages/index.css',
63+
rootContext: '/repo/demo/mpx-tailwindcss-v4',
64+
} as any,
65+
[
66+
'@import "tailwindcss" source(none);',
67+
'@config "../../../tailwind.config.sub-normal.js";',
68+
].join('\n'),
69+
)
70+
71+
await Promise.resolve(result)
72+
73+
expect(result).toBe([
74+
`@import "${pkgDir}/index.css" source(none);`,
75+
'@config "./tailwind.config.sub-normal.js";',
76+
].join('\n'))
77+
expect(registerCssSource).toHaveBeenCalledWith({
78+
file: '/repo/demo/mpx-tailwindcss-v4/src/sub-normal/pages/index.css',
79+
css: [
80+
'@import "tailwindcss" source(none);',
81+
'@config "./tailwind.config.sub-normal.js";',
82+
].join('\n'),
83+
})
84+
})
85+
86+
it('keeps absolute and package import @config requests unchanged in the webpack loader', () => {
87+
expect(transformCssImportRewriteSource('@config "/repo/tailwind.config.js";', {
88+
tailwindcssImportRewrite: { pkgDir },
89+
})).toBe('@config "/repo/tailwind.config.js";')
90+
91+
expect(transformCssImportRewriteSource('@config "#tw-config";', {
92+
tailwindcssImportRewrite: { pkgDir },
93+
})).toBe('@config "#tw-config";')
94+
})
95+
5296
it('preserves original source when loader options are missing or unchanged', () => {
5397
const source = '@import "local.css";'
5498
const buffer = Buffer.from(source)

0 commit comments

Comments
 (0)