Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/antfu>
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.

View file

@ -0,0 +1,66 @@
# vite-plugin-inspect
[![NPM version](https://img.shields.io/npm/v/vite-plugin-inspect?color=a1b858&label=)](https://www.npmjs.com/package/vite-plugin-inspect)
Inspect the intermediate state of Vite plugins. Useful for debugging and authoring plugins.
<img width="1488" alt="Screenshot 2024-11-27 at 19 01 26" src="https://github.com/user-attachments/assets/ab6b86ac-d7ce-4424-a23f-02f265f547ea">
## Install
```bash
npm i -D vite-plugin-inspect
```
> [!NOTE]
>
> v10.x requires **Vite v6.0.1** or above.
>
> For Vite v2 to v5, use v0.8.x of `vite-plugin-inspect`. If you want to use it with both Vite 6 and below, you can still use v0.8.x, it's forwards compatible.
Add plugin to your `vite.config.ts`:
```ts
// vite.config.ts
import Inspect from 'vite-plugin-inspect'
export default {
plugins: [
Inspect()
],
}
```
Then run `npm run dev` and visit [localhost:5173/__inspect/](http://localhost:5173/__inspect/) to inspect the modules.
## Build Mode
To inspect transformation in build mode, you can pass the `build: true` option:
```ts
// vite.config.ts
import Inspect from 'vite-plugin-inspect'
export default {
plugins: [
Inspect({
build: true,
outputDir: '.vite-inspect'
})
],
}
```
After running `vite build`, the inspector client will be generated under `.vite-inspect`, where you can use `npx serve .vite-inspect` to check the result.
## Sponsors
<p align="center">
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
<img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
</a>
</p>
## License
[MIT](./LICENSE) License &copy; 2021-PRESENT [Anthony Fu](https://github.com/antfu)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,240 @@
import { Fragment, computed, createBaseVNode, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, h, normalizeClass, normalizeStyle, openBlock, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, withCtx } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
import { isDark, toggleDark, usePayloadStore } from "./payload-BX9lTMvN.js";
import { __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-DfavQbjy.js";
const _sfc_main = {};
const _hoisted_1$4 = { class: "h-[calc(100vh-55px)]" };
function _sfc_render(_ctx, _cache) {
return openBlock(), createElementBlock("div", _hoisted_1$4, [renderSlot(_ctx.$slots, "default")]);
}
var Container_default = /* @__PURE__ */ __plugin_vue_export_helper_default(_sfc_main, [["render", _sfc_render]]);
/**
* Predefined color map for matching the branding
*
* Accpet a 6-digit hex color string or a hue number
* Hue numbers are preferred because they will adapt better contrast in light/dark mode
*
* Hue numbers reference:
* - 0: red
* - 30: orange
* - 60: yellow
* - 120: green
* - 180: cyan
* - 240: blue
* - 270: purple
*/
const predefinedColorMap = {
error: 0,
client: 60,
bailout: -1,
ssr: 270,
vite: 250,
vite1: 240,
vite2: 120,
virtual: 140
};
function getHashColorFromString(name, opacity = 1) {
if (predefinedColorMap[name]) return getHsla(predefinedColorMap[name], opacity);
let hash = 0;
for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);
const hue = hash % 360;
return getHsla(hue, opacity);
}
function getHsla(hue, opacity = 1) {
const saturation = hue === -1 ? 0 : isDark.value ? 50 : 100;
const lightness = isDark.value ? 60 : 20;
return `hsla(${hue}, ${saturation}%, ${lightness}%, ${opacity})`;
}
function getPluginColor(name, opacity = 1) {
if (predefinedColorMap[name]) {
const color = predefinedColorMap[name];
if (typeof color === "number") return getHsla(color, opacity);
else {
if (opacity === 1) return color;
const opacityHex = Math.floor(opacity * 255).toString(16).padStart(2, "0");
return color + opacityHex;
}
}
return getHashColorFromString(name, opacity);
}
var PluginName_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "PluginName",
props: {
name: {},
compact: { type: Boolean },
colored: { type: Boolean },
hide: { type: Boolean }
},
setup(__props) {
const props = __props;
const startsGeneric = [
"__load__",
"vite-plugin-",
"vite-",
"rollup-plugin-",
"rollup-",
"unplugin-"
];
const startCompact = [...startsGeneric, "vite:"];
function render() {
const starts = props.compact ? startCompact : startsGeneric;
for (const s of starts) if (props.name.startsWith(s)) {
if (props.compact) return h("span", props.name.slice(s.length));
return h("span", [h("span", { class: "op50" }, s), h("span", props.name.slice(s.length))]);
}
const parts = props.name.split(":");
if (parts.length > 1) return h("span", [h("span", { style: { color: getHashColorFromString(parts[0]) } }, `${parts[0]}:`), h("span", parts.slice(1).join(":"))]);
return h("span", props.name);
}
return (_ctx, _cache) => {
return openBlock(), createBlock(resolveDynamicComponent(render));
};
}
});
var PluginName_default = PluginName_vue_vue_type_script_setup_true_lang_default;
const _hoisted_1$3 = ["textContent"];
var Badge_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "Badge",
props: {
text: {},
color: {
type: [Boolean, Number],
default: true
},
as: {},
size: {}
},
setup(__props) {
const props = __props;
const style = computed(() => {
if (!props.text || props.color === false) return {};
return {
color: typeof props.color === "number" ? getHsla(props.color) : getHashColorFromString(props.text),
background: typeof props.color === "number" ? getHsla(props.color, .1) : getHashColorFromString(props.text, .1)
};
});
const sizeClasses = computed(() => {
switch (props.size || "sm") {
case "sm": return "px-1.5 text-11px leading-1.6em";
}
return "";
});
return (_ctx, _cache) => {
return openBlock(), createBlock(resolveDynamicComponent(_ctx.as || "span"), {
"ws-nowrap": "",
rounded: "",
class: normalizeClass(unref(sizeClasses)),
style: normalizeStyle(unref(style))
}, {
default: withCtx(() => [renderSlot(_ctx.$slots, "default", {}, () => [createBaseVNode("span", { textContent: toDisplayString(props.text) }, null, 8, _hoisted_1$3)])]),
_: 3
}, 8, ["class", "style"]);
};
}
});
var Badge_default = Badge_vue_vue_type_script_setup_true_lang_default;
const _hoisted_1$2 = {
"h-54px": "",
flex: "~ none gap-2",
border: "b main",
"pl-4": "",
"pr-4": "",
"font-light": "",
"children:my-auto": ""
};
var NavBar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "NavBar",
setup(__props) {
const payload = usePayloadStore();
return (_ctx, _cache) => {
return openBlock(), createElementBlock("nav", _hoisted_1$2, [renderSlot(_ctx.$slots, "default"), renderSlot(_ctx.$slots, "actions", {}, () => [!unref(payload).metadata.embedded ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
_cache[2] || (_cache[2] = createBaseVNode("div", {
mx1: "",
"h-full": "",
"w-0": "",
border: "r main"
}, null, -1)),
_cache[3] || (_cache[3] = createBaseVNode("a", {
"icon-btn": "",
"text-lg": "",
href: "https://github.com/antfu/vite-plugin-inspect",
target: "_blank"
}, [createBaseVNode("div", { "i-carbon-logo-github": "" })], -1)),
createBaseVNode("button", {
class: "icon-btn text-lg",
title: "Toggle Dark Mode",
onClick: _cache[0] || (_cache[0] = ($event) => unref(toggleDark)())
}, [..._cache[1] || (_cache[1] = [createBaseVNode("span", {
"i-carbon-sun": "",
"dark:i-carbon-moon": ""
}, null, -1)])])
], 64)) : createCommentVNode("", true)])]);
};
}
});
var NavBar_default = NavBar_vue_vue_type_script_setup_true_lang_default;
const _hoisted_1$1 = {
flex: "~ gap-1 items-center",
border: "~ subtle rounded",
"bg-subtle": "",
p1: ""
};
var SegmentControl_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "SegmentControl",
props: {
options: {},
modelValue: {}
},
emits: ["update:modelValue"],
setup(__props) {
return (_ctx, _cache) => {
const _component_Badge = Badge_default;
return openBlock(), createElementBlock("div", _hoisted_1$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.options, (option) => {
return openBlock(), createBlock(_component_Badge, {
key: option.value,
class: normalizeClass(["px-2 py-1 text-xs font-mono", option.value === _ctx.modelValue ? "" : "op50"]),
color: option.value === _ctx.modelValue,
"aria-pressed": option.value === _ctx.modelValue,
size: "none",
text: option.label,
as: "button",
onClick: ($event) => _ctx.$emit("update:modelValue", option.value)
}, null, 8, [
"class",
"color",
"aria-pressed",
"text",
"onClick"
]);
}), 128))]);
};
}
});
var SegmentControl_default = SegmentControl_vue_vue_type_script_setup_true_lang_default;
const _hoisted_1 = { flex: "~ gap-2" };
var QuerySelector_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "QuerySelector",
setup(__props) {
const payload = usePayloadStore();
return (_ctx, _cache) => {
const _component_SegmentControl = SegmentControl_default;
return openBlock(), createElementBlock("div", _hoisted_1, [unref(payload).metadata.instances.length > 1 ? (openBlock(), createBlock(_component_SegmentControl, {
key: 0,
modelValue: unref(payload).query.vite,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(payload).query.vite = $event),
options: unref(payload).metadata.instances.map((i) => ({
label: i.vite,
value: i.vite
}))
}, null, 8, ["modelValue", "options"])) : createCommentVNode("", true), createVNode(_component_SegmentControl, {
modelValue: unref(payload).query.env,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => unref(payload).query.env = $event),
options: unref(payload).instance.environments.map((i) => ({
label: i,
value: i
}))
}, null, 8, ["modelValue", "options"])]);
};
}
});
var QuerySelector_default = QuerySelector_vue_vue_type_script_setup_true_lang_default;
export { Badge_default, Container_default, NavBar_default, PluginName_default, QuerySelector_default, SegmentControl_default, getPluginColor };

View file

@ -0,0 +1,8 @@
import { createElementBlock, openBlock } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
import { __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-DfavQbjy.js";
const _sfc_main = {};
function _sfc_render(_ctx, _cache) {
return openBlock(), createElementBlock("div", null, " Not Found ");
}
var _____all__default = /* @__PURE__ */ __plugin_vue_export_helper_default(_sfc_main, [["render", _sfc_render]]);
export { _____all__default as default };

View file

@ -0,0 +1,6 @@
var __plugin_vue_export_helper_default = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) target[key] = val;
return target;
};
export { __plugin_vue_export_helper_default };

View file

