Skip to content

Commit fbe7432

Browse files
lzl0304antfu
andauthoredJul 27, 2024··
fix(cli): fix deduplication for files containing @media (#3882)
Co-authored-by: Anthony Fu <github@antfu.me> Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
1 parent 8ae6736 commit fbe7432

File tree

3 files changed

+61
-46
lines changed

3 files changed

+61
-46
lines changed
 

‎packages/cli/src/index.ts

+25-45
Original file line numberDiff line numberDiff line change
@@ -123,64 +123,44 @@ export async function build(_options: CliOptions) {
123123
async function generate(options: ResolvedCliOptions) {
124124
const sourceCache = Array.from(fileCache).map(([id, code]) => ({ id, code }))
125125

126-
const preTransform = await transformFiles(sourceCache, 'pre')
127-
const defaultTransform = await transformFiles(preTransform)
128-
const postTransform = await transformFiles(defaultTransform, 'post')
126+
const afterPreTrans = await transformFiles(sourceCache, 'pre')
127+
const afterDefaultTrans = await transformFiles(afterPreTrans)
128+
const afterPostTrans = await transformFiles(afterDefaultTrans, 'post')
129129

130130
// update source file
131131
if (options.writeTransformed) {
132132
await Promise.all(
133-
postTransform
133+
afterPostTrans
134134
.filter(({ transformedCode }) => !!transformedCode)
135-
.map(({ transformedCode, id }) => new Promise<void>((resolve) => {
135+
.map(async ({ transformedCode, id }) => {
136136
if (existsSync(id))
137-
fs.writeFile(id, transformedCode as string, 'utf-8').then(resolve)
138-
})),
137+
await fs.writeFile(id, transformedCode as string, 'utf-8')
138+
}),
139139
)
140140
}
141-
const firstIdType = postTransform[0].id.split('.').pop()!
142-
const isSameFileType = postTransform.every(({ id }) => id.split('.').pop() === firstIdType)
143-
let css!: string
144-
let matched: Set<string>
145-
if (isSameFileType) {
146-
// if all files are the same type, we can generate them all at once
147-
const { css: _css, matched: _matched } = await ctx.uno.generate(
148-
[...postTransform.map(({ code, transformedCode }) => (transformedCode ?? code).replace(SKIP_COMMENT_RE, ''))].join('\n'),
141+
142+
const tokens = new Set<string>()
143+
144+
for (const file of afterPostTrans) {
145+
const { matched } = await ctx.uno.generate(
146+
(file.transformedCode || file.code).replace(SKIP_COMMENT_RE, ''),
149147
{
150-
preflights: options.preflights,
151-
minify: options.minify,
152-
id: postTransform[0].id,
148+
preflights: false,
149+
minify: true,
150+
id: file.id,
153151
},
154152
)
155-
css = _css
156-
matched = _matched
157-
}
158-
else {
159-
// if files are different types, we need to generate them one by one
160-
const result = await Promise.all(postTransform.map(({ code, transformedCode, id }) =>
161-
ctx.uno.generate(transformedCode ?? code, {
162-
preflights: options.preflights,
163-
minify: options.minify,
164-
id,
165-
})))
166-
const cssCollection: Record<string, string[]> = {}
167-
result.forEach(({ css, layers }) => {
168-
css
169-
.split(/\/\*.*?\*\//g) // Remove inline comments
170-
.filter(Boolean).forEach((c, i) => {
171-
if (!cssCollection[layers[i]]) {
172-
cssCollection[layers[i]] = c.split('\n')
173-
}
174-
else {
175-
// remove duplicates
176-
cssCollection[layers[i]] = [...new Set([...cssCollection[layers[i]], ...c.split('\n')])]
177-
}
178-
})
179-
})
180-
css = result[0].layers.map(layer => `/* layer: ${layer} */${cssCollection[layer].join('\n')}`).join('\n')
181-
matched = new Set(result.map(({ matched }) => [...matched]).flat())
153+
matched.forEach(i => tokens.add(i))
182154
}
183155

156+
const { css, matched } = await ctx.uno.generate(
157+
tokens,
158+
{
159+
preflights: options.preflights,
160+
minify: options.minify,
161+
},
162+
)
163+
184164
if (options.stdout) {
185165
process.stdout.write(css)
186166
return

‎packages/cli/test/__snapshots__/cli.test.ts.snap

+14
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ exports[`cli > builds uno.css 1`] = `
1111
.p-4{padding:1rem;}"
1212
`;
1313

14+
exports[`cli > should correctly deduplicate files of different types containing @media 1`] = `
15+
"/* layer: shortcuts */
16+
.box{margin-left:auto;margin-right:auto;max-width:80rem;border-radius:0.375rem;--un-bg-opacity:1;background-color:rgb(243 244 246 / var(--un-bg-opacity)) /* #f3f4f6 */;padding:1rem;--un-shadow:var(--un-shadow-inset) 0 1px 2px 0 var(--un-shadow-color, rgb(0 0 0 / 0.05));box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow);}
17+
/* layer: default */
18+
@media (min-width: 768px){
19+
.md\\:p-4{padding:1rem;}
20+
}
21+
@media (min-width: 1024px){
22+
.lg\\:p-8{padding:2rem;}
23+
}"
24+
`;
25+
26+
exports[`cli > should correctly deduplicate files of different types containing @media 2`] = `".box { }@media (min-width: 640px){.box{padding:0.5rem;}}"`;
27+
1428
exports[`cli > supports directives transformer 1`] = `""`;
1529

1630
exports[`cli > supports directives transformer 2`] = `".btn-center{@apply text-center my-0 font-medium;}"`;

‎packages/cli/test/cli.test.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,27 @@ export default defineConfig({
207207
}
208208
})
209209

210+
it('should correctly deduplicate files of different types containing @media', async () => {
211+
const { output, transform } = await runCli(
212+
{
213+
'views/index1.html': '<div class="lg:p-8"></div>',
214+
'views/index2.html': '<div class="md:p-4"></div>',
215+
'views/index3.html': '<div class="box"></div>',
216+
'views/index.css': '.box { @apply pd-6 sm:p-2; }',
217+
'unocss.config.js': `
218+
import { defineConfig, transformerDirectives } from 'unocss'
219+
export default defineConfig({
220+
transformers: [transformerDirectives()]
221+
})
222+
`.trim(),
223+
},
224+
{ transformFile: 'views/index.css', args: ['--write-transformed'] },
225+
)
226+
227+
expect(output).toMatchSnapshot()
228+
expect(transform).toMatchSnapshot()
229+
})
230+
210231
it('@unocss-skip uno.css', async () => {
211232
const { output } = await runCli({
212233
'views/index.html': `
@@ -300,7 +321,7 @@ async function runCli(files: Record<string, string>, options?: { transformFile?:
300321
const output = await readFile(testDir)
301322

302323
if (options?.transformFile) {
303-
const transform = await readFile(testDir, options?.transformFile)
324+
const transform = await readFile(testDir, options.transformFile)
304325
return {
305326
output,
306327
transform,

0 commit comments

Comments
 (0)
Please sign in to comment.