penambahan web socket

This commit is contained in:
2025-09-18 19:01:22 +07:00
parent 1d053646a9
commit d7bb2eb5bb
15070 changed files with 2402916 additions and 0 deletions

No files matched your search

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,109 @@
# @vitejs/plugin-vue-jsx [![npm](https://img.shields.io/npm/v/@vitejs/plugin-vue-jsx.svg)](https://npmjs.com/package/@vitejs/plugin-vue-jsx)
Provides Vue 3 JSX & TSX support with HMR.
```js
// vite.config.js
import vueJsx from '@vitejs/plugin-vue-jsx'
export default {
plugins: [
vueJsx({
// options are passed on to @vue/babel-plugin-jsx
}),
],
}
```
## Options
### include
Type: `(string | RegExp)[] | string | RegExp | null`
Default: `/\.[jt]sx$/`
A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files the plugin should operate on.
### exclude
Type: `(string | RegExp)[] | string | RegExp | null`
Default: `undefined`
A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files to be ignored by the plugin.
> See [@vue/babel-plugin-jsx](https://github.com/vuejs/jsx-next) for other options.
### defineComponentName
Type: `string[]`
Default: `['defineComponent']`
The name of the function to be used for defining components. This is useful when you have a custom `defineComponent` function.
### tsTransform
Type: `'babel' | 'built-in'`
Default: `'babel'`
Defines how `typescript` transformation is handled for `.tsx` files.
`'babel'` - `typescript` transformation is handled by `@babel/plugin-transform-typescript` during `babel` invocation for JSX transformation.
`'built-in'` - `babel` is invoked only for JSX transformation and then `typescript` transformation is handled by the same toolchain used for `.ts` files (currently `esbuild`).
### babelPlugins
Type: `any[]`
Default: `undefined`
Provide additional plugins for `babel` invocation for JSX transformation.
### tsPluginOptions
Type: `any`
Default: `undefined`
Defines options for `@babel/plugin-transform-typescript` plugin.
## HMR Detection
This plugin supports HMR of Vue JSX components. The detection requirements are:
- The component must be exported.
- The component must be declared by calling `defineComponent` or the name specified in `defineComponentName` via a root-level statement, either variable declaration or export declaration.
### Supported patterns
```jsx
import { defineComponent } from 'vue'
// named exports w/ variable declaration: ok
export const Foo = defineComponent({})
// named exports referencing variable declaration: ok
const Bar = defineComponent({ render() { return <div>Test</div> }})
export { Bar }
// default export call: ok
export default defineComponent({ render() { return <div>Test</div> }})
// default export referencing variable declaration: ok
const Baz = defineComponent({ render() { return <div>Test</div> }})
export default Baz
```
### Non-supported patterns
```jsx
// not using `defineComponent` call
export const Bar = { ... }
// not exported
const Foo = defineComponent(...)
```
@@ -0,0 +1,22 @@
import { VueJSXPluginOptions } from "@vue/babel-plugin-jsx";
import { FilterPattern, Plugin } from "vite";
//#region src/types.d.ts
interface FilterOptions {
include?: FilterPattern;
exclude?: FilterPattern;
}
interface Options extends VueJSXPluginOptions, FilterOptions {
babelPlugins?: any[];
/** @default ['defineComponent'] */
defineComponentName?: string[];
tsPluginOptions?: any;
/** @default 'babel' */
tsTransform?: 'babel' | 'built-in';
}
//#endregion
//#region src/index.d.ts
declare function vueJsxPlugin(options?: Options): Plugin;
declare function vueJsxPluginCjs(this: unknown, options: Options): Plugin;
//#endregion
export { FilterOptions, Options, vueJsxPlugin as default, vueJsxPluginCjs as "module.exports" };
@@ -0,0 +1,210 @@
import crypto from "node:crypto";
import path from "node:path";
import * as babel from "@babel/core";
import { types } from "@babel/core";
import jsx from "@vue/babel-plugin-jsx";
import { createFilter, normalizePath } from "vite";
import { exactRegex, makeIdFiltersToMatchWithQuery } from "@rolldown/pluginutils";
//#region src/index.ts
const ssrRegisterHelperId = "/__vue-jsx-ssr-register-helper";
const ssrRegisterHelperCode = `import { useSSRContext } from "vue"\nexport const ssrRegisterHelper = ${ssrRegisterHelper.toString()}`;
/**
* This function is serialized with toString() and evaluated as a virtual
* module during SSR
*/
function ssrRegisterHelper(comp, filename) {
const setup = comp.setup;
comp.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add(filename);
if (setup) return setup(props, ctx);
};
}
function vueJsxPlugin(options = {}) {
let root = "";
let needHmr = false;
let needSourceMap = true;
const { include = /\.[jt]sx$/, exclude, babelPlugins = [], defineComponentName = ["defineComponent"], tsPluginOptions = {}, tsTransform,...babelPluginOptions } = options;
const filter = createFilter(include, exclude);
return {
name: "vite:vue-jsx",
config(config) {
const parseDefine = (v) => {
try {
return typeof v === "string" ? JSON.parse(v) : v;
} catch (err) {
return v;
}
};
return {
esbuild: tsTransform === "built-in" ? { exclude: /\.jsx?$/ } : { include: /\.ts$/ },
define: {
__VUE_OPTIONS_API__: parseDefine(config.define?.__VUE_OPTIONS_API__) ?? true,
__VUE_PROD_DEVTOOLS__: parseDefine(config.define?.__VUE_PROD_DEVTOOLS__) ?? false,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: parseDefine(config.define?.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__) ?? false
},
optimizeDeps: this && "rolldownVersion" in this.meta ? { rolldownOptions: { transform: { jsx: "preserve" } } } : {}
};
},
configResolved(config) {
needHmr = config.command === "serve" && !config.isProduction;
needSourceMap = config.command === "serve" || !!config.build.sourcemap;
root = config.root;
},
resolveId: {
filter: { id: exactRegex(ssrRegisterHelperId) },
handler(id) {
if (id === ssrRegisterHelperId) return id;
}
},
load: {
filter: { id: exactRegex(ssrRegisterHelperId) },
handler(id) {
if (id === ssrRegisterHelperId) return ssrRegisterHelperCode;
}
},
transform: {
order: tsTransform === "built-in" ? "pre" : void 0,
filter: { id: {
include: include ? makeIdFiltersToMatchWithQuery(include) : void 0,
exclude: exclude ? makeIdFiltersToMatchWithQuery(exclude) : void 0
} },
async handler(code, id, opt) {
const ssr = opt?.ssr === true;
const [filepath] = id.split("?");
if (filter(id) || filter(filepath)) {
const plugins = [[jsx, babelPluginOptions], ...babelPlugins];
if (id.endsWith(".tsx") || filepath.endsWith(".tsx")) if (tsTransform === "built-in") plugins.push([await import("@babel/plugin-syntax-typescript").then((r) => r.default), { isTSX: true }]);
else plugins.push([await import("@babel/plugin-transform-typescript").then((r) => r.default), {
...tsPluginOptions,
isTSX: true,
allowExtensions: true
}]);
if (!ssr && !needHmr) plugins.push(() => {
return { visitor: { CallExpression: { enter(_path) {
if (isDefineComponentCall(_path.node, defineComponentName)) {
const callee = _path.node.callee;
callee.name = `/* @__PURE__ */ ${callee.name}`;
}
} } } };
});
else plugins.push(() => {
return { visitor: { ExportDefaultDeclaration: { enter(_path) {
const unwrappedDeclaration = unwrapTypeAssertion(_path.node.declaration);
if (isDefineComponentCall(unwrappedDeclaration, defineComponentName)) {
const declaration = unwrappedDeclaration;
const nodesPath = _path.replaceWithMultiple([types.variableDeclaration("const", [types.variableDeclarator(types.identifier("__default__"), types.callExpression(declaration.callee, declaration.arguments))]), types.exportDefaultDeclaration(types.identifier("__default__"))]);
_path.scope.registerDeclaration(nodesPath[0]);
}
} } } };
});
const result = babel.transformSync(code, {
babelrc: false,
ast: true,
plugins,
sourceMaps: needSourceMap,
sourceFileName: id,
configFile: false
});
if (!ssr && !needHmr) {
if (!result.code) return;
return {
code: result.code,
map: result.map
};
}
const declaredComponents = [];
const hotComponents = [];
for (const node of result.ast.program.body) {
if (node.type === "VariableDeclaration") {
const names = parseComponentDecls(node, defineComponentName);
if (names.length) declaredComponents.push(...names);
}
if (node.type === "ExportNamedDeclaration") {
if (node.declaration && node.declaration.type === "VariableDeclaration") hotComponents.push(...parseComponentDecls(node.declaration, defineComponentName).map((name) => ({
local: name,
exported: name,
id: getHash(id + name)
})));
else if (node.specifiers.length) {
for (const spec of node.specifiers) if (spec.type === "ExportSpecifier" && spec.exported.type === "Identifier") {
const matched = declaredComponents.find((name) => name === spec.local.name);
if (matched) hotComponents.push({
local: spec.local.name,
exported: spec.exported.name,
id: getHash(id + spec.exported.name)
});
}
}
}
if (node.type === "ExportDefaultDeclaration") {
if (node.declaration.type === "Identifier") {
const _name = node.declaration.name;
const matched = declaredComponents.find((name) => name === _name);
if (matched) hotComponents.push({
local: _name,
exported: "default",
id: getHash(id + "default")
});
} else if (isDefineComponentCall(unwrapTypeAssertion(node.declaration), defineComponentName)) hotComponents.push({
local: "__default__",
exported: "default",
id: getHash(id + "default")
});
}
}
if (hotComponents.length) {
if (needHmr && !ssr && !/\?vue&type=script/.test(id)) {
let code$1 = result.code;
let callbackCode = ``;
for (const { local, exported, id: id$1 } of hotComponents) {
code$1 += `\n${local}.__hmrId = "${id$1}"\n__VUE_HMR_RUNTIME__.createRecord("${id$1}", ${local})`;
callbackCode += `\n__VUE_HMR_RUNTIME__.reload("${id$1}", __${exported})`;
}
const newCompNames = hotComponents.map((c) => `${c.exported}: __${c.exported}`).join(",");
code$1 += `\nimport.meta.hot.accept(({${newCompNames}}) => {${callbackCode}\n})`;
result.code = code$1;
}
if (ssr) {
const normalizedId = normalizePath(path.relative(root, id));
let ssrInjectCode = `\nimport { ssrRegisterHelper } from "${ssrRegisterHelperId}"\nconst __moduleId = ${JSON.stringify(normalizedId)}`;
for (const { local } of hotComponents) ssrInjectCode += `\nssrRegisterHelper(${local}, __moduleId)`;
result.code += ssrInjectCode;
}
}
if (!result.code) return;
return {
code: result.code,
map: result.map
};
}
}
}
};
}
function parseComponentDecls(node, fnNames) {
const names = [];
for (const decl of node.declarations) if (decl.id.type === "Identifier" && isDefineComponentCall(unwrapTypeAssertion(decl.init), fnNames)) names.push(decl.id.name);
return names;
}
function isDefineComponentCall(node, names) {
return node && node.type === "CallExpression" && node.callee.type === "Identifier" && names.includes(node.callee.name);
}
function unwrapTypeAssertion(node) {
if (!node) return node;
let current = node;
while (current.type === "TSAsExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion") current = current.expression;
return current;
}
function getHash(text) {
return crypto.hash("sha256", text, "hex").substring(0, 8);
}
var src_default = vueJsxPlugin;
function vueJsxPluginCjs(options) {
return vueJsxPlugin.call(this, options);
}
Object.assign(vueJsxPluginCjs, { default: vueJsxPluginCjs });
//#endregion
export { src_default as default, vueJsxPluginCjs as "module.exports" };
@@ -0,0 +1,25 @@
MIT License
Copyright (c) 2024-present VoidZero Inc. & Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
end of terms and conditions
The licenses of externally maintained libraries from which parts of the Software is derived are listed [here](https://github.com/rolldown/rolldown/blob/main/THIRD-PARTY-LICENSE).
@@ -0,0 +1,85 @@
# @rolldown/pluginutils
A utility library for building flexible, composable filter expressions that can be used in plugin hook filters of Rolldown/Vite/Rollup/Unplugin plugins.
## Installation
```sh
pnpm add @rolldown/pluginutils
```
## Usage
### Simple Filters
```ts
import {
exactRegex,
makeIdFiltersToMatchWithQuery,
prefixRegex,
} from '@rolldown/pluginutils';
// Match exactly 'foo.js'
const filter = exactRegex('foo.js');
// Match any id starting with 'lib/'
const prefix = prefixRegex('lib/');
// Match ids with query params (e.g. 'foo.js?bar')
const idFilters = makeIdFiltersToMatchWithQuery(['**/*.js', /\.ts$/]);
// Usage in a plugin to define a hook filter
const myPlugin = {
resolveId: {
filter: {
id: [exactRegex('MY_ID_TO_CHECK'), /some-other-regex/],
},
handler(id) {
// Your code here
},
},
};
```
### Composable Filters
> [!WARNING] Composable filters are not yet supported in Vite, Rolldown-Vite or unplugin. They can be used in Rolldown plugins only.
```ts
import { and, id, include, moduleType, query } from '@rolldown/pluginutils';
// Build a filter expression
const filterExpr = and(
id(/\.ts$/),
moduleType('ts'),
query('foo', true),
);
// Usage in a plugin to define a hook filter
const myPlugin = {
transform: {
filter: [include(filterExpr)],
handler(code, id, options) {
// Your code here
},
},
};
```
## API Reference
### Simple Filters
- `exactRegex(str: string, flags?: string): RegExp` — Matches the exact string.
- `prefixRegex(str: string, flags?: string): RegExp` — Matches values with the given prefix.
- `makeIdFiltersToMatchWithQuery(input: string | RegExp | (string | RegExp)[]): string | RegExp | (string | RegExp)[]` — Adapts filters to match ids with query params.
### Composable Filters
- `and(...exprs)` / `or(...exprs)` / `not(expr)` — Logical composition of filter expressions.
- `id(pattern, params?)` — Filter by id (string or RegExp).
- `moduleType(type)` — Filter by module type (e.g. 'js', 'tsx', or 'json').
- `code(pattern)` — Filter by code content.
- `query(key, pattern)` — Filter by query parameter.
- `include(expr)` / `exclude(expr)` — Top-level include/exclude wrappers.
- `queries(obj)` — Compose multiple query filters.
@@ -0,0 +1,157 @@
//#region src/composable-filters.d.ts
type StringOrRegExp = string | RegExp;
type PluginModuleType = "js" | "jsx" | "ts" | "tsx" | "json" | "text" | "base64" | "dataurl" | "binary" | "empty" | (string & {});
type FilterExpressionKind = FilterExpression["kind"];
type FilterExpression = And | Or | Not | Id | ModuleType | Code | Query;
type TopLevelFilterExpression = Include | Exclude;
declare class And {
kind: "and";
args: FilterExpression[];
constructor(...args: FilterExpression[]);
}
declare class Or {
kind: "or";
args: FilterExpression[];
constructor(...args: FilterExpression[]);
}
declare class Not {
kind: "not";
expr: FilterExpression;
constructor(expr: FilterExpression);
}
interface QueryFilterObject {
[key: string]: StringOrRegExp | boolean;
}
interface IdParams {
cleanUrl?: boolean;
}
declare class Id {
kind: "id";
pattern: StringOrRegExp;
params: IdParams;
constructor(pattern: StringOrRegExp, params?: IdParams);
}
declare class ModuleType {
kind: "moduleType";
pattern: PluginModuleType;
constructor(pattern: PluginModuleType);
}
declare class Code {
kind: "code";
pattern: StringOrRegExp;
constructor(expr: StringOrRegExp);
}
declare class Query {
kind: "query";
key: string;
pattern: StringOrRegExp | boolean;
constructor(key: string, pattern: StringOrRegExp | boolean);
}
declare class Include {
kind: "include";
expr: FilterExpression;
constructor(expr: FilterExpression);
}
declare class Exclude {
kind: "exclude";
expr: FilterExpression;
constructor(expr: FilterExpression);
}
declare function and(...args: FilterExpression[]): And;
declare function or(...args: FilterExpression[]): Or;
declare function not(expr: FilterExpression): Not;
declare function id(pattern: StringOrRegExp, params?: IdParams): Id;
declare function moduleType(pattern: PluginModuleType): ModuleType;
declare function code(pattern: StringOrRegExp): Code;
declare function query(key: string, pattern: StringOrRegExp | boolean): Query;
declare function include(expr: FilterExpression): Include;
declare function exclude(expr: FilterExpression): Exclude;
/**
* convert a queryObject to FilterExpression like
* ```js
* and(query(k1, v1), query(k2, v2))
* ```
* @param queryFilterObject The query filter object needs to be matched.
* @returns a `And` FilterExpression
*/
declare function queries(queryFilter: QueryFilterObject): And;
declare function interpreter(exprs: TopLevelFilterExpression | TopLevelFilterExpression[], code?: string, id?: string, moduleType?: PluginModuleType): boolean;
interface InterpreterCtx {
urlSearchParamsCache?: URLSearchParams;
}
declare function interpreterImpl(expr: TopLevelFilterExpression[], code?: string, id?: string, moduleType?: PluginModuleType, ctx?: InterpreterCtx): boolean;
declare function exprInterpreter(expr: FilterExpression, code?: string, id?: string, moduleType?: PluginModuleType, ctx?: InterpreterCtx): boolean;
//#endregion
//#region src/simple-filters.d.ts
/**
* Constructs a RegExp that matches the exact string specified.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { exactRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: exactRegex('foo') },
* handler(id) {} // will only be called for `foo`
* }
* }
* ```
*/
declare function exactRegex(str: string, flags?: string): RegExp;
/**
* Constructs a RegExp that matches a value that has the specified prefix.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { prefixRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: prefixRegex('foo') },
* handler(id) {} // will only be called for IDs starting with `foo`
* }
* }
* ```
*/
declare function prefixRegex(str: string, flags?: string): RegExp;
type WidenString<T> = T extends string ? string : T;
/**
* Converts a id filter to match with an id with a query.
*
* @param input the id filters to convert.
*
* @example
* ```ts
* import { makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* transform: {
* filter: { id: makeIdFiltersToMatchWithQuery(['**' + '/*.js', /\.ts$/]) },
* // The handler will be called for IDs like:
* // - foo.js
* // - foo.js?foo
* // - foo.txt?foo.js
* // - foo.ts
* // - foo.ts?foo
* // - foo.txt?foo.ts
* handler(code, id) {}
* }
* }
* ```
*/
declare function makeIdFiltersToMatchWithQuery<T extends string | RegExp>(input: T): WidenString<T>;
declare function makeIdFiltersToMatchWithQuery<T extends string | RegExp>(input: readonly T[]): WidenString<T>[];
declare function makeIdFiltersToMatchWithQuery(input: string | RegExp | readonly (string | RegExp)[]): string | RegExp | (string | RegExp)[];
//#endregion
export { FilterExpression, FilterExpressionKind, QueryFilterObject, TopLevelFilterExpression, and, code, exactRegex, exclude, exprInterpreter, id, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query };
@@ -0,0 +1,250 @@
//#region src/utils.ts
const postfixRE = /[?#].*$/;
function cleanUrl(url) {
return url.replace(postfixRE, "");
}
function extractQueryWithoutFragment(url) {
const questionMarkIndex = url.indexOf("?");
if (questionMarkIndex === -1) return "";
const fragmentIndex = url.indexOf("#", questionMarkIndex);
if (fragmentIndex === -1) return url.substring(questionMarkIndex);
else return url.substring(questionMarkIndex, fragmentIndex);
}
//#endregion
//#region src/composable-filters.ts
var And = class {
kind;
args;
constructor(...args) {
if (args.length === 0) throw new Error("`And` expects at least one operand");
this.args = args;
this.kind = "and";
}
};
var Or = class {
kind;
args;
constructor(...args) {
if (args.length === 0) throw new Error("`Or` expects at least one operand");
this.args = args;
this.kind = "or";
}
};
var Not = class {
kind;
expr;
constructor(expr) {
this.expr = expr;
this.kind = "not";
}
};
var Id = class {
kind;
pattern;
params;
constructor(pattern, params) {
this.pattern = pattern;
this.kind = "id";
this.params = params ?? { cleanUrl: false };
}
};
var ModuleType = class {
kind;
pattern;
constructor(pattern) {
this.pattern = pattern;
this.kind = "moduleType";
}
};
var Code = class {
kind;
pattern;
constructor(expr) {
this.pattern = expr;
this.kind = "code";
}
};
var Query = class {
kind;
key;
pattern;
constructor(key, pattern) {
this.pattern = pattern;
this.key = key;
this.kind = "query";
}
};
var Include = class {
kind;
expr;
constructor(expr) {
this.expr = expr;
this.kind = "include";
}
};
var Exclude = class {
kind;
expr;
constructor(expr) {
this.expr = expr;
this.kind = "exclude";
}
};
function and(...args) {
return new And(...args);
}
function or(...args) {
return new Or(...args);
}
function not(expr) {
return new Not(expr);
}
function id(pattern, params) {
return new Id(pattern, params);
}
function moduleType(pattern) {
return new ModuleType(pattern);
}
function code(pattern) {
return new Code(pattern);
}
function query(key, pattern) {
return new Query(key, pattern);
}
function include(expr) {
return new Include(expr);
}
function exclude(expr) {
return new Exclude(expr);
}
/**
* convert a queryObject to FilterExpression like
* ```js
* and(query(k1, v1), query(k2, v2))
* ```
* @param queryFilterObject The query filter object needs to be matched.
* @returns a `And` FilterExpression
*/
function queries(queryFilter) {
let arr = Object.entries(queryFilter).map(([key, value]) => {
return new Query(key, value);
});
return and(...arr);
}
function interpreter(exprs, code$1, id$1, moduleType$1) {
let arr = [];
if (Array.isArray(exprs)) arr = exprs;
else arr = [exprs];
return interpreterImpl(arr, code$1, id$1, moduleType$1);
}
function interpreterImpl(expr, code$1, id$1, moduleType$1, ctx = {}) {
let hasInclude = false;
for (const e of expr) switch (e.kind) {
case "include":
hasInclude = true;
if (exprInterpreter(e.expr, code$1, id$1, moduleType$1, ctx)) return true;
break;
case "exclude":
if (exprInterpreter(e.expr, code$1, id$1, moduleType$1)) return false;
break;
}
return !hasInclude;
}
function exprInterpreter(expr, code$1, id$1, moduleType$1, ctx = {}) {
switch (expr.kind) {
case "and": return expr.args.every((e) => exprInterpreter(e, code$1, id$1, moduleType$1, ctx));
case "or": return expr.args.some((e) => exprInterpreter(e, code$1, id$1, moduleType$1, ctx));
case "not": return !exprInterpreter(expr.expr, code$1, id$1, moduleType$1, ctx);
case "id":
if (id$1 === void 0) throw new Error("`id` is required for `id` expression");
if (expr.params.cleanUrl) id$1 = cleanUrl(id$1);
return typeof expr.pattern === "string" ? id$1 === expr.pattern : expr.pattern.test(id$1);
case "moduleType":
if (moduleType$1 === void 0) throw new Error("`moduleType` is required for `moduleType` expression");
return moduleType$1 === expr.pattern;
case "code":
if (code$1 === void 0) throw new Error("`code` is required for `code` expression");
return typeof expr.pattern === "string" ? code$1.includes(expr.pattern) : expr.pattern.test(code$1);
case "query": {
if (id$1 === void 0) throw new Error("`id` is required for `Query` expression");
if (!ctx.urlSearchParamsCache) {
let queryString = extractQueryWithoutFragment(id$1);
ctx.urlSearchParamsCache = new URLSearchParams(queryString);
}
let urlParams = ctx.urlSearchParamsCache;
if (typeof expr.pattern === "boolean") if (expr.pattern) return urlParams.has(expr.key);
else return !urlParams.has(expr.key);
else if (typeof expr.pattern === "string") return urlParams.get(expr.key) === expr.pattern;
else return expr.pattern.test(urlParams.get(expr.key) ?? "");
}
default: throw new Error(`Expression ${JSON.stringify(expr)} is not expected.`);
}
}
//#endregion
//#region src/simple-filters.ts
/**
* Constructs a RegExp that matches the exact string specified.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { exactRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: exactRegex('foo') },
* handler(id) {} // will only be called for `foo`
* }
* }
* ```
*/
function exactRegex(str, flags) {
return new RegExp(`^${escapeRegex(str)}$`, flags);
}
/**
* Constructs a RegExp that matches a value that has the specified prefix.
*
* This is useful for plugin hook filters.
*
* @param str the string to match.
* @param flags flags for the RegExp.
*
* @example
* ```ts
* import { prefixRegex } from '@rolldown/pluginutils';
* const plugin = {
* name: 'plugin',
* resolveId: {
* filter: { id: prefixRegex('foo') },
* handler(id) {} // will only be called for IDs starting with `foo`
* }
* }
* ```
*/
function prefixRegex(str, flags) {
return new RegExp(`^${escapeRegex(str)}`, flags);
}
const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
function escapeRegex(str) {
return str.replace(escapeRegexRE, "\\$&");
}
function makeIdFiltersToMatchWithQuery(input) {
if (!Array.isArray(input)) return makeIdFilterToMatchWithQuery(input);
return input.map((i) => makeIdFilterToMatchWithQuery(i));
}
function makeIdFilterToMatchWithQuery(input) {
if (typeof input === "string") return `${input}{?*,}`;
return makeRegexIdFilterToMatchWithQuery(input);
}
function makeRegexIdFilterToMatchWithQuery(input) {
return new RegExp(input.source.replace(/(?<!\\)\$/g, "(?:\\?.*)?$"), input.flags);
}
//#endregion
export { and, code, exactRegex, exclude, exprInterpreter, id, include, interpreter, interpreterImpl, makeIdFiltersToMatchWithQuery, moduleType, not, or, prefixRegex, queries, query };
@@ -0,0 +1,38 @@
{
"name": "@rolldown/pluginutils",
"version": "1.0.0-beta.38",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/rolldown/rolldown.git",
"directory": "packages/pluginutils"
},
"publishConfig": {
"access": "public"
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"exports": {
".": "./dist/index.mjs",
"./package.json": "./package.json"
},
"files": [
"dist"
],
"devDependencies": {
"@types/picomatch": "^4.0.0",
"picomatch": "^4.0.2",
"tsdown": "0.15.1",
"vitest": "^3.0.1"
},
"tsdown": {
"exports": true,
"fixedExtension": true
},
"scripts": {
"build": "tsdown",
"test": "vitest --typecheck"
}
}
@@ -0,0 +1,51 @@
{
"name": "@vitejs/plugin-vue-jsx",
"version": "5.1.1",
"type": "module",
"license": "MIT",
"author": "Evan You",
"description": "Provides Vue 3 JSX & TSX support with HMR.",
"keywords": [
"vite",
"vite-plugin",
"vue"
],
"files": [
"dist"
],
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vitejs/vite-plugin-vue.git",
"directory": "packages/plugin-vue-jsx"
},
"bugs": {
"url": "https://github.com/vitejs/vite-plugin-vue/issues"
},
"homepage": "https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx#readme",
"dependencies": {
"@babel/core": "^7.28.3",
"@babel/plugin-syntax-typescript": "^7.27.1",
"@babel/plugin-transform-typescript": "^7.28.0",
"@rolldown/pluginutils": "^1.0.0-beta.34",
"@vue/babel-plugin-jsx": "^1.5.0"
},
"devDependencies": {
"tsdown": "^0.14.2",
"vite": "^7.1.3"
},
"peerDependencies": {
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
"vue": "^3.0.0"
},
"scripts": {
"dev": "tsdown --watch",
"build": "tsdown"
}
}
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,278 @@
# @vitejs/plugin-vue [![npm](https://img.shields.io/npm/v/@vitejs/plugin-vue.svg)](https://npmjs.com/package/@vitejs/plugin-vue)
> Note: as of `vue` 3.2.13+ and `@vitejs/plugin-vue` 1.9.0+, `@vue/compiler-sfc` is no longer required as a peer dependency.
```js
// vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
plugins: [vue()],
}
```
For JSX / TSX support, [`@vitejs/plugin-vue-jsx`](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx) is also needed.
## Options
```ts
export interface Options {
include?: string | RegExp | (string | RegExp)[]
exclude?: string | RegExp | (string | RegExp)[]
isProduction?: boolean
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[]
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean
/**
* Customize the component ID generation strategy.
* - `'filepath'`: hash the file path (relative to the project root)
* - `'filepath-source'`: hash the file path and the source code
* - `function`: custom function that takes the file path, source code,
* whether in production mode, and the default hash function as arguments
* - **default:** `'filepath'` in development, `'filepath-source'` in production
*/
componentIdGenerator?:
| 'filepath'
| 'filepath-source'
| ((
filepath: string,
source: string,
isProduction: boolean | undefined,
getHash: (text: string) => string,
) => string)
}
// `script`, `template` and `style` are lower-level compiler options
// to pass on to respective APIs of `vue/compiler-sfc`
script?: Partial<
Omit<
SFCScriptCompileOptions,
| 'id'
| 'isProd'
| 'inlineTemplate'
| 'templateOptions'
| 'sourceMap'
| 'genDefaultAs'
| 'customElement'
>
>
template?: Partial<
Omit<
SFCTemplateCompileOptions,
| 'id'
| 'source'
| 'ast'
| 'filename'
| 'scoped'
| 'slotted'
| 'isProd'
| 'inMap'
| 'ssr'
| 'ssrCssVars'
| 'preprocessLang'
>
>
style?: Partial<
Omit<
SFCStyleCompileOptions,
| 'filename'
| 'id'
| 'isProd'
| 'source'
| 'scoped'
| 'cssDevSourcemap'
| 'postcssOptions'
| 'map'
| 'postcssPlugins'
| 'preprocessCustomRequire'
| 'preprocessLang'
| 'preprocessOptions'
>
>
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler
/**
* @deprecated moved to `features.customElement`.
*/
customElements?: boolean | string | RegExp | (string | RegExp)[]
}
```
## Asset URL handling
When `@vitejs/plugin-vue` compiles the `<template>` blocks in SFCs, it also converts any encountered asset URLs into ESM imports.
For example, the following template snippet:
```vue
<img src="../image.png" />
```
Is the same as:
```vue
<script setup>
import _imports_0 from '../image.png'
</script>
<img :src="_imports_0" />
```
By default the following tag/attribute combinations are transformed, and can be configured using the `template.transformAssetUrls` option.
```js
{
video: ['src', 'poster'],
source: ['src'],
img: ['src'],
image: ['xlink:href', 'href'],
use: ['xlink:href', 'href']
}
```
Note that only attribute values that are static strings are transformed. Otherwise, you'd need to import the asset manually, e.g. `import imgUrl from '../image.png'`.
## Example for passing options to `vue/compiler-sfc`:
```ts
import vue from '@vitejs/plugin-vue'
export default {
plugins: [
vue({
template: {
compilerOptions: {
// ...
},
transformAssetUrls: {
// ...
},
},
}),
],
}
```
## Example for transforming custom blocks
```ts
import vue from '@vitejs/plugin-vue'
import yaml from 'js-yaml'
const vueI18nPlugin = {
name: 'vue-i18n',
transform(code, id) {
// if .vue file don't have <i18n> block, just return
if (!/vue&type=i18n/.test(id)) {
return
}
// parse yaml
if (/\.ya?ml$/.test(id)) {
code = JSON.stringify(yaml.load(code.trim()))
}
// mount the value on the i18n property of the component instance
return `export default Comp => {
Comp.i18n = ${code}
}`
},
}
export default {
plugins: [vue(), vueI18nPlugin],
}
```
Create a file named `Demo.vue`, add `lang="yaml"` to the `<i18n>` blocks, then you can use the syntax of `YAML`:
```vue
<template>Hello</template>
<i18n lang="yaml">
message: 'world'
fullWord: 'hello world'
</i18n>
```
`message` is mounted on the i18n property of the component instance, you can use like this:
```vue
<script setup lang="ts">
import Demo from 'components/Demo.vue'
</script>
<template>
<Demo /> {{ Demo.i18n.message }}
<div>{{ Demo.i18n.fullWord }}</div>
</template>
```
## Using Vue SFCs as Custom Elements
> Requires `vue@^3.2.0` & `@vitejs/plugin-vue@^1.4.0`
Vue 3.2 introduces the `defineCustomElement` method, which works with SFCs. By default, `<style>` tags inside SFCs are extracted and merged into CSS files during build. However when shipping a library of custom elements, it may be desirable to inline the styles as JavaScript strings and inject them into the custom elements' shadow root instead.
Starting in 1.4.0, files ending with `*.ce.vue` will be compiled in "custom elements" mode: its `<style>` tags are compiled into inlined CSS strings and attached to the component as its `styles` property:
```js
import { defineCustomElement } from 'vue'
import Example from './Example.ce.vue'
console.log(Example.styles) // ['/* css content */']
// register
customElements.define('my-example', defineCustomElement(Example))
```
Note in custom elements mode there is no need to use `<style scoped>` since the CSS is already scoped inside the shadow DOM.
The `customElement` plugin option can be used to configure the behavior:
- `{ customElement: true }` will import all `*.vue` files in custom element mode.
- Use a string or regex pattern to change how files should be loaded as Custom Elements (this check is applied after `include` and `exclude` matches).
## License
MIT
@@ -0,0 +1,120 @@
import { Plugin, ViteDevServer } from "vite";
import * as _compiler from "vue/compiler-sfc";
import { SFCScriptCompileOptions, SFCStyleCompileOptions, SFCTemplateCompileOptions } from "vue/compiler-sfc";
//#region src/utils/query.d.ts
interface VueQuery {
vue?: boolean;
src?: string;
type?: 'script' | 'template' | 'style' | 'custom';
index?: number;
lang?: string;
raw?: boolean;
url?: boolean;
scoped?: boolean;
id?: string;
}
declare function parseVueRequest(id: string): {
filename: string;
query: VueQuery;
};
//#endregion
//#region src/index.d.ts
interface Options {
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
/**
* In Vite, this option follows Vite's config.
*/
isProduction?: boolean;
script?: Partial<Omit<SFCScriptCompileOptions, 'id' | 'isProd' | 'inlineTemplate' | 'templateOptions' | 'sourceMap' | 'genDefaultAs' | 'customElement' | 'defineModel' | 'propsDestructure'>> & {
/**
* @deprecated defineModel is now a stable feature and always enabled if
* using Vue 3.4 or above.
*/
defineModel?: boolean;
/**
* @deprecated moved to `features.propsDestructure`.
*/
propsDestructure?: boolean;
};
template?: Partial<Omit<SFCTemplateCompileOptions, 'id' | 'source' | 'ast' | 'filename' | 'scoped' | 'slotted' | 'isProd' | 'inMap' | 'ssr' | 'ssrCssVars' | 'preprocessLang'>>;
style?: Partial<Omit<SFCStyleCompileOptions, 'filename' | 'id' | 'isProd' | 'source' | 'scoped' | 'cssDevSourcemap' | 'postcssOptions' | 'map' | 'postcssPlugins' | 'preprocessCustomRequire' | 'preprocessLang' | 'preprocessOptions'>>;
/**
* Use custom compiler-sfc instance. Can be used to force a specific version.
*/
compiler?: typeof _compiler;
/**
* Requires @vitejs/plugin-vue@^5.1.0
*/
features?: {
/**
* Enable reactive destructure for `defineProps`.
* - Available in Vue 3.4 and later.
* - **default:** `false` in Vue 3.4 (**experimental**), `true` in Vue 3.5+
*/
propsDestructure?: boolean;
/**
* Transform Vue SFCs into custom elements.
* - `true`: all `*.vue` imports are converted into custom elements
* - `string | RegExp`: matched files are converted into custom elements
* - **default:** /\.ce\.vue$/
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
/**
* Set to `false` to disable Options API support and allow related code in
* Vue core to be dropped via dead-code elimination in production builds,
* resulting in smaller bundles.
* - **default:** `true`
*/
optionsAPI?: boolean;
/**
* Set to `true` to enable devtools support in production builds.
* Results in slightly larger bundles.
* - **default:** `false`
*/
prodDevtools?: boolean;
/**
* Set to `true` to enable detailed information for hydration mismatch
* errors in production builds. Results in slightly larger bundles.
* - **default:** `false`
*/
prodHydrationMismatchDetails?: boolean;
/**
* Customize the component ID generation strategy.
* - `'filepath'`: hash the file path (relative to the project root)
* - `'filepath-source'`: hash the file path and the source code
* - `function`: custom function that takes the file path, source code,
* whether in production mode, and the default hash function as arguments
* - **default:** `'filepath'` in development, `'filepath-source'` in production
*/
componentIdGenerator?: 'filepath' | 'filepath-source' | ((filepath: string, source: string, isProduction: boolean | undefined, getHash: (text: string) => string) => string);
};
/**
* @deprecated moved to `features.customElement`.
*/
customElement?: boolean | string | RegExp | (string | RegExp)[];
}
interface ResolvedOptions extends Omit<Options, 'include' | 'exclude'> {
compiler: typeof _compiler;
root: string;
sourceMap: boolean;
cssDevSourcemap: boolean;
devServer?: ViteDevServer;
devToolsEnabled?: boolean;
}
interface Api {
get options(): ResolvedOptions;
set options(value: ResolvedOptions);
get include(): string | RegExp | (string | RegExp)[] | undefined;
/** include cannot be updated after `options` hook is called */
set include(value: string | RegExp | (string | RegExp)[] | undefined);
get exclude(): string | RegExp | (string | RegExp)[] | undefined;
/** exclude cannot be updated after `options` hook is called */
set exclude(value: string | RegExp | (string | RegExp)[] | undefined);
version: string;
}
declare function vuePlugin(rawOptions?: Options): Plugin<Api>;
declare function vuePluginCjs(this: unknown, options: Options): Plugin<Api>;
//#endregion
export { Api, Options, ResolvedOptions, type VueQuery, vuePlugin as default, vuePluginCjs as "module.exports", parseVueRequest };
File diff suppressed because it is too large Load diff
@@ -0,0 +1,54 @@
{
"name": "@vitejs/plugin-vue",
"version": "6.0.1",
"type": "module",
"license": "MIT",
"author": "Evan You",
"description": "The official plugin for Vue SFC support in Vite.",
"keywords": [
"vite",
"vite-plugin",
"vue"
],
"files": [
"dist"
],
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vitejs/vite-plugin-vue.git",
"directory": "packages/plugin-vue"
},
"bugs": {
"url": "https://github.com/vitejs/vite-plugin-vue/issues"
},
"homepage": "https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#readme",
"peerDependencies": {
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
"vue": "^3.2.25"
},
"devDependencies": {
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.29",
"debug": "^4.4.1",
"rollup": "^4.45.1",
"slash": "^5.1.0",
"source-map-js": "^1.2.1",
"tsdown": "^0.13.0",
"vite": "^7.0.5",
"vue": "^3.5.18"
},
"dependencies": {
"@rolldown/pluginutils": "1.0.0-beta.29"
},
"scripts": {
"dev": "tsdown --watch",
"build": "tsdown"
}
}