@ -0,0 +1,866 @@
(function() {
"use strict";
/**
* @license
* Copyright 2019 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
const proxyMarker = Symbol("Comlink.proxy");
const createEndpoint = Symbol("Comlink.endpoint");
const releaseProxy = Symbol("Comlink.releaseProxy");
const finalizer = Symbol("Comlink.finalizer");
const throwMarker = Symbol("Comlink.thrown");
const isObject = (val) => typeof val === "object" && val !== null || typeof val === "function";
/**
* Internal transfer handle to handle objects marked to proxy.
*/
const proxyTransferHandler = {
canHandle: (val) => isObject(val) && val[proxyMarker],
serialize(obj) {
const { port1, port2 } = new MessageChannel();
expose(obj, port1);
return [port2, [port2]];
},
deserialize(port) {
port.start();
return wrap(port);
}
};
/**
* Internal transfer handler to handle thrown exceptions.
*/
const throwTransferHandler = {
canHandle: (value) => isObject(value) && throwMarker in value,
serialize({ value }) {
let serialized;
if (value instanceof Error) serialized = {
isError: true,
value: {
message: value.message,
name: value.name,
stack: value.stack
}
};
else serialized = {
isError: false,
value
};
return [serialized, []];
},
deserialize(serialized) {
if (serialized.isError) throw Object.assign(new Error(serialized.value.message), serialized.value);
throw serialized.value;
}
};
/**
* Allows customizing the serialization of certain values.
*/
const transferHandlers = new Map([["proxy", proxyTransferHandler], ["throw", throwTransferHandler]]);
function isAllowedOrigin(allowedOrigins, origin) {
for (const allowedOrigin of allowedOrigins) {
if (origin === allowedOrigin || allowedOrigin === "*") return true;
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) return true;
}
return false;
}
function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
ep.addEventListener("message", function callback(ev) {
if (!ev || !ev.data) return;
if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
return;
}
const { id, type, path } = Object.assign({ path: [] }, ev.data);
const argumentList = (ev.data.argumentList || []).map(fromWireValue);
let returnValue;
try {
const parent = path.slice(0, -1).reduce((obj$1, prop) => obj$1[prop], obj);
const rawValue = path.reduce((obj$1, prop) => obj$1[prop], obj);
switch (type) {
case "GET":
returnValue = rawValue;
break;
case "SET":
{
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
returnValue = true;
}
break;
case "APPLY":
returnValue = rawValue.apply(parent, argumentList);
break;
case "CONSTRUCT":
{
const value = new rawValue(...argumentList);
returnValue = proxy(value);
}
break;
case "ENDPOINT":
{
const { port1, port2 } = new MessageChannel();
expose(obj, port2);
returnValue = transfer(port1, [port1]);
}
break;
case "RELEASE":
returnValue = void 0;
break;
default: return;
}
} catch (value) {
returnValue = {
value,
[throwMarker]: 0
};
}
Promise.resolve(returnValue).catch((value) => {
return {
value,
[throwMarker]: 0
};
}).then((returnValue$1) => {
const [wireValue, transferables] = toWireValue(returnValue$1);
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
if (type === "RELEASE") {
ep.removeEventListener("message", callback);
closeEndPoint(ep);
if (finalizer in obj && typeof obj[finalizer] === "function") obj[finalizer]();
}
}).catch((error) => {
const [wireValue, transferables] = toWireValue({
value: new TypeError("Unserializable return value"),
[throwMarker]: 0
});
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
});
});
if (ep.start) ep.start();
}
function isMessagePort(endpoint) {
return endpoint.constructor.name === "MessagePort";
}
function closeEndPoint(endpoint) {
if (isMessagePort(endpoint)) endpoint.close();
}
function wrap(ep, target) {
const pendingListeners = new Map();
ep.addEventListener("message", function handleMessage(ev) {
const { data } = ev;
if (!data || !data.id) return;
const resolver = pendingListeners.get(data.id);
if (!resolver) return;
try {
resolver(data);
} finally {
pendingListeners.delete(data.id);
}
});
return createProxy(ep, pendingListeners, [], target);
}
function throwIfProxyReleased(isReleased) {
if (isReleased) throw new Error("Proxy has been released and is not useable");
}
function releaseEndpoint(ep) {
return requestResponseMessage(ep, new Map(), { type: "RELEASE" }).then(() => {
closeEndPoint(ep);
});
}
const proxyCounter = new WeakMap();
const proxyFinalizers = "FinalizationRegistry" in globalThis && new FinalizationRegistry((ep) => {
const newCount = (proxyCounter.get(ep) || 0) - 1;
proxyCounter.set(ep, newCount);
if (newCount === 0) releaseEndpoint(ep);
});
function registerProxy(proxy$1, ep) {
const newCount = (proxyCounter.get(ep) || 0) + 1;
proxyCounter.set(ep, newCount);
if (proxyFinalizers) proxyFinalizers.register(proxy$1, ep, proxy$1);
}
function unregisterProxy(proxy$1) {
if (proxyFinalizers) proxyFinalizers.unregister(proxy$1);
}
function createProxy(ep, pendingListeners, path = [], target = function() {}) {
let isProxyReleased = false;
const proxy$1 = new Proxy(target, {
get(_target, prop) {
throwIfProxyReleased(isProxyReleased);
if (prop === releaseProxy) return () => {
unregisterProxy(proxy$1);
releaseEndpoint(ep);
pendingListeners.clear();
isProxyReleased = true;
};
if (prop === "then") {
if (path.length === 0) return { then: () => proxy$1 };
const r = requestResponseMessage(ep, pendingListeners, {
type: "GET",
path: path.map((p) => p.toString())
}).then(fromWireValue);
return r.then.bind(r);
}
return createProxy(ep, pendingListeners, [...path, prop]);
},
set(_target, prop, rawValue) {
throwIfProxyReleased(isProxyReleased);
const [value, transferables] = toWireValue(rawValue);
return requestResponseMessage(ep, pendingListeners, {
type: "SET",
path: [...path, prop].map((p) => p.toString()),
value
}, transferables).then(fromWireValue);
},
apply(_target, _thisArg, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const last = path[path.length - 1];
if (last === createEndpoint) return requestResponseMessage(ep, pendingListeners, { type: "ENDPOINT" }).then(fromWireValue);
if (last === "bind") return createProxy(ep, pendingListeners, path.slice(0, -1));
const [argumentList, transferables] = processArguments(rawArgumentList);
return requestResponseMessage(ep, pendingListeners, {
type: "APPLY",
path: path.map((p) => p.toString()),
argumentList
}, transferables).then(fromWireValue);
},
construct(_target, rawArgumentList) {
throwIfProxyReleased(isProxyReleased);
const [argumentList, transferables] = processArguments(rawArgumentList);
return requestResponseMessage(ep, pendingListeners, {
type: "CONSTRUCT",
path: path.map((p) => p.toString()),
argumentList
}, transferables).then(fromWireValue);
}
});
registerProxy(proxy$1, ep);
return proxy$1;
}
function myFlat(arr) {
return Array.prototype.concat.apply([], arr);
}
function processArguments(argumentList) {
const processed = argumentList.map(toWireValue);
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
}
const transferCache = new WeakMap();
function transfer(obj, transfers) {
transferCache.set(obj, transfers);
return obj;
}
function proxy(obj) {
return Object.assign(obj, { [proxyMarker]: true });
}
function toWireValue(value) {
for (const [name, handler] of transferHandlers) if (handler.canHandle(value)) {
const [serializedValue, transferables] = handler.serialize(value);
return [{
type: "HANDLER",
name,
value: serializedValue
}, transferables];
}
return [{
type: "RAW",
value
}, transferCache.get(value) || []];
}
function fromWireValue(value) {
switch (value.type) {
case "HANDLER": return transferHandlers.get(value.name).deserialize(value.value);
case "RAW": return value.value;
}
}
function requestResponseMessage(ep, pendingListeners, msg, transfers) {
return new Promise((resolve) => {
const id = generateUUID();
pendingListeners.set(id, resolve);
if (ep.start) ep.start();
ep.postMessage(Object.assign({ id }, msg), transfers);
});
}
function generateUUID() {
return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
}
const defaultOptions = /* @__PURE__ */ Object.freeze({
diffTimeout: 1,
diffEditCost: 4,
matchThreshold: .5,
matchDistance: 1e3,
patchDeleteThreshold: .5,
patchMargin: 4,
matchMaxBits: 32
});
function resolveOptions(options) {
if (options?.__resolved) return options;
const resolved = {
...defaultOptions,
...options
};
Object.defineProperty(resolved, "__resolved", {
value: true,
enumerable: false
});
return resolved;
}
const DIFF_DELETE = -1;
const DIFF_INSERT = 1;
const DIFF_EQUAL = 0;
function createDiff(op, text) {
return [op, text];
}
function diffMain(text1, text2, options, opt_checklines = true, opt_deadline) {
const resolved = resolveOptions(options);
if (typeof opt_deadline == "undefined") if (resolved.diffTimeout <= 0) opt_deadline = Number.MAX_VALUE;
else opt_deadline = (/* @__PURE__ */ new Date()).getTime() + resolved.diffTimeout * 1e3;
const deadline = opt_deadline;
if (text1 == null || text2 == null) throw new Error("Null input. (diff_main)");
if (text1 === text2) {
if (text1) return [createDiff(DIFF_EQUAL, text1)];
return [];
}
const checklines = opt_checklines;
let commonlength = diffCommonPrefix(text1, text2);
const commonprefix = text1.substring(0, commonlength);
text1 = text1.substring(commonlength);
text2 = text2.substring(commonlength);
commonlength = diffCommonSuffix(text1, text2);
const commonsuffix = text1.substring(text1.length - commonlength);
text1 = text1.substring(0, text1.length - commonlength);
text2 = text2.substring(0, text2.length - commonlength);
const diffs = diffCompute(text1, text2, resolved, checklines, deadline);
if (commonprefix) diffs.unshift(createDiff(DIFF_EQUAL, commonprefix));
if (commonsuffix) diffs.push(createDiff(DIFF_EQUAL, commonsuffix));
diffCleanupMerge(diffs);
return diffs;
}
function diffCompute(text1, text2, options, checklines, deadline) {
let diffs;
if (!text1) return [createDiff(DIFF_INSERT, text2)];
if (!text2) return [createDiff(DIFF_DELETE, text1)];
const longtext = text1.length > text2.length ? text1 : text2;
const shorttext = text1.length > text2.length ? text2 : text1;
const i = longtext.indexOf(shorttext);
if (i !== -1) {
diffs = [
createDiff(DIFF_INSERT, longtext.substring(0, i)),
createDiff(DIFF_EQUAL, shorttext),
createDiff(DIFF_INSERT, longtext.substring(i + shorttext.length))
];
if (text1.length > text2.length) diffs[0][0] = diffs[2][0] = DIFF_DELETE;
return diffs;
}
if (shorttext.length === 1) return [createDiff(DIFF_DELETE, text1), createDiff(DIFF_INSERT, text2)];
const hm = diffHalfMatch(text1, text2, options);
if (hm) {
const text1_a = hm[0];
const text1_b = hm[1];
const text2_a = hm[2];
const text2_b = hm[3];
const mid_common = hm[4];
const diffs_a = diffMain(text1_a, text2_a, options, checklines, deadline);
const diffs_b = diffMain(text1_b, text2_b, options, checklines, deadline);
return diffs_a.concat([createDiff(DIFF_EQUAL, mid_common)], diffs_b);
}
if (checklines && text1.length > 100 && text2.length > 100) return diffLineMode(text1, text2, options, deadline);
return diffBisect(text1, text2, options, deadline);
}
function diffLineMode(text1, text2, options, deadline) {
const a = diffLinesToChars(text1, text2);
text1 = a.chars1;
text2 = a.chars2;
const linearray = a.lineArray;
const diffs = diffMain(text1, text2, options, false, deadline);
diffCharsToLines(diffs, linearray);
diffCleanupSemantic(diffs);
diffs.push(createDiff(DIFF_EQUAL, ""));
let pointer = 0;
let count_delete = 0;
let count_insert = 0;
let text_delete = "";
let text_insert = "";
while (pointer < diffs.length) {
switch (diffs[pointer][0]) {
case DIFF_INSERT:
count_insert++;
text_insert += diffs[pointer][1];
break;
case DIFF_DELETE:
count_delete++;
text_delete += diffs[pointer][1];
break;
case DIFF_EQUAL:
if (count_delete >= 1 && count_insert >= 1) {
diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert);
pointer = pointer - count_delete - count_insert;
const subDiff = diffMain(text_delete, text_insert, options, false, deadline);
for (let j = subDiff.length - 1; j >= 0; j--) diffs.splice(pointer, 0, subDiff[j]);
pointer = pointer + subDiff.length;
}
count_insert = 0;
count_delete = 0;
text_delete = "";
text_insert = "";
break;
}
pointer++;
}
diffs.pop();
return diffs;
}
function diffBisect(text1, text2, options, deadline) {
const text1_length = text1.length;
const text2_length = text2.length;
const max_d = Math.ceil((text1_length + text2_length) / 2);
const v_offset = max_d;
const v_length = 2 * max_d;
const v1 = new Array(v_length);
const v2 = new Array(v_length);
for (let x = 0; x < v_length; x++) {
v1[x] = -1;
v2[x] = -1;
}
v1[v_offset + 1] = 0;
v2[v_offset + 1] = 0;
const delta = text1_length - text2_length;
const front = delta % 2 !== 0;
let k1start = 0;
let k1end = 0;
let k2start = 0;
let k2end = 0;
for (let d = 0; d < max_d; d++) {
if ((/* @__PURE__ */ new Date()).getTime() > deadline) break;
for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
const k1_offset = v_offset + k1;
let x1;
if (k1 === -d || k1 !== d && v1[k1_offset - 1] < v1[k1_offset + 1]) x1 = v1[k1_offset + 1];
else x1 = v1[k1_offset - 1] + 1;
let y1 = x1 - k1;
while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) === text2.charAt(y1)) {
x1++;
y1++;
}
v1[k1_offset] = x1;
if (x1 > text1_length) k1end += 2;
else if (y1 > text2_length) k1start += 2;
else if (front) {
const k2_offset = v_offset + delta - k1;
if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] !== -1) {
const x2 = text1_length - v2[k2_offset];
if (x1 >= x2) return diffBisectSplit(text1, text2, options, x1, y1, deadline);
}
}
}
for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
const k2_offset = v_offset + k2;
let x2;
if (k2 === -d || k2 !== d && v2[k2_offset - 1] < v2[k2_offset + 1]) x2 = v2[k2_offset + 1];
else x2 = v2[k2_offset - 1] + 1;
let y2 = x2 - k2;
while (x2 < text1_length && y2 < text2_length && text1.charAt(text1_length - x2 - 1) === text2.charAt(text2_length - y2 - 1)) {
x2++;
y2++;
}
v2[k2_offset] = x2;
if (x2 > text1_length) k2end += 2;
else if (y2 > text2_length) k2start += 2;
else if (!front) {
const k1_offset = v_offset + delta - k2;
if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] !== -1) {
const x1 = v1[k1_offset];
const y1 = v_offset + x1 - k1_offset;
x2 = text1_length - x2;
if (x1 >= x2) return diffBisectSplit(text1, text2, options, x1, y1, deadline);
}
}
}
}
return [createDiff(DIFF_DELETE, text1), createDiff(DIFF_INSERT, text2)];
}
function diffBisectSplit(text1, text2, options, x, y, deadline) {
const text1a = text1.substring(0, x);
const text2a = text2.substring(0, y);
const text1b = text1.substring(x);
const text2b = text2.substring(y);
const diffs = diffMain(text1a, text2a, options, false, deadline);
const diffsb = diffMain(text1b, text2b, options, false, deadline);
return diffs.concat(diffsb);
}
function diffLinesToChars(text1, text2) {
const lineArray = [];
const lineHash = {};
let maxLines = 4e4;
lineArray[0] = "";
function diffLinesToCharsMunge(text) {
let chars = "";
let lineStart = 0;
let lineEnd = -1;
let lineArrayLength = lineArray.length;
while (lineEnd < text.length - 1) {
lineEnd = text.indexOf("\n", lineStart);
if (lineEnd === -1) lineEnd = text.length - 1;
let line = text.substring(lineStart, lineEnd + 1);
if (lineHash.hasOwnProperty ? Object.prototype.hasOwnProperty.call(lineHash, line) : lineHash[line] !== void 0) chars += String.fromCharCode(lineHash[line]);
else {
if (lineArrayLength === maxLines) {
line = text.substring(lineStart);
lineEnd = text.length;
}
chars += String.fromCharCode(lineArrayLength);
lineHash[line] = lineArrayLength;
lineArray[lineArrayLength++] = line;
}
lineStart = lineEnd + 1;
}
return chars;
}
const chars1 = diffLinesToCharsMunge(text1);
maxLines = 65535;
const chars2 = diffLinesToCharsMunge(text2);
return {
chars1,
chars2,
lineArray
};
}
function diffCharsToLines(diffs, lineArray) {
for (let i = 0; i < diffs.length; i++) {
const chars = diffs[i][1];
const text = [];
for (let j = 0; j < chars.length; j++) text[j] = lineArray[chars.charCodeAt(j)];
diffs[i][1] = text.join("");
}
}
function diffCommonPrefix(text1, text2) {
if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) return 0;
let pointermin = 0;
let pointermax = Math.min(text1.length, text2.length);
let pointermid = pointermax;
let pointerstart = 0;
while (pointermin < pointermid) {
if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) {
pointermin = pointermid;
pointerstart = pointermin;
} else pointermax = pointermid;
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
}
function diffCommonSuffix(text1, text2) {
if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) return 0;
let pointermin = 0;
let pointermax = Math.min(text1.length, text2.length);
let pointermid = pointermax;
let pointerend = 0;
while (pointermin < pointermid) {
if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) {
pointermin = pointermid;
pointerend = pointermin;
} else pointermax = pointermid;
pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
}
return pointermid;
}
function diffCommonOverlap(text1, text2) {
const text1_length = text1.length;
const text2_length = text2.length;
if (text1_length === 0 || text2_length === 0) return 0;
if (text1_length > text2_length) text1 = text1.substring(text1_length - text2_length);
else if (text1_length < text2_length) text2 = text2.substring(0, text1_length);
const text_length = Math.min(text1_length, text2_length);
if (text1 === text2) return text_length;
let best = 0;
let length = 1;
while (true) {
const pattern = text1.substring(text_length - length);
const found = text2.indexOf(pattern);
if (found === -1) return best;
length += found;
if (found === 0 || text1.substring(text_length - length) === text2.substring(0, length)) {
best = length;
length++;
}
}
}
function diffHalfMatch(text1, text2, options) {
if (options.diffTimeout <= 0) return null;
const longtext = text1.length > text2.length ? text1 : text2;
const shorttext = text1.length > text2.length ? text2 : text1;
if (longtext.length < 4 || shorttext.length * 2 < longtext.length) return null;
function diffHalfMatchI(longtext2, shorttext2, i) {
const seed = longtext2.substring(i, i + Math.floor(longtext2.length / 4));
let j = -1;
let best_common = "";
let best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
while ((j = shorttext2.indexOf(seed, j + 1)) !== -1) {
const prefixLength = diffCommonPrefix(longtext2.substring(i), shorttext2.substring(j));
const suffixLength = diffCommonSuffix(longtext2.substring(0, i), shorttext2.substring(0, j));
if (best_common.length < suffixLength + prefixLength) {
best_common = shorttext2.substring(j - suffixLength, j) + shorttext2.substring(j, j + prefixLength);
best_longtext_a = longtext2.substring(0, i - suffixLength);
best_longtext_b = longtext2.substring(i + prefixLength);
best_shorttext_a = shorttext2.substring(0, j - suffixLength);
best_shorttext_b = shorttext2.substring(j + prefixLength);
}
}
if (best_common.length * 2 >= longtext2.length) return [
best_longtext_a,
best_longtext_b,
best_shorttext_a,
best_shorttext_b,
best_common
];
else return null;
}
const hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4));
const hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2));
let hm;
if (!hm1 && !hm2) return null;
else if (!hm2) hm = hm1;
else if (!hm1) hm = hm2;
else hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
let text1_a, text1_b, text2_a, text2_b;
if (text1.length > text2.length) {
text1_a = hm[0];
text1_b = hm[1];
text2_a = hm[2];
text2_b = hm[3];
} else {
text2_a = hm[0];
text2_b = hm[1];
text1_a = hm[2];
text1_b = hm[3];
}
const mid_common = hm[4];
return [
text1_a,
text1_b,
text2_a,
text2_b,
mid_common
];
}
function diffCleanupSemantic(diffs) {
let changes = false;
const equalities = [];
let equalitiesLength = 0;
let lastEquality = null;
let pointer = 0;
let length_insertions1 = 0;
let length_deletions1 = 0;
let length_insertions2 = 0;
let length_deletions2 = 0;
while (pointer < diffs.length) {
if (diffs[pointer][0] === DIFF_EQUAL) {
equalities[equalitiesLength++] = pointer;
length_insertions1 = length_insertions2;
length_deletions1 = length_deletions2;
length_insertions2 = 0;
length_deletions2 = 0;
lastEquality = diffs[pointer][1];
} else {
if (diffs[pointer][0] === DIFF_INSERT) length_insertions2 += diffs[pointer][1].length;
else length_deletions2 += diffs[pointer][1].length;
if (lastEquality && lastEquality.length <= Math.max(length_insertions1, length_deletions1) && lastEquality.length <= Math.max(length_insertions2, length_deletions2)) {
diffs.splice(equalities[equalitiesLength - 1], 0, createDiff(DIFF_DELETE, lastEquality));
diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
equalitiesLength--;
equalitiesLength--;
pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
length_insertions1 = 0;
length_deletions1 = 0;
length_insertions2 = 0;
length_deletions2 = 0;
lastEquality = null;
changes = true;
}
}
pointer++;
}
if (changes) diffCleanupMerge(diffs);
diffCleanupSemanticLossless(diffs);
pointer = 1;
while (pointer < diffs.length) {
if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
const deletion = diffs[pointer - 1][1];
const insertion = diffs[pointer][1];
const overlap_length1 = diffCommonOverlap(deletion, insertion);
const overlap_length2 = diffCommonOverlap(insertion, deletion);
if (overlap_length1 >= overlap_length2) {
if (overlap_length1 >= deletion.length / 2 || overlap_length1 >= insertion.length / 2) {
diffs.splice(pointer, 0, createDiff(DIFF_EQUAL, insertion.substring(0, overlap_length1)));
diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlap_length1);
diffs[pointer + 1][1] = insertion.substring(overlap_length1);
pointer++;
}
} else if (overlap_length2 >= deletion.length / 2 || overlap_length2 >= insertion.length / 2) {
diffs.splice(pointer, 0, createDiff(DIFF_EQUAL, deletion.substring(0, overlap_length2)));
diffs[pointer - 1][0] = DIFF_INSERT;
diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlap_length2);
diffs[pointer + 1][0] = DIFF_DELETE;
diffs[pointer + 1][1] = deletion.substring(overlap_length2);
pointer++;
}
pointer++;
}
pointer++;
}
}
const nonAlphaNumericRegex_ = /[^a-z0-9]/i;
const whitespaceRegex_ = /\s/;
const linebreakRegex_ = /[\r\n]/;
const blanklineEndRegex_ = /\n\r?\n$/;
const blanklineStartRegex_ = /^\r?\n\r?\n/;
function diffCleanupSemanticLossless(diffs) {
function diffCleanupSemanticScore(one, two) {
if (!one || !two) return 6;
const char1 = one.charAt(one.length - 1);
const char2 = two.charAt(0);
const nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_);
const nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_);
const whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_);
const whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_);
const lineBreak1 = whitespace1 && char1.match(linebreakRegex_);
const lineBreak2 = whitespace2 && char2.match(linebreakRegex_);
const blankLine1 = lineBreak1 && one.match(blanklineEndRegex_);
const blankLine2 = lineBreak2 && two.match(blanklineStartRegex_);
if (blankLine1 || blankLine2) return 5;
else if (lineBreak1 || lineBreak2) return 4;
else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) return 3;
else if (whitespace1 || whitespace2) return 2;
else if (nonAlphaNumeric1 || nonAlphaNumeric2) return 1;
return 0;
}
let pointer = 1;
while (pointer < diffs.length - 1) {
if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
let equality1 = diffs[pointer - 1][1];
let edit = diffs[pointer][1];
let equality2 = diffs[pointer + 1][1];
const commonOffset = diffCommonSuffix(equality1, edit);
if (commonOffset) {
const commonString = edit.substring(edit.length - commonOffset);
equality1 = equality1.substring(0, equality1.length - commonOffset);
edit = commonString + edit.substring(0, edit.length - commonOffset);
equality2 = commonString + equality2;
}
let bestEquality1 = equality1;
let bestEdit = edit;
let bestEquality2 = equality2;
let bestScore = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
while (edit.charAt(0) === equality2.charAt(0)) {
equality1 += edit.charAt(0);
edit = edit.substring(1) + equality2.charAt(0);
equality2 = equality2.substring(1);
const score = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
if (score >= bestScore) {
bestScore = score;
bestEquality1 = equality1;
bestEdit = edit;
bestEquality2 = equality2;
}
}
if (diffs[pointer - 1][1] !== bestEquality1) {
if (bestEquality1) diffs[pointer - 1][1] = bestEquality1;
else {
diffs.splice(pointer - 1, 1);
pointer--;
}
diffs[pointer][1] = bestEdit;
if (bestEquality2) diffs[pointer + 1][1] = bestEquality2;
else {
diffs.splice(pointer + 1, 1);
pointer--;
}
}
}
pointer++;
}
}
function diffCleanupMerge(diffs) {
diffs.push(createDiff(DIFF_EQUAL, ""));
let pointer = 0;
let count_delete = 0;
let count_insert = 0;
let text_delete = "";
let text_insert = "";
let commonlength;
while (pointer < diffs.length) switch (diffs[pointer][0]) {
case DIFF_INSERT:
count_insert++;
text_insert += diffs[pointer][1];
pointer++;
break;
case DIFF_DELETE:
count_delete++;
text_delete += diffs[pointer][1];
pointer++;
break;
case DIFF_EQUAL:
if (count_delete + count_insert > 1) {
if (count_delete !== 0 && count_insert !== 0) {
commonlength = diffCommonPrefix(text_insert, text_delete);
if (commonlength !== 0) {
if (pointer - count_delete - count_insert > 0 && diffs[pointer - count_delete - count_insert - 1][0] === DIFF_EQUAL) diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength);
else {
diffs.splice(0, 0, createDiff(DIFF_EQUAL, text_insert.substring(0, commonlength)));
pointer++;
}
text_insert = text_insert.substring(commonlength);
text_delete = text_delete.substring(commonlength);
}
commonlength = diffCommonSuffix(text_insert, text_delete);
if (commonlength !== 0) {
diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1];
text_insert = text_insert.substring(0, text_insert.length - commonlength);
text_delete = text_delete.substring(0, text_delete.length - commonlength);
}
}
pointer -= count_delete + count_insert;
diffs.splice(pointer, count_delete + count_insert);
if (text_delete.length) {
diffs.splice(pointer, 0, createDiff(DIFF_DELETE, text_delete));
pointer++;
}
if (text_insert.length) {
diffs.splice(pointer, 0, createDiff(DIFF_INSERT, text_insert));
pointer++;
}
pointer++;
} else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
diffs[pointer - 1][1] += diffs[pointer][1];
diffs.splice(pointer, 1);
} else pointer++;
count_insert = 0;
count_delete = 0;
text_delete = "";
text_insert = "";
break;
}
if (diffs[diffs.length - 1][1] === "") diffs.pop();
let changes = false;
pointer = 1;
while (pointer < diffs.length - 1) {
if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) {
diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length);
diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
diffs.splice(pointer - 1, 1);
changes = true;
} else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) {
diffs[pointer - 1][1] += diffs[pointer + 1][1];
diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1];
diffs.splice(pointer + 1, 1);
changes = true;
}
}
pointer++;
}
if (changes) diffCleanupMerge(diffs);
}
function calculateDiff(left, right) {
const changes = diffMain(left.replace(/\r\n/g, "\n"), right.replace(/\r\n/g, "\n"));
diffCleanupSemantic(changes);
return changes;
}
const exports$1 = { calculateDiff };
expose(exports$1);
})();

