UNPKG

@mega-apps/vue-addon-loader

Version:

Vue addon loader, for SFCs and components. You can use it for vue component online.

348 lines (347 loc) 11.6 kB
import { ParserPlugin as TBabelParserPlugin } from "@babel/parser"; /*** * --------------------------------------------------------------------------------------------------- */ export declare type TModuleCacheId = string; export interface ICache { get(key: string): Promise<string>; set(key: string, value: string): Promise<void>; } export interface IValueFactoryApi { preventCache(): void; } export declare type TValueFactoryCreate = (api: IValueFactoryApi) => Promise<any>; export interface IModuleExport { } export declare type Module = { exports: IModuleExport; }; /** * 抽象路径类型 * 它可以是一个简单的字符串或一个对象,如URL。 AbstractPath必须始终可转换为字符串。 */ export interface IAbstractPath { toString(): string; } /** * A PathContext represents a path (relPath) relative to a path (refPath) * Note that relPath is not necessary relative, but it is, relPath is relative to refPath. * * @example * * 示例: * refPath: /etc 绝对路径 * relPath ./config 相对路径 */ export interface IPathContext { /** reference path:参照路径 */ refPath: IAbstractPath; /** relative to @refPath:相对于 refPath 的相对路径 */ relPath: IAbstractPath; } /** relative to absolute module path resolution */ export declare type TPathResolveHandler = (pathContext: IPathContext) => IAbstractPath; /** * 内容数据格式类型 */ export declare type TContentData = string | ArrayBuffer; /** * 抽象文件对象模型 */ export interface IAbstractFile { /** The content data accessor (request data as text of binary)*/ getContentData: (asBinary?: Boolean) => Promise<TContentData> | TContentData; /** The content type (file extension name, eg. '.svg' ) */ type: string; } /** * Used by the library when it needs to handle a does not know how to handle a given file type (eg. `.json` files). * @param type The type of the file. It can be anything, but must be '.vue', '.js' or '.mjs' for vue, js and esm files. * @param getContentData The method to get the content data of a file (text or binary). see [[ File['getContentData'] ]] * @param path The path of the file * @param options The options * * * **example:** * * ```javascript * ... * ... * ``` */ export declare type TModuleHandler = (type: string, getContentData: IAbstractFile["getContentData"], path: IAbstractPath, options: ILoadModuleOptions) => Promise<IModuleExport | null>; export interface IResource { /** * 'abstract' unique id of the resource. * This id is used as the key of the [[Options.moduleCache]] */ id: TModuleCacheId; /** file path of the resource */ path: IAbstractPath; /** asynchronously get the content of the resource. Once you got the content, you can asynchronously get the data through the getContentData(asBinary) method. */ getContent: () => Promise<IAbstractFile>; } /** * 自定义块的回调函数 */ export declare type TCustomBlockCallback = (component: IModuleExport) => void; export interface ICustomBlock { type: string; content: string; attrs: Record<string, string | true>; } export interface ILoadingType<T> { promise: Promise<T>; } /** * 定义加载模块的Options */ export interface ILoadModuleOptions { /** * 模块缓存Map * Initial cache that will contain resolved dependencies. All new modules go here. * `vue` must initially be contained in this object. * [[moduleCache]] is mandatory and should be shared between options objects used for you application (note that you can also pass the same options object through multiple loadModule calls) * It is recommended to provide a prototype-less object (`Object.create(null)`) to avoid potential conflict with `Object` properties (constructor, __proto__, hasOwnProperty, ...). ​ * * See also [[options.loadModule]]. * * **example:** * ```javascript * ... * moduleCache: Object.assign(Object.create(null), { * vue: Vue, * }), * ... * ``` * */ moduleCache: Record<TModuleCacheId, ILoadingType<IModuleExport> | IModuleExport>; /** * 自定义分割符 * 用于统一解决不同内容的模板字符串 * Sets the delimiters used for text interpolation within the template. * Typically this is used to avoid conflicting with server-side frameworks that also use mustache syntax. * * ```javascript * ... * <script> * * // <!-- * const vueContent = ` * <template> Hello [[[[ who ]]]] !</template> * <script> * export default { * data() { * return { * who: 'world' * } * } * } * </script> * `; * // --> * * const options = { * moduleCache: { vue: Vue }, * getFileContent: () => vueContent, * addStyle: () => {}, * delimiters: ['[[[[', ']]]]'], * } * * const app = Vue.createApp(Vue.defineAsyncComponent(() => window['vue3-addon-loader'].loadModule('file.vue', options))); * app.mount(document.body); * * </script> * ... * ``` */ delimiters?: [string, string]; /** * 附加babel解析插件 * Additional babel parser plugins. [TBD] * * ```javascript * ... * ... * ``` */ additionalBabelParserPlugins?: TBabelParserPlugin[] | any[]; /** * 附加的babel转义插件 * Additional babel plugins. [TBD] * * ```javascript * ... * ... * ``` */ additionalBabelPlugins?: Record<string, any> | any; /** * 模块处理器。用于对不同类型的模块,进行处理 * Handle additional module types (eg. '.svg', '.json' ). see [[ModuleHandler]] * */ handleModule?: TModuleHandler; /** * 编译缓存 * [[get]]() and [[set]]() functions of this object are called when the lib needs to save or load already compiled code. get and set functions must return a `Promise` (or can be `async`). * Since compilation consume a lot of CPU, is is always a good idea to provide this object. * * **example:** * * In the following example, we cache the compiled code in the browser's local storage. Note that local storage is a limited place (usually 5MB). * Here we handle space limitation in a very basic way. * Maybe (not tested), the following libraries may help you to gain more space [pako](https://github.com/nodeca/pako), [lz-string](https://github.com/pieroxy/lz-string/) * ```javascript * ... * compiledCache: { * set(key, str) { * * // naive storage space management * for (;;) { * * try { * * // doc: https://developer.mozilla.org/en-US/docs/Web/API/Storage * window.localStorage.setItem(key, str); * break; * } catch(ex) { * // here we handle DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of 'XXX' exceeded the quota * * window.localStorage.removeItem(window.localStorage.key(0)); * } * } * }, * get(key) { * * return window.localStorage.getItem(key); * }, * }, * ... * ``` */ compiledCache?: ICache; /** * 路径解析处理函数 * Abstact path handling * */ pathResolve: TPathResolveHandler; /** * 获得文件内容 * Called by the library when it needs a file. * @param path The path of the file * @returns a Promise of the file content or an accessor to the file content that handles text or binary data * * **example:** * ```javascript * ... * async getFileContent(url) { * * const res = await fetch(url); * * if ( !res.ok ) * throw Object.assign(new Error(url+' '+res.statusText), { res }); * * return { * getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(), * } * * return await res.text(); * }, * ... * ``` */ getFileContent(path: IAbstractPath): Promise<IAbstractFile | TContentData>; /** * 附加样式数据 * Called by the library when CSS style must be added in the HTML document. * @param style The CSS style chunk * @param scopeId The scope ID of the CSS style chunk * @return * * **example:** * ```javascript * ... * addStyle(styleStr) { * * const style = document.createElement('style'); * style.textContent = styleStr; * const ref = document.head.getElementsByTagName('style')[0] || null; * document.head.insertBefore(style, ref); * }, * ... * ``` */ addStyle(style: string, scopeId: string | undefined): void; /** * 日志信息 * Called by the library when there is something to log (eg. scripts compilation errors, template compilation errors, template compilation tips, style compilation errors, ...) * @return * * ```javascript * ... * log(...args) { * * console.log(...args); * }, * ... * ``` * @param data */ log?(...data: any[]): void; /** * 加载模块函数 * Called when the lib requires a module. Do return `undefined` to let the library handle this. * @param path The path of the module. * @param options The options object. * @returns A Promise of the module or undefined * * [[moduleCache]] and [[Options.loadModule]] are strongly related, in the sense that the result of [[options.loadModule]] is stored in [[moduleCache]]. * However, [[options.loadModule]] is asynchronous and may help you to handle modules or components that are conditionally required (optional features, current languages, plugins, ...). * ```javascript * ... * loadModule(path, options) { * * if ( path === 'vue' ) * return Vue; * }, * ... * ``` */ loadModule?(path: IAbstractPath, options: ILoadModuleOptions): Promise<IModuleExport | undefined>; /** * 资源获取器 * Abstact resource handling * */ getResource(pathCx: IPathContext, options: ILoadModuleOptions): IResource; /** * 自定义块处理器 * Called for each custom block. * @returns A Promise of the module or undefined * * ```javascript * ... * customBlockHandler(block, filename, options) { * * if ( block.type !== 'i18n' ) * return; * * return (component) => { * * component.i18n = JSON.parse(block.content); * } * } * ... * ``` */ customBlockHandler?(block: ICustomBlock, filename: IAbstractPath, options: ILoadModuleOptions): Promise<TCustomBlockCallback | undefined>; } /** * 语言处理器处理函数 * * @return Promise<string>|string */ export declare type TLangProcessorHandler = (source: string, preprocessOptions?: any) => Promise<string> | string;