2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
import type { Plugin } from 'vite';
import { type FilterPattern } from '@rollup/pluginutils';
export interface ConsoleOptions {
method: string;
filename?: (filename: string) => string;
include?: FilterPattern;
exclude?: FilterPattern;
}
export declare function uniConsolePlugin(options: ConsoleOptions): Plugin;
+42
View File
@@ -0,0 +1,42 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniConsolePlugin = void 0;
const debug_1 = __importDefault(require("debug"));
const pluginutils_1 = require("@rollup/pluginutils");
const utils_1 = require("../utils");
const console_1 = require("../../logs/console");
const utils_2 = require("../../vite/utils/utils");
const debugConsole = (0, debug_1.default)('uni:console');
function uniConsolePlugin(options) {
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
let resolvedConfig;
return {
name: 'uni:console',
enforce: 'pre',
configResolved(config) {
resolvedConfig = config;
},
transform(code, id) {
if (!filter(id))
return null;
if (!(0, utils_1.isJsFile)(id))
return null;
let { filename } = (0, utils_1.parseVueRequest)(id);
if (options.filename) {
filename = options.filename(filename);
}
if (!filename) {
return null;
}
if (!code.includes('console.')) {
return null;
}
debugConsole(id);
return (0, console_1.rewriteConsoleExpr)(options.method, id, filename, code, (0, utils_2.withSourcemap)(resolvedConfig));
},
};
}
exports.uniConsolePlugin = uniConsolePlugin;
+10
View File
@@ -0,0 +1,10 @@
import type { WatchOptions } from 'chokidar';
import type { Plugin } from 'vite';
import { type FileWatcherOptions } from '../../watcher';
export type UniViteCopyPluginTarget = Omit<FileWatcherOptions, 'verbose'> & {
watchOptions?: WatchOptions;
};
export interface UniViteCopyPluginOptions {
targets: UniViteCopyPluginTarget[];
}
export declare function uniViteCopyPlugin({ targets, }: UniViteCopyPluginOptions): Plugin;
+58
View File
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniViteCopyPlugin = void 0;
const watcher_1 = require("../../watcher");
const messages_1 = require("../../messages");
const logs_1 = require("../../logs");
const uni_shared_1 = require("@dcloudio/uni-shared");
function uniViteCopyPlugin({ targets, }) {
let resolvedConfig;
let initialized = false;
let isFirstBuild = true;
return {
name: 'uni:copy',
apply: 'build',
configResolved(config) {
resolvedConfig = config;
},
async writeBundle() {
if (initialized) {
return;
}
if (resolvedConfig.build.ssr) {
return;
}
initialized = true;
const is_prod = process.env.NODE_ENV !== 'development' ||
process.env.UNI_AUTOMATOR_CONFIG;
const onChange = is_prod
? undefined
: (0, uni_shared_1.debounce)(() => {
if (isFirstBuild) {
return;
}
(0, logs_1.resetOutput)('log');
(0, logs_1.output)('log', messages_1.M['dev.watching.end']);
}, 100, { setTimeout, clearTimeout });
return new Promise((resolve) => {
Promise.all(targets.map(({ watchOptions, ...target }) => {
return new Promise((resolve) => {
new watcher_1.FileWatcher({
...target,
}).watch({
cwd: process.env.UNI_INPUT_DIR,
persistent: is_prod ? false : true,
...watchOptions,
}, () => {
resolve(void 0);
}, onChange);
});
})).then(() => resolve());
});
},
closeBundle() {
isFirstBuild = false;
},
};
}
exports.uniViteCopyPlugin = uniViteCopyPlugin;
@@ -0,0 +1,8 @@
import type { Plugin } from 'vite';
export declare function addScoped(code: string): string;
interface UniCssScopedPluginOptions {
filter: (id: string) => boolean;
}
export declare function uniRemoveCssScopedPlugin({ filter }?: UniCssScopedPluginOptions): Plugin;
export declare function uniCssScopedPlugin({ filter }?: UniCssScopedPluginOptions): Plugin;
export {};
+82
View File
@@ -0,0 +1,82 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniCssScopedPlugin = exports.uniRemoveCssScopedPlugin = exports.addScoped = void 0;
const path_1 = __importDefault(require("path"));
const debug_1 = __importDefault(require("debug"));
const constants_1 = require("../../constants");
const preprocess_1 = require("../../preprocess");
const parse_1 = require("../../vue/parse");
const utils_1 = require("../../utils");
const debugScoped = (0, debug_1.default)('uni:scoped');
const SCOPED_RE = /<style\s[^>]*scoped[^>]*>/i;
function addScoped(code) {
return code.replace(/(<style\b[^><]*)>/gi, (str, $1) => {
if ($1.includes('scoped')) {
return str;
}
return `${$1} scoped>`;
});
}
exports.addScoped = addScoped;
function removeScoped(code) {
if (!SCOPED_RE.test(code)) {
return code;
}
return code.replace(/(<style.*)scoped(.*>)/gi, '$1$2');
}
function uniRemoveCssScopedPlugin({ filter } = { filter: () => false }) {
return {
name: 'uni:css-remove-scoped',
enforce: 'pre',
transform(code, id) {
if (!filter(id))
return null;
debugScoped(id);
return {
code: removeScoped(code),
map: null,
};
},
};
}
exports.uniRemoveCssScopedPlugin = uniRemoveCssScopedPlugin;
function uniCssScopedPlugin({ filter } = { filter: () => false }) {
return {
name: 'uni:css-scoped',
enforce: 'pre',
transform(code, id) {
if (!filter(id))
return null;
debugScoped(id);
return {
code: addScoped(code),
map: null,
};
},
// 仅 h5
handleHotUpdate(ctx) {
if (!constants_1.EXTNAME_VUE.includes(path_1.default.extname(ctx.file))) {
return;
}
const scoped = !(0, utils_1.isAppVue)(ctx.file);
debugScoped('hmr', ctx.file);
const oldRead = ctx.read;
ctx.read = async () => {
let code = await oldRead();
// hotUpdate preprocess
if (code.includes('#endif')) {
code = (0, preprocess_1.preJs)((0, preprocess_1.preHtml)(code));
}
if (scoped) {
code = addScoped(code);
}
// 处理 block, wxs 等
return (0, parse_1.parseVueCode)(code).code;
};
},
};
}
exports.uniCssScopedPlugin = uniCssScopedPlugin;
@@ -0,0 +1,2 @@
import type { Plugin } from 'vite';
export declare function dynamicImportPolyfill(promise?: boolean): Plugin;
@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.dynamicImportPolyfill = void 0;
function dynamicImportPolyfill(promise = false) {
return {
name: 'dynamic-import-polyfill',
renderDynamicImport() {
return {
left: promise ? 'Promise.resolve(' : '(',
right: ')',
};
},
};
}
exports.dynamicImportPolyfill = dynamicImportPolyfill;
+8
View File
@@ -0,0 +1,8 @@
import type { Plugin } from 'vite';
import { type FilterPattern } from '@rollup/pluginutils';
interface UniEasycomPluginOptions {
include?: FilterPattern;
exclude?: FilterPattern;
}
export declare function uniEasycomPlugin(options: UniEasycomPluginOptions): Plugin;
export {};
+54
View File
@@ -0,0 +1,54 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniEasycomPlugin = void 0;
const path_1 = __importDefault(require("path"));
const shared_1 = require("@vue/shared");
const pluginutils_1 = require("@rollup/pluginutils");
const url_1 = require("../utils/url");
const constants_1 = require("../../constants");
const easycom_1 = require("../../easycom");
function uniEasycomPlugin(options) {
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
return {
name: 'uni:app-easycom',
transform(code, id) {
if (!filter(id)) {
return;
}
const { filename } = (0, url_1.parseVueRequest)(id);
if (!constants_1.EXTNAME_VUE_TEMPLATE.includes(path_1.default.extname(filename))) {
return;
}
if (!code.includes('_resolveComponent')) {
return;
}
let i = 0;
const importDeclarations = [];
code = code.replace(/_resolveComponent\("(.+?)"(, true)?\)/g, (str, name) => {
if (name && !name.startsWith('_')) {
const source = (0, easycom_1.matchEasycom)(name);
if (source) {
// 处理easycom组件优先级
return (0, easycom_1.genResolveEasycomCode)(importDeclarations, str, (0, easycom_1.addImportDeclaration)(importDeclarations, `__easycom_${i++}`, source, source.includes('uts-proxy')
? (0, shared_1.capitalize)((0, shared_1.camelize)(name)) + 'Component'
: source.includes('uni_helpers')
? (0, shared_1.capitalize)((0, shared_1.camelize)(name))
: ''));
}
}
return str;
});
if (importDeclarations.length) {
code = importDeclarations.join('') + code;
}
return {
code,
map: null,
};
},
};
}
exports.uniEasycomPlugin = uniEasycomPlugin;
+17
View File
@@ -0,0 +1,17 @@
export * from './cssScoped';
export * from './copy';
export * from './inject';
export * from './mainJs';
export * from './jsonJs';
export * from './console';
export * from './dynamicImportPolyfill';
export * from './uts/uni_modules';
export * from './uts/uvue';
export * from './uts/ext-api';
export * from './easycom';
export * from './json';
export * from './pre';
export { uniViteSfcSrcImportPlugin } from './sfc';
export { assetPlugin, parseAssets, getAssetHash } from './vitejs/plugins/asset';
export { isCSSRequest, cssPlugin, cssPostPlugin, minifyCSS, cssLangRE, commonjsProxyRE, rewriteScssReadFileSync, getCssDepMap, } from './vitejs/plugins/css';
export { generateCodeFrame, locToStartAndEnd, offsetToStartAndEnd, } from './vitejs/utils';
+49
View File
@@ -0,0 +1,49 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.offsetToStartAndEnd = exports.locToStartAndEnd = exports.generateCodeFrame = exports.getCssDepMap = exports.rewriteScssReadFileSync = exports.commonjsProxyRE = exports.cssLangRE = exports.minifyCSS = exports.cssPostPlugin = exports.cssPlugin = exports.isCSSRequest = exports.getAssetHash = exports.parseAssets = exports.assetPlugin = exports.uniViteSfcSrcImportPlugin = void 0;
__exportStar(require("./cssScoped"), exports);
__exportStar(require("./copy"), exports);
__exportStar(require("./inject"), exports);
__exportStar(require("./mainJs"), exports);
__exportStar(require("./jsonJs"), exports);
__exportStar(require("./console"), exports);
__exportStar(require("./dynamicImportPolyfill"), exports);
__exportStar(require("./uts/uni_modules"), exports);
__exportStar(require("./uts/uvue"), exports);
__exportStar(require("./uts/ext-api"), exports);
__exportStar(require("./easycom"), exports);
__exportStar(require("./json"), exports);
__exportStar(require("./pre"), exports);
var sfc_1 = require("./sfc");
Object.defineProperty(exports, "uniViteSfcSrcImportPlugin", { enumerable: true, get: function () { return sfc_1.uniViteSfcSrcImportPlugin; } });
var asset_1 = require("./vitejs/plugins/asset");
Object.defineProperty(exports, "assetPlugin", { enumerable: true, get: function () { return asset_1.assetPlugin; } });
Object.defineProperty(exports, "parseAssets", { enumerable: true, get: function () { return asset_1.parseAssets; } });
Object.defineProperty(exports, "getAssetHash", { enumerable: true, get: function () { return asset_1.getAssetHash; } });
var css_1 = require("./vitejs/plugins/css");
Object.defineProperty(exports, "isCSSRequest", { enumerable: true, get: function () { return css_1.isCSSRequest; } });
Object.defineProperty(exports, "cssPlugin", { enumerable: true, get: function () { return css_1.cssPlugin; } });
Object.defineProperty(exports, "cssPostPlugin", { enumerable: true, get: function () { return css_1.cssPostPlugin; } });
Object.defineProperty(exports, "minifyCSS", { enumerable: true, get: function () { return css_1.minifyCSS; } });
Object.defineProperty(exports, "cssLangRE", { enumerable: true, get: function () { return css_1.cssLangRE; } });
Object.defineProperty(exports, "commonjsProxyRE", { enumerable: true, get: function () { return css_1.commonjsProxyRE; } });
Object.defineProperty(exports, "rewriteScssReadFileSync", { enumerable: true, get: function () { return css_1.rewriteScssReadFileSync; } });
Object.defineProperty(exports, "getCssDepMap", { enumerable: true, get: function () { return css_1.getCssDepMap; } });
var utils_1 = require("./vitejs/utils");
Object.defineProperty(exports, "generateCodeFrame", { enumerable: true, get: function () { return utils_1.generateCodeFrame; } });
Object.defineProperty(exports, "locToStartAndEnd", { enumerable: true, get: function () { return utils_1.locToStartAndEnd; } });
Object.defineProperty(exports, "offsetToStartAndEnd", { enumerable: true, get: function () { return utils_1.offsetToStartAndEnd; } });
+13
View File
@@ -0,0 +1,13 @@
import type { Plugin } from 'vite';
import { type FilterPattern } from '@rollup/pluginutils';
type Injectment = string | [string, string];
export interface InjectOptions {
enforce?: 'pre' | 'post';
sourceMap?: boolean;
callback?: (imports: Map<any, any>, mod: [string, string]) => void;
include?: FilterPattern;
exclude?: FilterPattern;
[str: string]: Injectment | FilterPattern | Boolean | Function | undefined;
}
export declare function uniViteInjectPlugin(name: string, options: InjectOptions): Plugin;
export {};
+195
View File
@@ -0,0 +1,195 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniViteInjectPlugin = void 0;
const path_1 = require("path");
const debug_1 = __importDefault(require("debug"));
const pluginutils_1 = require("@rollup/pluginutils");
const estree_walker_1 = require("estree-walker");
const shared_1 = require("@vue/shared");
const magic_string_1 = __importDefault(require("magic-string"));
const utils_1 = require("../utils");
const debugInject = (0, debug_1.default)('uni:inject');
// const debugInjectTry = debug('uni:inject-try')
function uniViteInjectPlugin(name, options) {
if (!options)
throw new Error('Missing options');
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
const modules = (0, shared_1.extend)({}, options);
delete modules.include;
delete modules.exclude;
delete modules.sourceMap;
delete modules.callback;
const reassignments = new Set();
const modulesMap = new Map();
const namespaceModulesMap = new Map();
Object.keys(modules).forEach((name) => {
if (name.endsWith('.')) {
namespaceModulesMap.set(name, modules[name]);
}
modulesMap.set(name, modules[name]);
});
const hasNamespace = namespaceModulesMap.size > 0;
// Fix paths on Windows
if (path_1.sep !== '/') {
normalizeModulesMap(modulesMap);
normalizeModulesMap(namespaceModulesMap);
}
const firstpass = new RegExp(`(?:${Array.from(modulesMap.keys()).map(escape).join('|')})`, 'g');
const sourceMap = options.sourceMap !== false;
const callback = options.callback;
return {
name,
// 确保在 commonjs 之后,否则会混合 es6 module 与 cjs 的代码,导致 commonjs 失效
enforce: options.enforce ?? 'post',
transform(code, id) {
if (!filter(id))
return null;
if (!(0, utils_1.isJsFile)(id))
return null;
// debugInjectTry(id)
if (code.search(firstpass) === -1)
return null;
if (path_1.sep !== '/')
id = id.split(path_1.sep).join('/');
const ast = this.parse(code);
const imports = new Set();
ast.body.forEach((node) => {
if (node.type === 'ImportDeclaration') {
node.specifiers.forEach((specifier) => {
imports.add(specifier.local.name);
});
}
});
// analyse scopes
let scope = (0, pluginutils_1.attachScopes)(ast, 'scope');
const magicString = new magic_string_1.default(code);
const newImports = new Map();
function handleReference(node, name, keypath, parent) {
let mod = modulesMap.get(keypath);
if (!mod && hasNamespace) {
const mods = keypath.split('.');
if (mods.length === 2) {
mod = namespaceModulesMap.get(mods[0] + '.');
if (mod) {
if ((0, shared_1.isArray)(mod)) {
const testFn = mod[1];
if (testFn(mods[1])) {
mod = [mod[0], mods[1]];
}
else {
mod = undefined;
}
}
else {
mod = [mod, mods[1]];
}
}
}
}
if (mod && !imports.has(name) && !scope.contains(name)) {
if ((0, shared_1.isString)(mod))
mod = [mod, 'default'];
if (mod[0] === id)
return false;
const hash = `${keypath}:${mod[0]}:${mod[1]}`;
// 当 API 被覆盖定义后,不再摇树
if (reassignments.has(hash)) {
return false;
}
if (parent &&
(0, utils_1.isAssignmentExpression)(parent) &&
parent.left === node) {
reassignments.add(hash);
return false;
}
const importLocalName = name === keypath ? name : (0, pluginutils_1.makeLegalIdentifier)(`$inject_${keypath}`);
if (!newImports.has(hash)) {
if (mod[1] === '*') {
newImports.set(hash, `import * as ${importLocalName} from '${mod[0]}';`);
}
else {
newImports.set(hash, `import { ${mod[1]} as ${importLocalName} } from '${mod[0]}';`);
callback && callback(newImports, mod);
}
}
if (name !== keypath) {
magicString.overwrite(node.start, node.end, importLocalName, {
storeName: true,
});
}
return true;
}
return false;
}
(0, estree_walker_1.walk)(ast, {
enter(node, parent) {
if (sourceMap) {
magicString.addSourcemapLocation(node.start);
magicString.addSourcemapLocation(node.end);
}
if (node.scope) {
scope = node.scope;
}
if ((0, utils_1.isProperty)(node) && node.shorthand) {
const { name } = node.key;
handleReference(node, name, name);
this.skip();
return;
}
if ((0, utils_1.isReference)(node, parent)) {
const { name, keypath } = flatten(node);
const handled = handleReference(node, name, keypath, parent);
if (handled) {
this.skip();
}
}
},
leave(node) {
if (node.scope) {
scope = scope.parent;
}
},
});
debugInject(id, newImports.size);
if (newImports.size === 0) {
return {
code,
// 不能返回 ast ,否则会导致代码不能被再次修改
// 比如 App.vue 中,console.log('uniCloud') 触发了 inject 检测,检测完,发现不需要
// 此时返回 ast,会导致 import { setupApp } from '@dcloudio/uni-h5' 不会被编译
// ast
map: null,
};
}
const importBlock = Array.from(newImports.values()).join('\n\n');
magicString.prepend(`${importBlock}\n\n`);
return {
code: magicString.toString(),
map: sourceMap ? magicString.generateMap({ hires: true }) : null,
};
},
};
}
exports.uniViteInjectPlugin = uniViteInjectPlugin;
const escape = (str) => str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
const flatten = (startNode) => {
const parts = [];
let node = startNode;
while ((0, utils_1.isMemberExpression)(node)) {
parts.unshift(node.property.name);
node = node.object;
}
const { name } = node;
parts.unshift(name);
return { name, keypath: parts.join('.') };
};
function normalizeModulesMap(modulesMap) {
modulesMap.forEach((mod, key) => {
modulesMap.set(key, (0, shared_1.isArray)(mod)
? [mod[0].split(path_1.sep).join('/'), mod[1]]
: mod.split(path_1.sep).join('/'));
});
}
+2
View File
@@ -0,0 +1,2 @@
import type { Plugin } from 'vite';
export declare function uniJsonPlugin(): Plugin;
+30
View File
@@ -0,0 +1,30 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniJsonPlugin = void 0;
const path_1 = __importDefault(require("path"));
const json_1 = require("../../json");
const preprocess_1 = require("../../preprocess");
const utils_1 = require("../utils");
function uniJsonPlugin() {
return {
name: 'uni:json',
enforce: 'pre',
transform(code, id) {
// 如果已经被其他插件处理过了,就不再处理,比如 commonjs 插件,ICAPRegistrar.json?commonjs-external
if (id.startsWith('\0')) {
return;
}
if (path_1.default.extname((0, utils_1.parseVueRequest)(id).filename) !== '.json') {
return;
}
return {
code: JSON.stringify((0, json_1.parseJson)((0, preprocess_1.preJson)(code)), null, 2),
map: null,
};
},
};
}
exports.uniJsonPlugin = uniJsonPlugin;
+3
View File
@@ -0,0 +1,3 @@
import type { CreateUniViteFilterPlugin } from '../utils/plugin';
export declare const defineUniPagesJsonPlugin: (createVitePlugin: CreateUniViteFilterPlugin) => import("vite").Plugin<any>;
export declare const defineUniManifestJsonPlugin: (createVitePlugin: CreateUniViteFilterPlugin) => import("vite").Plugin<any>;
+55
View File
@@ -0,0 +1,55 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineUniManifestJsonPlugin = exports.defineUniPagesJsonPlugin = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const constants_1 = require("../../constants");
const utils_1 = require("../../utils");
exports.defineUniPagesJsonPlugin = createDefineJsonJsPlugin('pages.json');
exports.defineUniManifestJsonPlugin = createDefineJsonJsPlugin('manifest.json');
function createDefineJsonJsPlugin(name) {
const JSON_JS = constants_1.JSON_JS_MAP[name];
return function (createVitePlugin) {
const opts = {
resolvedConfig: {},
filter(id) {
return id.endsWith(JSON_JS);
},
};
const plugin = createVitePlugin(opts);
const origLoad = plugin.load;
const origResolveId = plugin.resolveId;
const origConfigResolved = plugin.configResolved;
let jsonPath = '';
let jsonJsPath = '';
plugin.resolveId = function (id, importer, options) {
const res = origResolveId && origResolveId.call(this, id, importer, options);
if (res) {
return res;
}
if (id.endsWith(JSON_JS)) {
return jsonJsPath;
}
};
plugin.configResolved = function (config) {
opts.resolvedConfig = config;
jsonPath = (0, utils_1.normalizePath)(path_1.default.join(process.env.UNI_INPUT_DIR, name));
jsonJsPath = (0, utils_1.normalizePath)(path_1.default.join(process.env.UNI_INPUT_DIR, JSON_JS));
return origConfigResolved && origConfigResolved(config);
};
plugin.load = function (id, ssr) {
const res = origLoad && origLoad.call(this, id, ssr);
if (res) {
return res;
}
if (!opts.filter(id)) {
return;
}
return fs_1.default.readFileSync(jsonPath, 'utf8');
};
return plugin;
};
}
+2
View File
@@ -0,0 +1,2 @@
import type { CreateUniViteFilterPlugin } from '../utils/plugin';
export declare function defineUniMainJsPlugin(createUniMainJsPlugin: CreateUniViteFilterPlugin): import("vite").Plugin<any>;
+31
View File
@@ -0,0 +1,31 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defineUniMainJsPlugin = void 0;
const path_1 = __importDefault(require("path"));
const utils_1 = require("../../utils");
function defineUniMainJsPlugin(createUniMainJsPlugin) {
const opts = {
resolvedConfig: {},
filter(id) {
return id === mainJsPath || id === mainTsPath || id === mainUTsPath;
},
};
const plugin = createUniMainJsPlugin(opts);
const origConfigResolved = plugin.configResolved;
let mainJsPath = '';
let mainTsPath = '';
let mainUTsPath = '';
plugin.configResolved = function (config) {
opts.resolvedConfig = config;
const mainPath = (0, utils_1.normalizePath)(path_1.default.resolve(process.env.UNI_INPUT_DIR, 'main'));
mainJsPath = mainPath + '.js';
mainTsPath = mainPath + '.ts';
mainUTsPath = mainPath + '.uts';
return origConfigResolved && origConfigResolved(config);
};
return plugin;
}
exports.defineUniMainJsPlugin = defineUniMainJsPlugin;
+6
View File
@@ -0,0 +1,6 @@
import type { Plugin, ResolvedConfig } from 'vite';
import { type FilterPattern } from '@rollup/pluginutils';
export declare function uniPrePlugin(config: ResolvedConfig, options: {
include?: FilterPattern;
exclude?: FilterPattern;
}): Plugin;
+59
View File
@@ -0,0 +1,59 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniPrePlugin = void 0;
const path_1 = __importDefault(require("path"));
const debug_1 = __importDefault(require("debug"));
const pluginutils_1 = require("@rollup/pluginutils");
const constants_1 = require("../../constants");
const preprocess_1 = require("../../preprocess");
const utils_1 = require("../utils");
const debugPreJs = (0, debug_1.default)('uni:pre-js');
const debugPreHtml = (0, debug_1.default)('uni:pre-html');
// const debugPreJsTry = debug('uni:pre-js-try')
function uniPrePlugin(config, options) {
const isX = process.env.UNI_APP_X === 'true';
const PRE_JS_EXTNAME = ['.json', '.css']
.concat(isX ? constants_1.X_EXTNAME_VUE : constants_1.EXTNAME_VUE)
.concat(constants_1.EXTNAME_JS); // 因为 1.0 也会使用 uts uni_modules,所以 EXTNAME_JS 直接包含了 .uts 后缀
const PRE_HTML_EXTNAME = isX ? constants_1.X_EXTNAME_VUE : constants_1.EXTNAME_VUE;
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
const isNVue = config.nvue;
const preJsFile = isNVue ? preprocess_1.preNVueJs : preprocess_1.preJs;
const preHtmlFile = isNVue ? preprocess_1.preNVueHtml : preprocess_1.preHtml;
return {
name: 'uni:pre',
transform(code, id) {
if (!filter(id)) {
return;
}
const { filename, query } = (0, utils_1.parseVueRequest)(id);
const extname = path_1.default.extname(filename);
const isHtml = query.type === 'template' || PRE_HTML_EXTNAME.includes(extname);
const isJs = PRE_JS_EXTNAME.includes(extname);
const isPre = isHtml || isJs;
if (isPre) {
// debugPreJsTry(id)
}
const hasEndif = isPre && code.includes('#endif');
if (!hasEndif) {
return;
}
if (isHtml) {
code = preHtmlFile(code);
debugPreHtml(id);
}
if (isJs) {
code = preJsFile(code);
debugPreJs(id);
}
return {
code,
map: (0, utils_1.withSourcemap)(config) ? this.getCombinedSourcemap() : null,
};
},
};
}
exports.uniPrePlugin = uniPrePlugin;
+6
View File
@@ -0,0 +1,6 @@
import type { Plugin } from 'vite';
export declare function isSrcImport(code: string): boolean;
export declare function isSrcImportVue(code: string): boolean;
export declare function uniViteSfcSrcImportPlugin({ onlyVue }?: {
onlyVue: boolean;
}): Plugin;
+136
View File
@@ -0,0 +1,136 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniViteSfcSrcImportPlugin = exports.isSrcImportVue = exports.isSrcImport = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const magic_string_1 = __importDefault(require("magic-string"));
const vue_1 = require("../../vue");
const utils_1 = require("../utils");
const preprocess_1 = require("../../preprocess");
const SRC_IMPORT_RE = /<(template|script|style)[^>]*src\s*=\s*["']([^"']+)["'][^>]*>/;
const SRC_IMPORT_VUE_RE = /<(template|script|style)[^>]*src\s*=\s*["'](.*\.uvue|.*\.vue)["'][^>]*>/;
function isSrcImport(code) {
return SRC_IMPORT_RE.test(code);
}
exports.isSrcImport = isSrcImport;
function isSrcImportVue(code) {
return SRC_IMPORT_VUE_RE.test(code);
}
exports.isSrcImportVue = isSrcImportVue;
function uniViteSfcSrcImportPlugin({ onlyVue } = { onlyVue: true }) {
const { parse } = require('@vue/compiler-sfc');
const hasImport = onlyVue ? isSrcImportVue : isSrcImport;
const isValidSrc = onlyVue ? vue_1.isVueSfcFile : () => true;
return {
name: 'uni:sfc-src-import',
async transform(code, id) {
if (!(0, vue_1.isVueSfcFile)(id)) {
return;
}
if (!hasImport(code)) {
return;
}
const s = new magic_string_1.default(code);
const sourceMap = process.env.NODE_ENV === 'development';
const createDescriptor = (filename, code, from) => {
if (from === 'vue' || (0, vue_1.isVueSfcFile)(filename)) {
const { descriptor, errors } = parse(code, {
filename,
sourceMap,
});
errors.forEach((error) => this.error((0, utils_1.createRollupError)('', filename, error, code)));
return descriptor;
}
else {
const descriptor = {
filename,
source: fs_extra_1.default.readFileSync(filename, 'utf-8'),
template: null,
script: null,
scriptSetup: null,
styles: [],
customBlocks: [],
};
if (from === 'template') {
descriptor.template = {
content: descriptor.source,
};
}
else if (from === 'script') {
descriptor.script = {
content: descriptor.source,
};
}
else if (from === 'style') {
descriptor.styles = [
{
content: descriptor.source,
},
];
}
return descriptor;
}
};
const descriptor = createDescriptor(id, code, 'vue');
const cache = new Map();
const getSrcDescriptor = async (src, from) => {
if (cache.has(src)) {
return cache.get(src);
}
const resolved = await this.resolve(src, descriptor.filename);
if (resolved) {
const filename = resolved.id;
const srcDescriptor = createDescriptor(filename, (0, preprocess_1.preUVueJs)((0, preprocess_1.preUVueHtml)(fs_extra_1.default.readFileSync(filename, 'utf-8'))), from);
cache.set(src, srcDescriptor);
this.addWatchFile(filename);
return srcDescriptor;
}
};
if (descriptor.template?.src && isValidSrc(descriptor.template.src)) {
const srcDescriptor = await getSrcDescriptor(descriptor.template.src, 'template');
if (srcDescriptor && srcDescriptor.template?.content) {
overwriteContent(s, descriptor.template.loc, srcDescriptor.template.content);
}
}
if (descriptor.script?.src && isValidSrc(descriptor.script.src)) {
const srcDescriptor = await getSrcDescriptor(descriptor.script.src, 'script');
if (srcDescriptor && srcDescriptor.script?.content) {
overwriteContent(s, descriptor.script.loc, srcDescriptor.script.content);
}
}
for (const style of descriptor.styles) {
if (style.src && isValidSrc(style.src)) {
const srcDescriptor = await getSrcDescriptor(style.src, 'style');
if (srcDescriptor && srcDescriptor.styles[0]) {
overwriteContent(s, style.loc, srcDescriptor.styles[0].content);
}
}
}
if (!s.hasChanged()) {
return;
}
// 移除所有的 src 属性
const regex = /(<(template|script|style)[^>]*)src\s*=\s*["']([^"']+)["']([^>]*>)/g;
let match;
while ((match = regex.exec(code))) {
const [_, start, _tag, _src, end] = match;
s.overwrite(match.index, match.index + _.length, `${start}${end}`);
}
return {
code: s.toString(),
map: sourceMap ? s.generateMap({ hires: true }) : { mappings: '' },
};
},
};
}
exports.uniViteSfcSrcImportPlugin = uniViteSfcSrcImportPlugin;
function overwriteContent(s, loc, content) {
if (loc.start.offset === loc.end.offset) {
s.appendRight(loc.start.offset, content);
}
else {
s.overwrite(loc.start.offset, loc.end.offset, content);
}
}
@@ -0,0 +1,13 @@
import type { Plugin } from 'vite';
import { type Injects, parseUniExtApis } from '../../../uni_modules';
export declare const parseUniExtApisOnce: typeof parseUniExtApis;
export declare function uniUTSExtApiReplace(): Plugin;
/**
* { 'uni.getBatteryInfo': ['@/uni_modules/uni-getbatteryinfo/utssdk/web/index.uts','getBatteryInfo'] }
* { '@/uni_modules/uni-getbatteryinfo/utssdk/web/index.ts': [['getBatteryInfo', 'uni_getBatteryInfo']] }
* @param injects
*/
export declare function injectsToAutoImports(injects: Injects): {
from: string;
imports: [string, string][];
}[];
+80
View File
@@ -0,0 +1,80 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.injectsToAutoImports = exports.uniUTSExtApiReplace = exports.parseUniExtApisOnce = void 0;
const shared_1 = require("@vue/shared");
const uni_shared_1 = require("@dcloudio/uni-shared");
const vite_1 = __importDefault(require("unplugin-auto-import/vite"));
const uni_modules_1 = require("../../../uni_modules");
const url_1 = require("../../utils/url");
const escape = (str) => str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
exports.parseUniExtApisOnce = (0, uni_shared_1.once)(uni_modules_1.parseUniExtApis);
function uniUTSExtApiReplace() {
const injects = (0, exports.parseUniExtApisOnce)(true, process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE);
const injectApis = Object.keys(injects);
const firstPass = new RegExp(`(?:${injectApis.map(escape).join('|')})`, 'g');
return {
name: 'uni:uts-ext-api-replace',
configResolved(config) {
const index = config.plugins.findIndex((p) => p.name === 'uts');
if (index > -1) {
if (Object.keys(injects).length) {
// @ts-expect-error
config.plugins.splice(index, 0, (0, vite_1.default)({
include: [/\.[u]?ts$/, /\.[u]?vue/],
exclude: [/[\\/]\.git[\\/]/],
imports: injectsToAutoImports(injects),
dts: false,
}));
}
}
},
transform(code, id) {
if (!injectApis.length) {
return;
}
if (!(0, url_1.isJsFile)(id)) {
return;
}
if (code.search(firstPass) === -1) {
return;
}
injectApis.forEach((api) => {
code = code.replaceAll(api, api.replace('.', '_'));
});
return {
code,
map: { mappings: '' },
};
},
};
}
exports.uniUTSExtApiReplace = uniUTSExtApiReplace;
/**
* { 'uni.getBatteryInfo': ['@/uni_modules/uni-getbatteryinfo/utssdk/web/index.uts','getBatteryInfo'] }
* { '@/uni_modules/uni-getbatteryinfo/utssdk/web/index.ts': [['getBatteryInfo', 'uni_getBatteryInfo']] }
* @param injects
*/
function injectsToAutoImports(injects) {
const autoImports = {};
Object.keys(injects).forEach((api) => {
const options = injects[api];
if ((0, shared_1.isArray)(options) && options.length >= 2) {
const source = options[0];
const name = options[1];
if (!autoImports[source]) {
autoImports[source] = [];
}
autoImports[source].push([name, api.replace('.', '_')]);
}
});
return Object.keys(autoImports).map((source) => {
return {
from: source,
imports: autoImports[source],
};
});
}
exports.injectsToAutoImports = injectsToAutoImports;
@@ -0,0 +1,23 @@
import type { Plugin } from 'vite';
import type { SyncUniModulesFilePreprocessor } from '@dcloudio/uni-uts-v1';
export declare function rewriteUniModulesConsoleExpr(fileName: string, content: string): string;
export declare function createAppAndroidUniModulesSyncFilePreprocessorOnce(isX: boolean): SyncUniModulesFilePreprocessor;
export declare function createAppIosUniModulesSyncFilePreprocessorOnce(isX: boolean): SyncUniModulesFilePreprocessor;
export declare function createAppHarmonyUniModulesSyncFilePreprocessorOnce(isX: boolean): SyncUniModulesFilePreprocessor;
interface UniUTSPluginOptions {
x?: boolean;
extApis?: Record<string, [string, string]>;
isSingleThread?: boolean;
}
export declare function getCurrentCompiledUTSPlugins(): Set<string>;
export declare function getCurrentCompiledUTSProviders(): Set<string>;
export declare function uniUTSAppUniModulesPlugin(options?: UniUTSPluginOptions): Plugin;
export declare function buildUniExtApis(): Promise<void>;
export declare function resolveExtApiProvider(pkg: Record<string, any>): {
name?: string | undefined;
plugin?: string | undefined;
service: string;
servicePlugin: string;
} | undefined;
export declare function uniDecryptUniModulesPlugin(): Plugin;
export {};
@@ -0,0 +1,514 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniDecryptUniModulesPlugin = exports.resolveExtApiProvider = exports.buildUniExtApis = exports.uniUTSAppUniModulesPlugin = exports.getCurrentCompiledUTSProviders = exports.getCurrentCompiledUTSPlugins = exports.createAppHarmonyUniModulesSyncFilePreprocessorOnce = exports.createAppIosUniModulesSyncFilePreprocessorOnce = exports.createAppAndroidUniModulesSyncFilePreprocessorOnce = exports.rewriteUniModulesConsoleExpr = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const uni_shared_1 = require("@dcloudio/uni-shared");
const pluginutils_1 = require("@rollup/pluginutils");
const uts_1 = require("../../../uts");
const utils_1 = require("../../utils");
const uni_modules_1 = require("../../../uni_modules");
const uni_modules_cloud_1 = require("../../../uni_modules.cloud");
const utils_2 = require("../../../utils");
const json_1 = require("../../../json");
const fs_1 = require("../../../fs");
const context_1 = require("../../../preprocess/context");
const hbx_1 = require("../../../hbx");
const console_1 = require("../../../logs/console");
/* eslint-disable no-restricted-globals */
const { preprocess } = require('../../../../lib/preprocess');
function rewriteUniModulesConsoleExpr(fileName, content) {
// 仅开发模式补充console.log的at信息
if (process.env.NODE_ENV !== 'development') {
return content;
}
if (content.includes('console.')) {
return (0, console_1.rewriteConsoleExpr)('__f__', '', (0, utils_2.normalizePath)(path_1.default.relative(process.env.UNI_INPUT_DIR, fileName.split('?')[0])), content, false).code;
}
return content;
}
exports.rewriteUniModulesConsoleExpr = rewriteUniModulesConsoleExpr;
function createUniModulesSyncFilePreprocessor(platform, utsPlatform, isX) {
const { preVueContext, preUVueContext } = (0, context_1.initScopedPreContext)(platform, undefined, utsPlatform, isX);
const preContext = isX ? preUVueContext : preVueContext;
if (!isX) {
if (utsPlatform === 'app-android') {
preContext.APP_ANDROID = true;
}
if (utsPlatform === 'app-ios') {
preContext.APP_IOS = true;
}
if (utsPlatform === 'app-harmony') {
preContext.APP_HARMONY = true;
}
}
function preJs(jsCode) {
return preprocess(jsCode, preContext, { type: 'js' });
}
function preHtml(htmlCode) {
return preprocess(htmlCode, preContext, { type: 'html' });
}
return async (content, fileName) => {
const extname = path_1.default.extname(fileName);
if (extname === '.json') {
return (0, pluginutils_1.dataToEsm)(JSON.parse(preJs(content)), {
namedExports: true,
preferConst: true,
});
}
else if (extname === '.uts' || extname === '.ts') {
return replaceExtApiPages(rewriteUniModulesConsoleExpr(fileName, preJs(content)));
}
else if (extname === '.uvue' || extname === '.vue') {
return rewriteUniModulesConsoleExpr(fileName, preJs(preHtml(content)));
}
return content;
};
}
function replaceExtApiPages(code) {
// 定制实现
if (process.env.UNI_COMPILE_EXT_API_PAGES) {
const pages = JSON.parse(process.env.UNI_COMPILE_EXT_API_PAGES);
Object.keys(pages).forEach((page) => {
code = code.replaceAll(page, pages[page]);
});
}
return code;
}
function createAppAndroidUniModulesSyncFilePreprocessorOnce(isX) {
return isX
? createUniXAppAndroidUniModulesSyncFilePreprocessorOnce()
: createUniAppAndroidUniModulesSyncFilePreprocessorOnce();
}
exports.createAppAndroidUniModulesSyncFilePreprocessorOnce = createAppAndroidUniModulesSyncFilePreprocessorOnce;
function createAppIosUniModulesSyncFilePreprocessorOnce(isX) {
return isX
? createUniXAppIosUniModulesSyncFilePreprocessorOnce()
: createUniAppIosUniModulesSyncFilePreprocessorOnce();
}
exports.createAppIosUniModulesSyncFilePreprocessorOnce = createAppIosUniModulesSyncFilePreprocessorOnce;
function createAppHarmonyUniModulesSyncFilePreprocessorOnce(isX) {
return isX
? createUniXAppHarmonyUniModulesSyncFilePreprocessorOnce()
: createUniAppHarmonyUniModulesSyncFilePreprocessorOnce();
}
exports.createAppHarmonyUniModulesSyncFilePreprocessorOnce = createAppHarmonyUniModulesSyncFilePreprocessorOnce;
const createUniAppAndroidUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-android', false);
});
const createUniAppIosUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-ios', false);
});
const createUniAppHarmonyUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-harmony', false);
});
const createUniXAppAndroidUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-android', true);
});
const createUniXAppIosUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-ios', true);
});
const createUniXAppHarmonyUniModulesSyncFilePreprocessorOnce = (0, uni_shared_1.once)(() => {
return createUniModulesSyncFilePreprocessor('app', 'app-harmony', true);
});
const utsModuleCaches = new Map();
const utsPlugins = new Set();
const utsProviders = new Set();
function getCurrentCompiledUTSPlugins() {
return utsPlugins;
}
exports.getCurrentCompiledUTSPlugins = getCurrentCompiledUTSPlugins;
function getCurrentCompiledUTSProviders() {
return utsProviders;
}
exports.getCurrentCompiledUTSProviders = getCurrentCompiledUTSProviders;
let uniExtApiCompiler = async () => { };
function emptyCacheDir(platform) {
const uvueOutputDir = (0, uts_1.uvueOutDir)(platform);
const tscOutputDir = (0, uts_1.tscOutDir)(platform);
function emptyUVueDir() {
if (fs_extra_1.default.existsSync(uvueOutputDir)) {
(0, fs_1.emptyDir)(uvueOutputDir);
}
}
emptyUVueDir();
function emptyTscDir() {
if (fs_extra_1.default.existsSync(tscOutputDir)) {
(0, fs_1.emptyDir)(tscOutputDir);
}
}
emptyTscDir();
}
const emptyKotlinCacheDirOnce = (0, uni_shared_1.once)(() => {
emptyCacheDir('app-android');
});
const emptySwiftCacheDirOnce = (0, uni_shared_1.once)(() => {
emptyCacheDir('app-ios');
});
const emptyHarmonyCacheDirOnce = (0, uni_shared_1.once)(() => {
emptyCacheDir('app-harmony');
});
// 该插件仅限app-android、app-ios、app-harmony
function uniUTSAppUniModulesPlugin(options = {}) {
const isX = process.env.UNI_APP_X === 'true';
const inputDir = process.env.UNI_INPUT_DIR;
process.env.UNI_UTS_USING_ROLLUP = 'true';
const uniModulesDir = (0, utils_2.normalizePath)(path_1.default.resolve(inputDir, 'uni_modules'));
// 非 x 项目,非 HBuilderX
if (!isX && !(0, hbx_1.isInHBuilderX)()) {
try {
(0, uts_1.resolveUTSCompiler)(true);
}
catch (e) {
return {
name: 'uni:uts-uni_modules-placeholder',
apply: 'build',
enforce: 'pre',
};
}
}
const { createUniXKotlinCompilerOnce, createUniXSwiftCompilerOnce, createUniXArkTSCompilerOnce, syncUniModuleFilesByCompiler, resolveTscUniModuleIndexFileName, } = (0, uts_1.resolveUTSCompiler)();
const uniXKotlinCompiler = process.env.UNI_APP_X_TSC === 'true' &&
(process.env.UNI_UTS_PLATFORM === 'app-android' ||
process.env.UNI_UTS_PLATFORM === 'app')
? createUniXKotlinCompilerOnce()
: null;
const uniXSwiftCompiler = process.env.UNI_APP_X_TSC === 'true' &&
(process.env.UNI_UTS_PLATFORM === 'app-ios' ||
process.env.UNI_UTS_PLATFORM === 'app')
? createUniXSwiftCompilerOnce()
: null;
const uniXArkTSCompiler = process.env.UNI_APP_X_TSC === 'true' &&
process.env.UNI_UTS_PLATFORM === 'app-harmony'
? createUniXArkTSCompilerOnce()
: null;
if (uniXKotlinCompiler) {
emptyKotlinCacheDirOnce();
(0, uts_1.genUniExtApiDeclarationFileOnce)((0, uts_1.tscOutDir)('app-android'));
}
if (uniXSwiftCompiler) {
emptySwiftCacheDirOnce();
(0, uts_1.genUniExtApiDeclarationFileOnce)((0, uts_1.tscOutDir)('app-ios'));
}
if (uniXArkTSCompiler) {
emptyHarmonyCacheDirOnce();
(0, uts_1.genUniExtApiDeclarationFileOnce)((0, uts_1.tscOutDir)('app-harmony'));
}
const changedFiles = new Map();
const compilePlugin = async (pluginDir) => {
const pluginId = path_1.default.basename(pluginDir);
if (uniXKotlinCompiler) {
const platform = 'app-android';
await syncUniModuleFilesByCompiler(platform, uniXKotlinCompiler, pluginDir, createAppAndroidUniModulesSyncFilePreprocessorOnce(isX));
}
if (uniXSwiftCompiler) {
const platform = 'app-ios';
await syncUniModuleFilesByCompiler(platform, uniXSwiftCompiler, pluginDir, createAppIosUniModulesSyncFilePreprocessorOnce(isX));
}
if (uniXArkTSCompiler) {
const platform = 'app-harmony';
await syncUniModuleFilesByCompiler(platform, uniXArkTSCompiler, pluginDir, createAppHarmonyUniModulesSyncFilePreprocessorOnce(isX));
}
if (!utsPlugins.has(pluginId)) {
utsPlugins.add(pluginId);
if (uniXKotlinCompiler) {
const platform = 'app-android';
const indexFileName = resolveTscUniModuleIndexFileName(platform, pluginDir);
if (indexFileName) {
await uniXKotlinCompiler.addRootFile(indexFileName);
}
}
if (uniXSwiftCompiler) {
const platform = 'app-ios';
const indexFileName = resolveTscUniModuleIndexFileName(platform, pluginDir);
if (indexFileName) {
await uniXSwiftCompiler.addRootFile(indexFileName);
}
}
if (uniXArkTSCompiler) {
const platform = 'app-harmony';
const indexFileName = resolveTscUniModuleIndexFileName(platform, pluginDir);
if (indexFileName) {
await uniXArkTSCompiler.addRootFile(indexFileName);
}
}
}
// 处理uni_modules中的文件变更
const files = changedFiles.get(pluginId);
if (files) {
// 仅限watch模式是会生效
changedFiles.delete(pluginId);
if (uniXKotlinCompiler) {
await uniXKotlinCompiler.invalidate(files);
}
if (uniXSwiftCompiler) {
await uniXSwiftCompiler.invalidate(files);
}
if (uniXArkTSCompiler) {
await uniXArkTSCompiler.invalidate(files);
}
}
const pkgJson = require(path_1.default.join(pluginDir, 'package.json'));
const isExtApi = !!pkgJson.uni_modules?.['uni-ext-api'];
const extApiProvider = resolveExtApiProvider(pkgJson);
// 如果是 provider 扩展,需要判断 provider 的宿主插件是否在本地,在的话,自动导入该宿主插件包名
let uniExtApiProviderServicePlugin = '';
if (extApiProvider?.servicePlugin) {
if (fs_extra_1.default.existsSync(path_1.default.resolve(inputDir, 'uni_modules', extApiProvider.servicePlugin))) {
uniExtApiProviderServicePlugin = extApiProvider.servicePlugin;
}
}
const compiler = (0, uts_1.resolveUTSCompiler)();
// 处理依赖的 uts 插件
// TODO 当本地有ext-api时,也应该自动加入deps,不然uts内部使用了该api,也会导致编译失败
const deps = (0, uni_modules_1.parseUTSModuleDeps)(pkgJson.uni_modules?.dependencies || [], inputDir);
if (deps.length) {
for (const dep of deps) {
await compilePlugin(path_1.default.resolve(inputDir, 'uni_modules', dep));
}
}
if (process.env.UNI_PLATFORM === 'app-harmony') {
return compiler.compileArkTS(pluginDir, {
isX: !!options.x,
isExtApi,
transform: {
uniExtApiProviderName: extApiProvider?.name,
uniExtApiProviderService: extApiProvider?.service,
uniExtApiProviderServicePlugin,
},
});
}
function filterAutoImports(autoImports, source) {
if (autoImports[source]) {
// 移除 source
return Object.keys(autoImports).reduce((imports, key) => {
if (key !== source) {
imports[key] = autoImports[key];
}
return imports;
}, {});
}
return autoImports;
}
return compiler.compile(pluginDir, {
isX: !!options.x,
isSingleThread: !!options.isSingleThread,
isPlugin: true,
isExtApi,
extApis: options.extApis,
sourceMap: (0, utils_2.enableSourceMap)(),
uni_modules: deps,
transform: {
uniExtApiProviderName: extApiProvider?.name,
uniExtApiProviderService: extApiProvider?.service,
uniExtApiProviderServicePlugin,
},
async kotlinAutoImports() {
return (0, uts_1.initUTSKotlinAutoImportsOnce)().then((autoImports) => {
return filterAutoImports(autoImports, (0, uts_1.parseKotlinPackageWithPluginId)(pluginId, true));
});
},
async swiftAutoImports() {
return (0, uts_1.initUTSSwiftAutoImportsOnce)().then((autoImports) => {
return filterAutoImports(autoImports, (0, uts_1.parseSwiftPackageWithPluginId)(pluginId, true));
});
},
});
};
uniExtApiCompiler = async () => {
// 此方法为兜底方法,确保uni_modules中的所有插件都会编译,目前仅用于编译provider
// 获取 provider 扩展(编译所有uni)
const plugins = (0, uni_modules_1.getUniExtApiPlugins)().filter((provider) => !utsPlugins.has(provider.plugin));
for (const plugin of plugins) {
const pluginDir = path_1.default.resolve(inputDir, 'uni_modules', plugin.plugin);
// 如果是 app-js 环境
if (process.env.UNI_APP_X_UVUE_SCRIPT_ENGINE === 'js') {
if (fs_extra_1.default.existsSync(path_1.default.resolve(pluginDir, 'utssdk', 'app-js', 'index.uts'))) {
continue;
}
}
if (process.env.UNI_APP_X !== 'true' &&
process.env.UNI_PLATFORM === 'app-harmony') {
// uniExtApiCompiler本身是为X项目准备的,但是在app-harmony项目中也会调用
if (!fs_extra_1.default.existsSync(path_1.default.resolve(pluginDir, 'utssdk', 'app-harmony', 'index.uts'))) {
continue;
}
}
utsProviders.add(plugin.plugin);
const result = await compilePlugin(pluginDir);
if (result) {
// 时机不对,不能addWatch
// result.deps.forEach((dep) => {
// this.addWatchFile(dep)
// })
}
}
};
return {
name: 'uni:uts-uni_modules',
apply: 'build',
enforce: 'pre',
async configResolved() {
if (uniXKotlinCompiler) {
await uniXKotlinCompiler.init();
}
if (uniXSwiftCompiler) {
await uniXSwiftCompiler.init();
}
if (uniXArkTSCompiler) {
await uniXArkTSCompiler.init();
}
},
resolveId(id, importer) {
if ((0, uts_1.isUTSProxy)(id) || (0, uts_1.isUniHelpers)(id)) {
return id;
}
// 加密插件缓存目录的css文件
if (id.endsWith('.css')) {
return;
}
const module = (0, uts_1.resolveUTSAppModule)(process.env.UNI_UTS_PLATFORM, id, importer ? path_1.default.dirname(importer) : inputDir, options.x !== true);
if (module) {
// app-js 会直接返回 index.uts 路径,不需要 uts-proxy
if (module.endsWith('.uts')) {
return module;
}
// prefix the polyfill id with \0 to tell other plugins not to try to load or transform it
return module + '?uts-proxy';
}
},
load(id) {
if ((0, uts_1.isUTSProxy)(id)) {
return '';
}
},
async buildEnd() {
utsModuleCaches.clear();
changedFiles.clear();
if (process.env.NODE_ENV !== 'development' || !(0, utils_2.isNormalCompileTarget)()) {
if (uniXKotlinCompiler) {
await uniXKotlinCompiler.close();
}
if (uniXSwiftCompiler) {
await uniXSwiftCompiler.close();
}
}
},
watchChange(fileName, change) {
if (uniXKotlinCompiler || uniXSwiftCompiler || uniXArkTSCompiler) {
fileName = (0, utils_2.normalizePath)(fileName);
if (fileName.startsWith(uniModulesDir)) {
// 仅处理uni_modules中的文件
const plugin = fileName.slice(uniModulesDir.length + 1).split('/')[0];
if (utsPlugins.has(plugin)) {
const changeFile = { fileName, event: change.event };
if (!changedFiles.has(plugin)) {
changedFiles.set(plugin, [changeFile]);
}
else {
changedFiles.get(plugin).push(changeFile);
}
}
}
}
},
async transform(_, id, opts) {
if (opts && opts.ssr) {
return;
}
if (!(0, uts_1.isUTSProxy)(id)) {
return;
}
const { filename } = (0, utils_1.parseVueRequest)(id.replace('\0', ''));
// 当 vue 和 nvue 均引用了相同 uts 插件,解决两套编译器会编译两次 uts 插件的问题
// 通过缓存,保证同一个 uts 插件只编译一次
const pluginDir = (0, utils_2.normalizePath)(filename);
if (utsModuleCaches.get(pluginDir)) {
return utsModuleCaches.get(pluginDir)().then((result) => {
if (result) {
result.deps.forEach((dep) => {
this.addWatchFile(dep);
});
return {
code: result.code,
map: null,
syntheticNamedExports: result.encrypt,
meta: result.meta,
};
}
});
}
const compile = (0, uni_shared_1.once)(() => {
return compilePlugin(pluginDir);
});
utsModuleCaches.set(pluginDir, compile);
const result = await compile();
if (result) {
result.deps.forEach((dep) => {
this.addWatchFile(dep);
});
return {
code: result.code,
map: null,
syntheticNamedExports: result.encrypt,
meta: result.meta,
};
}
},
};
}
exports.uniUTSAppUniModulesPlugin = uniUTSAppUniModulesPlugin;
async function buildUniExtApis() {
await uniExtApiCompiler();
}
exports.buildUniExtApis = buildUniExtApis;
function resolveExtApiProvider(pkg) {
const provider = pkg.uni_modules?.['uni-ext-api']?.provider;
if (provider?.service) {
if (provider.name && !provider.servicePlugin) {
provider.servicePlugin = 'uni-' + provider.service;
}
return provider;
}
}
exports.resolveExtApiProvider = resolveExtApiProvider;
function uniDecryptUniModulesPlugin() {
const inputDir = process.env.UNI_INPUT_DIR;
const isX = process.env.UNI_APP_X === 'true';
return {
name: 'uni:uni_modules-d',
enforce: 'pre',
async configResolved() {
if (isX && (0, utils_2.isNormalCompileTarget)()) {
const manifest = (0, json_1.parseManifestJsonOnce)(inputDir);
await (0, uni_modules_cloud_1.checkEncryptUniModules)(inputDir, {
mode: process.env.NODE_ENV !== 'development'
? 'production'
: 'development',
packType: process.env.UNI_APP_PACK_TYPE ||
(process.env.NODE_ENV !== 'development' ? 'release' : 'debug'),
compilerVersion: process.env.UNI_COMPILER_VERSION,
appid: manifest.appid,
appname: manifest.name,
platform: process.env.UNI_UTS_PLATFORM,
'uni-app-x': isX,
});
}
},
resolveId(id) {
if ((0, uts_1.isUTSProxy)(id) || (0, uts_1.isUniHelpers)(id)) {
return id;
}
if (isX && (0, utils_2.isNormalCompileTarget)() && !id.endsWith('.css')) {
const resolvedId = (0, uni_modules_cloud_1.resolveEncryptUniModule)(id, process.env.UNI_UTS_PLATFORM, process.env.UNI_APP_X === 'true');
if (resolvedId) {
return resolvedId;
}
}
},
};
}
exports.uniDecryptUniModulesPlugin = uniDecryptUniModulesPlugin;
@@ -0,0 +1,2 @@
import type { Plugin } from 'vite';
export declare function uniUTSUVueJavaScriptPlugin(options?: {}): Plugin;
+36
View File
@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniUTSUVueJavaScriptPlugin = void 0;
const vue_1 = require("../../../vue");
function uniUTSUVueJavaScriptPlugin(options = {}) {
process.env.UNI_UTS_USING_ROLLUP = 'true';
return {
name: 'uni:uts-uvue',
enforce: 'pre',
configResolved(config) {
// 移除自带的 esbuild 处理 ts 文件
const index = config.plugins.findIndex((p) => p.name === 'vite:esbuild');
if (index > -1) {
// @ts-expect-error
config.plugins.splice(index, 1);
}
},
transform(code, id) {
if (!(0, vue_1.isVueSfcFile)(id)) {
return;
}
return {
code: code.replace(/<script([^>]*)>/gi, (match, attributes) => {
// 如果 <script> 标签中没有 lang 属性,添加 lang="uts"
if (!/lang=["']?[^"']*["']?/.test(attributes)) {
return `<script${attributes} lang="uts">`;
}
// 否则,将现有的 lang 属性替换为 lang="uts"
return match.replace(/lang=["']?ts["']?/, 'lang="uts"');
}),
map: { mappings: '' },
};
},
};
}
exports.uniUTSUVueJavaScriptPlugin = uniUTSUVueJavaScriptPlugin;
@@ -0,0 +1 @@
export declare function emptyCssComments(raw: string): string;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.emptyCssComments = void 0;
const utils_1 = require("./utils");
const blankReplacer = (s) => ' '.repeat(s.length);
function emptyCssComments(raw) {
return raw.replace(utils_1.multilineCommentsRE, blankReplacer);
}
exports.emptyCssComments = emptyCssComments;
@@ -0,0 +1 @@
export type { ResolvedConfig } from 'vite';
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts
*/
/**
* Prefix for resolved fs paths, since windows paths may not be valid as URLs.
*/
export declare const FS_PREFIX = "/@fs/";
export declare const CLIENT_PUBLIC_PATH = "/@vite/client";
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CLIENT_PUBLIC_PATH = exports.FS_PREFIX = void 0;
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts
*/
/**
* Prefix for resolved fs paths, since windows paths may not be valid as URLs.
*/
exports.FS_PREFIX = `/@fs/`;
exports.CLIENT_PUBLIC_PATH = `/@vite/client`;
@@ -0,0 +1 @@
export type { ResolveFn, ViteDevServer } from 'vite';
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
export type { Plugin } from 'vite';
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,43 @@
/// <reference types="node" />
import type { OutputOptions, PluginContext, RenderedChunk } from 'rollup';
import type { Plugin } from '../plugin';
import type { ResolvedConfig } from '../config';
export declare const assetUrlRE: RegExp;
export declare const chunkToEmittedAssetsMap: WeakMap<RenderedChunk, Set<string>>;
/**
* Also supports loading plain strings with import text from './foo.txt?raw'
*/
export declare function assetPlugin(config: ResolvedConfig, options?: {
isAndroidX?: boolean;
}): Plugin;
export declare function parseAssets(config: ResolvedConfig, code: string): string;
export declare function registerAssetToChunk(chunk: RenderedChunk, file: string): void;
export declare function checkPublicFile(url: string, { publicDir }: ResolvedConfig): string | undefined;
export declare function fileToUrl(id: string, config: ResolvedConfig, ctx: PluginContext, canInline: boolean | undefined, isStaticFile: (file: string) => boolean): string;
export declare function getAssetFilename(hash: string, config: ResolvedConfig): string | undefined;
/**
* converts the source filepath of the asset to the output filename based on the assetFileNames option. \
* this function imitates the behavior of rollup.js. \
* https://rollupjs.org/guide/en/#outputassetfilenames
*
* @example
* ```ts
* const content = Buffer.from('text');
* const fileName = assetFileNamesToFileName(
* 'assets/[name].[hash][extname]',
* '/path/to/file.txt',
* getAssetHash(content),
* content
* )
* // fileName: 'assets/file.982d9e3e.txt'
* ```
*
* @param assetFileNames filename pattern. e.g. `'assets/[name].[hash][extname]'`
* @param file filepath of the asset
* @param contentHash hash of the asset. used for `'[hash]'` placeholder
* @param content content of the asset. passed to `assetFileNames` if `assetFileNames` is a function
* @returns output filename
*/
export declare function assetFileNamesToFileName(assetFileNames: Exclude<OutputOptions['assetFileNames'], undefined>, file: string, contentHash: string, content: string | Buffer): string;
export declare function getAssetHash(content: Buffer | string): string;
export declare function urlToBuiltUrl(url: string, importer: string, config: ResolvedConfig, pluginContext: PluginContext, isStaticFile: (file: string) => boolean): string;
@@ -0,0 +1,340 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.urlToBuiltUrl = exports.getAssetHash = exports.assetFileNamesToFileName = exports.getAssetFilename = exports.fileToUrl = exports.checkPublicFile = exports.registerAssetToChunk = exports.parseAssets = exports.assetPlugin = exports.chunkToEmittedAssetsMap = exports.assetUrlRE = void 0;
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const lite_1 = __importDefault(require("mime/lite"));
const fs_extra_1 = __importStar(require("fs-extra"));
const magic_string_1 = __importDefault(require("magic-string"));
const crypto_1 = require("crypto");
const shared_1 = require("@vue/shared");
const utils_1 = require("../utils");
const utils_2 = require("../../../../vite/utils/utils");
const utils_3 = require("../../../../utils");
const static_1 = require("./static");
exports.assetUrlRE = /__VITE_ASSET__([a-z\d]{8})__(?:\$_(.*?)__)?/g;
const rawRE = /(\?|&)raw(?:&|$)/;
const urlRE = /(\?|&)url(?:&|$)/;
exports.chunkToEmittedAssetsMap = new WeakMap();
const assetCache = new WeakMap();
const assetHashToFilenameMap = new WeakMap();
// save hashes of the files that has been emitted in build watch
const emittedHashMap = new WeakMap();
/**
* Also supports loading plain strings with import text from './foo.txt?raw'
*/
function assetPlugin(config, options) {
// assetHashToFilenameMap initialization in buildStart causes getAssetFilename to return undefined
assetHashToFilenameMap.set(config, new Map());
return {
name: 'vite:asset',
buildStart() {
assetCache.set(config, [new Map(), new Map()]);
emittedHashMap.set(config, new Set());
},
resolveId(id) {
if (!config.assetsInclude((0, utils_1.cleanUrl)(id))) {
return;
}
// imports to absolute urls pointing to files in /public
// will fail to resolve in the main resolver. handle them here.
const publicFile = checkPublicFile(id, config);
if (publicFile) {
return id;
}
},
async load(id) {
if (id.startsWith('\0')) {
// Rollup convention, this id should be handled by the
// plugin that marked it with \0
return;
}
// raw requests, read from disk
if (rawRE.test(id)) {
const file = checkPublicFile(id, config) || (0, utils_1.cleanUrl)(id);
// raw query, read file and return as string
return `export default ${JSON.stringify(await fs_extra_1.promises.readFile(file, 'utf-8'))}`;
}
if (!config.assetsInclude((0, utils_1.cleanUrl)(id)) && !urlRE.test(id)) {
return;
}
id = id.replace(urlRE, '$1').replace(/[\?&]$/, '');
const url = await fileToUrl(id, config, options?.isAndroidX
? {
emitFile(emittedFile) {
// 直接写入目标目录
fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, emittedFile.fileName), emittedFile.source);
},
}
: this, false, (0, static_1.getIsStaticFile)());
if (options?.isAndroidX) {
this.emitFile({
type: 'asset',
fileName: (0, utils_3.normalizeEmitAssetFileName)((0, utils_3.normalizeNodeModules)(path_1.default.relative(process.env.UNI_INPUT_DIR, id))),
source: `export default ${JSON.stringify(parseAssets(config, url))}`,
});
}
return `export default ${JSON.stringify(url)}`;
},
renderChunk(code, chunk) {
let match;
let s;
exports.assetUrlRE.lastIndex = 0;
// Urls added with JS using e.g.
// imgElement.src = "__VITE_ASSET__5aa0ddc0__" are using quotes
// Urls added in CSS that is imported in JS end up like
// var inlined = ".inlined{color:green;background:url(__VITE_ASSET__5aa0ddc0__)}\n";
// In both cases, the wrapping should already be fine
while ((match = exports.assetUrlRE.exec(code))) {
s = s || (s = new magic_string_1.default(code));
const [full, hash, postfix = ''] = match;
// some internal plugins may still need to emit chunks (e.g. worker) so
// fallback to this.getFileName for that.
const file = getAssetFilename(hash, config) || this.getFileName(hash);
registerAssetToChunk(chunk, file);
const outputFilepath = config.base + file + postfix;
s.overwrite(match.index, match.index + full.length, outputFilepath);
}
if (s) {
return {
code: s.toString(),
map: (0, utils_2.withSourcemap)(config) ? s.generateMap({ hires: true }) : null,
};
}
else {
return null;
}
},
};
}
exports.assetPlugin = assetPlugin;
function parseAssets(config, code) {
let match;
let s;
exports.assetUrlRE.lastIndex = 0;
while ((match = exports.assetUrlRE.exec(code))) {
s = s || (s = new magic_string_1.default(code));
const [full, hash, postfix = ''] = match;
// some internal plugins may still need to emit chunks (e.g. worker) so
// fallback to this.getFileName for that.
const file = getAssetFilename(hash, config);
const outputFilepath = config.base + file + postfix;
s.overwrite(match.index, match.index + full.length, outputFilepath);
}
if (s) {
return s.toString();
}
return code;
}
exports.parseAssets = parseAssets;
function registerAssetToChunk(chunk, file) {
let emitted = exports.chunkToEmittedAssetsMap.get(chunk);
if (!emitted) {
emitted = new Set();
exports.chunkToEmittedAssetsMap.set(chunk, emitted);
}
emitted.add((0, utils_1.cleanUrl)(file));
}
exports.registerAssetToChunk = registerAssetToChunk;
function checkPublicFile(url, { publicDir }) {
// note if the file is in /public, the resolver would have returned it
// as-is so it's not going to be a fully resolved path.
if (!publicDir || !url.startsWith('/')) {
return;
}
const publicFile = path_1.default.join(publicDir, (0, utils_1.cleanUrl)(url));
if (fs_extra_1.default.existsSync(publicFile)) {
return publicFile;
}
else {
return;
}
}
exports.checkPublicFile = checkPublicFile;
function fileToUrl(id, config, ctx, canInline = false, isStaticFile) {
return fileToBuiltUrl(id, config, ctx, false, canInline, isStaticFile);
}
exports.fileToUrl = fileToUrl;
function getAssetFilename(hash, config) {
return assetHashToFilenameMap.get(config)?.get(hash);
}
exports.getAssetFilename = getAssetFilename;
/**
* converts the source filepath of the asset to the output filename based on the assetFileNames option. \
* this function imitates the behavior of rollup.js. \
* https://rollupjs.org/guide/en/#outputassetfilenames
*
* @example
* ```ts
* const content = Buffer.from('text');
* const fileName = assetFileNamesToFileName(
* 'assets/[name].[hash][extname]',
* '/path/to/file.txt',
* getAssetHash(content),
* content
* )
* // fileName: 'assets/file.982d9e3e.txt'
* ```
*
* @param assetFileNames filename pattern. e.g. `'assets/[name].[hash][extname]'`
* @param file filepath of the asset
* @param contentHash hash of the asset. used for `'[hash]'` placeholder
* @param content content of the asset. passed to `assetFileNames` if `assetFileNames` is a function
* @returns output filename
*/
function assetFileNamesToFileName(assetFileNames, file, contentHash, content) {
const basename = path_1.default.basename(file);
// placeholders for `assetFileNames`
// `hash` is slightly different from the rollup's one
const extname = path_1.default.extname(basename);
const ext = extname.substring(1);
const name = basename.slice(0, -extname.length);
const hash = contentHash;
if ((0, shared_1.isFunction)(assetFileNames)) {
assetFileNames = assetFileNames({
name: file,
originalFileName: null,
source: content,
type: 'asset',
});
if (!(0, shared_1.isString)(assetFileNames)) {
throw new TypeError('assetFileNames must return a string');
}
}
else if (!(0, shared_1.isString)(assetFileNames)) {
throw new TypeError('assetFileNames must be a string or a function');
}
const fileName = assetFileNames.replace(/\[\w+\]/g, (placeholder) => {
switch (placeholder) {
case '[ext]':
return ext;
case '[extname]':
return extname;
case '[hash]':
return hash;
case '[name]':
return sanitizeFileName(name);
}
throw new Error(`invalid placeholder ${placeholder} in assetFileNames "${assetFileNames}"`);
});
return fileName;
}
exports.assetFileNamesToFileName = assetFileNamesToFileName;
// taken from https://github.com/rollup/rollup/blob/a8647dac0fe46c86183be8596ef7de25bc5b4e4b/src/utils/sanitizeFileName.ts
// https://datatracker.ietf.org/doc/html/rfc2396
// eslint-disable-next-line no-control-regex
const INVALID_CHAR_REGEX = /[\x00-\x1F\x7F<>*#"{}|^[\]`;?:&=+$,]/g;
const DRIVE_LETTER_REGEX = /^[a-z]:/i;
function sanitizeFileName(name) {
const match = DRIVE_LETTER_REGEX.exec(name);
const driveLetter = match ? match[0] : '';
// A `:` is only allowed as part of a windows drive letter (ex: C:\foo)
// Otherwise, avoid them because they can refer to NTFS alternate data streams.
return (driveLetter +
name.substring(driveLetter.length).replace(INVALID_CHAR_REGEX, '_'));
}
/**
* Register an asset to be emitted as part of the bundle (if necessary)
* and returns the resolved public URL
*/
function fileToBuiltUrl(id, config, pluginContext, skipPublicCheck = false, canInline = false, isStaticFile) {
if (!skipPublicCheck && checkPublicFile(id, config)) {
return config.base + id.slice(1);
}
const [cacheForUrl, cacheForBase64] = assetCache.get(config);
const cache = canInline ? cacheForBase64 : cacheForUrl;
const cached = cache.get(id);
if (cached) {
return cached;
}
const file = (0, utils_1.cleanUrl)(id);
const content = fs_extra_1.default.readFileSync(file);
let url;
if (canInline && content.length < Number(config.build.assetsInlineLimit)) {
// base64 inlined as a string
url = `data:${lite_1.default.getType(file)};base64,${content.toString('base64')}`;
}
else {
const map = assetHashToFilenameMap.get(config);
const contentHash = getAssetHash(content);
const { search, hash } = (0, url_1.parse)(id);
const postfix = (search || '') + (hash || '');
const output = config.build?.rollupOptions?.output;
const defaultAssetFileNames = path_1.default.posix.join(config.build.assetsDir, '[name].[hash][extname]');
// Steps to determine which assetFileNames will be actually used.
// First, if output is an object or string, use assetFileNames in it.
// And a default assetFileNames as fallback.
let assetFileNames = (output && !Array.isArray(output) ? output.assetFileNames : undefined) ??
defaultAssetFileNames;
if (output && Array.isArray(output)) {
// Second, if output is an array, adopt assetFileNames in the first object.
assetFileNames = output[0].assetFileNames ?? assetFileNames;
}
const inputDir = (0, utils_1.normalizePath)(process.env.UNI_INPUT_DIR);
const isStatic = isStaticFile(file);
let fileName = file.startsWith(inputDir) && isStatic
? // 需要处理 HBuilderX 项目中的 node_modules 目录
(0, utils_3.normalizeNodeModules)(path_1.default.posix.relative(inputDir, file))
: assetFileNamesToFileName(assetFileNames, file, contentHash, content);
if (!map.has(contentHash)) {
map.set(contentHash, fileName);
}
if (!isStatic) {
const emittedSet = emittedHashMap.get(config);
if (!emittedSet.has(contentHash)) {
pluginContext.emitFile({
name: fileName,
fileName,
type: 'asset',
source: content,
});
emittedSet.add(contentHash);
}
}
url = `__VITE_ASSET__${contentHash}__${postfix ? `$_${postfix}__` : ``}`;
}
cache.set(id, url);
return url;
}
function getAssetHash(content) {
return (0, crypto_1.createHash)('sha256').update(content).digest('hex').slice(0, 8);
}
exports.getAssetHash = getAssetHash;
function urlToBuiltUrl(url, importer, config, pluginContext, isStaticFile) {
if (checkPublicFile(url, config)) {
return config.base + url.slice(1);
}
const file = url.startsWith('/')
? path_1.default.join(config.root, url)
: path_1.default.join(path_1.default.dirname(importer), url);
return fileToBuiltUrl(file, config, pluginContext,
// skip public check since we just did it above
true, false, isStaticFile);
}
exports.urlToBuiltUrl = urlToBuiltUrl;
@@ -0,0 +1,71 @@
import type { SFCDescriptor } from '@vue/compiler-sfc';
import type { ExistingRawSourceMap, RollupError } from 'rollup';
import type * as PostCSS from 'postcss';
import type { Plugin } from '../plugin';
import type { ResolvedConfig } from '../config';
import type { ResolveFn } from '../';
import * as Postcss from 'postcss';
export interface CSSOptions {
/**
* https://github.com/css-modules/postcss-modules
*/
modules?: CSSModulesOptions | false;
preprocessorOptions?: Record<string, any>;
postcss?: string | (Postcss.ProcessOptions & {
plugins?: Postcss.Plugin[];
});
}
export interface CSSModulesOptions {
getJSON?: (cssFileName: string, json: Record<string, string>, outputFileName: string) => void;
scopeBehaviour?: 'global' | 'local';
globalModulePaths?: RegExp[];
generateScopedName?: string | ((name: string, filename: string, css: string) => string);
hashPrefix?: string;
/**
* default: null
*/
localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly' | null;
}
export declare const cssLangRE: RegExp;
export declare const commonjsProxyRE: RegExp;
export declare const isCSSRequest: (request: string) => boolean;
export declare const isDirectCSSRequest: (request: string) => boolean;
export declare function getCssDepMap(): Map<string, Set<string>>;
/**
* Plugin applied before user plugins
*/
export declare function cssPlugin(config: ResolvedConfig, options?: {
isAndroidX: boolean;
getDescriptor?(filename: string): SFCDescriptor | undefined;
createUrlReplacer?: (resolve: ResolveFn) => CssUrlReplacer;
}): Plugin;
/**
* Plugin applied after user plugins
*/
export declare function cssPostPlugin(config: ResolvedConfig, { platform, isJsCode, preserveModules, chunkCssFilename, chunkCssCode, includeComponentCss, }: {
platform: UniApp.PLATFORM;
isJsCode?: boolean;
preserveModules?: boolean;
chunkCssFilename: (id: string) => string | void;
chunkCssCode: (filename: string, cssCode: string) => Promise<string> | string;
includeComponentCss?: boolean;
}): Plugin;
export declare function formatPostcssSourceMap(rawMap: ExistingRawSourceMap, file: string): ExistingRawSourceMap;
export type CssUrlReplacer = (url: string, importer?: string, source?: PostCSS.Source) => string | Promise<string>;
export declare const cssUrlRE: RegExp;
export declare const cssDataUriRE: RegExp;
export declare const importCssRE: RegExp;
export declare function minifyCSS(css: string, config: ResolvedConfig): Promise<string>;
export declare function hoistAtRules(css: string): Promise<string>;
export interface StylePreprocessorResults {
code: string;
map?: ExistingRawSourceMap | undefined;
additionalMap?: ExistingRawSourceMap | undefined;
errors: RollupError[];
deps: string[];
}
/**
* 重写 readFileSync
* 目前主要解决 scss 文件被 @import 的条件编译
*/
export declare function rewriteScssReadFileSync(): void;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
export declare function createIsStaticFile(): (relativeFile: string) => boolean;
export declare function getIsStaticFile(): (file: string) => boolean;
@@ -0,0 +1,40 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getIsStaticFile = exports.createIsStaticFile = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const utils_1 = require("../utils");
const json_1 = require("../../../../json/json");
const uniModulesStaticRe = /^uni_modules\/[^/]+\/static\//;
function createIsStaticFile() {
let subPackageStatics = [];
const pagesFilename = path_1.default.join(process.env.UNI_INPUT_DIR, 'pages.json');
if (fs_1.default.existsSync(pagesFilename)) {
const pagesJson = (0, json_1.parseJson)(fs_1.default.readFileSync(pagesFilename, 'utf8'), true);
subPackageStatics = (pagesJson.subPackages || pagesJson.subpackages || [])
.filter((subPackage) => subPackage.root)
.map((subPackage) => {
return (0, utils_1.normalizePath)(path_1.default.join(subPackage.root, 'static')) + '/';
});
}
return function isStaticFile(relativeFile) {
if (path_1.default.isAbsolute(relativeFile)) {
relativeFile = (0, utils_1.normalizePath)(path_1.default.relative(process.env.UNI_INPUT_DIR, relativeFile));
}
return (relativeFile.startsWith('static/') ||
uniModulesStaticRe.test(relativeFile) ||
subPackageStatics.some((s) => relativeFile.startsWith(s)));
};
}
exports.createIsStaticFile = createIsStaticFile;
let isStaticFile;
function getIsStaticFile() {
if (!isStaticFile) {
isStaticFile = createIsStaticFile();
}
return isStaticFile;
}
exports.getIsStaticFile = getIsStaticFile;
@@ -0,0 +1 @@
export type { ModuleNode } from 'vite';
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,53 @@
import type { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping';
import type { Position, SourceLocation } from '@vue/compiler-core';
import { LinesAndColumns } from 'lines-and-columns';
export declare function slash(p: string): string;
export declare const bareImportRE: RegExp;
export declare const deepImportRE: RegExp;
export declare const isWindows: boolean;
export declare function normalizePath(id: string): string;
export declare const queryRE: RegExp;
export declare const hashRE: RegExp;
export declare const cleanUrl: (url: string) => string;
export declare const externalRE: RegExp;
export declare const isExternalUrl: (url: string) => boolean;
export declare const dataUrlRE: RegExp;
export declare const isDataUrl: (url: string) => boolean;
export declare const multilineCommentsRE: RegExp;
export declare function asyncReplace(input: string, re: RegExp, replacer: (match: RegExpExecArray) => string | Promise<string>): Promise<string>;
export declare function isObject(value: unknown): value is Record<string, any>;
export declare function pad(source: string, n?: number): string;
export declare function offsetToStartAndEnd(source: string, startOffset: number, endOffset: number): SourceLocation;
export declare function offsetToLineColumn(source: string, offset: number): {
line: number;
column: number;
};
export declare function offsetToLineColumnByLines(lines: LinesAndColumns, offset: number): Position;
export declare function posToNumber(source: string, pos: number | {
line: number;
column: number;
}): number;
export declare function locToStartAndEnd(source: string, loc: {
start: {
line: number;
column: number;
};
end: {
line: number;
column: number;
};
}): {
start: number;
end: number | undefined;
};
export declare function generateCodeFrame(source: string, start?: number | {
line: number;
column: number;
}, end?: number): string;
interface ImageCandidate {
url: string;
descriptor: string;
}
export declare function processSrcSet(srcs: string, replacer: (arg: ImageCandidate) => Promise<string>): Promise<string>;
export declare function combineSourcemaps(filename: string, sourcemapList: Array<DecodedSourceMap | RawSourceMap>, excludeContent?: boolean): RawSourceMap;
export {};
+241
View File
@@ -0,0 +1,241 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineSourcemaps = exports.processSrcSet = exports.generateCodeFrame = exports.locToStartAndEnd = exports.posToNumber = exports.offsetToLineColumnByLines = exports.offsetToLineColumn = exports.offsetToStartAndEnd = exports.pad = exports.isObject = exports.asyncReplace = exports.multilineCommentsRE = exports.isDataUrl = exports.dataUrlRE = exports.isExternalUrl = exports.externalRE = exports.cleanUrl = exports.hashRE = exports.queryRE = exports.normalizePath = exports.isWindows = exports.deepImportRE = exports.bareImportRE = exports.slash = void 0;
/**
* https://github.com/vitejs/vite/blob/main/packages/vite/src/node/utils.ts
*/
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const remapping_1 = __importDefault(require("@ampproject/remapping"));
const lines_and_columns_1 = require("lines-and-columns");
function slash(p) {
return p.replace(/\\/g, '/');
}
exports.slash = slash;
exports.bareImportRE = /^[\w@](?!.*:\/\/)/;
exports.deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//;
exports.isWindows = os_1.default.platform() === 'win32';
function normalizePath(id) {
return path_1.default.posix.normalize(exports.isWindows ? slash(id) : id);
}
exports.normalizePath = normalizePath;
exports.queryRE = /\?.*$/s;
exports.hashRE = /#.*$/s;
const cleanUrl = (url) => url.replace(exports.hashRE, '').replace(exports.queryRE, '');
exports.cleanUrl = cleanUrl;
exports.externalRE = /^(https?:)?\/\//;
const isExternalUrl = (url) => exports.externalRE.test(url);
exports.isExternalUrl = isExternalUrl;
exports.dataUrlRE = /^\s*data:/i;
const isDataUrl = (url) => exports.dataUrlRE.test(url);
exports.isDataUrl = isDataUrl;
exports.multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//gm;
async function asyncReplace(input, re, replacer) {
let match;
let remaining = input;
let rewritten = '';
while ((match = re.exec(remaining))) {
rewritten += remaining.slice(0, match.index);
rewritten += await replacer(match);
remaining = remaining.slice(match.index + match[0].length);
}
rewritten += remaining;
return rewritten;
}
exports.asyncReplace = asyncReplace;
function isObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
exports.isObject = isObject;
const splitRE = /\r?\n/;
const range = 2;
function pad(source, n = 2) {
const lines = source.split(splitRE);
return lines.map((l) => ` `.repeat(n) + l).join(`\n`);
}
exports.pad = pad;
function offsetToStartAndEnd(source, startOffset, endOffset) {
const lines = new lines_and_columns_1.LinesAndColumns(source);
return {
start: offsetToLineColumnByLines(lines, startOffset),
end: offsetToLineColumnByLines(lines, endOffset),
source: '',
};
}
exports.offsetToStartAndEnd = offsetToStartAndEnd;
function offsetToLineColumn(source, offset) {
return offsetToLineColumnByLines(new lines_and_columns_1.LinesAndColumns(source), offset);
}
exports.offsetToLineColumn = offsetToLineColumn;
function offsetToLineColumnByLines(lines, offset) {
let location = lines.locationForIndex(offset);
if (!location) {
location = lines.locationForIndex(offset);
}
// lines-and-columns is 0-indexed while positions are 1-indexed
return { line: location.line + 1, column: location.column, offset: 0 };
}
exports.offsetToLineColumnByLines = offsetToLineColumnByLines;
function posToNumber(source, pos) {
if (typeof pos === 'number')
return pos;
return posToNumberByLines(new lines_and_columns_1.LinesAndColumns(source), pos.line, pos.column);
}
exports.posToNumber = posToNumber;
function posToNumberByLines(lines, line, column) {
// lines-and-columns is 0-indexed while positions are 1-indexed
return lines.indexForLocation({ line: line - 1, column }) || 0;
}
function locToStartAndEnd(source, loc) {
const lines = new lines_and_columns_1.LinesAndColumns(source);
const start = posToNumberByLines(lines, loc.start.line, loc.start.column);
const end = loc.end
? posToNumberByLines(lines, loc.end.line, loc.end.column)
: undefined;
return { start, end };
}
exports.locToStartAndEnd = locToStartAndEnd;
function generateCodeFrame(source, start = 0, end) {
start = posToNumber(source, start);
end = end || start;
// Split the content into individual lines but capture the newline sequence
// that separated each line. This is important because the actual sequence is
// needed to properly take into account the full line length for offset
// comparison
let lines = source.split(/(\r?\n)/);
// Separate the lines and newline sequences into separate arrays for easier referencing
const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);
lines = lines.filter((_, idx) => idx % 2 === 0);
let count = 0;
const res = [];
for (let i = 0; i < lines.length; i++) {
count +=
lines[i].length +
((newlineSequences[i] && newlineSequences[i].length) || 0);
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length)
continue;
const line = j + 1;
res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
const lineLength = lines[j].length;
const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
if (j === i) {
// push underline
const pad = start - (count - (lineLength + newLineSeqLength));
const length = Math.max(1, end > count ? lineLength - pad : end - start);
res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
}
else if (j > i) {
if (end > count) {
const length = Math.max(Math.min(end - count, lineLength), 1);
res.push(` | ` + '^'.repeat(length));
}
count += lineLength + newLineSeqLength;
}
}
break;
}
}
return res.join('\n');
}
exports.generateCodeFrame = generateCodeFrame;
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g;
const imageSetUrlRE = /^(?:[\w\-]+\(.*?\)|'.*?'|".*?"|\S*)/;
async function processSrcSet(srcs, replacer) {
const imageCandidates = srcs
.split(',')
.map((s) => {
const src = s.replace(escapedSpaceCharacters, ' ').trim();
const [url] = imageSetUrlRE.exec(src) || [];
return {
url: url,
descriptor: src?.slice(url.length).trim(),
};
})
.filter(({ url }) => !!url);
const ret = await Promise.all(imageCandidates.map(async ({ url, descriptor }) => {
return {
url: await replacer({ url, descriptor }),
descriptor,
};
}));
const url = ret.reduce((prev, { url, descriptor }, index) => {
descriptor = descriptor || '';
return (prev +=
url + ` ${descriptor}${index === ret.length - 1 ? '' : ', '}`);
}, '');
return url;
}
exports.processSrcSet = processSrcSet;
function escapeToLinuxLikePath(path) {
if (/^[A-Z]:/.test(path)) {
return path.replace(/^([A-Z]):\//, '/windows/$1/');
}
if (/^\/[^/]/.test(path)) {
return `/linux${path}`;
}
return path;
}
function unescapeToLinuxLikePath(path) {
if (path.startsWith('/linux/')) {
return path.slice('/linux'.length);
}
if (path.startsWith('/windows/')) {
return path.replace(/^\/windows\/([A-Z])\//, '$1:/');
}
return path;
}
// based on https://github.com/sveltejs/svelte/blob/abf11bb02b2afbd3e4cac509a0f70e318c306364/src/compiler/utils/mapped_code.ts#L221
const nullSourceMap = {
names: [],
sources: [],
mappings: '',
version: 3,
};
function combineSourcemaps(filename, sourcemapList, excludeContent = true) {
if (sourcemapList.length === 0 ||
sourcemapList.every((m) => m.sources.length === 0)) {
return { ...nullSourceMap };
}
// hack for parse broken with normalized absolute paths on windows (C:/path/to/something).
// escape them to linux like paths
// also avoid mutation here to prevent breaking plugin's using cache to generate sourcemaps like vue (see #7442)
sourcemapList = sourcemapList.map((sourcemap) => {
const newSourcemaps = { ...sourcemap };
newSourcemaps.sources = sourcemap.sources.map((source) => source ? escapeToLinuxLikePath(source) : null);
if (sourcemap.sourceRoot) {
newSourcemaps.sourceRoot = escapeToLinuxLikePath(sourcemap.sourceRoot);
}
return newSourcemaps;
});
const escapedFilename = escapeToLinuxLikePath(filename);
// We don't declare type here so we can convert/fake/map as RawSourceMap
let map; //: SourceMap
let mapIndex = 1;
const useArrayInterface = sourcemapList.slice(0, -1).find((m) => m.sources.length !== 1) === undefined;
if (useArrayInterface) {
map = (0, remapping_1.default)(sourcemapList, () => null, excludeContent);
}
else {
map = (0, remapping_1.default)(sourcemapList[0], function loader(sourcefile) {
if (sourcefile === escapedFilename && sourcemapList[mapIndex]) {
return sourcemapList[mapIndex++];
}
else {
return null;
}
}, excludeContent);
}
if (!map.file) {
delete map.file;
}
// unescape the previous hack
map.sources = map.sources.map((source) => source ? unescapeToLinuxLikePath(source) : source);
map.file = filename;
return map;
}
exports.combineSourcemaps = combineSourcemaps;