View file

@ -0,0 +1,249 @@
function serialize(o) {
return typeof o == "string" ? `'${o}'` : new c().serialize(o);
}
const c = /* @__PURE__ */ function() {
class o {
#t = new Map();
compare(t, r$1) {
const e = typeof t, n = typeof r$1;
return e === "string" && n === "string" ? t.localeCompare(r$1) : e === "number" && n === "number" ? t - r$1 : String.prototype.localeCompare.call(this.serialize(t, true), this.serialize(r$1, true));
}
serialize(t, r$1) {
if (t === null) return "null";
switch (typeof t) {
case "string": return r$1 ? t : `'${t}'`;
case "bigint": return `${t}n`;
case "object": return this.$object(t);
case "function": return this.$function(t);
}
return String(t);
}
serializeObject(t) {
const r$1 = Object.prototype.toString.call(t);
if (r$1 !== "[object Object]") return this.serializeBuiltInType(r$1.length < 10 ? `unknown:${r$1}` : r$1.slice(8, -1), t);
const e = t.constructor, n = e === Object || e === void 0 ? "" : e.name;
if (n !== "" && globalThis[n] === e) return this.serializeBuiltInType(n, t);
if (typeof t.toJSON == "function") {
const i = t.toJSON();
return n + (i !== null && typeof i == "object" ? this.$object(i) : `(${this.serialize(i)})`);
}
return this.serializeObjectEntries(n, Object.entries(t));
}
serializeBuiltInType(t, r$1) {
const e = this["$" + t];
if (e) return e.call(this, r$1);
if (typeof r$1?.entries == "function") return this.serializeObjectEntries(t, r$1.entries());
throw new Error(`Cannot serialize ${t}`);
}
serializeObjectEntries(t, r$1) {
const e = Array.from(r$1).sort((i, a) => this.compare(i[0], a[0]));
let n = `${t}{`;
for (let i = 0; i < e.length; i++) {
const [a, l$1] = e[i];
n += `${this.serialize(a, true)}:${this.serialize(l$1)}`, i < e.length - 1 && (n += ",");
}
return n + "}";
}
$object(t) {
let r$1 = this.#t.get(t);
return r$1 === void 0 && (this.#t.set(t, `#${this.#t.size}`), r$1 = this.serializeObject(t), this.#t.set(t, r$1)), r$1;
}
$function(t) {
const r$1 = Function.prototype.toString.call(t);
return r$1.slice(-15) === "[native code] }" ? `${t.name || ""}()[native]` : `${t.name}(${t.length})${r$1.replace(/\s*\n\s*/g, "")}`;
}
$Array(t) {
let r$1 = "[";
for (let e = 0; e < t.length; e++) r$1 += this.serialize(t[e]), e < t.length - 1 && (r$1 += ",");
return r$1 + "]";
}
$Date(t) {
try {
return `Date(${t.toISOString()})`;
} catch {
return "Date(null)";
}
}
$ArrayBuffer(t) {
return `ArrayBuffer[${new Uint8Array(t).join(",")}]`;
}
$Set(t) {
return `Set${this.$Array(Array.from(t).sort((r$1, e) => this.compare(r$1, e)))}`;
}
$Map(t) {
return this.serializeObjectEntries("Map", t.entries());
}
}
for (const s of [
"Error",
"RegExp",
"URL"
]) o.prototype["$" + s] = function(t) {
return `${s}(${t})`;
};
for (const s of [
"Int8Array",
"Uint8Array",
"Uint8ClampedArray",
"Int16Array",
"Uint16Array",
"Int32Array",
"Uint32Array",
"Float32Array",
"Float64Array"
]) o.prototype["$" + s] = function(t) {
return `${s}[${t.join(",")}]`;
};
for (const s of ["BigInt64Array", "BigUint64Array"]) o.prototype["$" + s] = function(t) {
return `${s}[${t.join("n,")}${t.length > 0 ? "n" : ""}]`;
};
return o;
}();
const z = [
1779033703,
-1150833019,
1013904242,
-1521486534,
1359893119,
-1694144372,
528734635,
1541459225
], R = [
1116352408,
1899447441,
-1245643825,
-373957723,
961987163,
1508970993,
-1841331548,
-1424204075,
-670586216,
310598401,
607225278,
1426881987,
1925078388,
-2132889090,
-1680079193,
-1046744716,
-459576895,
-272742522,
264347078,
604807628,
770255983,
1249150122,
1555081692,
1996064986,
-1740746414,
-1473132947,
-1341970488,
-1084653625,
-958395405,
-710438585,
113926993,
338241895,
666307205,
773529912,
1294757372,
1396182291,
1695183700,
1986661051,
-2117940946,
-1838011259,
-1564481375,
-1474664885,
-1035236496,
-949202525,
-778901479,
-694614492,
-200395387,
275423344,
430227734,
506948616,
659060556,
883997877,
958139571,
1322822218,
1537002063,
1747873779,
1955562222,
2024104815,
-2067236844,
-1933114872,
-1866530822,
-1538233109,
-1090935817,
-965641998
], S = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", r = [];
var k = class {
_data = new l();
_hash = new l([...z]);
_nDataBytes = 0;
_minBufferSize = 0;
finalize(e) {
e && this._append(e);
const s = this._nDataBytes * 8, t = this._data.sigBytes * 8;
return this._data.words[t >>> 5] |= 128 << 24 - t % 32, this._data.words[(t + 64 >>> 9 << 4) + 14] = Math.floor(s / 4294967296), this._data.words[(t + 64 >>> 9 << 4) + 15] = s, this._data.sigBytes = this._data.words.length * 4, this._process(), this._hash;
}
_doProcessBlock(e, s) {
const t = this._hash.words;
let i = t[0], o = t[1], a = t[2], c$1 = t[3], h = t[4], g = t[5], f = t[6], y = t[7];
for (let n = 0; n < 64; n++) {
if (n < 16) r[n] = e[s + n] | 0;
else {
const d = r[n - 15], j = (d << 25 | d >>> 7) ^ (d << 14 | d >>> 18) ^ d >>> 3, B = r[n - 2], x = (B << 15 | B >>> 17) ^ (B << 13 | B >>> 19) ^ B >>> 10;
r[n] = j + r[n - 7] + x + r[n - 16];
}
const m = h & g ^ ~h & f, p = i & o ^ i & a ^ o & a, u = (i << 30 | i >>> 2) ^ (i << 19 | i >>> 13) ^ (i << 10 | i >>> 22), b = (h << 26 | h >>> 6) ^ (h << 21 | h >>> 11) ^ (h << 7 | h >>> 25), w = y + b + m + R[n] + r[n], M = u + p;
y = f, f = g, g = h, h = c$1 + w | 0, c$1 = a, a = o, o = i, i = w + M | 0;
}
t[0] = t[0] + i | 0, t[1] = t[1] + o | 0, t[2] = t[2] + a | 0, t[3] = t[3] + c$1 | 0, t[4] = t[4] + h | 0, t[5] = t[5] + g | 0, t[6] = t[6] + f | 0, t[7] = t[7] + y | 0;
}
_append(e) {
typeof e == "string" && (e = l.fromUtf8(e)), this._data.concat(e), this._nDataBytes += e.sigBytes;
}
_process(e) {
let s, t = this._data.sigBytes / 64;
e ? t = Math.ceil(t) : t = Math.max((t | 0) - this._minBufferSize, 0);
const i = t * 16, o = Math.min(i * 4, this._data.sigBytes);
if (i) {
for (let a = 0; a < i; a += 16) this._doProcessBlock(this._data.words, a);
s = this._data.words.splice(0, i), this._data.sigBytes -= o;
}
return new l(s, o);
}
};
var l = class l {
words;
sigBytes;
constructor(e, s) {
e = this.words = e || [], this.sigBytes = s === void 0 ? e.length * 4 : s;
}
static fromUtf8(e) {
const s = unescape(encodeURIComponent(e)), t = s.length, i = [];
for (let o = 0; o < t; o++) i[o >>> 2] |= (s.charCodeAt(o) & 255) << 24 - o % 4 * 8;
return new l(i, t);
}
toBase64() {
const e = [];
for (let s = 0; s < this.sigBytes; s += 3) {
const t = this.words[s >>> 2] >>> 24 - s % 4 * 8 & 255, i = this.words[s + 1 >>> 2] >>> 24 - (s + 1) % 4 * 8 & 255, o = this.words[s + 2 >>> 2] >>> 24 - (s + 2) % 4 * 8 & 255, a = t << 16 | i << 8 | o;
for (let c$1 = 0; c$1 < 4 && s * 8 + c$1 * 6 < this.sigBytes * 8; c$1++) e.push(S.charAt(a >>> 6 * (3 - c$1) & 63));
}
return e.join("");
}
concat(e) {
if (this.words[this.sigBytes >>> 2] &= 4294967295 << 32 - this.sigBytes % 4 * 8, this.words.length = Math.ceil(this.sigBytes / 4), this.sigBytes % 4) for (let s = 0; s < e.sigBytes; s++) {
const t = e.words[s >>> 2] >>> 24 - s % 4 * 8 & 255;
this.words[this.sigBytes + s >>> 2] |= t << 24 - (this.sigBytes + s) % 4 * 8;
}
else for (let s = 0; s < e.sigBytes; s += 4) this.words[this.sigBytes + s >>> 2] = e.words[s >>> 2];
this.sigBytes += e.sigBytes;
}
};
function digest(_) {
return new k().finalize(_).toBase64();
}
function hash(input) {
return digest(serialize(input));
}
export { hash };

View file

@ -0,0 +1,33 @@
import { createHotContext } from "./payload-BX9lTMvN.js";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __export = (target, all) => {
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
const hotContext = createHotContext();
async function getHot() {
return await hotContext;
}
export { __commonJSMin, __export, __toESM, getHot };

View file

@ -0,0 +1,96 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./pages-g-EVEhKa.js","./_plugin-vue_export-helper-DfavQbjy.js","./payload-BX9lTMvN.js","./runtime-core.esm-bundler-Cyv4obHQ.js","./ModuleList-ByxGSHde.js","./vue-router-BxYGFXy-.js","./QuerySelector-iLRAQoow.js","./options-D_MMddT_.js","./search-Bklj8tNk.js","./_...all_-DVz6Qbfk.js","./metric-D2Mof43y.js","./hot-D67q3Up2.js","./module-BFxZWV4q.js","./module-2YhSO2gi.css","./plugins-Ngzgf8uz.js"])))=>i.map(i=>d[i]);
import { Suspense, createBlock, createElementBlock, createTextVNode, createVNode, defineComponent, h, onMounted, openBlock, resolveComponent, withAsyncContext, withCtx } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
import { createApp, createRouter, createWebHashHistory } from "./vue-router-BxYGFXy-.js";
import { __vitePreload, createPinia, isStaticMode, usePayloadStore } from "./payload-BX9lTMvN.js";
(function polyfill() {
const relList = document.createElement("link").relList;
if (relList && relList.supports && relList.supports("modulepreload")) return;
for (const link of document.querySelectorAll("link[rel=\"modulepreload\"]")) processPreload(link);
new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type !== "childList") continue;
for (const node of mutation.addedNodes) if (node.tagName === "LINK" && node.rel === "modulepreload") processPreload(node);
}
}).observe(document, {
childList: true,
subtree: true
});
function getFetchOpts(link) {
const fetchOpts = {};
if (link.integrity) fetchOpts.integrity = link.integrity;
if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
if (link.crossOrigin === "use-credentials") fetchOpts.credentials = "include";
else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
else fetchOpts.credentials = "same-origin";
return fetchOpts;
}
function processPreload(link) {
if (link.ep) return;
link.ep = true;
const fetchOpts = getFetchOpts(link);
fetch(link.href, fetchOpts);
}
})();
const routes = [{
path: "/",
name: "/",
component: () => __vitePreload(() => import("./pages-g-EVEhKa.js"), __vite__mapDeps([0,1,2,3,4,5,6,7,8]), import.meta.url),
children: [
{
path: ":all(.*)",
name: "//[...all]",
component: () => __vitePreload(() => import("./_...all_-DVz6Qbfk.js"), __vite__mapDeps([9,1,3]), import.meta.url)
},
{
path: "metric",
name: "//metric",
component: () => __vitePreload(() => import("./metric-D2Mof43y.js"), __vite__mapDeps([10,1,2,3,8,7,6,11]), import.meta.url)
},
{
path: "module",
name: "//module",
component: () => __vitePreload(() => import("./module-BFxZWV4q.js"), __vite__mapDeps([12,1,2,3,4,5,6,7,11,13]), import.meta.url)
},
{
path: "plugins",
name: "//plugins",
component: () => __vitePreload(() => import("./plugins-Ngzgf8uz.js"), __vite__mapDeps([14,1,2,3,6]), import.meta.url)
}
]
}];
const _hoisted_1 = {
grid: "~ rows-[min-content_1fr]",
size: "h-screen w-screen"
};
var App_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "App",
async setup(__props) {
let __temp, __restore;
onMounted(() => {
if (isStaticMode) document.title = "Vite Inspect (Production)";
});
const payload = usePayloadStore();
[__temp, __restore] = withAsyncContext(() => payload.init()), await __temp, __restore();
return (_ctx, _cache) => {
const _component_RouterView = resolveComponent("RouterView");
return openBlock(), createElementBlock("main", _hoisted_1, [(openBlock(), createBlock(Suspense, null, {
fallback: withCtx(() => [..._cache[0] || (_cache[0] = [createTextVNode(" Loading... ", -1)])]),
default: withCtx(() => [createVNode(_component_RouterView)]),
_: 1
}))]);
};
}
});
var App_default = App_vue_vue_type_script_setup_true_lang_default;
const app = createApp(() => h(Suspense, {}, {
default: () => h(App_default),
fallback: "Loading..."
}));
const router = createRouter({
routes,
history: createWebHashHistory()
});
const pinia = createPinia();
app.use(pinia);
app.use(router);
app.mount("#app");

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,389 @@
.CodeMirror-dialog {
position: absolute;
left: 0; right: 0;
background: inherit;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: inherit;
}
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
top: 0;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
bottom: 0;
}
.CodeMirror-dialog input {
border: none;
outline: none;
background: transparent;
width: 20em;
color: inherit;
font-family: monospace;
}
.CodeMirror-dialog button {
font-size: 70%;
}
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
direction: ltr;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-fat-cursor .CodeMirror-line::selection,
.cm-fat-cursor .CodeMirror-line > span::selection,
.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
.cm-fat-cursor .CodeMirror-line::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
.cm-fat-cursor { caret-color: transparent; }
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 50px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -50px; margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
z-index: 0;
}
.CodeMirror-sizer {
position: relative;
border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
.diff-added {
background-color:rgb(74 222 128 / 0.15) /* #4ade80 */;
}
.diff-removed {
background-color:rgb(248 113 113 / 0.15) /* #f87171 */;
}
.diff-added-inline {
background-color:rgb(74 222 128 / 0.3) /* #4ade80 */;
}
.diff-removed-inline {
background-color:rgb(248 113 113 / 0.3) /* #f87171 */;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,114 @@
import { computed, createBaseVNode, createBlock, createElementBlock, defineComponent, normalizeClass, openBlock, toDisplayString, unref } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
import { defineStore, useLocalStorage } from "./payload-BX9lTMvN.js";
const _hoisted_1 = { block: "" };
const _hoisted_2 = {
"ml-0.4": "",
"text-xs": "",
op75: ""
};
var NumberWithUnit_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "NumberWithUnit",
props: {
number: {},
unit: {}
},
setup(__props) {
return (_ctx, _cache) => {
return openBlock(), createElementBlock("span", _hoisted_1, [createBaseVNode("span", null, toDisplayString(_ctx.number), 1), createBaseVNode("span", _hoisted_2, toDisplayString(_ctx.unit), 1)]);
};
}
});
var NumberWithUnit_default = NumberWithUnit_vue_vue_type_script_setup_true_lang_default;
var DurationDisplay_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "DurationDisplay",
props: {
duration: {},
factor: { default: 1 },
color: {
type: Boolean,
default: true
}
},
setup(__props) {
const props = __props;
function getDurationColor(duration) {
if (!props.color) return "";
if (duration == null) return "";
duration = duration * props.factor;
if (duration < 1) return "";
if (duration > 1e3) return "status-red";
if (duration > 500) return "status-yellow";
if (duration > 200) return "status-green";
return "";
}
const units = computed(() => {
if (!props.duration) return ["", "-"];
if (props.duration < 1) return ["<1", "ms"];
if (props.duration < 1e3) return [props.duration.toFixed(0), "ms"];
if (props.duration < 1e3 * 60) return [(props.duration / 1e3).toFixed(1), "s"];
return [(props.duration / 1e3 / 60).toFixed(1), "min"];
});
return (_ctx, _cache) => {
const _component_NumberWithUnit = NumberWithUnit_default;
return openBlock(), createBlock(_component_NumberWithUnit, {
class: normalizeClass(getDurationColor(_ctx.duration)),
number: unref(units)[0],
unit: unref(units)[1]
}, null, 8, [
"class",
"number",
"unit"
]);
};
}
});
var DurationDisplay_default = DurationDisplay_vue_vue_type_script_setup_true_lang_default;
const useOptionsStore = defineStore("options", () => {
const view = useLocalStorage(
"vite-inspect-v1-options",
// @keep-sorted
{
diff: true,
graphWeightMode: "deps",
lineWrapping: false,
listMode: "detailed",
metricDisplayHook: "transform",
panelSizeDiff: 30,
panelSizeModule: 10,
showBailout: false,
showOneColumn: false,
sort: "default"
},
{ mergeDefaults: true }
);
const search = useLocalStorage("vite-inspect-v1-search", {
text: "",
includeNodeModules: false,
includeVirtual: false,
includeUnreached: false,
exactSearch: false
}, { mergeDefaults: true });
function toggleSort() {
const rules = [
"default",
"time-asc",
"time-desc"
];
view.value.sort = rules[(rules.indexOf(view.value.sort) + 1) % rules.length];
}
function toggleListMode() {
const modes = [
"detailed",
"graph",
"list"
];
view.value.listMode = modes[(modes.indexOf(view.value.listMode) + 1) % modes.length];
}
return {
view,
search,
toggleSort,
toggleListMode
};
});
export { DurationDisplay_default, NumberWithUnit_default, useOptionsStore };

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,76 @@
import { Fragment, createBaseVNode, createBlock, createElementBlock, createVNode, defineComponent, h, openBlock, renderList, resolveComponent, resolveDynamicComponent, unref, withCtx } from "./runtime-core.esm-bundler-Cyv4obHQ.js";
import { usePayloadStore } from "./payload-BX9lTMvN.js";
import "./_plugin-vue_export-helper-DfavQbjy.js";
import { Badge_default, Container_default, NavBar_default, PluginName_default, QuerySelector_default } from "./QuerySelector-iLRAQoow.js";
const _hoisted_1 = { "w-full": "" };
var plugins_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "plugins",
setup(__props) {
const payload = usePayloadStore();
function renderRow(idx) {
const envs = payload.instance.environments.map((e) => payload.instance.environmentPlugins[e].includes(idx));
const nodes = [];
envs.forEach((e, i) => {
if (envs[i - 1] === e) return;
if (!e) nodes.push(h("td"));
else {
let length = envs.slice(i).findIndex((e$1) => !e$1);
if (length === -1) length = envs.length - i;
nodes.push(h("td", {
colspan: length,
class: "border border-main px4 py1"
}, [h(PluginName_default, { name: payload.instance.plugins[idx].name })]));
}
});
return () => nodes;
}
return (_ctx, _cache) => {
const _component_RouterLink = resolveComponent("RouterLink");
const _component_QuerySelector = QuerySelector_default;
const _component_NavBar = NavBar_default;
const _component_Badge = Badge_default;
const _component_Container = Container_default;
return openBlock(), createElementBlock(Fragment, null, [createVNode(_component_NavBar, null, {
default: withCtx(() => [
createVNode(_component_RouterLink, {
"my-auto": "",
"icon-btn": "",
"outline-none": "",
to: "/"
}, {
default: withCtx(() => [..._cache[0] || (_cache[0] = [createBaseVNode("div", { "i-carbon-arrow-left": "" }, null, -1)])]),
_: 1
}),
_cache[1] || (_cache[1] = createBaseVNode("div", { "flex-auto": "" }, null, -1)),
createVNode(_component_QuerySelector)
]),
_: 1
}), createVNode(_component_Container, {
flex: "",
"overflow-auto": "",
p5: ""
}, {
default: withCtx(() => [createBaseVNode("table", _hoisted_1, [createBaseVNode("thead", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(payload).instance.environments, (e) => {
return openBlock(), createElementBlock("td", {
key: e,
border: "~ main",
p2: "",
"text-center": ""
}, [createVNode(_component_Badge, {
text: e,
size: "none",
px2: "",
py1: "",
"text-sm": "",
"font-mono": ""
}, null, 8, ["text"])]);
}), 128))]), createBaseVNode("tbody", null, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(payload).instance.plugins, (p, idx) => {
return openBlock(), createElementBlock("tr", { key: idx }, [(openBlock(), createBlock(resolveDynamicComponent(renderRow(idx))))]);
}), 128))])])]),
_: 1
})], 64);
};
}
});
var plugins_default = plugins_vue_vue_type_script_setup_true_lang_default;
export { plugins_default as default };

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img"
class="iconify iconify--carbon" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32">
<style>
.a {
fill: #333;
}
@media (prefers-color-scheme: dark) {
.a {
fill: #eee;
}
}
</style>
<path class="a" d="M6 17h8v2H6z" />
<circle cx="3" cy="18" r="1" class="a" />
<circle cx="13" cy="14" r="1" class="a" />
<path class="a" d="M2 13h8v2H2zm4-4h8v2H6z" />
<circle cx="3" cy="10" r="1" class="a" />
<path class="a"
d="m30 28.6l-7.4-7.4c1.5-2 2.4-4.5 2.4-7.2c0-6.6-5.4-12-12-12c-3.3 0-6.4 1.3-8.7 3.8l1.5 1.4C7.6 5.1 10.2 4 13 4c5.5 0 10 4.5 10 10s-4.5 10-10 10c-3 0-5.8-1.3-7.7-3.6l-1.5 1.3C6 24.4 9.4 26 13 26c3.2 0 6.1-1.3 8.3-3.3l7.3 7.3l1.4-1.4z" />
</svg>

