Skip to content

Commit 5cfd6c4

Browse files
feat: use filter for plugins (#49) (#50) (#51) (#52) (#53)
Co-authored-by: IWANABETHATGUY <[email protected]>
1 parent d1f1aaf commit 5cfd6c4

File tree

6 files changed

+960
-868
lines changed

6 files changed

+960
-868
lines changed

packages/vite/src/node/__tests__/plugins/css.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
33
import { describe, expect, test, vi } from 'vitest'
4+
import type { Plugin } from 'rolldown'
45
import { resolveConfig } from '../../config'
56
import type { InlineConfig } from '../../config'
67
import {
@@ -219,7 +220,7 @@ async function createCssPluginTransform(
219220
const config = await resolveConfig(inlineConfig, 'serve')
220221
const environment = new PartialEnvironment('client', config)
221222

222-
const { transform, buildStart } = cssPlugin(config)
223+
const { transform, buildStart } = cssPlugin(config) as Plugin
223224

224225
// @ts-expect-error buildStart is function
225226
await buildStart.call({})
@@ -233,8 +234,8 @@ async function createCssPluginTransform(
233234

234235
return {
235236
async transform(code: string, id: string) {
236-
// @ts-expect-error transform is function
237-
return await transform.call(
237+
// @ts-expect-error transform.handler is function
238+
return await transform.handler.call(
238239
{
239240
addWatchFile() {
240241
return

packages/vite/src/node/plugins/assetImportMetaUrl.ts

Lines changed: 112 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from 'node:path'
22
import MagicString from 'magic-string'
33
import { stripLiteral } from 'strip-literal'
44
import { parseAst } from 'rollup/parseAst'
5-
import type { Plugin } from '../plugin'
5+
import type { RolldownPlugin } from 'rolldown'
66
import type { ResolvedConfig } from '../config'
77
import { injectQuery, isParentDirectory, transformStableResult } from '../utils'
88
import { CLIENT_ENTRY } from '../constants'
@@ -25,7 +25,9 @@ import { hasViteIgnoreRE } from './importAnalysis'
2525
* import.meta.glob('./dir/**.png', { eager: true, import: 'default' })[`./dir/${name}.png`]
2626
* ```
2727
*/
28-
export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
28+
export function assetImportMetaUrlPlugin(
29+
config: ResolvedConfig,
30+
): RolldownPlugin {
2931
const { publicDir } = config
3032
let assetResolver: ResolveIdFn
3133

@@ -40,121 +42,128 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
4042

4143
return {
4244
name: 'vite:asset-import-meta-url',
43-
async transform(code, id) {
44-
const { environment } = this
45-
if (
46-
environment.config.consumer === 'client' &&
47-
id !== preloadHelperId &&
48-
id !== CLIENT_ENTRY &&
49-
code.includes('new URL') &&
50-
code.includes(`import.meta.url`)
51-
) {
52-
let s: MagicString | undefined
53-
const assetImportMetaUrlRE =
54-
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
55-
const cleanString = stripLiteral(code)
45+
transform: {
46+
filter: {
47+
code: {
48+
include: ['new URL', 'import.meta.url'],
49+
},
50+
},
51+
async handler(code, id) {
52+
const { environment } = this
53+
if (
54+
environment.config.consumer === 'client' &&
55+
id !== preloadHelperId &&
56+
id !== CLIENT_ENTRY &&
57+
code.includes('new URL') &&
58+
code.includes(`import.meta.url`)
59+
) {
60+
let s: MagicString | undefined
61+
const assetImportMetaUrlRE =
62+
/\bnew\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*(?:,\s*)?\)/dg
63+
const cleanString = stripLiteral(code)
5664

57-
let match: RegExpExecArray | null
58-
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
59-
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
60-
if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue
65+
let match: RegExpExecArray | null
66+
while ((match = assetImportMetaUrlRE.exec(cleanString))) {
67+
const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!
68+
if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue
6169

62-
const rawUrl = code.slice(urlStart, urlEnd)
70+
const rawUrl = code.slice(urlStart, urlEnd)
6371

64-
if (!s) s = new MagicString(code)
72+
if (!s) s = new MagicString(code)
6573

66-
// potential dynamic template string
67-
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
68-
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
69-
const hasQueryDelimiter = queryDelimiterIndex !== -1
70-
const pureUrl = hasQueryDelimiter
71-
? rawUrl.slice(0, queryDelimiterIndex) + '`'
72-
: rawUrl
73-
const queryString = hasQueryDelimiter
74-
? rawUrl.slice(queryDelimiterIndex, -1)
75-
: ''
76-
const ast = parseAst(pureUrl)
77-
const templateLiteral = (ast as any).body[0].expression
78-
if (templateLiteral.expressions.length) {
79-
const pattern = buildGlobPattern(templateLiteral)
80-
if (pattern.startsWith('**')) {
81-
// don't transform for patterns like this
82-
// because users won't intend to do that in most cases
83-
continue
84-
}
74+
// potential dynamic template string
75+
if (rawUrl[0] === '`' && rawUrl.includes('${')) {
76+
const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)
77+
const hasQueryDelimiter = queryDelimiterIndex !== -1
78+
const pureUrl = hasQueryDelimiter
79+
? rawUrl.slice(0, queryDelimiterIndex) + '`'
80+
: rawUrl
81+
const queryString = hasQueryDelimiter
82+
? rawUrl.slice(queryDelimiterIndex, -1)
83+
: ''
84+
const ast = parseAst(pureUrl)
85+
const templateLiteral = (ast as any).body[0].expression
86+
if (templateLiteral.expressions.length) {
87+
const pattern = buildGlobPattern(templateLiteral)
88+
if (pattern.startsWith('**')) {
89+
// don't transform for patterns like this
90+
// because users won't intend to do that in most cases
91+
continue
92+
}
8593

86-
const globOptions = {
87-
eager: true,
88-
import: 'default',
89-
// A hack to allow 'as' & 'query' exist at the same time
90-
query: injectQuery(queryString, 'url'),
94+
const globOptions = {
95+
eager: true,
96+
import: 'default',
97+
// A hack to allow 'as' & 'query' exist at the same time
98+
query: injectQuery(queryString, 'url'),
99+
}
100+
s.update(
101+
startIndex,
102+
endIndex,
103+
`new URL((import.meta.glob(${JSON.stringify(
104+
pattern,
105+
)}, ${JSON.stringify(
106+
globOptions,
107+
)}))[${pureUrl}], import.meta.url)`,
108+
)
109+
continue
91110
}
92-
s.update(
93-
startIndex,
94-
endIndex,
95-
`new URL((import.meta.glob(${JSON.stringify(
96-
pattern,
97-
)}, ${JSON.stringify(
98-
globOptions,
99-
)}))[${pureUrl}], import.meta.url)`,
100-
)
101-
continue
102111
}
103-
}
104112

105-
const url = rawUrl.slice(1, -1)
106-
let file: string | undefined
107-
if (url[0] === '.') {
108-
file = slash(path.resolve(path.dirname(id), url))
109-
file = tryFsResolve(file, fsResolveOptions) ?? file
110-
} else {
111-
assetResolver ??= createBackCompatIdResolver(config, {
112-
extensions: [],
113-
mainFields: [],
114-
tryIndex: false,
115-
preferRelative: true,
116-
})
117-
file = await assetResolver(environment, url, id)
118-
file ??=
119-
url[0] === '/'
120-
? slash(path.join(publicDir, url))
121-
: slash(path.resolve(path.dirname(id), url))
122-
}
113+
const url = rawUrl.slice(1, -1)
114+
let file: string | undefined
115+
if (url[0] === '.') {
116+
file = slash(path.resolve(path.dirname(id), url))
117+
file = tryFsResolve(file, fsResolveOptions) ?? file
118+
} else {
119+
assetResolver ??= createBackCompatIdResolver(config, {
120+
extensions: [],
121+
mainFields: [],
122+
tryIndex: false,
123+
preferRelative: true,
124+
})
125+
file = await assetResolver(environment, url, id)
126+
file ??=
127+
url[0] === '/'
128+
? slash(path.join(publicDir, url))
129+
: slash(path.resolve(path.dirname(id), url))
130+
}
123131

124-
// Get final asset URL. If the file does not exist,
125-
// we fall back to the initial URL and let it resolve in runtime
126-
let builtUrl: string | undefined
127-
if (file) {
128-
try {
129-
if (publicDir && isParentDirectory(publicDir, file)) {
130-
const publicPath = '/' + path.posix.relative(publicDir, file)
131-
builtUrl = await fileToUrl(this, publicPath)
132-
} else {
133-
builtUrl = await fileToUrl(this, file)
132+
// Get final asset URL. If the file does not exist,
133+
// we fall back to the initial URL and let it resolve in runtime
134+
let builtUrl: string | undefined
135+
if (file) {
136+
try {
137+
if (publicDir && isParentDirectory(publicDir, file)) {
138+
const publicPath = '/' + path.posix.relative(publicDir, file)
139+
builtUrl = await fileToUrl(this, publicPath)
140+
} else {
141+
builtUrl = await fileToUrl(this, file)
142+
}
143+
} catch {
144+
// do nothing, we'll log a warning after this
134145
}
135-
} catch {
136-
// do nothing, we'll log a warning after this
137146
}
138-
}
139-
if (!builtUrl) {
140-
const rawExp = code.slice(startIndex, endIndex)
141-
config.logger.warnOnce(
142-
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
143-
`If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,
147+
if (!builtUrl) {
148+
const rawExp = code.slice(startIndex, endIndex)
149+
config.logger.warnOnce(
150+
`\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +
151+
`If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,
152+
)
153+
builtUrl = url
154+
}
155+
s.update(
156+
startIndex,
157+
endIndex,
158+
`new URL(${JSON.stringify(builtUrl)}, import.meta.url)`,
144159
)
145-
builtUrl = url
146160
}
147-
s.update(
148-
startIndex,
149-
endIndex,
150-
`new URL(${JSON.stringify(builtUrl)}, import.meta.url)`,
151-
)
152-
}
153-
if (s) {
154-
return transformStableResult(s, id, config)
161+
if (s) {
162+
return transformStableResult(s, id, config)
163+
}
155164
}
156-
}
157-
return null
165+
return null
166+
},
158167
},
159168
}
160169
}

0 commit comments

Comments
 (0)