You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1215 lines
50 KiB
1215 lines
50 KiB
globalThis.IMBA_MANIFEST={}
|
|
var __require = /* @__PURE__ */ ((x) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(x, {
|
|
get: (a, b) => (typeof require < "u" ? require : a)[b]
|
|
}) : x)(function(x) {
|
|
if (typeof require < "u")
|
|
return require.apply(this, arguments);
|
|
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
});
|
|
|
|
// src/utils/compile.ts
|
|
import { compile } from "imba/compiler";
|
|
|
|
// src/utils/hash.ts
|
|
import * as crypto from "crypto";
|
|
var hashes = /* @__PURE__ */ Object.create(null), hash_length = 12;
|
|
function safeBase64Hash(input) {
|
|
if (hashes[input])
|
|
return hashes[input];
|
|
let md5 = crypto.createHash("md5");
|
|
md5.update(input);
|
|
let hash = toSafe(md5.digest("base64")).slice(0, hash_length);
|
|
return hashes[input] = hash, hash;
|
|
}
|
|
var replacements = {
|
|
"+": "-",
|
|
"/": "_",
|
|
"=": ""
|
|
}, replaceRE = new RegExp(`[${Object.keys(replacements).join("")}]`, "g");
|
|
function toSafe(base64) {
|
|
return base64.replace(replaceRE, (x) => replacements[x]);
|
|
}
|
|
|
|
// src/utils/log.ts
|
|
import { cyan, yellow, red } from "kleur/colors";
|
|
import debug from "debug";
|
|
var levels = ["debug", "info", "warn", "error", "silent"], prefix = "vite-plugin-imba", loggers = {
|
|
debug: {
|
|
log: debug(`vite:${prefix}`),
|
|
enabled: !1,
|
|
isDebug: !0
|
|
},
|
|
info: {
|
|
color: cyan,
|
|
log: console.log,
|
|
enabled: !0
|
|
},
|
|
warn: {
|
|
color: yellow,
|
|
log: console.warn,
|
|
enabled: !0
|
|
},
|
|
error: {
|
|
color: red,
|
|
log: console.error,
|
|
enabled: !0
|
|
},
|
|
silent: {
|
|
enabled: !1
|
|
}
|
|
}, _level = "info";
|
|
function setLevel(level) {
|
|
if (level === _level)
|
|
return;
|
|
let levelIndex = levels.indexOf(level);
|
|
if (levelIndex > -1) {
|
|
_level = level;
|
|
for (let i = 0; i < levels.length; i++)
|
|
loggers[levels[i]].enabled = i >= levelIndex;
|
|
} else
|
|
_log(loggers.error, `invalid log level: ${level} `);
|
|
}
|
|
function _log(logger, message, payload) {
|
|
!logger.enabled || (logger.isDebug ? payload !== void 0 ? logger.log(message, payload) : logger.log(message) : (logger.log(logger.color(`${new Date().toLocaleTimeString()} [${prefix}] ${message}`)), payload && logger.log(payload)));
|
|
}
|
|
function createLogger(level) {
|
|
let logger = loggers[level], logFn = _log.bind(null, logger), logged = /* @__PURE__ */ new Set(), once = function(message, payload) {
|
|
logged.has(message) || (logged.add(message), logFn.apply(null, [message, payload]));
|
|
};
|
|
return Object.defineProperty(logFn, "enabled", {
|
|
get() {
|
|
return logger.enabled;
|
|
}
|
|
}), Object.defineProperty(logFn, "once", {
|
|
get() {
|
|
return once;
|
|
}
|
|
}), logFn;
|
|
}
|
|
var log = {
|
|
debug: createLogger("debug"),
|
|
info: createLogger("info"),
|
|
warn: createLogger("warn"),
|
|
error: createLogger("error"),
|
|
setLevel
|
|
};
|
|
function logCompilerWarnings(imbaRequest, warnings, options) {
|
|
var _a, _b, _c;
|
|
let { emitCss, onwarn, isBuild } = options, sendViaWS = !isBuild && ((_a = options.experimental) == null ? void 0 : _a.sendWarningsToBrowser), warn = isBuild ? warnBuild : warnDev, handledByDefaultWarn = [], notIgnored = warnings == null ? void 0 : warnings.filter((w) => !ignoreCompilerWarning(w, isBuild, emitCss)), extra = buildExtraWarnings(warnings, isBuild), allWarnings = [...notIgnored, ...extra];
|
|
if (sendViaWS) {
|
|
let _warn = warn;
|
|
warn = (w) => {
|
|
handledByDefaultWarn.push(w), _warn(w);
|
|
};
|
|
}
|
|
if (allWarnings.forEach((warning) => {
|
|
onwarn ? onwarn(warning, warn) : warn(warning);
|
|
}), sendViaWS) {
|
|
let message = {
|
|
id: imbaRequest.id,
|
|
filename: imbaRequest.filename,
|
|
normalizedFilename: imbaRequest.normalizedFilename,
|
|
timestamp: imbaRequest.timestamp,
|
|
warnings: handledByDefaultWarn,
|
|
allWarnings,
|
|
rawWarnings: warnings
|
|
};
|
|
log.debug(`sending imba:warnings message for ${imbaRequest.normalizedFilename}`), (_c = (_b = options.server) == null ? void 0 : _b.ws) == null || _c.send("imba:warnings", message);
|
|
}
|
|
}
|
|
function ignoreCompilerWarning(warning, isBuild, emitCss) {
|
|
return !emitCss && warning.code === "css-unused-selector" || !isBuild && isNoScopableElementWarning(warning);
|
|
}
|
|
function isNoScopableElementWarning(warning) {
|
|
return warning.code === "css-unused-selector" && warning.message.includes('"*"');
|
|
}
|
|
function buildExtraWarnings(warnings, isBuild) {
|
|
let extraWarnings = [];
|
|
if (!isBuild) {
|
|
let noScopableElementWarnings = warnings.filter((w) => isNoScopableElementWarning(w));
|
|
if (noScopableElementWarnings.length > 0) {
|
|
let noScopableElementWarning = noScopableElementWarnings[noScopableElementWarnings.length - 1];
|
|
extraWarnings.push({
|
|
...noScopableElementWarning,
|
|
code: "vite-plugin-imba-css-no-scopable-elements",
|
|
message: "No scopable elements found in template. If you're using global styles in the style tag, you should move it into an external stylesheet file and import it in JS. See https://github.com/imbajs/vite-plugin-imba/blob/main/docs/faq.md#where-should-i-put-my-global-styles."
|
|
});
|
|
}
|
|
}
|
|
return extraWarnings;
|
|
}
|
|
function warnDev(w) {
|
|
log.info.enabled && log.info(buildExtendedLogMessage(w));
|
|
}
|
|
function warnBuild(w) {
|
|
log.warn.enabled && log.warn(buildExtendedLogMessage(w), w.frame);
|
|
}
|
|
function buildExtendedLogMessage(w) {
|
|
let parts = [];
|
|
return w.filename && parts.push(w.filename), w.start && parts.push(":", w.start.line, ":", w.start.column), w.message && (parts.length > 0 && parts.push(" "), parts.push(w.message)), parts.join("");
|
|
}
|
|
|
|
// src/utils/compile.ts
|
|
var scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/, _createCompileImba = (makeHot) => async function(imbaRequest, code, options) {
|
|
var _a, _b, _c;
|
|
let { filename, normalizedFilename, cssId, ssr } = imbaRequest, { emitCss = !0 } = options, dependencies = [], compileOptions = {
|
|
...options.compilerOptions,
|
|
filename,
|
|
generate: ssr ? "ssr" : "dom",
|
|
format: "esm",
|
|
resolveColors: !0,
|
|
sourcePath: filename,
|
|
sourcemap: options.compilerOptions.sourcemap ?? "inline"
|
|
};
|
|
if (options.hot && options.emitCss) {
|
|
let hash = `s-${safeBase64Hash(normalizedFilename)}`;
|
|
log.debug(`setting cssHash ${hash} for ${normalizedFilename}`), compileOptions.cssHash = () => hash;
|
|
}
|
|
ssr && compileOptions.enableSourcemap !== !1 && (typeof compileOptions.enableSourcemap == "object" ? compileOptions.enableSourcemap.css = !1 : compileOptions.enableSourcemap = { js: !0, css: !1 });
|
|
let preprocessed, finalCode = preprocessed ? preprocessed.code : code, dynamicCompileOptions = await ((_b = (_a = options.experimental) == null ? void 0 : _a.dynamicCompileOptions) == null ? void 0 : _b.call(_a, {
|
|
filename,
|
|
code: finalCode,
|
|
compileOptions
|
|
}));
|
|
dynamicCompileOptions && log.debug.enabled && log.debug(
|
|
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`
|
|
);
|
|
let finalCompileOptions = dynamicCompileOptions ? {
|
|
...compileOptions,
|
|
...dynamicCompileOptions
|
|
} : compileOptions;
|
|
finalCompileOptions.config = finalCompileOptions, finalCompileOptions.styles = "extern";
|
|
let compiled = compile(finalCode, finalCompileOptions);
|
|
return compiled.js = { code: compiled.js }, compiled.css = { code: compiled.css }, emitCss && compiled.css.code && (compiled.js.code += `
|
|
/*__css_import__*/import ${JSON.stringify(cssId)};
|
|
`), !ssr && makeHot && (compiled.js.code = makeHot({
|
|
id: filename,
|
|
compiledCode: compiled.js.code,
|
|
hotOptions: options.hot,
|
|
compiled,
|
|
originalCode: code,
|
|
compileOptions: finalCompileOptions
|
|
})), compiled.js.dependencies = dependencies, {
|
|
filename,
|
|
normalizedFilename,
|
|
lang: ((_c = code.match(scriptLangRE)) == null ? void 0 : _c[1]) || "js",
|
|
compiled,
|
|
ssr,
|
|
dependencies
|
|
};
|
|
};
|
|
function createCompileImba(options) {
|
|
return _createCompileImba();
|
|
}
|
|
|
|
// src/svg-plugin.imba
|
|
import { readFileSync } from "fs";
|
|
import { parseAsset } from "imba/compiler";
|
|
function compileΞsvg(body, url2) {
|
|
let js, parsed = parseAsset({ body });
|
|
return js = `export default /* @__PURE__ */ Object.assign({
|
|
type: 'svg'
|
|
},` + JSON.stringify(parsed) + ")";
|
|
}
|
|
function svgΞplugin(options = {}) {
|
|
let cache = /* @__PURE__ */ new Map();
|
|
return {
|
|
name: "vite-plugin-imba-svg",
|
|
transform: async function(source, id, opts) {
|
|
if (id.endsWith(".svg")) {
|
|
let result2 = cache.get(id);
|
|
if (!result2) {
|
|
let body = readFileSync(id, "utf-8");
|
|
result2 = await compileΞsvg(body, id), cache.set(id, result2);
|
|
}
|
|
return result2;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// src/utils/id.ts
|
|
import { createFilter } from "@rollup/pluginutils";
|
|
import { normalizePath } from "vite";
|
|
import * as fs2 from "fs";
|
|
var VITE_FS_PREFIX = "/@fs/", IS_WINDOWS = process.platform === "win32";
|
|
function splitId(id) {
|
|
let parts = id.split("?", 2), filename = parts[0], rawQuery = parts[1];
|
|
return { filename, rawQuery };
|
|
}
|
|
function parseToImbaRequest(id, filename, rawQuery, root, timestamp, ssr) {
|
|
let query = parseRequestQuery(rawQuery);
|
|
if (query.url || query.raw)
|
|
return;
|
|
let normalizedFilename = normalize(filename, root), cssId = createVirtualImportId(filename, root, "style");
|
|
return {
|
|
id,
|
|
filename,
|
|
normalizedFilename,
|
|
cssId,
|
|
query,
|
|
timestamp,
|
|
ssr
|
|
};
|
|
}
|
|
function createVirtualImportId(filename, root, type) {
|
|
let parts = ["imba", `type=${type}`];
|
|
return type === "style" && parts.push("lang.css"), existsInRoot(filename, root) ? filename = root + filename : filename.startsWith(VITE_FS_PREFIX) && (filename = IS_WINDOWS ? filename.slice(VITE_FS_PREFIX.length) : filename.slice(VITE_FS_PREFIX.length - 1)), `${filename}?${parts.join("&")}`;
|
|
}
|
|
function parseRequestQuery(rawQuery) {
|
|
let query = Object.fromEntries(new URLSearchParams(rawQuery));
|
|
for (let key in query)
|
|
query[key] === "" && (query[key] = !0);
|
|
return query;
|
|
}
|
|
function normalize(filename, normalizedRoot) {
|
|
return stripRoot(normalizePath(filename), normalizedRoot);
|
|
}
|
|
function existsInRoot(filename, root) {
|
|
return filename.startsWith(VITE_FS_PREFIX) ? !1 : fs2.existsSync(root + filename);
|
|
}
|
|
function stripRoot(normalizedFilename, normalizedRoot) {
|
|
return normalizedFilename.startsWith(normalizedRoot + "/") ? normalizedFilename.slice(normalizedRoot.length) : normalizedFilename;
|
|
}
|
|
function buildFilter(include, exclude, extensions) {
|
|
let rollupFilter = createFilter(include, exclude);
|
|
return (filename) => rollupFilter(filename) && extensions.some((ext) => filename.endsWith(ext));
|
|
}
|
|
function buildIdParser(options) {
|
|
let { include, exclude, extensions, root } = options, normalizedRoot = normalizePath(root), filter = buildFilter(include, exclude, extensions);
|
|
return (id, ssr, timestamp = Date.now()) => {
|
|
let { filename, rawQuery } = splitId(id);
|
|
if (filter(filename))
|
|
return parseToImbaRequest(id, filename, rawQuery, normalizedRoot, timestamp, ssr);
|
|
};
|
|
}
|
|
|
|
// src/utils/options.ts
|
|
import {
|
|
normalizePath as normalizePath2
|
|
} from "vite";
|
|
|
|
// src/utils/load-imba-config.ts
|
|
import { createRequire } from "module";
|
|
import path from "path";
|
|
import fs3 from "fs";
|
|
import { pathToFileURL } from "url";
|
|
var esmRequire, knownImbaConfigNames = [
|
|
"imba.config.js",
|
|
"imbaconfig.json",
|
|
"imba.config.json"
|
|
], dynamicImportDefault = new Function(
|
|
"path",
|
|
"timestamp",
|
|
'return import(path + "?t=" + timestamp).then(m => m.default)'
|
|
), dynamicImportJSON = new Function(
|
|
"path",
|
|
"timestamp",
|
|
'return import(path + "?t=" + timestamp, {assert: {type: "json"}}).then(m => m.default)'
|
|
);
|
|
async function loadImbaConfig(viteConfig, inlineOptions) {
|
|
if ((inlineOptions == null ? void 0 : inlineOptions.configFile) === !1)
|
|
return;
|
|
let configFile = findConfigToLoad(viteConfig, inlineOptions);
|
|
if (configFile) {
|
|
let err;
|
|
if (configFile.endsWith(".json"))
|
|
try {
|
|
let result = await dynamicImportJSON(
|
|
pathToFileURL(configFile).href,
|
|
fs3.statSync(configFile).mtimeMs
|
|
);
|
|
if (result != null)
|
|
return {
|
|
...result,
|
|
configFile
|
|
};
|
|
throw new Error(`invalid export in ${configFile}`);
|
|
} catch (e) {
|
|
log.error(`failed to import config ${configFile}`, e), err = e;
|
|
}
|
|
if (configFile.endsWith(".js") || configFile.endsWith(".mjs") || configFile.endsWith(".json"))
|
|
try {
|
|
let result = await dynamicImportDefault(
|
|
pathToFileURL(configFile).href,
|
|
fs3.statSync(configFile).mtimeMs
|
|
);
|
|
if (result != null)
|
|
return {
|
|
...result,
|
|
configFile
|
|
};
|
|
throw new Error(`invalid export in ${configFile}`);
|
|
} catch (e) {
|
|
log.error(`failed to import config ${configFile}`, e), err = e;
|
|
}
|
|
if (!configFile.endsWith(".mjs"))
|
|
try {
|
|
let _require = import.meta.url ? esmRequire ?? (esmRequire = createRequire(import.meta.url)) : __require;
|
|
delete _require.cache[_require.resolve(configFile)];
|
|
let result = _require(configFile);
|
|
if (result != null)
|
|
return {
|
|
...result,
|
|
configFile
|
|
};
|
|
throw new Error(`invalid export in ${configFile}`);
|
|
} catch (e) {
|
|
log.error(`failed to require config ${configFile}`, e), err || (err = e);
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
function findConfigToLoad(viteConfig, inlineOptions) {
|
|
let root = (viteConfig == null ? void 0 : viteConfig.root) || process.cwd();
|
|
if (inlineOptions != null && inlineOptions.configFile) {
|
|
let abolutePath = path.isAbsolute(inlineOptions.configFile) ? inlineOptions.configFile : path.resolve(root, inlineOptions.configFile);
|
|
if (!fs3.existsSync(abolutePath))
|
|
throw new Error(`failed to find imba config file ${abolutePath}.`);
|
|
return abolutePath;
|
|
} else {
|
|
let existingKnownConfigFiles = knownImbaConfigNames.map((candidate) => path.resolve(root, candidate)).filter((file) => fs3.existsSync(file));
|
|
if (existingKnownConfigFiles.length === 0) {
|
|
log.debug(`no imba config found at ${root}`);
|
|
return;
|
|
} else
|
|
existingKnownConfigFiles.length > 1 && log.warn(
|
|
`found more than one imba config file, using ${existingKnownConfigFiles[0]}. you should only have one!`,
|
|
existingKnownConfigFiles
|
|
);
|
|
return existingKnownConfigFiles[0];
|
|
}
|
|
}
|
|
|
|
// src/utils/constants.ts
|
|
var VITE_RESOLVE_MAIN_FIELDS = ["module", "jsnext:main", "jsnext"], IMBA_RESOLVE_MAIN_FIELDS = ["imba", ...VITE_RESOLVE_MAIN_FIELDS], IMBA_IMPORTS = [], IMBA_HMR_IMPORTS = [];
|
|
|
|
// src/utils/options.ts
|
|
import path4 from "path";
|
|
|
|
// src/utils/dependencies.ts
|
|
import path2 from "path";
|
|
import fs4 from "fs";
|
|
import { createRequire as createRequire2 } from "module";
|
|
function findRootImbaDependencies(root, cwdFallback = !0) {
|
|
log.debug(`findImbaDependencies: searching imba dependencies in ${root}`);
|
|
let pkgFile = path2.join(root, "package.json");
|
|
if (!fs4.existsSync(pkgFile)) {
|
|
if (cwdFallback) {
|
|
let cwd = process.cwd();
|
|
if (root !== cwd)
|
|
return log.debug(`no package.json found in vite root ${root}`), findRootImbaDependencies(cwd, !1);
|
|
}
|
|
return log.warn("no package.json found, findRootImbaDependencies failed"), [];
|
|
}
|
|
let pkg = parsePkg(root);
|
|
if (!pkg)
|
|
return [];
|
|
let deps = [
|
|
...Object.keys(pkg.dependencies || {}),
|
|
...Object.keys(pkg.devDependencies || {})
|
|
].filter((dep) => !is_common_without_imba_field(dep));
|
|
return getImbaDependencies(deps, root);
|
|
}
|
|
function getImbaDependencies(deps, pkgDir, path7 = []) {
|
|
let result = [], localRequire = createRequire2(`${pkgDir}/package.json`), resolvedDeps = deps.map((dep) => resolveDependencyData(dep, localRequire)).filter(Boolean);
|
|
for (let { pkg, dir } of resolvedDeps) {
|
|
let type = getImbaDependencyType(pkg);
|
|
if (!!type && (result.push({ name: pkg.name, type, pkg, dir, path: path7 }), type === "component-library" && pkg.dependencies)) {
|
|
let dependencyNames = Object.keys(pkg.dependencies), circular = dependencyNames.filter((name) => path7.includes(name));
|
|
circular.length > 0 && (log.warn.enabled && log.warn(
|
|
"skipping circular imba dependencies in automated vite optimizeDeps handling",
|
|
circular.map((x) => path7.concat(x).join(">"))
|
|
), dependencyNames = dependencyNames.filter((name) => !path7.includes(name))), path7.length === 3 && log.debug.once(`encountered deep imba dependency tree: ${path7.join(">")}`), result.push(...getImbaDependencies(dependencyNames, dir, path7.concat(pkg.name)));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function resolveDependencyData(dep, localRequire) {
|
|
try {
|
|
let pkgJson = `${dep}/package.json`, pkg = localRequire(pkgJson);
|
|
return { dir: path2.dirname(localRequire.resolve(pkgJson)), pkg };
|
|
} catch (e) {
|
|
log.debug.once(`dependency ${dep} does not export package.json`, e);
|
|
try {
|
|
let dir = path2.dirname(localRequire.resolve(dep));
|
|
for (; dir; ) {
|
|
let pkg = parsePkg(dir, !0);
|
|
if (pkg && pkg.name === dep)
|
|
return { dir, pkg };
|
|
let parent = path2.dirname(dir);
|
|
if (parent === dir)
|
|
break;
|
|
dir = parent;
|
|
}
|
|
} catch (e2) {
|
|
log.debug.once(`error while trying to find package.json of ${dep}`, e2);
|
|
}
|
|
}
|
|
log.debug.once(`failed to resolve ${dep}`);
|
|
}
|
|
function parsePkg(dir, silent = !1) {
|
|
let pkgFile = path2.join(dir, "package.json");
|
|
try {
|
|
return JSON.parse(fs4.readFileSync(pkgFile, "utf-8"));
|
|
} catch (e) {
|
|
!silent && log.warn.enabled && log.warn(`failed to parse ${pkgFile}`, e);
|
|
}
|
|
}
|
|
function getImbaDependencyType(pkg) {
|
|
return isImbaComponentLib(pkg) ? "component-library" : isImbaLib(pkg) ? "js-library" : void 0;
|
|
}
|
|
function isImbaComponentLib(pkg) {
|
|
return !!pkg.imba;
|
|
}
|
|
function isImbaLib(pkg) {
|
|
var _a, _b;
|
|
return !!((_a = pkg.dependencies) != null && _a.imba) || !!((_b = pkg.peerDependencies) != null && _b.imba);
|
|
}
|
|
var COMMON_DEPENDENCIES_WITHOUT_IMBA_FIELD = [
|
|
"@lukeed/uuid",
|
|
"@playwright/test",
|
|
"@imbajs/vite-plugin-imba",
|
|
"@imbajs/kit",
|
|
"autoprefixer",
|
|
"cookie",
|
|
"dotenv",
|
|
"esbuild",
|
|
"eslint",
|
|
"jest",
|
|
"mdsvex",
|
|
"playwright",
|
|
"postcss",
|
|
"prettier",
|
|
"imba",
|
|
"imba-check",
|
|
"imba-hmr",
|
|
"imba-preprocess",
|
|
"tslib",
|
|
"typescript",
|
|
"vite",
|
|
"vitest",
|
|
"__vite-browser-external"
|
|
], COMMON_PREFIXES_WITHOUT_IMBA_FIELD = [
|
|
"@fontsource/",
|
|
"@postcss-plugins/",
|
|
"@rollup/",
|
|
"@imbajs/adapter-",
|
|
"@types/",
|
|
"@typescript-eslint/",
|
|
"eslint-",
|
|
"jest-",
|
|
"postcss-plugin-",
|
|
"prettier-plugin-",
|
|
"rollup-plugin-",
|
|
"vite-plugin-"
|
|
];
|
|
function is_common_without_imba_field(dependency) {
|
|
return COMMON_DEPENDENCIES_WITHOUT_IMBA_FIELD.includes(dependency) || COMMON_PREFIXES_WITHOUT_IMBA_FIELD.some(
|
|
(prefix2) => prefix2.startsWith("@") ? dependency.startsWith(prefix2) : dependency.substring(dependency.lastIndexOf("/") + 1).startsWith(prefix2)
|
|
);
|
|
}
|
|
function needsOptimization(dep, localRequire) {
|
|
let depData = resolveDependencyData(dep, localRequire);
|
|
if (!depData)
|
|
return !1;
|
|
let pkg = depData.pkg;
|
|
if (pkg.module || pkg.exports)
|
|
return !1;
|
|
if (pkg.main) {
|
|
let entryExt = path2.extname(pkg.main);
|
|
return !entryExt || entryExt === ".js" || entryExt === ".cjs";
|
|
} else
|
|
try {
|
|
return localRequire.resolve(`${dep}/index.js`), !0;
|
|
} catch {
|
|
return !1;
|
|
}
|
|
}
|
|
|
|
// src/utils/options.ts
|
|
import { createRequire as createRequire3 } from "module";
|
|
|
|
// src/utils/esbuild.ts
|
|
import { promises as fs5 } from "fs";
|
|
import { compile as compile2 } from "imba/compiler";
|
|
|
|
// src/utils/error.ts
|
|
function toRollupError(error, options) {
|
|
let { filename, frame, start, code, name, stack } = error, rollupError = {
|
|
name,
|
|
id: filename,
|
|
message: buildExtendedLogMessage(error),
|
|
frame: formatFrameForVite(frame),
|
|
code,
|
|
stack: options.isBuild || options.isDebug || !frame ? stack : ""
|
|
};
|
|
return start && (rollupError.loc = {
|
|
line: start.line,
|
|
column: start.column,
|
|
file: filename
|
|
}), rollupError;
|
|
}
|
|
function formatFrameForVite(frame) {
|
|
return frame ? frame.split(`
|
|
`).map((line) => line.match(/^\s+\^/) ? " " + line : " " + line.replace(":", " | ")).join(`
|
|
`) : "";
|
|
}
|
|
|
|
// src/utils/esbuild.ts
|
|
var facadeEsbuildImbaPluginName = "vite-plugin-imba:facade";
|
|
|
|
// src/utils/preprocess.ts
|
|
import MagicString2 from "magic-string";
|
|
|
|
// src/utils/sourcemap.ts
|
|
import MagicString from "magic-string";
|
|
async function buildMagicString(from, to, options) {
|
|
let diff_match_patch, DIFF_DELETE, DIFF_INSERT;
|
|
try {
|
|
let dmpPkg = await import("diff-match-patch");
|
|
diff_match_patch = dmpPkg.diff_match_patch, DIFF_INSERT = dmpPkg.DIFF_INSERT, DIFF_DELETE = dmpPkg.DIFF_DELETE;
|
|
} catch {
|
|
return log.error.once(
|
|
'Failed to import optional dependency "diff-match-patch". Please install it to enable generated sourcemaps.'
|
|
), null;
|
|
}
|
|
let dmp = new diff_match_patch(), diffs = dmp.diff_main(from, to);
|
|
dmp.diff_cleanupSemantic(diffs);
|
|
let m = new MagicString(from, options), pos = 0;
|
|
for (let i = 0; i < diffs.length; i++) {
|
|
let diff = diffs[i], nextDiff = diffs[i + 1];
|
|
diff[0] === DIFF_DELETE ? ((nextDiff == null ? void 0 : nextDiff[0]) === DIFF_INSERT ? (m.overwrite(pos, pos + diff[1].length, nextDiff[1]), i++) : m.remove(pos, pos + diff[1].length), pos += diff[1].length) : diff[0] === DIFF_INSERT ? nextDiff ? m.appendRight(pos, diff[1]) : m.append(diff[1]) : pos += diff[1].length;
|
|
}
|
|
return m;
|
|
}
|
|
async function buildSourceMap(from, to, filename) {
|
|
let m = await buildMagicString(from, to, { filename });
|
|
return m ? m.generateDecodedMap({ source: filename, hires: !0, includeContent: !1 }) : null;
|
|
}
|
|
|
|
// src/utils/preprocess.ts
|
|
import path3 from "path";
|
|
function createInjectScopeEverythingRulePreprocessorGroup() {
|
|
return {
|
|
style({ content, filename }) {
|
|
let s = new MagicString2(content);
|
|
return s.append(" *{}"), {
|
|
code: s.toString(),
|
|
map: s.generateDecodedMap({
|
|
source: filename ? path3.basename(filename) : void 0,
|
|
hires: !0
|
|
})
|
|
};
|
|
}
|
|
};
|
|
}
|
|
function buildExtraPreprocessors(options, config) {
|
|
var _a;
|
|
let prependPreprocessors = [], appendPreprocessors = [], pluginsWithPreprocessorsDeprecated = config.plugins.filter((p) => p == null ? void 0 : p.imbaPreprocess);
|
|
pluginsWithPreprocessorsDeprecated.length > 0 && (log.warn(
|
|
`The following plugins use the deprecated 'plugin.imbaPreprocess' field. Please contact their maintainers and ask them to move it to 'plugin.api.imbaPreprocess': ${pluginsWithPreprocessorsDeprecated.map((p) => p.name).join(", ")}`
|
|
), pluginsWithPreprocessorsDeprecated.forEach((p) => {
|
|
p.api || (p.api = {}), p.api.imbaPreprocess === void 0 ? p.api.imbaPreprocess = p.imbaPreprocess : log.error(
|
|
`ignoring plugin.imbaPreprocess of ${p.name} because it already defined plugin.api.imbaPreprocess.`
|
|
);
|
|
}));
|
|
let pluginsWithPreprocessors = config.plugins.filter((p) => {
|
|
var _a2;
|
|
return (_a2 = p == null ? void 0 : p.api) == null ? void 0 : _a2.imbaPreprocess;
|
|
}), ignored = [], included = [];
|
|
for (let p of pluginsWithPreprocessors)
|
|
options.ignorePluginPreprocessors === !0 || Array.isArray(options.ignorePluginPreprocessors) && ((_a = options.ignorePluginPreprocessors) == null ? void 0 : _a.includes(p.name)) ? ignored.push(p) : included.push(p);
|
|
return ignored.length > 0 && log.debug(
|
|
`Ignoring imba preprocessors defined by these vite plugins: ${ignored.map((p) => p.name).join(", ")}`
|
|
), included.length > 0 && (log.debug(
|
|
`Adding imba preprocessors defined by these vite plugins: ${included.map((p) => p.name).join(", ")}`
|
|
), appendPreprocessors.push(...pluginsWithPreprocessors.map((p) => p.api.imbaPreprocess))), options.hot && options.emitCss && appendPreprocessors.push(createInjectScopeEverythingRulePreprocessorGroup()), { prependPreprocessors, appendPreprocessors };
|
|
}
|
|
function addExtraPreprocessors(options, config) {
|
|
var _a;
|
|
let { prependPreprocessors, appendPreprocessors } = buildExtraPreprocessors(options, config);
|
|
(prependPreprocessors.length > 0 || appendPreprocessors.length > 0) && (options.preprocess ? Array.isArray(options.preprocess) ? (options.preprocess.unshift(...prependPreprocessors), options.preprocess.push(...appendPreprocessors)) : options.preprocess = [...prependPreprocessors, options.preprocess, ...appendPreprocessors] : options.preprocess = [...prependPreprocessors, ...appendPreprocessors]);
|
|
let generateMissingSourceMaps = !!((_a = options.experimental) != null && _a.generateMissingPreprocessorSourcemaps);
|
|
options.preprocess && generateMissingSourceMaps && (options.preprocess = Array.isArray(options.preprocess) ? options.preprocess.map((p, i) => validateSourceMapOutputWrapper(p, i)) : validateSourceMapOutputWrapper(options.preprocess, 0));
|
|
}
|
|
function validateSourceMapOutputWrapper(group, i) {
|
|
let wrapper = {};
|
|
for (let [processorType, processorFn] of Object.entries(group))
|
|
wrapper[processorType] = async (options) => {
|
|
var _a;
|
|
let result = await processorFn(options);
|
|
if (result && result.code !== options.content) {
|
|
let invalidMap = !1;
|
|
if (result.map ? ((_a = result.map) == null ? void 0 : _a.mappings) === "" && (invalidMap = !0, log.warn.enabled && log.warn.once(
|
|
`preprocessor at index ${i} returned an invalid empty sourcemap for ${processorType} transform`,
|
|
{
|
|
filename: options.filename,
|
|
type: processorType,
|
|
processor: processorFn.toString()
|
|
}
|
|
)) : (invalidMap = !0, log.warn.enabled && log.warn.once(
|
|
`preprocessor at index ${i} did not return a sourcemap for ${processorType} transform`,
|
|
{
|
|
filename: options.filename,
|
|
type: processorType,
|
|
processor: processorFn.toString()
|
|
}
|
|
)), invalidMap)
|
|
try {
|
|
let map = await buildSourceMap(options.content, result.code, options.filename);
|
|
map && (log.debug.enabled && log.debug(
|
|
`adding generated sourcemap to preprocesor result for ${options.filename}`
|
|
), result.map = map);
|
|
} catch (e) {
|
|
log.error("failed to build sourcemap", e);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
return wrapper;
|
|
}
|
|
|
|
// src/utils/options.ts
|
|
import deepmerge from "deepmerge";
|
|
var allowedPluginOptions = /* @__PURE__ */ new Set([
|
|
"include",
|
|
"exclude",
|
|
"emitCss",
|
|
"hot",
|
|
"ignorePluginPreprocessors",
|
|
"disableDependencyReinclusion",
|
|
"experimental",
|
|
"ssr"
|
|
]), knownRootOptions = /* @__PURE__ */ new Set(["extensions", "compilerOptions", "preprocess", "onwarn"]), allowedInlineOptions = /* @__PURE__ */ new Set([
|
|
"configFile",
|
|
"kit",
|
|
...allowedPluginOptions,
|
|
...knownRootOptions
|
|
]);
|
|
function validateInlineOptions(inlineOptions) {
|
|
let invalidKeys = Object.keys(inlineOptions || {}).filter(
|
|
(key) => !allowedInlineOptions.has(key)
|
|
);
|
|
invalidKeys.length && log.warn(`invalid plugin options "${invalidKeys.join(", ")}" in inline config`, inlineOptions);
|
|
}
|
|
function convertPluginOptions(config) {
|
|
if (!config)
|
|
return;
|
|
let invalidRootOptions = Object.keys(config).filter((key) => allowedPluginOptions.has(key));
|
|
if (invalidRootOptions.length > 0)
|
|
throw new Error(
|
|
`Invalid options in imba config. Move the following options into 'vitePlugin:{...}': ${invalidRootOptions.join(
|
|
", "
|
|
)}`
|
|
);
|
|
if (!config.vitePlugin)
|
|
return { compilerOptions: config };
|
|
let pluginOptions = config.vitePlugin, pluginOptionKeys = Object.keys(pluginOptions), rootOptionsInPluginOptions = pluginOptionKeys.filter((key) => knownRootOptions.has(key));
|
|
if (rootOptionsInPluginOptions.length > 0)
|
|
throw new Error(
|
|
`Invalid options in imba config under vitePlugin:{...}', move them to the config root : ${rootOptionsInPluginOptions.join(
|
|
", "
|
|
)}`
|
|
);
|
|
let duplicateOptions = pluginOptionKeys.filter(
|
|
(key) => Object.prototype.hasOwnProperty.call(config, key)
|
|
);
|
|
if (duplicateOptions.length > 0)
|
|
throw new Error(
|
|
`Invalid duplicate options in imba config under vitePlugin:{...}', they are defined in root too and must only exist once: ${duplicateOptions.join(
|
|
", "
|
|
)}`
|
|
);
|
|
let unknownPluginOptions = pluginOptionKeys.filter((key) => !allowedPluginOptions.has(key));
|
|
unknownPluginOptions.length > 0 && (log.warn(
|
|
`ignoring unknown plugin options in imba config under vitePlugin:{...}: ${unknownPluginOptions.join(
|
|
", "
|
|
)}`
|
|
), unknownPluginOptions.forEach((unkownOption) => {
|
|
delete pluginOptions[unkownOption];
|
|
}));
|
|
let result = {
|
|
...config,
|
|
...pluginOptions
|
|
};
|
|
return delete result.vitePlugin, { compilerOptions: result };
|
|
}
|
|
async function preResolveOptions(inlineOptions = {}, viteUserConfig, viteEnv) {
|
|
let viteConfigWithResolvedRoot = {
|
|
...viteUserConfig,
|
|
root: resolveViteRoot(viteUserConfig)
|
|
}, defaultOptions = {
|
|
extensions: [".imba", ".imba1"],
|
|
emitCss: !0
|
|
}, imbaConfig = convertPluginOptions(
|
|
await loadImbaConfig(viteConfigWithResolvedRoot, inlineOptions)
|
|
), extraOptions = {
|
|
root: viteConfigWithResolvedRoot.root,
|
|
isBuild: viteEnv.command === "build",
|
|
isServe: viteEnv.command === "serve",
|
|
isDebug: process.env.DEBUG != null
|
|
}, merged = mergeConfigs(
|
|
defaultOptions,
|
|
imbaConfig,
|
|
inlineOptions,
|
|
extraOptions
|
|
);
|
|
return imbaConfig != null && imbaConfig.configFile && (merged.configFile = imbaConfig.configFile, merged.config = imbaConfig), merged;
|
|
}
|
|
function mergeConfigs(...configs) {
|
|
let result = {};
|
|
for (let config of configs.filter(Boolean))
|
|
result = deepmerge(result, config, {
|
|
arrayMerge: (target, source) => source ?? target
|
|
});
|
|
return result;
|
|
}
|
|
function resolveOptions(preResolveOptions2, viteConfig) {
|
|
let defaultOptions = {
|
|
hot: viteConfig.isProduction ? !1 : { injectCss: !preResolveOptions2.emitCss },
|
|
compilerOptions: {
|
|
css: !preResolveOptions2.emitCss,
|
|
dev: !viteConfig.isProduction
|
|
}
|
|
}, extraOptions = {
|
|
root: viteConfig.root,
|
|
isProduction: viteConfig.isProduction
|
|
}, merged = mergeConfigs(defaultOptions, preResolveOptions2, extraOptions);
|
|
return removeIgnoredOptions(merged), addImbaKitOptions(merged), addExtraPreprocessors(merged, viteConfig), enforceOptionsForHmr(merged), enforceOptionsForProduction(merged), merged;
|
|
}
|
|
function enforceOptionsForHmr(options) {
|
|
options.hot && (options.compilerOptions.dev || (log.warn("hmr is enabled but compilerOptions.dev is false, forcing it to true"), options.compilerOptions.dev = !0), options.emitCss ? (options.hot !== !0 && options.hot.injectCss && (log.warn("hmr and emitCss are enabled but hot.injectCss is true, forcing it to false"), options.hot.injectCss = !1), options.compilerOptions.css && (log.warn(
|
|
"hmr and emitCss are enabled but compilerOptions.css is true, forcing it to false"
|
|
), options.compilerOptions.css = !1)) : ((options.hot === !0 || !options.hot.injectCss) && (log.warn(
|
|
"hmr with emitCss disabled requires option hot.injectCss to be enabled, forcing it to true"
|
|
), options.hot === !0 ? options.hot = { injectCss: !0 } : options.hot.injectCss = !0), options.compilerOptions.css || (log.warn(
|
|
"hmr with emitCss disabled requires compilerOptions.css to be enabled, forcing it to true"
|
|
), options.compilerOptions.css = !0)));
|
|
}
|
|
function enforceOptionsForProduction(options) {
|
|
options.isProduction && (options.hot && (log.warn("options.hot is enabled but does not work on production build, forcing it to false"), options.hot = !1), options.compilerOptions.dev && (log.warn(
|
|
"you are building for production but compilerOptions.dev is true, forcing it to false"
|
|
), options.compilerOptions.dev = !1));
|
|
}
|
|
function removeIgnoredOptions(options) {
|
|
let ignoredCompilerOptions = ["generate", "format", "filename"];
|
|
options.hot && options.emitCss && ignoredCompilerOptions.push("cssHash");
|
|
let passedIgnored = Object.keys(options.compilerOptions || {}).filter((o) => ignoredCompilerOptions.includes(o));
|
|
passedIgnored.length && (log.warn(
|
|
`The following Imba compilerOptions are controlled by vite-plugin-imba and essential to its functionality. User-specified values are ignored. Please remove them from your configuration: ${passedIgnored.join(
|
|
", "
|
|
)}`
|
|
), passedIgnored.forEach((ignored) => {
|
|
delete options.compilerOptions[ignored];
|
|
}));
|
|
}
|
|
function addImbaKitOptions(options) {
|
|
var _a;
|
|
if ((options == null ? void 0 : options.kit) != null) {
|
|
let kit_browser_hydrate = (_a = options.kit.browser) == null ? void 0 : _a.hydrate, hydratable = kit_browser_hydrate !== !1;
|
|
options.compilerOptions.hydratable != null && options.compilerOptions.hydratable !== hydratable && log.warn(
|
|
`Conflicting values "compilerOptions.hydratable: ${options.compilerOptions.hydratable}" and "kit.browser.hydrate: ${kit_browser_hydrate}" in your imba config. You should remove "compilerOptions.hydratable".`
|
|
), log.debug(`Setting compilerOptions.hydratable: ${hydratable} for ImbaKit`), options.compilerOptions.hydratable = hydratable;
|
|
}
|
|
}
|
|
function resolveViteRoot(viteConfig) {
|
|
return normalizePath2(viteConfig.root ? path4.resolve(viteConfig.root) : process.cwd());
|
|
}
|
|
function buildExtraViteConfig(options, config) {
|
|
var _a;
|
|
let imbaDeps = findRootImbaDependencies(options.root), extraViteConfig = {
|
|
resolve: {
|
|
mainFields: [...IMBA_RESOLVE_MAIN_FIELDS],
|
|
dedupe: [...IMBA_IMPORTS, ...IMBA_HMR_IMPORTS]
|
|
}
|
|
};
|
|
return extraViteConfig.optimizeDeps = buildOptimizeDepsForImba(
|
|
imbaDeps,
|
|
options,
|
|
config.optimizeDeps
|
|
), (_a = options.experimental) != null && _a.prebundleImbaLibraries && (extraViteConfig.optimizeDeps = {
|
|
...extraViteConfig.optimizeDeps,
|
|
extensions: options.extensions ?? [".imba", ".imba1"],
|
|
esbuildOptions: {
|
|
plugins: [{ name: facadeEsbuildImbaPluginName, setup: () => {
|
|
} }]
|
|
}
|
|
}), extraViteConfig.ssr = buildSSROptionsForImba(imbaDeps, options, config, extraViteConfig), extraViteConfig;
|
|
}
|
|
function buildOptimizeDepsForImba(imbaDeps, options, optimizeDeps) {
|
|
var _a;
|
|
let include = [], exclude = ["imba-hmr"], isIncluded = (dep) => {
|
|
var _a2;
|
|
return include.includes(dep) || ((_a2 = optimizeDeps == null ? void 0 : optimizeDeps.include) == null ? void 0 : _a2.includes(dep));
|
|
}, isExcluded = (dep) => {
|
|
var _a2;
|
|
return exclude.includes(dep) || ((_a2 = optimizeDeps == null ? void 0 : optimizeDeps.exclude) == null ? void 0 : _a2.some((id) => dep === id || id.startsWith(`${dep}/`)));
|
|
};
|
|
if (isExcluded("imba"))
|
|
log.debug('"imba" is excluded in optimizeDeps.exclude, skipped adding it to include.');
|
|
else {
|
|
let imbaImportsToInclude = IMBA_IMPORTS.filter((x) => x !== "imba/ssr");
|
|
log.debug(
|
|
`adding bare imba packages to optimizeDeps.include: ${imbaImportsToInclude.join(", ")} `
|
|
), include.push(...imbaImportsToInclude.filter((x) => !isIncluded(x)));
|
|
}
|
|
if ((_a = options.experimental) != null && _a.prebundleImbaLibraries)
|
|
return { include, exclude };
|
|
imbaDeps = imbaDeps.filter((dep) => dep.type === "component-library");
|
|
let imbaDepsToExclude = Array.from(new Set(imbaDeps.map((dep) => dep.name))).filter(
|
|
(dep) => !isIncluded(dep)
|
|
);
|
|
if (log.debug(`automatically excluding found imba dependencies: ${imbaDepsToExclude.join(", ")}`), exclude.push(...imbaDepsToExclude.filter((x) => !isExcluded(x))), options.disableDependencyReinclusion !== !0) {
|
|
let disabledReinclusions = options.disableDependencyReinclusion || [];
|
|
disabledReinclusions.length > 0 && log.debug("not reincluding transitive dependencies of", disabledReinclusions);
|
|
let transitiveDepsToInclude = imbaDeps.filter((dep) => !disabledReinclusions.includes(dep.name) && isExcluded(dep.name)).flatMap((dep) => {
|
|
let localRequire = createRequire3(`${dep.dir}/package.json`);
|
|
return Object.keys(dep.pkg.dependencies || {}).filter((depOfDep) => !isExcluded(depOfDep) && needsOptimization(depOfDep, localRequire)).map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(" > "));
|
|
});
|
|
log.debug(
|
|
"reincluding transitive dependencies of excluded imba dependencies",
|
|
transitiveDepsToInclude
|
|
), include.push(...transitiveDepsToInclude);
|
|
}
|
|
return { include, exclude };
|
|
}
|
|
function buildSSROptionsForImba(imbaDeps, options, config) {
|
|
var _a, _b;
|
|
let noExternal = [];
|
|
(_b = (_a = config.ssr) == null ? void 0 : _a.external) != null && _b.includes("imba") || noExternal.push("imba", /^imba\//), noExternal.push(
|
|
...Array.from(new Set(imbaDeps.map((s) => s.name))).filter(
|
|
(x) => {
|
|
var _a2, _b2;
|
|
return !((_b2 = (_a2 = config.ssr) == null ? void 0 : _a2.external) != null && _b2.includes(x));
|
|
}
|
|
)
|
|
);
|
|
let ssr = {
|
|
noExternal,
|
|
external: []
|
|
};
|
|
return options.isServe && (ssr.external = Array.from(
|
|
new Set(imbaDeps.flatMap((dep) => Object.keys(dep.pkg.dependencies || {})))
|
|
).filter(
|
|
(dep) => {
|
|
var _a2, _b2;
|
|
return !ssr.noExternal.includes(dep) && !((_b2 = (_a2 = config.ssr) == null ? void 0 : _a2.external) != null && _b2.includes(dep));
|
|
}
|
|
)), ssr;
|
|
}
|
|
|
|
// src/utils/vite-plugin-imba-cache.ts
|
|
var VitePluginImbaCache = class {
|
|
constructor() {
|
|
this._css = /* @__PURE__ */ new Map();
|
|
this._js = /* @__PURE__ */ new Map();
|
|
this._dependencies = /* @__PURE__ */ new Map();
|
|
this._dependants = /* @__PURE__ */ new Map();
|
|
this._resolvedImbaFields = /* @__PURE__ */ new Map();
|
|
this._errors = /* @__PURE__ */ new Map();
|
|
}
|
|
update(compileData) {
|
|
this._errors.delete(compileData.normalizedFilename), this.updateCSS(compileData), this.updateJS(compileData), this.updateDependencies(compileData);
|
|
}
|
|
has(imbaRequest) {
|
|
let id = imbaRequest.normalizedFilename;
|
|
return this._errors.has(id) || this._js.has(id) || this._css.has(id);
|
|
}
|
|
setError(imbaRequest, error) {
|
|
this.remove(imbaRequest, !0), this._errors.set(imbaRequest.normalizedFilename, error);
|
|
}
|
|
updateCSS(compileData) {
|
|
this._css.set(compileData.normalizedFilename, compileData.compiled.css);
|
|
}
|
|
updateJS(compileData) {
|
|
compileData.ssr || this._js.set(compileData.normalizedFilename, compileData.compiled.js);
|
|
}
|
|
updateDependencies(compileData) {
|
|
let id = compileData.normalizedFilename, prevDependencies = this._dependencies.get(id) || [], dependencies = compileData.dependencies;
|
|
this._dependencies.set(id, dependencies);
|
|
let removed = prevDependencies.filter((d) => !dependencies.includes(d));
|
|
dependencies.filter((d) => !prevDependencies.includes(d)).forEach((d) => {
|
|
this._dependants.has(d) || this._dependants.set(d, /* @__PURE__ */ new Set()), this._dependants.get(d).add(compileData.filename);
|
|
}), removed.forEach((d) => {
|
|
this._dependants.get(d).delete(compileData.filename);
|
|
});
|
|
}
|
|
remove(imbaRequest, keepDependencies = !1) {
|
|
let id = imbaRequest.normalizedFilename, removed = !1;
|
|
if (this._errors.delete(id) && (removed = !0), this._js.delete(id) && (removed = !0), this._css.delete(id) && (removed = !0), !keepDependencies) {
|
|
let dependencies = this._dependencies.get(id);
|
|
dependencies && (removed = !0, dependencies.forEach((d) => {
|
|
let dependants = this._dependants.get(d);
|
|
dependants && dependants.has(imbaRequest.filename) && dependants.delete(imbaRequest.filename);
|
|
}), this._dependencies.delete(id));
|
|
}
|
|
return removed;
|
|
}
|
|
getCSS(imbaRequest) {
|
|
return this._css.get(imbaRequest.normalizedFilename);
|
|
}
|
|
getJS(imbaRequest) {
|
|
if (!imbaRequest.ssr)
|
|
return this._js.get(imbaRequest.normalizedFilename);
|
|
}
|
|
getError(imbaRequest) {
|
|
return this._errors.get(imbaRequest.normalizedFilename);
|
|
}
|
|
getDependants(path7) {
|
|
let dependants = this._dependants.get(path7);
|
|
return dependants ? [...dependants] : [];
|
|
}
|
|
getResolvedImbaField(name, importer) {
|
|
return this._resolvedImbaFields.get(this._getResolvedImbaFieldKey(name, importer));
|
|
}
|
|
setResolvedImbaField(importee, importer = void 0, resolvedImba) {
|
|
this._resolvedImbaFields.set(
|
|
this._getResolvedImbaFieldKey(importee, importer),
|
|
resolvedImba
|
|
);
|
|
}
|
|
_getResolvedImbaFieldKey(importee, importer) {
|
|
return importer ? `${importer} > ${importee}` : importee;
|
|
}
|
|
};
|
|
|
|
// src/utils/resolve.ts
|
|
import path5 from "path";
|
|
import { builtinModules, createRequire as createRequire4 } from "module";
|
|
function resolveViaPackageJsonImba(importee, importer, cache) {
|
|
if (importer && isBareImport(importee) && !isNodeInternal(importee) && !is_common_without_imba_field(importee)) {
|
|
let cached = cache.getResolvedImbaField(importee, importer);
|
|
if (cached)
|
|
return cached;
|
|
let localRequire = createRequire4(importer), pkgData = resolveDependencyData(importee, localRequire);
|
|
if (pkgData) {
|
|
let { pkg, dir } = pkgData;
|
|
if (pkg.imba) {
|
|
let result = path5.resolve(dir, pkg.imba);
|
|
return cache.setResolvedImbaField(importee, importer, result), result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function isNodeInternal(importee) {
|
|
return importee.startsWith("node:") || builtinModules.includes(importee);
|
|
}
|
|
function isBareImport(importee) {
|
|
if (!importee || importee[0] === "." || importee[0] === "\0" || importee.includes(":") || path5.isAbsolute(importee))
|
|
return !1;
|
|
let parts = importee.split("/");
|
|
switch (parts.length) {
|
|
case 1:
|
|
return !0;
|
|
case 2:
|
|
return parts[0].startsWith("@");
|
|
default:
|
|
return !1;
|
|
}
|
|
}
|
|
|
|
// src/utils/watch.ts
|
|
import fs6 from "fs";
|
|
import path6 from "path";
|
|
function setupWatchers(options, cache, requestParser) {
|
|
let { server, configFile: imbaConfigFile } = options;
|
|
if (!server)
|
|
return;
|
|
let { watcher, ws } = server, { root, server: serverConfig } = server.config, emitChangeEventOnDependants = (filename) => {
|
|
cache.getDependants(filename).forEach((dependant) => {
|
|
fs6.existsSync(dependant) && (log.debug(
|
|
`emitting virtual change event for "${dependant}" because depdendency "${filename}" changed`
|
|
), watcher.emit("change", dependant));
|
|
});
|
|
}, removeUnlinkedFromCache = (filename) => {
|
|
let imbaRequest = requestParser(filename, !1);
|
|
imbaRequest && cache.remove(imbaRequest) && log.debug(`cleared VitePluginImbaCache for deleted file ${filename}`);
|
|
}, triggerViteRestart = (filename) => {
|
|
if (serverConfig.middlewareMode) {
|
|
let message = "Imba config change detected, restart your dev process to apply the changes.";
|
|
log.info(message, filename), ws.send({
|
|
type: "error",
|
|
err: { message, stack: "", plugin: "vite-plugin-imba", id: filename }
|
|
});
|
|
} else
|
|
log.info(`imba config changed: restarting vite server. - file: ${filename}`), server.restart();
|
|
}, listenerCollection = {
|
|
add: [],
|
|
change: [emitChangeEventOnDependants],
|
|
unlink: [removeUnlinkedFromCache, emitChangeEventOnDependants]
|
|
};
|
|
if (imbaConfigFile !== !1) {
|
|
let possibleImbaConfigs = knownImbaConfigNames.map((cfg) => path6.join(root, cfg)), restartOnConfigAdd = (filename) => {
|
|
possibleImbaConfigs.includes(filename) && triggerViteRestart(filename);
|
|
}, restartOnConfigChange = (filename) => {
|
|
filename === imbaConfigFile && triggerViteRestart(filename);
|
|
};
|
|
imbaConfigFile ? (listenerCollection.change.push(restartOnConfigChange), listenerCollection.unlink.push(restartOnConfigChange)) : listenerCollection.add.push(restartOnConfigAdd);
|
|
}
|
|
Object.entries(listenerCollection).forEach(([evt, listeners]) => {
|
|
listeners.length > 0 && watcher.on(evt, (filename) => listeners.forEach((listener) => listener(filename)));
|
|
});
|
|
}
|
|
function ensureWatchedFile(watcher, file, root) {
|
|
file && !file.startsWith(root + "/") && !file.includes("\0") && fs6.existsSync(file) && watcher.add(path6.resolve(file));
|
|
}
|
|
|
|
// src/handle-imba-hot-update.imba
|
|
import "vite";
|
|
import * as Diff from "diff";
|
|
async function handleImbaHotUpdate(compileImba, ctx, imbaRequest, cache, options) {
|
|
if (!cache.has(imbaRequest)) {
|
|
log.debug("handleHotUpdate called before initial transform for " + imbaRequest.id);
|
|
return;
|
|
}
|
|
let { read, server } = ctx, cachedJS = cache.getJS(imbaRequest), cachedCss = cache.getCSS(imbaRequest), content = await read(), compileData;
|
|
try {
|
|
options.compilerOptions.sourcemap = !1, compileData = await compileImba(imbaRequest, content, options), cache.update(compileData);
|
|
} catch (e) {
|
|
throw cache.setError(imbaRequest, e), e;
|
|
}
|
|
let affectedModules = /* @__PURE__ */ new Set(), cssModule = server.moduleGraph.getModuleById(imbaRequest.cssId), mainModule = server.moduleGraph.getModuleById(imbaRequest.id);
|
|
cssModule && cssChanged(cachedCss, compileData.compiled.css) && (log.debug("handleHotUpdate css changed for " + imbaRequest.cssId), affectedModules.add(cssModule));
|
|
let jsUpdated = mainModule && jsChanged(cachedJS, compileData.compiled.js, imbaRequest.filename);
|
|
jsUpdated && (log.debug("handleHotUpdate js changed for " + imbaRequest.id), affectedModules.add(mainModule)), jsUpdated || logCompilerWarnings(imbaRequest, compileData.compiled.warnings, options);
|
|
let result = [...affectedModules].filter(Boolean), ssrModulesToInvalidate = result.filter(function(m) {
|
|
return !!m.ssrTransformResult;
|
|
});
|
|
return ssrModulesToInvalidate.length > 0 && (log.debug("invalidating modules " + ssrModulesToInvalidate.map(function(_0) {
|
|
return _0.id;
|
|
}).join(", ")), ssrModulesToInvalidate.forEach(function(moduleNode) {
|
|
return server.moduleGraph.invalidateModule(moduleNode);
|
|
})), result.length > 0 && log.debug("handleHotUpdate for " + imbaRequest.id + " result: " + result.map(function(_0) {
|
|
return _0.id;
|
|
}).join(", ")), result;
|
|
}
|
|
function isCodeEqual(prev, next) {
|
|
return !prev && !next ? !0 : !prev && next || prev && !next ? !1 : prev === next;
|
|
}
|
|
function cssChanged(prev, next) {
|
|
return !isCodeEqual(prev == null ? void 0 : prev.code, next == null ? void 0 : next.code);
|
|
}
|
|
function jsChanged(prev, next, filename) {
|
|
let prevJs = prev == null ? void 0 : prev.code;
|
|
if (!prevJs)
|
|
return !0;
|
|
let i = prevJs.indexOf(`
|
|
/*__css_import__*/`);
|
|
prevJs = prevJs.replace(/^\/\/#\ssourceMapp(.*)$/mg, "").replace(`
|
|
|
|
/*__css_import__*/`, "/*__css_import__*/");
|
|
let nextJs = next == null ? void 0 : next.code, diff = Diff.diffChars(prevJs, nextJs), addedOrRemoved = [];
|
|
return diff.forEach(function(part) {
|
|
let color = part.added ? "\x1B[32m" : part.removed ? "\x1B[31m" : "\x1B[33m", what = part.added ? "part.added" : part.removed ? "part.removed" : "no change";
|
|
if (part.added || part.removed)
|
|
return addedOrRemoved.push({ color, what, value: part.value });
|
|
}), !!addedOrRemoved.find(function(_0) {
|
|
return _0.value.replace(/\n/g, "") !== "";
|
|
});
|
|
}
|
|
|
|
// src/index.imba
|
|
import "url";
|
|
function imba(inlineOptions = {}) {
|
|
let name = "vite-plugin-imba", enforce = "pre", requestParser, compileImba, options, viteConfig, api = {}, resolvedImbaSSR, testΦ;
|
|
validateInlineOptions(inlineOptions);
|
|
let cache = new VitePluginImbaCache(), plugins = [];
|
|
async function config(config2, configEnv) {
|
|
process.env.DEBUG ? log.setLevel("debug") : config2.logLevel && log.setLevel(config2.logLevel), options = await preResolveOptions(inlineOptions, config2, configEnv);
|
|
let extraViteConfig = buildExtraViteConfig(options, config2);
|
|
return log.debug("additional vite config", extraViteConfig), testΦ = configEnv.mode === "test", extraViteConfig;
|
|
}
|
|
function configResolved(config2) {
|
|
return options = resolveOptions(options, config2), requestParser = buildIdParser(options), compileImba = createCompileImba(options), viteConfig = config2, api.options = options, log.debug("resolved options", options);
|
|
}
|
|
async function transform(code, id, opts) {
|
|
let ssr = !!(opts != null && opts.ssr), imbaRequest = requestParser(id, ssr);
|
|
if (!imbaRequest || imbaRequest.query.imba)
|
|
return;
|
|
let compiledData;
|
|
try {
|
|
compiledData = await compileImba(imbaRequest, code, options);
|
|
} catch (e) {
|
|
throw cache.setError(imbaRequest, e), toRollupError(e, options);
|
|
}
|
|
return logCompilerWarnings(
|
|
imbaRequest,
|
|
compiledData.compiled.warnings,
|
|
options
|
|
), cache.update(compiledData), compiledData.dependencies.length && options.server && compiledData.dependencies.forEach(function(d) {
|
|
return ensureWatchedFile(options.server.watcher, d, options.root);
|
|
}), log.debug("transform returns compiled js for " + imbaRequest.filename), {
|
|
...compiledData.compiled.js,
|
|
meta: {
|
|
vite: {
|
|
lang: compiledData.lang
|
|
}
|
|
}
|
|
};
|
|
}
|
|
function load(id, opts) {
|
|
let ssr = !!(opts != null && opts.ssr), imbaRequest = requestParser(id, !!ssr);
|
|
if (imbaRequest) {
|
|
let { filename, query } = imbaRequest;
|
|
if (query.imba && query.type === "style") {
|
|
let _css = cache.getCSS(imbaRequest);
|
|
if (_css)
|
|
return log.debug("load returns css for " + filename), _css;
|
|
console.log("cache empty: loading " + id);
|
|
}
|
|
if (viteConfig.assetsInclude(filename))
|
|
return log.debug("load returns raw content for " + filename), fs.readFileSync(filename, "utf-8");
|
|
}
|
|
}
|
|
function resolveId(importee, importer, opts) {
|
|
let ssr = !!(opts != null && opts.ssr) || options.ssr;
|
|
testΦ && (ssr = !1);
|
|
let imbaRequest = requestParser(importee, ssr);
|
|
if (imbaRequest != null && imbaRequest.query.imba)
|
|
return imbaRequest.query.type === "style" ? (log.debug("resolveId resolved virtual css module " + imbaRequest.cssId), imbaRequest.cssId) : (log.debug("resolveId resolved " + importee), importee);
|
|
if (ssr && importee === "imba")
|
|
return resolvedImbaSSR || (resolvedImbaSSR = this.resolve("imba/server", void 0, { skipSelf: !0 }).then(function(imbaSSR) {
|
|
return log.debug("resolved imba to imba/server"), imbaSSR;
|
|
})), resolvedImbaSSR;
|
|
try {
|
|
let resolved = resolveViaPackageJsonImba(importee, importer, cache);
|
|
if (resolved)
|
|
return log.debug("resolveId resolved $" + resolved + " via package.json imba field of " + importee), resolved;
|
|
} catch (e) {
|
|
return log.debug.once("error trying to resolve " + importee + " from " + importer + " via package.json imba field ", e);
|
|
}
|
|
}
|
|
function configureServer(server) {
|
|
return options.server = server, setupWatchers(options, cache, requestParser);
|
|
}
|
|
async function handleHotUpdate(ctx) {
|
|
if (!options.hot || !options.emitCss)
|
|
return;
|
|
let imbaRequest = requestParser(ctx.file, !1, ctx.timestamp);
|
|
if (imbaRequest)
|
|
try {
|
|
return await handleImbaHotUpdate(compileImba, ctx, imbaRequest, cache, options);
|
|
} catch (e) {
|
|
throw toRollupError(e, options);
|
|
}
|
|
}
|
|
return plugins.push(svgΞplugin()), plugins.push(
|
|
{
|
|
name: "vite-plugin-imba",
|
|
enforce: "pre",
|
|
api,
|
|
config,
|
|
configResolved,
|
|
transform,
|
|
load,
|
|
resolveId,
|
|
configureServer,
|
|
handleHotUpdate
|
|
}
|
|
), plugins;
|
|
}
|
|
export {
|
|
imba
|
|
};
|
|
//__FOOT__
|
|
|