After

Width:  |  Height:  |  Size: 857 B

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="./favicon.svg" type="image/svg+xml">
<title>Vite Inspect</title>
<script type="module" crossorigin src="./assets/index---UmQy10.js"></script>
<link rel="modulepreload" crossorigin href="./assets/runtime-core.esm-bundler-Cyv4obHQ.js">
<link rel="modulepreload" crossorigin href="./assets/payload-BX9lTMvN.js">
<link rel="modulepreload" crossorigin href="./assets/vue-router-BxYGFXy-.js">
<link rel="stylesheet" crossorigin href="./assets/index-shvuXdj8.css">
</head>
<body data-vite-inspect-mode="DEV" class="bg-main text-main font-sans">
<div id="app"></div>
<script>
(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('color-schema') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light'))
document.documentElement.classList.toggle('dark', true)
})()
;(function () {
if (!location.pathname.endsWith('/'))
location.pathname += '/'
})()
</script>
</body>
</html>

View file

@ -0,0 +1,4 @@
declare const DIR_DIST: any;
declare const DIR_CLIENT: any;
export { DIR_CLIENT, DIR_DIST };

View file

@ -0,0 +1,7 @@
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const DIR_DIST = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
const DIR_CLIENT = resolve(DIR_DIST, "../dist/client");
export { DIR_CLIENT, DIR_DIST };

