refactor(compiler): use vite plugin types

This commit is contained in:
Rahim
2026-06-17 17:13:40 -07:00
parent f941eacf37
commit 21392ccd16
4 changed files with 46 additions and 30 deletions
+9
View File
@@ -64,6 +64,14 @@
"test:watch": "vitest",
"clean": "rimraf --glob dist types '*.tsbuildinfo'"
},
"peerDependencies": {
"vite": "^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"vite": {
"optional": true
}
},
"dependencies": {
"@videojs/utils": "workspace:*",
"kleur": "^4.1.5",
@@ -74,6 +82,7 @@
"devDependencies": {
"@videojs/core": "workspace:*",
"tsdown": "^0.21.4",
"vite": "^8.0.0",
"vitest": "^4.1.0"
}
}
@@ -2,6 +2,19 @@ import { describe, expect, it, vi } from 'vitest';
import type { CompilerConfig } from '../../config';
import { vjsCompiler } from '../vite';
type TestPlugin = {
resolveId(id: string): string | null;
load(id: string): string | null;
transform(
this: { warn(warning: unknown): void },
code: string,
id: string
): Promise<{ code: string; map: null } | null>;
};
const createPlugin = (...args: Parameters<typeof vjsCompiler>): TestPlugin =>
vjsCompiler(...args) as unknown as TestPlugin;
const createCssStyle = (source: string): NonNullable<CompilerConfig['styles']> => ({
name: 'fixture',
setup(context) {
@@ -16,10 +29,9 @@ const createCssStyle = (source: string): NonNullable<CompilerConfig['styles']> =
describe('vjsCompiler', () => {
it('imports emitted CSS assets as virtual modules', async () => {
const plugin = vjsCompiler({ config: { styles: createCssStyle('.foo{display:flex;}') } });
plugin.configResolved?.({ root: '/workspace' });
const plugin = createPlugin({ config: { styles: createCssStyle('.foo{display:flex;}') } });
const result = await plugin.transform!.call(
const result = await plugin.transform.call(
{ warn: () => {} },
`function App(){ return <Foo className="foo"/>; }`,
'/workspace/skin.tsx'
@@ -31,14 +43,14 @@ describe('vjsCompiler', () => {
const id = match![1]!;
expect(id).toContain('virtual:@videojs/compiler/css/');
expect(plugin.resolveId?.(id)).toBe(`\0${id}`);
expect(plugin.load?.(`\0${id}`)).toBe('.foo{display:flex;}');
expect(plugin.resolveId(id)).toBe(`\0${id}`);
expect(plugin.load(`\0${id}`)).toBe('.foo{display:flex;}');
expect(result!.code).toContain('function App');
});
it('forwards compiler warnings to Vite', async () => {
const warn = vi.fn();
const plugin = vjsCompiler({
const plugin = createPlugin({
config: {
styles: {
name: 'fixture',
@@ -50,14 +62,14 @@ describe('vjsCompiler', () => {
},
});
await plugin.transform!.call({ warn }, `function App(){ return <Foo/>; }`, '/workspace/skin.tsx');
await plugin.transform.call({ warn }, `function App(){ return <Foo/>; }`, '/workspace/skin.tsx');
expect(warn).toHaveBeenCalledWith('Check this');
});
it('forwards located compiler warnings to Vite', async () => {
const warn = vi.fn();
const plugin = vjsCompiler({
const plugin = createPlugin({
config: {
styles: {
name: 'fixture',
@@ -77,7 +89,7 @@ describe('vjsCompiler', () => {
},
});
await plugin.transform!.call({ warn }, `function App(){ return <Foo/>; }`, '/workspace/skin.tsx');
await plugin.transform.call({ warn }, `function App(){ return <Foo/>; }`, '/workspace/skin.tsx');
expect(warn).toHaveBeenCalledWith({
message: 'Check this location',
+13 -21
View File
@@ -1,3 +1,4 @@
import type { Plugin } from 'vite';
import { compile } from '../compile';
import type { CompilerConfig, CompilerDiagnostic } from '../config';
import { type LoadedCompilerConfig, loadConfig } from '../load-config';
@@ -9,27 +10,18 @@ export interface VideojsCompilerPluginOptions {
exclude?: readonly string[] | undefined;
}
export interface VitePluginContext {
warn(warning: string | VitePluginWarning): void;
}
type ViteHookContext<Hook> = Hook extends (this: infer Context, ...args: never[]) => unknown
? Context
: Hook extends { handler: (this: infer Context, ...args: never[]) => unknown }
? Context
: never;
export interface VitePluginWarning {
message: string;
id?: string | undefined;
loc?: { file?: string | undefined; line: number; column?: number | undefined } | undefined;
pluginCode?: string | undefined;
}
type ViteTransformContext = ViteHookContext<NonNullable<Plugin['transform']>>;
type VitePluginWarning = ViteTransformContext extends { warn: (...args: infer WarningParameters) => unknown }
? WarningParameters[0]
: string;
export interface VitePlugin {
name: string;
enforce?: 'pre' | 'post';
configResolved?: (config: { root: string }) => void;
resolveId?: (id: string) => string | null;
load?: (id: string) => string | null;
transform?: (this: VitePluginContext, code: string, id: string) => Promise<{ code: string; map: null } | null>;
}
export function vjsCompiler(options: VideojsCompilerPluginOptions = {}): VitePlugin {
export function vjsCompiler(options: VideojsCompilerPluginOptions = {}): Plugin {
const include = options.include ?? ['.tsx'];
const exclude = options.exclude ?? [];
const cssById = new Map<string, string>();
@@ -84,7 +76,7 @@ function cssVirtualId(id: string, fileName: string, index: number): string {
return `virtual:@videojs/compiler/css/${encodeURIComponent(id)}/${index}/${encodeURIComponent(fileName)}`;
}
function viteWarningFromDiagnostic(diagnostic: CompilerDiagnostic): string | VitePluginWarning {
function viteWarningFromDiagnostic(diagnostic: CompilerDiagnostic): VitePluginWarning {
if (!diagnostic.file || !diagnostic.line) return diagnostic.message;
return {
message: diagnostic.message,
@@ -92,7 +84,7 @@ function viteWarningFromDiagnostic(diagnostic: CompilerDiagnostic): string | Vit
loc: {
file: diagnostic.file,
line: diagnostic.line,
...(diagnostic.column ? { column: diagnostic.column } : {}),
column: diagnostic.column ?? 0,
},
pluginCode: diagnostic.code,
};
+3
View File
@@ -245,6 +245,9 @@ importers:
tsdown:
specifier: ^0.21.4
version: 0.21.9(@typescript/native-preview@7.0.0-dev.20260421.1)(typescript@6.0.2)
vite:
specifier: ^8.0.0
version: 8.0.0(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)
vitest:
specifier: ^4.1.0
version: 4.1.0(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.0)(@vitest/ui@4.1.0)(happy-dom@18.0.1)(jsdom@27.4.0)(vite@8.0.0(@types/node@24.12.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))