View file

@ -0,0 +1,118 @@
import { Plugin } from 'vite';
import { StackFrame } from 'error-stack-parser-es';
import { V as ViteInspectOptions } from './shared/vite-plugin-inspect.CtoQ7j4S.mjs';
export { F as FilterPattern } from './shared/vite-plugin-inspect.CtoQ7j4S.mjs';
interface TransformInfo {
name: string;
result?: string;
start: number;
end: number;
order?: string;
sourcemaps?: any;
error?: ParsedError;
}
interface ParsedError {
message: string;
stack: StackFrame[];
raw?: any;
}
interface ModuleInfo {
id: string;
plugins: {
name: string;
transform?: number;
resolveId?: number;
}[];
deps: string[];
importers: string[];
virtual: boolean;
totalTime: number;
invokeCount: number;
sourceSize: number;
distSize: number;
}
type ModulesList = ModuleInfo[];
interface ModuleTransformInfo {
resolvedId: string;
transforms: TransformInfo[];
}
interface PluginMetricInfo {
name: string;
enforce?: string;
transform: {
invokeCount: number;
totalTime: number;
};
resolveId: {
invokeCount: number;
totalTime: number;
};
}
interface ServerMetrics {
middleware?: Record<string, {
name: string;
self: number;
total: number;
}[]>;
}
interface SerializedPlugin {
name: string;
enforce?: string;
resolveId: string;
load: string;
transform: string;
generateBundle: string;
handleHotUpdate: string;
api: string;
}
interface InstanceInfo {
root: string;
/**
* Vite instance ID
*/
vite: string;
/**
* Environment names
*/
environments: string[];
/**
* Plugins
*/
plugins: SerializedPlugin[];
/**
* Environment plugins, the index of the plugin in the `plugins` array
*/
environmentPlugins: Record<string, number[]>;
}
interface Metadata {
instances: InstanceInfo[];
embedded?: boolean;
}
interface RpcFunctions {
getMetadata: () => Promise<Metadata>;
getModulesList: (query: QueryEnv) => Promise<ModulesList>;
getModuleTransformInfo: (query: QueryEnv, id: string, clear?: boolean) => Promise<ModuleTransformInfo>;
getPluginMetrics: (query: QueryEnv) => Promise<PluginMetricInfo[]>;
getServerMetrics: (query: QueryEnv) => Promise<ServerMetrics>;
resolveId: (query: QueryEnv, id: string) => Promise<string>;
onModuleUpdated: () => Promise<void>;
}
interface QueryEnv {
/**
* Vite instance ID
*/
vite: string;
/**
* Environment name
*/
env: string;
}
interface ViteInspectAPI {
rpc: RpcFunctions;
}
declare function PluginInspect(options?: ViteInspectOptions): Plugin;
export { ViteInspectOptions, PluginInspect as default };
export type { ViteInspectAPI };

View file

@ -0,0 +1,16 @@
export { P as default } from './shared/vite-plugin-inspect.BzUKaD4x.mjs';
import 'node:process';
import 'ansis';
import 'perfect-debounce';
import 'sirv';
import 'vite-dev-rpc';
import './dirs.mjs';
import 'node:path';
import 'node:url';
import 'node:fs/promises';
import 'ohash';
import 'node:buffer';
import 'unplugin-utils';
import 'debug';
import 'error-stack-parser-es';
import 'node:http';

View file

@ -0,0 +1,5 @@
export { V as ModuleOptions } from './shared/vite-plugin-inspect.CtoQ7j4S.mjs';
declare const _default: any;
export { _default as default };

View file

@ -0,0 +1,29 @@
import { defineNuxtModule, addVitePlugin } from '@nuxt/kit';
import { P as PluginInspect } from './shared/vite-plugin-inspect.BzUKaD4x.mjs';
import 'node:process';
import 'ansis';
import 'perfect-debounce';
import 'sirv';
import 'vite-dev-rpc';
import './dirs.mjs';
import 'node:path';
import 'node:url';
import 'node:fs/promises';
import 'ohash';
import 'node:buffer';
import 'unplugin-utils';
import 'debug';
import 'error-stack-parser-es';
import 'node:http';
const nuxt = defineNuxtModule({
meta: {
name: "vite-plugin-inspect",
configKey: "inspect"
},
setup(options) {
addVitePlugin(() => PluginInspect(options));
}
});
export { nuxt as default };

View file

@ -0,0 +1,736 @@
import process from 'node:process';
import c from 'ansis';
import { debounce } from 'perfect-debounce';
import sirv from 'sirv';
import { createRPCServer } from 'vite-dev-rpc';
import { DIR_CLIENT } from '../dirs.mjs';
import fs from 'node:fs/promises';
import { isAbsolute, resolve, join } from 'node:path';
import { hash } from 'ohash';
import { Buffer } from 'node:buffer';
import { createFilter } from 'unplugin-utils';
import Debug from 'debug';
import { parse } from 'error-stack-parser-es';
import { createServer } from 'node:http';
function createEnvOrderHooks(environmentNames, { onFirst, onEach, onLast }) {
const remainingEnvs = new Set(environmentNames);
let ranFirst = false;
let ranLast = false;
return async (envName, ...args) => {
if (!ranFirst) {
ranFirst = true;
await onFirst?.(...args);
}
remainingEnvs.delete(envName);
await onEach?.(...args);
if (!ranLast && remainingEnvs.size === 0) {
ranLast = true;
await onLast?.(...args);
}
};
}
function createBuildGenerator(ctx) {
const {
outputDir = ".vite-inspect"
} = ctx.options;
const targetDir = isAbsolute(outputDir) ? outputDir : resolve(process.cwd(), outputDir);
const reportsDir = join(targetDir, "reports");
return {
getOutputDir() {
return targetDir;
},
async setupOutputDir() {
await fs.rm(targetDir, { recursive: true, force: true });
await fs.mkdir(reportsDir, { recursive: true });
await fs.cp(DIR_CLIENT, targetDir, { recursive: true });
await Promise.all([
fs.writeFile(
join(targetDir, "index.html"),
(await fs.readFile(join(targetDir, "index.html"), "utf-8")).replace(
'data-vite-inspect-mode="DEV"',
'data-vite-inspect-mode="BUILD"'
)
)
]);
},
async generateForEnv(pluginCtx) {
const env = pluginCtx.environment;
await Promise.all(
[...ctx._idToInstances.values()].filter((v) => v.environments.has(env.name)).map((v) => {
const e = v.environments.get(env.name);
const key = `${v.id}-${env.name}`;
return [key, e];
}).map(async ([key, env2]) => {
await fs.mkdir(join(reportsDir, key, "transforms"), { recursive: true });
return await Promise.all([
writeJSON(
join(reportsDir, key, "modules.json"),
env2.getModulesList(pluginCtx)
),
writeJSON(
join(reportsDir, key, "metric-plugins.json"),
env2.getPluginMetrics()
),
...Object.entries(env2.data.transform).map(([id, info]) => writeJSON(
join(reportsDir, key, "transforms", `${hash(id)}.json`),
{
resolvedId: id,
transforms: info
}
))
]);
})
);
},
async generateMetadata() {
await writeJSON(
join(reportsDir, "metadata.json"),
ctx.getMetadata()
);
}
};
}
function writeJSON(filename, data) {
return fs.writeFile(filename, `${JSON.stringify(data, null, 2)}
`);
}
const DUMMY_LOAD_PLUGIN_NAME = "__load__";
async function openBrowser(address) {
await import('open').then((r) => r.default(address, { newInstance: true })).catch(() => {
});
}
function serializePlugin(plugin) {
return JSON.parse(JSON.stringify(plugin, (key, value) => {
if (typeof value === "function") {
let name = value.name;
if (name === "anonymous")
name = "";
if (name === key)
name = "";
if (name)
return `[Function ${name}]`;
return "[Function]";
}
if (key === "api" && value)
return "[Object API]";
return value;
}));
}
function removeVersionQuery(url) {
if (url.includes("v=")) {
return url.replace(/&v=\w+/, "").replace(/\?v=\w+/, "?").replace(/\?$/, "");
}
return url;
}
let viteCount = 0;
class InspectContext {
constructor(options) {
this.options = options;
this.filter = createFilter(options.include, options.exclude);
}
_configToInstances = /* @__PURE__ */ new Map();
_idToInstances = /* @__PURE__ */ new Map();
filter;
getMetadata() {
return {
instances: [...this._idToInstances.values()].map((vite) => ({
root: vite.config.root,
vite: vite.id,
plugins: vite.config.plugins.map((i) => serializePlugin(i)),
environments: [...vite.environments.keys()],
environmentPlugins: Object.fromEntries(
[...vite.environments.entries()].map(([name, env]) => {
return [name, env.env.getTopLevelConfig().plugins.map((i) => vite.config.plugins.indexOf(i))];
})
)
})),
embedded: this.options.embedded
};
}
getViteContext(configOrId) {
if (typeof configOrId === "string") {
if (!this._idToInstances.has(configOrId))
throw new Error(`Can not found vite context for ${configOrId}`);
return this._idToInstances.get(configOrId);
}
if (this._configToInstances.has(configOrId))
return this._configToInstances.get(configOrId);
const id = `vite${++viteCount}`;
const vite = new InspectContextVite(id, this, configOrId);
this._idToInstances.set(id, vite);
this._configToInstances.set(configOrId, vite);
return vite;
}
getEnvContext(env) {
if (!env)
return void 0;
const vite = this.getViteContext(env.getTopLevelConfig());
return vite.getEnvContext(env);
}
queryEnv(query) {
const vite = this.getViteContext(query.vite);
const env = vite.getEnvContext(query.env);
return env;
}
}
class InspectContextVite {
constructor(id, context, config) {
this.id = id;
this.context = context;
this.config = config;
}
environments = /* @__PURE__ */ new Map();
data = {
serverMetrics: {
middleware: {}
}
};
getEnvContext(env) {
if (typeof env === "string") {
if (!this.environments.has(env))
throw new Error(`Can not found environment context for ${env}`);
return this.environments.get(env);
}
if (env.getTopLevelConfig() !== this.config)
throw new Error("Environment config does not match Vite config");
if (!this.environments.has(env.name))
this.environments.set(env.name, new InspectContextViteEnv(this.context, this, env));
return this.environments.get(env.name);
}
}
class InspectContextViteEnv {
constructor(contextMain, contextVite, env) {
this.contextMain = contextMain;
this.contextVite = contextVite;
this.env = env;
}
data = {
transform: {},
resolveId: {},
transformCounter: {}
};
recordTransform(id, info, preTransformCode) {
id = this.normalizeId(id);
if (!this.data.transform[id] || !this.data.transform[id].some((tr) => tr.result)) {
this.data.transform[id] = [{
name: DUMMY_LOAD_PLUGIN_NAME,
result: preTransformCode,
start: info.start,
end: info.start,
sourcemaps: info.sourcemaps
}];
this.data.transformCounter[id] = (this.data.transformCounter[id] || 0) + 1;
}
this.data.transform[id].push(info);
}
recordLoad(id, info) {
id = this.normalizeId(id);
this.data.transform[id] = [info];
this.data.transformCounter[id] = (this.data.transformCounter[id] || 0) + 1;
}
recordResolveId(id, info) {
id = this.normalizeId(id);
if (!this.data.resolveId[id])
this.data.resolveId[id] = [];
this.data.resolveId[id].push(info);
}
invalidate(id) {
id = this.normalizeId(id);
delete this.data.transform[id];
}
normalizeId(id) {
if (this.contextMain.options.removeVersionQuery !== false)
return removeVersionQuery(id);
return id;
}
getModulesList(pluginCtx) {
const moduleGraph = this.env.mode === "dev" ? this.env.moduleGraph : void 0;
const getDeps = moduleGraph ? (id) => Array.from(moduleGraph.getModuleById(id)?.importedModules || []).map((i) => i.id || "").filter(Boolean) : pluginCtx ? (id) => pluginCtx.getModuleInfo(id)?.importedIds || [] : () => [];
const getImporters = moduleGraph ? (id) => Array.from(moduleGraph?.getModuleById(id)?.importers || []).map((i) => i.id || "").filter(Boolean) : pluginCtx ? (id) => pluginCtx.getModuleInfo(id)?.importers || [] : () => [];
function isVirtual(pluginName, transformName) {
return pluginName !== DUMMY_LOAD_PLUGIN_NAME && transformName !== "vite:load-fallback" && transformName !== "vite:build-load-fallback";
}
const transformedIdMap = Object.values(this.data.resolveId).reduce((map, ids2) => {
ids2.forEach((id) => {
map[id.result] ??= [];
map[id.result].push(id);
});
return map;
}, {});
const ids = new Set(Object.keys(this.data.transform).concat(Object.keys(transformedIdMap)));
return Array.from(ids).sort().map((id) => {
let totalTime = 0;
const plugins = (this.data.transform[id] || []).filter((tr) => tr.result).map((transItem) => {
const delta = transItem.end - transItem.start;
totalTime += delta;
return { name: transItem.name, transform: delta };
}).concat(
// @ts-expect-error transform is optional
(transformedIdMap[id] || []).map((idItem) => {
return { name: idItem.name, resolveId: idItem.end - idItem.start };
})
);
function getSize(str) {
if (!str)
return 0;
return Buffer.byteLength(str, "utf8");
}
return {
id,
deps: getDeps(id),
importers: getImporters(id),
plugins,
virtual: isVirtual(plugins[0]?.name || "", this.data.transform[id]?.[0].name || ""),
totalTime,
invokeCount: this.data.transformCounter?.[id] || 0,
sourceSize: getSize(this.data.transform[id]?.[0]?.result),
distSize: getSize(this.data.transform[id]?.[this.data.transform[id].length - 1]?.result)
};
});
}
resolveId(id = "", ssr = false) {
if (id.startsWith("./"))
id = resolve(this.env.getTopLevelConfig().root, id).replace(/\\/g, "/");
return this.resolveIdRecursive(id, ssr);
}
resolveIdRecursive(id, ssr = false) {
const resolved = this.data.resolveId[id]?.[0]?.result;
return resolved ? this.resolveIdRecursive(resolved, ssr) : id;
}
getPluginMetrics() {
const map = {};
const defaultMetricInfo = () => ({
transform: { invokeCount: 0, totalTime: 0 },
resolveId: { invokeCount: 0, totalTime: 0 }
});
this.env.getTopLevelConfig().plugins.forEach((i) => {
map[i.name] = {
...defaultMetricInfo(),
name: i.name,
enforce: i.enforce
};
});
Object.values(this.data.transform).forEach((transformInfos) => {
transformInfos.forEach(({ name, start, end }) => {
if (name === DUMMY_LOAD_PLUGIN_NAME)
return;
if (!map[name])
map[name] = { ...defaultMetricInfo(), name };
map[name].transform.totalTime += end - start;
map[name].transform.invokeCount += 1;
});
});
Object.values(this.data.resolveId).forEach((resolveIdInfos) => {
resolveIdInfos.forEach(({ name, start, end }) => {
if (!map[name])
map[name] = { ...defaultMetricInfo(), name };
map[name].resolveId.totalTime += end - start;
map[name].resolveId.invokeCount += 1;
});
});
const metrics = Object.values(map).filter(Boolean).sort((a, b) => a.name.localeCompare(b.name));
return metrics;
}
async getModuleTransformInfo(id, clear = false) {
if (clear) {
this.clearId(id);
try {
if (this.env.mode === "dev")
await this.env.transformRequest(id);
} catch {
}
}
const resolvedId = this.resolveId(id);
return {
resolvedId,
transforms: this.data.transform[resolvedId] || []
};
}
clearId(_id) {
const id = this.resolveId(_id);
if (id) {
const moduleGraph = this.env.mode === "dev" ? this.env.moduleGraph : void 0;
const mod = moduleGraph?.getModuleById(id);
if (mod)
moduleGraph?.invalidateModule(mod);
this.invalidate(id);
}
}
}
const debug = Debug("vite-plugin-inspect");
function hijackHook(plugin, name, wrapper) {
if (!plugin[name])
return;
debug(`hijack plugin "${name}"`, plugin.name);
let order = plugin.order || plugin.enforce || "normal";
const hook = plugin[name];
if ("handler" in hook) {
const oldFn = hook.handler;
order += `-${hook.order || hook.enforce || "normal"}`;
hook.handler = function(...args) {
return wrapper(oldFn, this, args, order);
};
} else if ("transform" in hook) {
const oldFn = hook.transform;
order += `-${hook.order || hook.enforce || "normal"}`;
hook.transform = function(...args) {
return wrapper(oldFn, this, args, order);
};
} else {
const oldFn = hook;
plugin[name] = function(...args) {
return wrapper(oldFn, this, args, order);
};
}
}
const hijackedPlugins = /* @__PURE__ */ new WeakSet();
function hijackPlugin(plugin, ctx) {
if (hijackedPlugins.has(plugin))
return;
hijackedPlugins.add(plugin);
hijackHook(plugin, "transform", async (fn, context, args, order) => {
const code = args[0];
const id = args[1];
let _result;
let error;
const start = Date.now();
try {
_result = await fn.apply(context, args);
} catch (_err) {
error = _err;
}
const end = Date.now();
const result = error ? "[Error]" : typeof _result === "string" ? _result : _result?.code;
if (ctx.filter(id)) {
const sourcemaps = typeof _result === "string" ? null : _result?.map;
ctx.getEnvContext(context?.environment)?.recordTransform(id, {
name: plugin.name,
result,
start,
end,
order,
sourcemaps,
error: error ? parseError(error) : void 0
}, code);
}
if (error)
throw error;
return _result;
});
hijackHook(plugin, "load", async (fn, context, args) => {
const id = args[0];
let _result;
let error;
const start = Date.now();
try {
_result = await fn.apply(context, args);
} catch (err) {
error = err;
}
const end = Date.now();
const result = error ? "[Error]" : typeof _result === "string" ? _result : _result?.code;
const sourcemaps = typeof _result === "string" ? null : _result?.map;
if (result) {
ctx.getEnvContext(context?.environment)?.recordLoad(id, {
name: plugin.name,
result,
start,
end,
sourcemaps,
error: error ? parseError(error) : void 0
});
}
if (error)
throw error;
return _result;
});
hijackHook(plugin, "resolveId", async (fn, context, args) => {
const id = args[0];
let _result;
let error;
const start = Date.now();
try {
_result = await fn.apply(context, args);
} catch (err) {
error = err;
}
const end = Date.now();
if (!ctx.filter(id)) {
if (error)
throw error;
return _result;
}
const result = error ? stringifyError(error) : typeof _result === "object" ? _result?.id : _result;
if (result && result !== id) {
ctx.getEnvContext(context?.environment)?.recordResolveId(id, {
name: plugin.name,
result,
start,
end,
error
});
}
if (error)
throw error;
return _result;
});
}
function parseError(error) {
const stack = parse(error, { allowEmpty: true });
const message = error.message || String(error);
return {
message,
stack,
raw: error
};
}
function stringifyError(err) {
return String(err.stack ? err.stack : err);
}
function createPreviewServer(staticPath) {
const server = createServer();
const statics = sirv(staticPath);
server.on("request", (req, res) => {
statics(req, res, () => {
res.statusCode = 404;
res.end("File not found");
});
});
server.listen(0, () => {
const { port } = server.address();
const url = `http://localhost:${port}`;
console.log(` ${c.green("\u279C")} ${c.bold("Inspect Preview Started")}: ${url}`);
openBrowser(url);
});
}
function createServerRpc(ctx) {
const rpc = {
async getMetadata() {
return ctx.getMetadata();
},
async getModulesList(query) {
return ctx.queryEnv(query).getModulesList();
},
async getPluginMetrics(query) {
return ctx.queryEnv(query).getPluginMetrics();
},
async getModuleTransformInfo(query, id, clear) {
return ctx.queryEnv(query).getModuleTransformInfo(id, clear);
},
async resolveId(query, id) {
return ctx.queryEnv(query).resolveId(id);
},
async getServerMetrics(query) {
return ctx.getViteContext(query.vite).data.serverMetrics || {};
},
async onModuleUpdated() {
}
};
return rpc;
}
const NAME = "vite-plugin-inspect";
const isCI = !!process.env.CI;
function PluginInspect(options = {}) {
const {
dev = true,
build = false,
silent = false,
open: _open = false
} = options;
if (!dev && !build) {
return {
name: NAME
};
}
const ctx = new InspectContext(options);
let onBuildEnd;
const timestampRE = /\bt=\d{13}&?\b/;
const trailingSeparatorRE = /[?&]$/;
function setupMiddlewarePerf(ctx2, middlewares) {
let firstMiddlewareIndex = -1;
middlewares.forEach((middleware, index) => {
const { handle: originalHandle } = middleware;
if (typeof originalHandle !== "function" || !originalHandle.name)
return middleware;
middleware.handle = function(...middlewareArgs) {
let req;
if (middlewareArgs.length === 4)
[, req] = middlewareArgs;
else
[req] = middlewareArgs;
const start = Date.now();
const url = req.url?.replace(timestampRE, "").replace(trailingSeparatorRE, "");
ctx2.data.serverMetrics.middleware[url] ??= [];
if (firstMiddlewareIndex < 0)
firstMiddlewareIndex = index;
if (index === firstMiddlewareIndex)
ctx2.data.serverMetrics.middleware[url] = [];
const result = originalHandle.apply(this, middlewareArgs);
Promise.resolve(result).then(() => {
const total = Date.now() - start;
const metrics = ctx2.data.serverMetrics.middleware[url];
ctx2.data.serverMetrics.middleware[url].push({
self: metrics.length ? Math.max(total - metrics[metrics.length - 1].total, 0) : total,
total,
name: originalHandle.name
});
});
return result;
};
Object.defineProperty(middleware.handle, "name", {
value: originalHandle.name,
configurable: true,
enumerable: true
});
return middleware;
});
}
function configureServer(server) {
const config = server.config;
Object.values(server.environments).forEach((env) => {
const envCtx = ctx.getEnvContext(env);
const _invalidateModule = env.moduleGraph.invalidateModule;
env.moduleGraph.invalidateModule = function(...args) {
const mod = args[0];
if (mod?.id)
envCtx.invalidate(mod.id);
return _invalidateModule.apply(this, args);
};
});
const base = (options.base ?? server.config.base) || "/";
server.middlewares.use(`${base}__inspect`, sirv(DIR_CLIENT, {
single: true,
dev: true
}));
const rpc = createServerRpc(ctx);
const rpcServer = createRPCServer(
"vite-plugin-inspect",
server.ws,
rpc
);
const debouncedModuleUpdated = debounce(() => {
rpcServer.onModuleUpdated.asEvent();
}, 100);
server.middlewares.use((req, res, next) => {
debouncedModuleUpdated();
next();
});
const _print = server.printUrls;
server.printUrls = () => {
let host = `${config.server.https ? "https" : "http"}://localhost:${config.server.port || "80"}`;
const url = server.resolvedUrls?.local[0];
if (url) {
try {
const u = new URL(url);
host = `${u.protocol}//${u.host}`;
} catch (error) {
config.logger.warn(`Parse resolved url failed: ${error}`);
}
}
_print();
if (!silent) {
const colorUrl = (url2) => c.green(url2.replace(/:(\d+)\//, (_, port) => `:${c.bold(port)}/`));
config.logger.info(` ${c.green("\u279C")} ${c.bold("Inspect")}: ${colorUrl(`${host}${base}__inspect/`)}`);
}
if (_open && !isCI) {
setTimeout(() => {
openBrowser(`${host}${base}__inspect/`);
}, 500);
}
};
return rpc;
}
const plugin = {
name: NAME,
enforce: "pre",
apply(_, { command }) {
if (command === "serve" && dev)
return true;
if (command === "build" && build)
return true;
return false;
},
configResolved(config) {
config.plugins.forEach((plugin2) => hijackPlugin(plugin2, ctx));
const _createResolver = config.createResolver;
config.createResolver = function(...args) {
const _resolver = _createResolver.apply(this, args);
return async function(...args2) {
const id = args2[0];
const aliasOnly = args2[2];
const ssr = args2[3];
const start = Date.now();
const result = await _resolver.apply(this, args2);
const end = Date.now();
if (result && result !== id) {
const pluginName = aliasOnly ? "alias" : "vite:resolve (+alias)";
const vite = ctx.getViteContext(config);
const env = vite.getEnvContext(ssr ? "ssr" : "client");
env.recordResolveId(id, { name: pluginName, result, start, end });
}
return result;
};
};
if (build) {
const buildGenerator = createBuildGenerator(ctx);
onBuildEnd = createEnvOrderHooks(Object.keys(config.environments), {
async onFirst() {
await buildGenerator.setupOutputDir();
},
async onEach(pluginCtx) {
await buildGenerator.generateForEnv(pluginCtx);
},
async onLast(pluginCtx) {
await buildGenerator.generateMetadata();
const dir = buildGenerator.getOutputDir();
pluginCtx.environment.logger.info(`${c.green("Inspect report generated at")} ${c.dim(dir)}`);
if (_open && !isCI)
createPreviewServer(dir);
}
});
}
},
configureServer(server) {
const rpc = configureServer(server);
plugin.api = {
rpc
};
return () => {
setupMiddlewarePerf(
ctx.getViteContext(server.config),
server.middlewares.stack
);
};
},
load: {
order: "pre",
handler(id) {
ctx.getEnvContext(this.environment)?.invalidate(id);
return null;
}
},
hotUpdate({ modules }) {
const ids = modules.map((module) => module.id);
this.environment.hot.send({
type: "custom",
event: "vite-plugin-inspect:update",
data: { ids }
});
},
async buildEnd() {
onBuildEnd?.(this.environment.name, this);
},
sharedDuringBuild: true
};
return plugin;
}
export { PluginInspect as P };

View file

@ -0,0 +1,66 @@
type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null;
interface ViteInspectOptions {
/**
* Enable the inspect plugin in dev mode (could be some performance overhead)
*
* @default true
*/
dev?: boolean;
/**
* Enable the inspect plugin in build mode, and output the report to `.vite-inspect`
*
* @default false
*/
build?: boolean;
/**
* @deprecated use `dev` or `build` option instead.
*/
enabled?: boolean;
/**
* Directory for build inspector UI output
* Only work in build mode
*
* @default '.vite-inspect'
*/
outputDir?: string;
/**
* Filter for modules to be inspected
*/
include?: FilterPattern;
/**
* Filter for modules to not be inspected
*/
exclude?: FilterPattern;
/**
* Base URL for inspector UI
*
* @default read from Vite's config
*/
base?: string;
/**
* Print URL output silently in the terminal
*
* @default false
*/
silent?: boolean;
/**
* Automatically open inspect page
*
* @default false
*/
open?: boolean;
/**
* Remove version query `?v=xxx` and treat them as the same module
*
* @default true
*/
removeVersionQuery?: boolean;
/**
* Enable embedded mode
*
* @default false
*/
embedded?: boolean;
}
export type { FilterPattern as F, ViteInspectOptions as V };

View file

@ -0,0 +1,31 @@
/**
Define a [lazily evaluated](https://en.wikipedia.org/wiki/Lazy_evaluation) property on an object.
@param object - Object to add the property to.
@param propertyName - Name of the property to add.
@param valueGetter - Called the first time `propertyName` is accessed.
@example
```
import defineLazyProperty from 'define-lazy-prop';
const unicorn = {
// …
};
defineLazyProperty(unicorn, 'rainbow', () => expensiveComputation());
app.on('user-action', () => {
doSomething(unicorn.rainbow);
});
```
*/
export default function defineLazyProperty<
ObjectType extends Record<string, any>,
PropertyNameType extends string,
PropertyValueType
>(
object: ObjectType,
propertyName: PropertyNameType,
valueGetter: () => PropertyValueType
): ObjectType & {[K in PropertyNameType]: PropertyValueType};

View file

@ -0,0 +1,18 @@
export default function defineLazyProperty(object, propertyName, valueGetter) {
const define = value => Object.defineProperty(object, propertyName, {value, enumerable: true, writable: true});
Object.defineProperty(object, propertyName, {
configurable: true,
enumerable: true,
get() {
const result = valueGetter();
define(result);
return result;
},
set(value) {
define(value);
}
});
return object;
}

View file

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
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.

View file

@ -0,0 +1,51 @@
{
"name": "define-lazy-prop",
"version": "3.0.0",
"description": "Define a lazily evaluated property on an object",
"license": "MIT",
"repository": "sindresorhus/define-lazy-prop",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">=12"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"lazy",
"property",
"properties",
"prop",
"define",
"object",
"value",
"lazily",
"laziness",
"evaluation",
"eval",
"execute",
"getter",
"function",
"fn",
"memoize",
"cache",
"defer",
"deferred"
],
"devDependencies": {
"ava": "^3.15.0",
"tsd": "^0.14.0",
"xo": "^0.38.2"
}
}

View file

@ -0,0 +1,55 @@
# define-lazy-prop
> Define a [lazily evaluated](https://en.wikipedia.org/wiki/Lazy_evaluation) property on an object
Useful when the value of a property is expensive to generate, so you want to delay the computation until the property is needed. For example, improving startup performance by deferring nonessential operations.
## Install
```
$ npm install define-lazy-prop
```
## Usage
```js
import defineLazyProperty from 'define-lazy-prop';
const unicorn = {
// …
};
defineLazyProperty(unicorn, 'rainbow', () => expensiveComputation());
app.on('user-action', () => {
doSomething(unicorn.rainbow);
});
```
## API
### defineLazyProperty(object, propertyName, valueGetter)
#### object
Type: `object`
Object to add the property to.
#### propertyName
Type: `string`
Name of the property to add.
#### valueGetter
Type: `Function`
Called the first time `propertyName` is accessed. Expected to return a value.
## Related
- [lazy-value](https://github.com/sindresorhus/lazy-value) - Create a lazily evaluated value
- [import-lazy](https://github.com/sindresorhus/import-lazy) - Import a module lazily
- [p-lazy](https://github.com/sindresorhus/p-lazy) - Create a lazy promise

View file

@ -0,0 +1,158 @@
import {type ChildProcess} from 'node:child_process';
export type Options = {
/**
Wait for the opened app to exit before fulfilling the promise. If `false` it's fulfilled immediately when opening the app.
Note that it waits for the app to exit, not just for the window to close.
On Windows, you have to explicitly specify an app for it to be able to wait.
@default false
*/
readonly wait?: boolean;
/**
__macOS only__
Do not bring the app to the foreground.
@default false
*/
readonly background?: boolean;
/**
__macOS only__
Open a new instance of the app even it's already running.
A new instance is always opened on other platforms.
@default false
*/
readonly newInstance?: boolean;
/**
Specify the `name` of the app to open the `target` with, and optionally, app `arguments`. `app` can be an array of apps to try to open and `name` can be an array of app names to try. If each app fails, the last error will be thrown.
The app name is platform dependent. Don't hard code it in reusable modules. For example, Chrome is `google chrome` on macOS, `google-chrome` on Linux and `chrome` on Windows. If possible, use `apps` which auto-detects the correct binary to use.
You may also pass in the app's full path. For example on WSL, this can be `/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe` for the Windows installation of Chrome.
The app `arguments` are app dependent. Check the app's documentation for what arguments it accepts.
*/
readonly app?: App | readonly App[];
/**
Allow the opened app to exit with nonzero exit code when the `wait` option is `true`.
We do not recommend setting this option. The convention for success is exit code zero.
@default false
*/
readonly allowNonzeroExitCode?: boolean;
};
export type OpenAppOptions = {
/**
Arguments passed to the app.
These arguments are app dependent. Check the app's documentation for what arguments it accepts.
*/
readonly arguments?: readonly string[];
} & Omit<Options, 'app'>;
export type AppName =
| 'chrome'
| 'brave'
| 'firefox'
| 'edge'
| 'browser'
| 'browserPrivate';
export type App = {
name: string | readonly string[];
arguments?: readonly string[];
};
/**
An object containing auto-detected binary names for common apps. Useful to work around cross-platform differences.
@example
```
import open, {apps} from 'open';
await open('https://google.com', {
app: {
name: apps.chrome
}
});
```
*/
export const apps: Record<AppName, string | readonly string[]>;
/**
Open stuff like URLs, files, executables. Cross-platform.
Uses the command `open` on macOS, `start` on Windows and `xdg-open` on other platforms.
There is a caveat for [double-quotes on Windows](https://github.com/sindresorhus/open#double-quotes-on-windows) where all double-quotes are stripped from the `target`.
@param target - The thing you want to open. Can be a URL, file, or executable. Opens in the default app for the file type. For example, URLs open in your default browser.
@returns The [spawned child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess). You would normally not need to use this for anything, but it can be useful if you'd like to attach custom event listeners or perform other operations directly on the spawned process.
@example
```
import open, {apps} from 'open';
// Opens the image in the default image viewer.
await open('unicorn.png', {wait: true});
console.log('The image viewer app quit');
// Opens the URL in the default browser.
await open('https://sindresorhus.com');
// Opens the URL in a specified browser.
await open('https://sindresorhus.com', {app: {name: 'firefox'}});
// Specify app arguments.
await open('https://sindresorhus.com', {app: {name: 'google chrome', arguments: ['--incognito']}});
// Opens the URL in the default browser in incognito mode.
await open('https://sindresorhus.com', {app: {name: apps.browserPrivate}});
```
*/
export default function open(
target: string,
options?: Options
): Promise<ChildProcess>;
/**
Open an app. Cross-platform.
Uses the command `open` on macOS, `start` on Windows and `xdg-open` on other platforms.
@param name - The app you want to open. Can be either builtin supported `apps` names or other name supported in platform.
@returns The [spawned child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess). You would normally not need to use this for anything, but it can be useful if you'd like to attach custom event listeners or perform other operations directly on the spawned process.
@example
```
import open, {openApp, apps} from 'open';
// Open Firefox.
await openApp(apps.firefox);
// Open Chrome in incognito mode.
await openApp(apps.chrome, {arguments: ['--incognito']});
// Open default browser.
await openApp(apps.browser);
// Open default browser in incognito mode.
await openApp(apps.browserPrivate);
// Open Xcode.
await openApp('xcode');
```
*/
export function openApp(name: App['name'], options?: OpenAppOptions): Promise<ChildProcess>;

View file

@ -0,0 +1,366 @@
import process from 'node:process';
import {Buffer} from 'node:buffer';
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import {promisify} from 'node:util';
import childProcess from 'node:child_process';
import fs, {constants as fsConstants} from 'node:fs/promises';
import {isWsl, powerShellPath} from 'wsl-utils';
import defineLazyProperty from 'define-lazy-prop';
import defaultBrowser from 'default-browser';
import isInsideContainer from 'is-inside-container';
const execFile = promisify(childProcess.execFile);
// Path to included `xdg-open`.
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const localXdgOpenPath = path.join(__dirname, 'xdg-open');
const {platform, arch} = process;
/**
Get the default browser name in Windows from WSL.
@returns {Promise<string>} Browser name.
*/
async function getWindowsDefaultBrowserFromWsl() {
const powershellPath = await powerShellPath();
const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
const encodedCommand = Buffer.from(rawCommand, 'utf16le').toString('base64');
const {stdout} = await execFile(
powershellPath,
[
'-NoProfile',
'-NonInteractive',
'-ExecutionPolicy',
'Bypass',
'-EncodedCommand',
encodedCommand,
],
{encoding: 'utf8'},
);
const progId = stdout.trim();
// Map ProgId to browser IDs
const browserMap = {
ChromeHTML: 'com.google.chrome',
BraveHTML: 'com.brave.Browser',
MSEdgeHTM: 'com.microsoft.edge',
FirefoxURL: 'org.mozilla.firefox',
};
return browserMap[progId] ? {id: browserMap[progId]} : {};
}
const pTryEach = async (array, mapper) => {
let latestError;
for (const item of array) {
try {
return await mapper(item); // eslint-disable-line no-await-in-loop
} catch (error) {
latestError = error;
}
}
throw latestError;
};
// eslint-disable-next-line complexity
const baseOpen = async options => {
options = {
wait: false,
background: false,
newInstance: false,
allowNonzeroExitCode: false,
...options,
};
if (Array.isArray(options.app)) {
return pTryEach(options.app, singleApp => baseOpen({
...options,
app: singleApp,
}));
}
let {name: app, arguments: appArguments = []} = options.app ?? {};
appArguments = [...appArguments];
if (Array.isArray(app)) {
return pTryEach(app, appName => baseOpen({
...options,
app: {
name: appName,
arguments: appArguments,
},
}));
}
if (app === 'browser' || app === 'browserPrivate') {
// IDs from default-browser for macOS and windows are the same
const ids = {
'com.google.chrome': 'chrome',
'google-chrome.desktop': 'chrome',
'com.brave.Browser': 'brave',
'org.mozilla.firefox': 'firefox',
'firefox.desktop': 'firefox',
'com.microsoft.msedge': 'edge',
'com.microsoft.edge': 'edge',
'com.microsoft.edgemac': 'edge',
'microsoft-edge.desktop': 'edge',
};
// Incognito flags for each browser in `apps`.
const flags = {
chrome: '--incognito',
brave: '--incognito',
firefox: '--private-window',
edge: '--inPrivate',
};
const browser = isWsl ? await getWindowsDefaultBrowserFromWsl() : await defaultBrowser();
if (browser.id in ids) {
const browserName = ids[browser.id];
if (app === 'browserPrivate') {
appArguments.push(flags[browserName]);
}
return baseOpen({
...options,
app: {
name: apps[browserName],
arguments: appArguments,
},
});
}
throw new Error(`${browser.name} is not supported as a default browser`);
}
let command;
const cliArguments = [];
const childProcessOptions = {};
if (platform === 'darwin') {
command = 'open';
if (options.wait) {
cliArguments.push('--wait-apps');
}
if (options.background) {
cliArguments.push('--background');
}
if (options.newInstance) {
cliArguments.push('--new');
}
if (app) {
cliArguments.push('-a', app);
}
} else if (platform === 'win32' || (isWsl && !isInsideContainer() && !app)) {
command = await powerShellPath();
cliArguments.push(
'-NoProfile',
'-NonInteractive',
'-ExecutionPolicy',
'Bypass',
'-EncodedCommand',
);
if (!isWsl) {
childProcessOptions.windowsVerbatimArguments = true;
}
const encodedArguments = ['Start'];
if (options.wait) {
encodedArguments.push('-Wait');
}
if (app) {
// Double quote with double quotes to ensure the inner quotes are passed through.
// Inner quotes are delimited for PowerShell interpretation with backticks.
encodedArguments.push(`"\`"${app}\`""`);
if (options.target) {
appArguments.push(options.target);
}
} else if (options.target) {
encodedArguments.push(`"${options.target}"`);
}
if (appArguments.length > 0) {
appArguments = appArguments.map(argument => `"\`"${argument}\`""`);
encodedArguments.push('-ArgumentList', appArguments.join(','));
}
// Using Base64-encoded command, accepted by PowerShell, to allow special characters.
options.target = Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
} else {
if (app) {
command = app;
} else {
// When bundled by Webpack, there's no actual package file path and no local `xdg-open`.
const isBundled = !__dirname || __dirname === '/';
// Check if local `xdg-open` exists and is executable.
let exeLocalXdgOpen = false;
try {
await fs.access(localXdgOpenPath, fsConstants.X_OK);
exeLocalXdgOpen = true;
} catch {}
const useSystemXdgOpen = process.versions.electron
?? (platform === 'android' || isBundled || !exeLocalXdgOpen);
command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
}
if (appArguments.length > 0) {
cliArguments.push(...appArguments);
}
if (!options.wait) {
// `xdg-open` will block the process unless stdio is ignored
// and it's detached from the parent even if it's unref'd.
childProcessOptions.stdio = 'ignore';
childProcessOptions.detached = true;
}
}
if (platform === 'darwin' && appArguments.length > 0) {
cliArguments.push('--args', ...appArguments);
}
// This has to come after `--args`.
if (options.target) {
cliArguments.push(options.target);
}
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
if (options.wait) {
return new Promise((resolve, reject) => {
subprocess.once('error', reject);
subprocess.once('close', exitCode => {
if (!options.allowNonzeroExitCode && exitCode > 0) {
reject(new Error(`Exited with code ${exitCode}`));
return;
}
resolve(subprocess);
});
});
}
subprocess.unref();
return subprocess;
};
const open = (target, options) => {
if (typeof target !== 'string') {
throw new TypeError('Expected a `target`');
}
return baseOpen({
...options,
target,
});
};
export const openApp = (name, options) => {
if (typeof name !== 'string' && !Array.isArray(name)) {
throw new TypeError('Expected a valid `name`');
}
const {arguments: appArguments = []} = options ?? {};
if (appArguments !== undefined && appArguments !== null && !Array.isArray(appArguments)) {
throw new TypeError('Expected `appArguments` as Array type');
}
return baseOpen({
...options,
app: {
name,
arguments: appArguments,
},
});
};
function detectArchBinary(binary) {
if (typeof binary === 'string' || Array.isArray(binary)) {
return binary;
}
const {[arch]: archBinary} = binary;
if (!archBinary) {
throw new Error(`${arch} is not supported`);
}
return archBinary;
}
function detectPlatformBinary({[platform]: platformBinary}, {wsl}) {
if (wsl && isWsl) {
return detectArchBinary(wsl);
}
if (!platformBinary) {
throw new Error(`${platform} is not supported`);
}
return detectArchBinary(platformBinary);
}
export const apps = {};
defineLazyProperty(apps, 'chrome', () => detectPlatformBinary({
darwin: 'google chrome',
win32: 'chrome',
linux: ['google-chrome', 'google-chrome-stable', 'chromium'],
}, {
wsl: {
ia32: '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe',
x64: ['/mnt/c/Program Files/Google/Chrome/Application/chrome.exe', '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'],
},
}));
defineLazyProperty(apps, 'brave', () => detectPlatformBinary({
darwin: 'brave browser',
win32: 'brave',
linux: ['brave-browser', 'brave'],
}, {
wsl: {
ia32: '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe',
x64: ['/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe', '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe'],
},
}));
defineLazyProperty(apps, 'firefox', () => detectPlatformBinary({
darwin: 'firefox',
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
linux: 'firefox',
}, {
wsl: '/mnt/c/Program Files/Mozilla Firefox/firefox.exe',
}));
defineLazyProperty(apps, 'edge', () => detectPlatformBinary({
darwin: 'microsoft edge',
win32: 'msedge',
linux: ['microsoft-edge', 'microsoft-edge-dev'],
}, {
wsl: '/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe',
}));
defineLazyProperty(apps, 'browser', () => 'browser');
defineLazyProperty(apps, 'browserPrivate', () => 'browserPrivate');
export default open;

View file

@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
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.

View file

@ -0,0 +1,68 @@
{
"name": "open",
"version": "10.2.0",
"description": "Open stuff like URLs, files, executables. Cross-platform.",
"license": "MIT",
"repository": "sindresorhus/open",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": {
"types": "./index.d.ts",
"default": "./index.js"
},
"sideEffects": false,
"engines": {
"node": ">=18"
},
"scripts": {
"test": "xo && tsd"
},
"files": [
"index.js",
"index.d.ts",
"xdg-open"
],
"keywords": [
"app",
"open",
"opener",
"opens",
"launch",
"start",
"xdg-open",
"xdg",
"default",
"cmd",
"browser",
"editor",
"executable",
"exe",
"url",
"urls",
"arguments",
"args",
"spawn",
"exec",
"child",
"process",
"website",
"file"
],
"dependencies": {
"default-browser": "^5.2.1",
"define-lazy-prop": "^3.0.0",
"is-inside-container": "^1.0.0",
"wsl-utils": "^0.1.0"
},
"devDependencies": {
"@types/node": "^20.10.5",
"ava": "^6.4.0",
"tsd": "^0.32.0",
"xo": "^1.1.1"
}
}

View file

@ -0,0 +1,183 @@
# open
> Open stuff like URLs, files, executables. Cross-platform.
This is meant to be used in command-line tools and scripts, not in the browser.
If you need this for Electron, use [`shell.openPath()`](https://www.electronjs.org/docs/api/shell#shellopenpathpath) instead.
This package does not make any security guarantees. If you pass in untrusted input, it's up to you to properly sanitize it.
#### Why?
- Actively maintained.
- Supports app arguments.
- Safer as it uses `spawn` instead of `exec`.
- Fixes most of the original `node-open` issues.
- Includes the latest [`xdg-open` script](https://gitlab.freedesktop.org/xdg/xdg-utils/-/blob/master/scripts/xdg-open.in) for Linux.
- Supports WSL paths to Windows apps.
## Install
```sh
npm install open
```
**Warning:** This package is native [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) and no longer provides a CommonJS export. If your project uses CommonJS, you will have to [convert to ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) or use the [dynamic `import()`](https://v8.dev/features/dynamic-import) function. Please don't open issues for questions regarding CommonJS / ESM.
## Usage
```js
import open, {openApp, apps} from 'open';
// Opens the image in the default image viewer and waits for the opened app to quit.
await open('unicorn.png', {wait: true});
console.log('The image viewer app quit');
// Opens the URL in the default browser.
await open('https://sindresorhus.com');
// Opens the URL in a specified browser.
await open('https://sindresorhus.com', {app: {name: 'firefox'}});
// Specify app arguments.
await open('https://sindresorhus.com', {app: {name: 'google chrome', arguments: ['--incognito']}});
// Opens the URL in the default browser in incognito mode.
await open('https://sindresorhus.com', {app: {name: apps.browserPrivate}});
// Open an app.
await openApp('xcode');
// Open an app with arguments.
await openApp(apps.chrome, {arguments: ['--incognito']});
```
## API
It uses the command `open` on macOS, `start` on Windows and `xdg-open` on other platforms.
### open(target, options?)
Returns a promise for the [spawned child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess). You would normally not need to use this for anything, but it can be useful if you'd like to attach custom event listeners or perform other operations directly on the spawned process.
#### target
Type: `string`
The thing you want to open. Can be a URL, file, or executable.
Opens in the default app for the file type. For example, URLs opens in your default browser.
#### options
Type: `object`
##### wait
Type: `boolean`\
Default: `false`
Wait for the opened app to exit before fulfilling the promise. If `false` it's fulfilled immediately when opening the app.
Note that it waits for the app to exit, not just for the window to close.
On Windows, you have to explicitly specify an app for it to be able to wait.
##### background <sup>(macOS only)</sup>
Type: `boolean`\
Default: `false`
Do not bring the app to the foreground.
##### newInstance <sup>(macOS only)</sup>
Type: `boolean`\
Default: `false`
Open a new instance of the app even it's already running.
A new instance is always opened on other platforms.
##### app
Type: `{name: string | string[], arguments?: string[]} | Array<{name: string | string[], arguments: string[]}>`
Specify the `name` of the app to open the `target` with, and optionally, app `arguments`. `app` can be an array of apps to try to open and `name` can be an array of app names to try. If each app fails, the last error will be thrown.
The app name is platform dependent. Don't hard code it in reusable modules. For example, Chrome is `google chrome` on macOS, `google-chrome` on Linux and `chrome` on Windows. If possible, use [`apps`](#apps) which auto-detects the correct binary to use.
You may also pass in the app's full path. For example on WSL, this can be `/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe` for the Windows installation of Chrome.
The app `arguments` are app dependent. Check the app's documentation for what arguments it accepts.
##### allowNonzeroExitCode
Type: `boolean`\
Default: `false`
Allow the opened app to exit with nonzero exit code when the `wait` option is `true`.
We do not recommend setting this option. The convention for success is exit code zero.
### openApp(name, options?)
Open an app.
Returns a promise for the [spawned child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess). You would normally not need to use this for anything, but it can be useful if you'd like to attach custom event listeners or perform other operations directly on the spawned process.
#### name
Type: `string`
The app name is platform dependent. Don't hard code it in reusable modules. For example, Chrome is `google chrome` on macOS, `google-chrome` on Linux and `chrome` on Windows. If possible, use [`apps`](#apps) which auto-detects the correct binary to use.
You may also pass in the app's full path. For example on WSL, this can be `/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe` for the Windows installation of Chrome.
#### options
Type: `object`
Same options as [`open`](#options) except `app` and with the following additions:
##### arguments
Type: `string[]`\
Default: `[]`
Arguments passed to the app.
These arguments are app dependent. Check the app's documentation for what arguments it accepts.
### apps
An object containing auto-detected binary names for common apps. Useful to work around [cross-platform differences](#app).
```js
import open, {apps} from 'open';
await open('https://google.com', {
app: {
name: apps.chrome
}
});
```
`browser` and `browserPrivate` can also be used to access the user's default browser through [`default-browser`](https://github.com/sindresorhus/default-browser).
#### Supported apps
- [`chrome`](https://www.google.com/chrome) - Web browser
- [`firefox`](https://www.mozilla.org/firefox) - Web browser
- [`edge`](https://www.microsoft.com/edge) - Web browser
- [`brave`](https://brave.com/) - Web browser
- `browser` - Default web browser
- `browserPrivate` - Default web browser in incognito mode
`browser` and `browserPrivate` only supports `chrome`, `firefox`, `edge`, and `brave`.
## Related
- [open-cli](https://github.com/sindresorhus/open-cli) - CLI for this module
- [open-editor](https://github.com/sindresorhus/open-editor) - Open files in your editor at a specific line and column

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,43 @@
The MIT License (MIT)
Copyright © 2025-PRESENT Kevin Deng (https://github.com/sxzz)
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.
The MIT License (MIT)
Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/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.

View file

@ -0,0 +1,74 @@
# unplugin-utils
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![Unit Test][unit-test-src]][unit-test-href]
[![codecov][codecov-src]][codecov-href]
A set of utility functions commonly used by unplugins.
Thanks to [@rollup/pluginutils](https://github.com/rollup/plugins/tree/master/packages/pluginutils). This projects is heavily copied from it.
## Why Fork?
- 🌍 Platform agnostic, supports running in the browser, Node.js...
- ✂️ Subset, smaller bundle size.
- **💯 Coverage**: 100% test coverage.
## Install
```bash
npm i unplugin-utils
```
## Usage
### createFilter
```ts
export default function myPlugin(options = {}) {
const filter = createFilter(options.include, options.exclude)
return {
transform(code, id) {
if (!filter(id)) return
// proceed with the transformation...
},
}
}
```
### normalizePath
```ts
import { normalizePath } from 'unplugin-utils'
normalizePath(String.raw`foo\bar`) // 'foo/bar'
normalizePath('foo/bar') // 'foo/bar'
```
## Sponsors
<p align="center">
<a href="https://cdn.jsdelivr.net/gh/sxzz/sponsors/sponsors.svg">
<img src='https://cdn.jsdelivr.net/gh/sxzz/sponsors/sponsors.svg'/>
</a>
</p>
## License
[MIT](./LICENSE) License © 2025-PRESENT [Kevin Deng](https://github.com/sxzz)
[MIT](./LICENSE) Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/unplugin-utils.svg
[npm-version-href]: https://npmjs.com/package/unplugin-utils
[npm-downloads-src]: https://img.shields.io/npm/dm/unplugin-utils
[npm-downloads-href]: https://www.npmcharts.com/compare/unplugin-utils?interval=30
[unit-test-src]: https://github.com/sxzz/unplugin-utils/actions/workflows/unit-test.yml/badge.svg
[unit-test-href]: https://github.com/sxzz/unplugin-utils/actions/workflows/unit-test.yml
[codecov-src]: https://codecov.io/gh/sxzz/unplugin-utils/graph/badge.svg?token=VDWXCPSL1O
[codecov-href]: https://codecov.io/gh/sxzz/unplugin-utils

View file

@ -0,0 +1,31 @@
//#region src/filter.d.ts
/**
* A valid `picomatch` glob pattern, or array of patterns.
*/
type FilterPattern = ReadonlyArray<string | RegExp> | string | RegExp | null;
/**
* Constructs a filter function which can be used to determine whether or not
* certain modules should be operated upon.
* @param include If `include` is omitted or has zero length, filter will return `true` by default.
* @param exclude ID must not match any of the `exclude` patterns.
* @param options Additional options.
* @param options.resolve Optionally resolves the patterns against a directory other than `process.cwd()`.
* If a `string` is specified, then the value will be used as the base directory.
* Relative paths will be resolved against `process.cwd()` first.
* If `false`, then the patterns will not be resolved against any directory.
* This can be useful if you want to create a filter for virtual module names.
*/
declare function createFilter(include?: FilterPattern, exclude?: FilterPattern, options?: {
resolve?: string | false | null;
}): (id: string | unknown) => boolean;
//#endregion
//#region src/path.d.ts
/**
* Converts path separators to forward slash.
*/
declare function normalizePath(filename: string): string;
//#endregion
//#region src/utils.d.ts
declare function toArray<T>(thing: readonly T[] | T | undefined | null): readonly T[];
//#endregion
export { FilterPattern, createFilter, normalizePath, toArray };

View file

@ -0,0 +1,67 @@
import { isAbsolute, join, resolve } from "pathe";
import pm from "picomatch";
//#region src/path.ts
/**
* Converts path separators to forward slash.
*/
function normalizePath(filename) {
return filename.replaceAll("\\", "/");
}
//#endregion
//#region src/utils.ts
const isArray = Array.isArray;
function toArray(thing) {
if (isArray(thing)) return thing;
if (thing == null) return [];
return [thing];
}
//#endregion
//#region src/filter.ts
const escapeMark = "[_#EsCaPe#_]";
function getMatcherString(id, resolutionBase) {
if (resolutionBase === false || isAbsolute(id) || id.startsWith("**")) return normalizePath(id);
const basePath = normalizePath(resolve(resolutionBase || "")).replaceAll(/[-^$*+?.()|[\]{}]/g, `${escapeMark}$&`);
return join(basePath, normalizePath(id)).replaceAll(escapeMark, "\\");
}
/**
* Constructs a filter function which can be used to determine whether or not
* certain modules should be operated upon.
* @param include If `include` is omitted or has zero length, filter will return `true` by default.
* @param exclude ID must not match any of the `exclude` patterns.
* @param options Additional options.
* @param options.resolve Optionally resolves the patterns against a directory other than `process.cwd()`.
* If a `string` is specified, then the value will be used as the base directory.
* Relative paths will be resolved against `process.cwd()` first.
* If `false`, then the patterns will not be resolved against any directory.
* This can be useful if you want to create a filter for virtual module names.
*/
function createFilter(include, exclude, options) {
const resolutionBase = options && options.resolve;
const getMatcher = (id) => id instanceof RegExp ? id : { test: (what) => {
const pattern = getMatcherString(id, resolutionBase);
return pm(pattern, { dot: true })(what);
} };
const includeMatchers = toArray(include).map(getMatcher);
const excludeMatchers = toArray(exclude).map(getMatcher);
if (!includeMatchers.length && !excludeMatchers.length) return (id) => typeof id === "string" && !id.includes("\0");
return function result(id) {
if (typeof id !== "string") return false;
if (id.includes("\0")) return false;
const pathId = normalizePath(id);
for (const matcher of excludeMatchers) {
if (matcher instanceof RegExp) matcher.lastIndex = 0;
if (matcher.test(pathId)) return false;
}
for (const matcher of includeMatchers) {
if (matcher instanceof RegExp) matcher.lastIndex = 0;
if (matcher.test(pathId)) return true;
}
return !includeMatchers.length;
};
}
//#endregion
export { createFilter, normalizePath, toArray };

View file

@ -0,0 +1,67 @@
{
"name": "unplugin-utils",
"version": "0.3.1",
"description": "A set of utility functions commonly used by unplugins.",
"type": "module",
"license": "MIT",
"homepage": "https://github.com/sxzz/unplugin-utils#readme",
"bugs": {
"url": "https://github.com/sxzz/unplugin-utils/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sxzz/unplugin-utils.git"
},
"author": "Kevin Deng <sxzz@sxzz.moe>",
"funding": "https://github.com/sponsors/sxzz",
"files": [
"dist"
],
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"pathe": "^2.0.3",
"picomatch": "^4.0.3"
},
"devDependencies": {
"@sxzz/eslint-config": "^7.2.7",
"@sxzz/prettier-config": "^2.2.4",
"@types/node": "^24.7.0",
"@types/picomatch": "^4.0.2",
"@vitest/coverage-v8": "3.2.4",
"bumpp": "^10.3.1",
"eslint": "^9.37.0",
"oxc-transform": "^0.94.0",
"prettier": "^3.6.2",
"tsdown": "^0.15.6",
"tsx": "^4.20.6",
"typescript": "^5.9.3",
"vitest": "^3.2.4"
},
"engines": {
"node": ">=20.19.0"
},
"prettier": "@sxzz/prettier-config",
"tsdown": {
"platform": "neutral",
"exports": true
},
"scripts": {
"lint": "eslint --cache .",
"lint:fix": "pnpm run lint --fix",
"build": "tsdown",
"dev": "tsdown --watch",
"test": "vitest",
"typecheck": "tsc --noEmit",
"format": "prettier --cache --write .",
"release": "bumpp"
}
}

View file

@ -0,0 +1,120 @@
{
"name": "vite-plugin-inspect",
"type": "module",
"version": "11.3.3",
"description": "Inspect the intermediate state of Vite plugins",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
"license": "MIT",
"funding": "https://github.com/sponsors/antfu",
"homepage": "https://github.com/antfu/vite-plugin-inspect#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/antfu/vite-plugin-inspect.git"
},
"bugs": {
"url": "https://github.com/antfu/vite-plugin-inspect/issues"
},
"keywords": [
"vite-plugin"
],
"exports": {
".": "./dist/index.mjs",
"./nuxt": "./dist/nuxt.mjs",
"./*": "./*"
},
"main": "dist/index.mjs",
"module": "dist/index.mjs",
"types": "dist/index.d.mts",
"files": [
"dist"
],
"engines": {
"node": ">=14"
},
"peerDependencies": {
"vite": "^6.0.0 || ^7.0.0-0"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
}
},
"dependencies": {
"ansis": "^4.1.0",
"debug": "^4.4.1",
"error-stack-parser-es": "^1.0.5",
"ohash": "^2.0.11",
"open": "^10.2.0",
"perfect-debounce": "^2.0.0",
"sirv": "^3.0.1",
"unplugin-utils": "^0.3.0",
"vite-dev-rpc": "^1.1.0"
},
"devDependencies": {
"@antfu/eslint-config": "^5.2.1",
"@antfu/ni": "^25.0.0",
"@antfu/utils": "^9.2.0",
"@iconify/json": "^2.2.377",
"@nuxt/kit": "^4.0.3",
"@types/codemirror": "^5.60.16",
"@types/debug": "^4.1.12",
"@types/node": "^24.3.0",
"@unocss/eslint-config": "^66.4.2",
"@unocss/eslint-plugin": "^66.4.2",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/compiler-sfc": "^3.5.19",
"@vueuse/core": "^13.7.0",
"@vueuse/router": "^13.7.0",
"bumpp": "^10.2.3",
"codemirror": "^5.65.16",
"codemirror-theme-vars": "^0.1.2",
"comlink": "^4.4.2",
"diff-match-patch-es": "^1.0.1",
"echarts": "^5.6.0",
"eslint": "^9.34.0",
"floating-vue": "^5.2.2",
"fuse.js": "^7.1.0",
"lint-staged": "^16.1.5",
"pathe": "^2.0.3",
"pinia": "^3.0.3",
"rimraf": "^6.0.1",
"simple-git-hooks": "^2.13.1",
"splitpanes": "^4.0.4",
"typescript": "^5.9.2",
"unbuild": "^3.6.1",
"unocss": "^66.4.2",
"unplugin-auto-import": "^20.0.0",
"unplugin-vue-components": "^29.0.0",
"unplugin-vue-router": "^0.15.0",
"vis-data": "^8.0.1",
"vis-network": "^10.0.1",
"vite": "npm:rolldown-vite@6.3.0-beta.5",
"vite-hot-client": "^2.1.0",
"vue": "^3.5.19",
"vue-echarts": "^7.0.3",
"vue-router": "^4.5.1",
"vue-tsc": "^3.0.6"
},
"resolutions": {
"vite": "catalog:dev"
},
"simple-git-hooks": {
"pre-commit": "npx lint-staged"
},
"lint-staged": {
"*.{js,ts,vue,md}": [
"eslint --cache --fix"
]
},
"scripts": {
"build": "rimraf dist && pnpm run --sequential /^build:/",
"build:client": "vite build src/client",
"build:js": "unbuild",
"dev": "nr stub && INSPECT_DEV=true vite src/client",
"dev:client": "vite build src/client --watch",
"stub": "unbuild --stub",
"lint": "eslint .",
"typecheck": "vue-tsc --noEmit",
"release": "bumpp && pnpm publish"
}
}