diff --git a/.github/workflows/issue-comment.yml b/.github/workflows/issue-comment.yml index 4214af706..26be43ac5 100644 --- a/.github/workflows/issue-comment.yml +++ b/.github/workflows/issue-comment.yml @@ -17,6 +17,7 @@ jobs: body: | Hello @${{ github.event.issue.user.login }}. We totally like your proposal/feedback, welcome to send us a Pull Request for it. Please be sure to submit compliant commit message, provide changelog/documentation/test cases, we will review it soon. We appreciate your effort in advance and looking forward to your contribution! 您好 @${{ github.event.issue.user.login }},我们完全同意您的提议/反馈,欢迎直接在此仓库创建一个 Pull Request 来解决这个问题。请务必填写符合规范的commit message,提供改动所需相应的 changelog、测试用例、文档等,我们会尽快进行 Review,提前感谢和期待您的贡献。 + - name: pls use issue template if: github.event.label.name == 'pls use issue template' uses: actions-cool/issues-helper@v2.0.0 @@ -26,6 +27,7 @@ jobs: body: | Hello @${{ github.event.issue.user.login }}. Please use the issue template to report. This issue will be closed. 您好 @${{ github.event.issue.user.login }},请使用 issue 模板反馈问题。该 issue 将要被关闭。 + - name: Need Reproduction if: github.event.label.name == 'Need Reproduction' uses: actions-cool/issues-helper@v2.0.0 @@ -35,3 +37,13 @@ jobs: body: | Hello @${{ github.event.issue.user.login }}. In order to facilitate location and troubleshooting, we need you to provide a realistic GitHub repository. 您好 @${{ github.event.issue.user.login }}, 为了方便定位和排查问题,我们需要您提供一个重现实例,请提供一个尽可能精简的 GitHub 仓库地址。 + + - name: fixed + if: github.event.label.name == 'fixed' + uses: actions-cool/issues-helper@v2.0.0 + with: + actions: 'create-comment, close-issue' + issue-number: ${{ github.event.issue.number }} + body: | + Hello @${{ github.event.issue.user.login }}. The issue you reported has been fixed. This issue will be closed. Thank you for your feedback. + 您好 @${{ github.event.issue.user.login }},您反馈的问题已修复,该 issue 将要被关闭,感谢反馈。 diff --git a/Contact.md b/Contact.md index 2f8c154a6..72332fee6 100644 --- a/Contact.md +++ b/Contact.md @@ -1,7 +1,15 @@ 欢迎小伙伴们加入micro-app微信群交流^ ^ -![IMG_8085](https://github.com/micro-zoe/micro-app/assets/14011130/f3447ec5-61dd-4c9c-a590-72478b608377) +![IMG_9187](https://github.com/user-attachments/assets/64d16edc-311a-46ea-8ce7-c6fcbe0651d3) + + + + + + + + diff --git a/README.md b/README.md index 2d9f4ddc8..84d760615 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- logo + logo

diff --git a/dev/children/react16/public/index.html b/dev/children/react16/public/index.html index 6a553b2f9..42f30cb22 100644 --- a/dev/children/react16/public/index.html +++ b/dev/children/react16/public/index.html @@ -40,7 +40,6 @@ color:#fff; } - diff --git a/dev/children/react16/src/index.css b/dev/children/react16/src/index.css index 337743648..193c4f4b2 100644 --- a/dev/children/react16/src/index.css +++ b/dev/children/react16/src/index.css @@ -56,5 +56,46 @@ code { } .test-back-var { - background-color: rgb(255 255 255 / var(--opacity)); + background-color: rgb(255 255 255 / var(--opacity));;;; +} + +/* @layer规则 */ +@layer theme, layout, utilities; + +.test-layer { + background-color: red; +} + +@layer utilities { + .padding-sm { + padding: 0.5rem; + } + + .padding-lg { + padding: 0.8rem; + } +} + +@layer framework { + @layer layout { + .test-layer { + .test-layer-nest { + color: red; + } + } + } +} + +// 错误1 +.basic-layout-side-menu{.ant-menu-item-group{&:last-child{border-bottom:none!important}}} + +// 错误2 +.chat-message-markdown-wrap{table{width:100%!important;border:1px solid #ccc}table td,table th{border-bottom:1px solid #ccc;border-right:1px solid #ccc;padding:5px 10px}table th{text-align:center;background:#dee8ee}table th:last-child{border-right:none}table td:last-child{border-right:none}table tr:last-child td{border-bottom:none}tr:nth-child(2n){background:#eff3f5}blockquote{display:block;border-left:8px solid #d0e5f2;padding:5px 10px;margin:10px 0;line-height:1.4;font-size:100%;background-color:#f1f1f1}ul,ol{margin:10px 0 10px 20px}} + +.nest-a { + .nest-b { + .nest-c { + color: red; + } + } } diff --git a/dev/children/react16/src/index.js b/dev/children/react16/src/index.js index 84f7f0413..b3c759871 100644 --- a/dev/children/react16/src/index.js +++ b/dev/children/react16/src/index.js @@ -8,20 +8,27 @@ import './ant-custom.css'; // 自定义antd class前缀 import './index.css'; import Router from './router'; import { Modal, notification, ConfigProvider } from 'antd'; -import subMicroApp from '@micro-zoe/micro-app'; +import microApp from '@micro-zoe/micro-app'; // import './flexible'; // import '@alifd/next/dist/next.css'; // import { atan2 } from 'mathjs' // 卡死 +// import './setImmediate.js' // 循环内嵌 -subMicroApp.start({ - tagName: 'micro-app-sub' +microApp.start({ + tagName: 'micro-app-react16' }) ConfigProvider.config({ prefixCls: 'react16', }) +console.log('react16 通过 window.microApp.getData 获取的初始化数据:', window.microApp?.getData()) + +// window.setImmediate(function () { +// alert(11111111) +// }) + // 数据监听 window.microApp?.addDataListener((data) => { console.log('react16 来自基座应用的数据', data) @@ -71,6 +78,7 @@ window.addEventListener('appstate-change', function (e) { // // 注册unmount函数,卸载时会自动执行 // window.unmount = () => { // ReactDOM.unmountComponentAtNode(document.getElementById('root')); +// // window.microApp. // console.log('微应用react16卸载了 -- 默认模式'); // } @@ -124,10 +132,10 @@ window.onunmount = () => { // // console.log(this) // }, false) -// document.onclick = function () { -// console.log(`子应用${window.__MICRO_APP_NAME__}内部的document.onclick绑定`) -// // console.log(this) -// } +document.onclick = function () { + console.log(`子应用${window.__MICRO_APP_NAME__}内部的document.onclick绑定`) + // console.log(this) +} // window.addEventListener('click', function () { // console.log(`子应用${window.__MICRO_APP_NAME__}内部的window.addEventListener绑定`) @@ -373,8 +381,8 @@ if (window.__MICRO_APP_ENVIRONMENT__) { // Vue是系统默认绑定变量 console.assert(window.Vue === undefined, 'window.Vue 应该为false') console.assert(('Vue' in window) === false, 'Vue in window 应该为false') - window.Vue = '自定义Vue' - console.assert(window.Vue === '自定义Vue', 'window.Vue 应该为自定义Vue') + window.Vue = '子应用内部自定义Vue' + console.assert(window.Vue === '子应用内部自定义Vue', 'window.Vue 应该为子应用内部自定义Vue') // ----------------------- scope相关---------------------结束 @@ -393,27 +401,28 @@ if (window.__MICRO_APP_ENVIRONMENT__) { } /* ---------------------- pureCreateElement & removeDomScope --------------------- */ -if (window.__MICRO_APP_ENVIRONMENT__) { - // const unBoundDom1 = window.microApp.pureCreateElement('div') - // unBoundDom1.innerHTML = 'unBoundDom1' - // document.body.appendChild(unBoundDom1) - - // /** - // * !!!! 注意removeDomScope(true)是异步清空的,这里会导致一个问题 - // * 执行removeDomScope(true)后再执行window.mount方法,会导致子应用初始化失败 - // */ - // window.microApp.removeDomScope(true) - // const unBoundDom2 = window.document.createElement('div') - // unBoundDom2.innerHTML = 'unBoundDom2' - // document.body.appendChild(unBoundDom2) - - // const unBoundDom3 = window.rawDocument.createElement('div') - // unBoundDom3.innerHTML = 'unBoundDom3' - // document.body.appendChild(unBoundDom3) - - // const dynamicSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') - // document.body.appendChild(dynamicSvg) -} +// if (window.__MICRO_APP_ENVIRONMENT__) { +// // pureCreateElement创建的元素无法拦截,插入到主应用body中 +// const unBoundDom1 = window.microApp.pureCreateElement('div') +// unBoundDom1.innerHTML = 'unBoundDom1' +// document.body.appendChild(unBoundDom1) + +// // 解除元素绑定,unBoundDom2插入到主应用body中 +// window.microApp.removeDomScope(true) // 解除元素绑定 +// const unBoundDom2 = window.document.createElement('div') +// unBoundDom2.innerHTML = 'unBoundDom2' +// document.body.appendChild(unBoundDom2) +// window.microApp.removeDomScope(false) // 恢复元素绑定 + +// // 元素绑定已经恢复,unBoundDom3插入到子应用 micro-app-body中 +// const unBoundDom3 = window.rawDocument.createElement('div') +// unBoundDom3.innerHTML = 'unBoundDom3' +// document.body.appendChild(unBoundDom3) + +// // 插入子应用 micro-app-body中 +// const dynamicSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') +// document.body.appendChild(dynamicSvg) +// } /* ---------------------- 获取原生window 和 document --------------------- */ @@ -429,15 +438,15 @@ if (window.__MICRO_APP_ENVIRONMENT__) { /* ---------------------- location 相关 --------------------- */ // 获取location信息 if (window.__MICRO_APP_ENVIRONMENT__) { - console.log(`${window.__MICRO_APP_NAME__} location.href`, location.href, window.rawWindow.location.href) - console.log(`${window.__MICRO_APP_NAME__} location.origin`, location.origin, window.rawWindow.location.origin) - console.log(`${window.__MICRO_APP_NAME__} location.host`, location.host, window.rawWindow.location.host) - console.log(`${window.__MICRO_APP_NAME__} location.hostname`, location.hostname, window.rawWindow.location.hostname) - console.log(`${window.__MICRO_APP_NAME__} location.port`, location.port, window.rawWindow.location.port) - console.log(`${window.__MICRO_APP_NAME__} location.protocol`, location.protocol, window.rawWindow.location.protocol) - console.log(`${window.__MICRO_APP_NAME__} location.pathname`, location.pathname, window.rawWindow.location.pathname) - console.log(`${window.__MICRO_APP_NAME__} location.hash`, location.hash, window.rawWindow.location.hash) - console.log(`${window.__MICRO_APP_NAME__} location.search`, location.search, window.rawWindow.location.search) + // console.log(`${window.__MICRO_APP_NAME__} location.href`, location.href, window.rawWindow.location.href) + // console.log(`${window.__MICRO_APP_NAME__} location.origin`, location.origin, window.rawWindow.location.origin) + // console.log(`${window.__MICRO_APP_NAME__} location.host`, location.host, window.rawWindow.location.host) + // console.log(`${window.__MICRO_APP_NAME__} location.hostname`, location.hostname, window.rawWindow.location.hostname) + // console.log(`${window.__MICRO_APP_NAME__} location.port`, location.port, window.rawWindow.location.port) + // console.log(`${window.__MICRO_APP_NAME__} location.protocol`, location.protocol, window.rawWindow.location.protocol) + // console.log(`${window.__MICRO_APP_NAME__} location.pathname`, location.pathname, window.rawWindow.location.pathname) + // console.log(`${window.__MICRO_APP_NAME__} location.hash`, location.hash, window.rawWindow.location.hash) + // console.log(`${window.__MICRO_APP_NAME__} location.search`, location.search, window.rawWindow.location.search) // 依次放开每个注释来,尽可能覆盖所有场景 setTimeout(() => { @@ -560,3 +569,49 @@ console.log('micro-app容器元素document.microAppElement', document.microAppEl // new Promise((resolve, reject) => { // throw 'promise 逃逸的错误' // }) + +/* ---------------------- 测试iframe document.body/head 获取元素 --------------------- */ +// if (window.__MICRO_APP_ENVIRONMENT__) { +// setTimeout(() => { +// // 场景1 querySelector: 不设置appName导致查询元素无法被拦截到子应用内部 +// console.log(`document.body.querySelector('#root') ==>`, document.body.querySelector('#root')) +// // console.log(`获取子应用root元素 -- document.querySelector`, document.querySelector('body').querySelector('#root')) +// console.log(`document.body.querySelector('script') ==>`, document.body.querySelector('script')) +// console.log(`document.head.querySelector('script') ==>`, document.head.querySelector('script')) + +// // 场景2 querySelectorAll: 不设置appName导致查询元素无法被拦截到子应用内部 +// console.log(`document.body.querySelectorAll('#root') ==>`, document.body.querySelectorAll('#root')) +// // console.log(`document.querySelector('body').querySelectorAll('#root') ==>`, document.querySelector('body').querySelectorAll('#root')) +// console.log(`document.body.querySelectorAll('script') ==>`, document.body.querySelectorAll('script')) +// console.log(`document.head.querySelectorAll('script') ==>`, document.head.querySelectorAll('script')) + +// console.log(`document.querySelector('script') ==>`, document.querySelector('script')) +// console.log(`document.querySelectorAll('script') ==>`, document.querySelectorAll('script')) + +// console.log(`document.getElementsByTagName('head')[0].querySelector('script') ==>`, document.getElementsByTagName('head')[0].querySelector('script')) +// console.log(`document.querySelector('body').querySelectorAll('script') ==>`, document.querySelector('body').querySelectorAll('script')) + + +// // 场景2:设置appName导致基座元素插入子应用 +// // window.microApp.removeDomScope(true) +// window.rawWindow.insertNodeFromBaseApp() // 调用主应用方法插入元素 +// // window.microApp.removeDomScope(false) +// }, 1000); +// } + +/* ---------------------- 测试 DocumentFragment --------------------- */ +// if (window.__MICRO_APP_ENVIRONMENT__) { +// setTimeout(() => { +// // window.microApp.removeDomScope(true) +// const a = document.createDocumentFragment() +// const b = document.createElement('script') +// // const b = window.microApp.pureCreateElement('script') +// b.src = 'http://127.0.0.1:8080/js/test.js' +// // a.appendChild(b) +// // a.append(b) +// a.prepend(b) +// // Element.prototype.appendChild.call(a, b) +// document.body.prepend(a) +// // window.microApp.removeDomScope(false) +// }, 1000); +// } diff --git a/dev/children/react16/src/pages/nest/nest.js b/dev/children/react16/src/pages/nest/nest.js index 063e7babd..4be8d71b9 100644 --- a/dev/children/react16/src/pages/nest/nest.js +++ b/dev/children/react16/src/pages/nest/nest.js @@ -27,10 +27,11 @@ function Vue2 () { { showLoading && } - hideLoading(false)} onMounted={() => hideLoading(false)} // shadowDOM @@ -38,7 +39,7 @@ function Vue2 () { inline // disableScopecss // disableSandbox - iframe + // iframe /> logo diff --git a/dev/children/react16/src/pages/page2/page2.js b/dev/children/react16/src/pages/page2/page2.js index 8f28347a6..0aabdee48 100644 --- a/dev/children/react16/src/pages/page2/page2.js +++ b/dev/children/react16/src/pages/page2/page2.js @@ -79,8 +79,8 @@ const Page2 = () => { const testClick = () => { console.log('click from test button') // window.dispatchEvent(new PopStateEvent('popstate', { state: window.history.state })) - window.location.href = '/micro-app/react16/page2' - window.history.go(-1) + // window.location.href = '/micro-app/react16/page2' + // window.history.go(-1) } const showDrawer = () => { diff --git a/dev/children/react16/src/setImmediate.js b/dev/children/react16/src/setImmediate.js new file mode 100644 index 000000000..c35b01000 --- /dev/null +++ b/dev/children/react16/src/setImmediate.js @@ -0,0 +1,194 @@ +/* eslint-disable */ +(function (global, undefined) { + "use strict"; + + if (global.setImmediate) { + delete global.setImmediate + } + + var nextHandle = 1; // Spec says greater than zero + var tasksByHandle = {}; + var currentlyRunningATask = false; + var doc = global.document; + var registerImmediate; + + function setImmediate(callback) { + console.log(333333333) + // Callback can either be a function or a string + if (typeof callback !== "function") { + callback = new Function("" + callback); + } + // Copy function arguments + var args = new Array(arguments.length - 1); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i + 1]; + } + // Store and register the task + var task = { callback: callback, args: args }; + tasksByHandle[nextHandle] = task; + registerImmediate(nextHandle); + return nextHandle++; + } + + function clearImmediate(handle) { + delete tasksByHandle[handle]; + } + + function run(task) { + var callback = task.callback; + var args = task.args; + switch (args.length) { + case 0: + callback(); + break; + case 1: + callback(args[0]); + break; + case 2: + callback(args[0], args[1]); + break; + case 3: + callback(args[0], args[1], args[2]); + break; + default: + callback.apply(undefined, args); + break; + } + } + + function runIfPresent(handle) { + // From the spec: "Wait until any invocations of this algorithm started before this one have completed." + // So if we're currently running a task, we'll need to delay this invocation. + if (currentlyRunningATask) { + // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a + // "too much recursion" error. + setTimeout(runIfPresent, 0, handle); + } else { + var task = tasksByHandle[handle]; + if (task) { + currentlyRunningATask = true; + try { + run(task); + } finally { + clearImmediate(handle); + currentlyRunningATask = false; + } + } + } + } + + function installNextTickImplementation() { + registerImmediate = function(handle) { + process.nextTick(function () { runIfPresent(handle); }); + }; + } + + function canUsePostMessage() { + // The test against `importScripts` prevents this implementation from being installed inside a web worker, + // where `global.postMessage` means something completely different and can't be used for this purpose. + if (global.postMessage && !global.importScripts) { + var postMessageIsAsynchronous = true; + var oldOnMessage = global.onmessage; + global.onmessage = function() { + postMessageIsAsynchronous = false; + }; + global.postMessage("", "*"); + global.onmessage = oldOnMessage; + return postMessageIsAsynchronous; + } + } + + // 初始化时立即执行 + function installPostMessageImplementation() { + // Installs an event handler on `global` for the `message` event: see + // * https://developer.mozilla.org/en/DOM/window.postMessage + // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages + + var messagePrefix = "setImmediate$" + Math.random() + "$"; + var onGlobalMessage = function(event) { + if (event.source === global && + typeof event.data === "string" && + event.data.indexOf(messagePrefix) === 0) { + runIfPresent(+event.data.slice(messagePrefix.length)); + } + }; + + if (global.addEventListener) { + global.addEventListener("message", onGlobalMessage, false); + } else { + global.attachEvent("onmessage", onGlobalMessage); + } + + registerImmediate = function(handle) { + global.postMessage(messagePrefix + handle, "*"); + }; + } + + function installMessageChannelImplementation() { + var channel = new MessageChannel(); + channel.port1.onmessage = function(event) { + var handle = event.data; + runIfPresent(handle); + }; + + registerImmediate = function(handle) { + channel.port2.postMessage(handle); + }; + } + + function installReadyStateChangeImplementation() { + var html = doc.documentElement; + registerImmediate = function(handle) { + // Create a + + + diff --git a/dev/children/vue2/src/router.js b/dev/children/vue2/src/router.js index 06da1e511..a99ef7921 100644 --- a/dev/children/vue2/src/router.js +++ b/dev/children/vue2/src/router.js @@ -20,6 +20,11 @@ const routes = [ name: 'table', component: () => import(/* webpackChunkName: "table" */ './pages/table.vue'), }, + { + path: '/nest', + name: 'nest', + component: () => import(/* webpackChunkName: "nest" */ './pages/nest.vue'), + }, ]; export default routes; diff --git a/dev/children/vue2/vue.config.js b/dev/children/vue2/vue.config.js index 3ddfa394a..bac0a8ead 100644 --- a/dev/children/vue2/vue.config.js +++ b/dev/children/vue2/vue.config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { publicPath: '/micro-app/vue2/', outputDir: 'vue2', @@ -23,4 +25,8 @@ module.exports = { // globalObject: 'window', } }, + chainWebpack: config => { + config.resolve.alias + .set("@micro-zoe/micro-app", path.join(__dirname, '../../../lib/index.esm.js')) + }, } diff --git a/dev/main-react16/src/global.jsx b/dev/main-react16/src/global.jsx index 0d432c285..d7f6aa07d 100644 --- a/dev/main-react16/src/global.jsx +++ b/dev/main-react16/src/global.jsx @@ -22,7 +22,7 @@ const prefetchConfig = [ // }, { name: 'vue2', - url: `${config.vue2}micro-app/vue2`, + url: `${config.vue2}micro-app/vue2/`, // 'disable-scopecss': true, level: 3, // 'default-page': '/micro-app/vue2/#/page2', @@ -250,3 +250,14 @@ window.onclick = function () { // window.onunhandledrejection = (event) => { // console.error(`基座Promise报错监听 -- window.onunhandledrejection: `, event); // } + +/* ---------------------- 测试message, postMessage --------------------- */ +// window.addEventListener('message', function(event) { +// console.log('基座监听的message事件', event.data, event) +// }) + +window.insertNodeFromBaseApp = function () { + const div = window.document.createElement('div') + div.innerHTML = 'insertNodeFromBaseApp' + document.body.appendChild(div) +} diff --git a/dev/main-react16/src/pages/angular11/angular11.js b/dev/main-react16/src/pages/angular11/angular11.js index 97e07c763..1d97c35e9 100644 --- a/dev/main-react16/src/pages/angular11/angular11.js +++ b/dev/main-react16/src/pages/angular11/angular11.js @@ -36,7 +36,7 @@ function Angular11 () { inline // disableScopecss // keep-alive - // iframe + iframe // disable-memory-router > diff --git a/dev/main-react16/src/pages/angular14/angular14.js b/dev/main-react16/src/pages/angular14/angular14.js index 2b0d5308a..abd8d8bd1 100644 --- a/dev/main-react16/src/pages/angular14/angular14.js +++ b/dev/main-react16/src/pages/angular14/angular14.js @@ -39,7 +39,7 @@ function Angular14 () { // disableScopecss // keep-alive // esmodule - // iframe + iframe > diff --git a/dev/main-react16/src/pages/react16/react16.js b/dev/main-react16/src/pages/react16/react16.js index eb94b436b..8657c03ac 100644 --- a/dev/main-react16/src/pages/react16/react16.js +++ b/dev/main-react16/src/pages/react16/react16.js @@ -351,28 +351,28 @@ export default class App extends React.Component { // }) // }, 0); - this.releaseBeforeEach1 = microApp.router.beforeEach((to, from, appName) => { - // const a = document.createElement('div') - // a.innerHTML = '44444444' - // document.body.appendChild(a) - console.log('全局 beforeEach: ', to, from, appName) - }) + // this.releaseBeforeEach1 = microApp.router.beforeEach((to, from, appName) => { + // // const a = document.createElement('div') + // // a.innerHTML = '44444444' + // // document.body.appendChild(a) + // console.log('全局 beforeEach: ', to, from, appName) + // }) - this.releaseBeforeEach2 = microApp.router.beforeEach({ - react16 (to, from) { - console.log('指定 beforeEach: ', to, from) - } - }) + // this.releaseBeforeEach2 = microApp.router.beforeEach({ + // react16 (to, from) { + // console.log('指定 beforeEach: ', to, from) + // } + // }) - this.releaseAfterEach1 = microApp.router.afterEach((to, from, appName) => { - console.log('全局 afterEach: ', to, from, appName) - }) + // this.releaseAfterEach1 = microApp.router.afterEach((to, from, appName) => { + // console.log('全局 afterEach: ', to, from, appName) + // }) - this.releaseAfterEach2 = microApp.router.afterEach({ - react16 (to, from) { - console.log('指定 afterEach: ', to, from) - } - }) + // this.releaseAfterEach2 = microApp.router.afterEach({ + // react16 (to, from) { + // console.log('指定 afterEach: ', to, from) + // } + // }) microApp.router.setBaseAppRouter(this.props.history) } @@ -433,14 +433,14 @@ export default class App extends React.Component { baseroute={this.state.baseroute} // keep-alive // destroy - // inline + inline // disableSandbox // disable-sandbox // disableScopecss // disable-scopecss // shadowDOM // disable-memory-router - // router-mode={this.state.routerMode} + router-mode={this.state.routerMode} // keep-router-state // default-page='/micro-app/react16/page2' // hidden-router @@ -453,7 +453,7 @@ export default class App extends React.Component { ) } - {/* */} + {/* */} diff --git a/dev/main-react16/src/pages/vue2/vue2.js b/dev/main-react16/src/pages/vue2/vue2.js index 4e68b786e..4646dc69a 100644 --- a/dev/main-react16/src/pages/vue2/vue2.js +++ b/dev/main-react16/src/pages/vue2/vue2.js @@ -29,7 +29,7 @@ function Vue2 () { } function jumpToHome () { - microApp.router.push({name: 'vue2', path: '/micro-app/vue2/#/'}) + microApp.router.push({name: 'vue22', path: '/micro-app/vue2/#/'}) } function jumpToPage2 () { @@ -90,7 +90,7 @@ function Vue2 () { // disable-scopecss // disableSandbox // clear-data - // iframe + iframe router-mode='native' > diff --git a/dev/main-vue2/src/pages/react16.vue b/dev/main-vue2/src/pages/react16.vue index 34bdaaa64..56a4eb18f 100644 --- a/dev/main-vue2/src/pages/react16.vue +++ b/dev/main-vue2/src/pages/react16.vue @@ -23,8 +23,9 @@ @datachange='handleDataChange' inline baseRoute='/react16' + iframe > - + diff --git a/dev/main-vue2/src/pages/vue2.vue b/dev/main-vue2/src/pages/vue2.vue index 4537195f4..2f1d6b08b 100644 --- a/dev/main-vue2/src/pages/vue2.vue +++ b/dev/main-vue2/src/pages/vue2.vue @@ -6,6 +6,7 @@ url='http://localhost:4001/micro-app/vue2' :data='data' inline + iframe > diff --git a/docs/0.x/index.html b/docs/0.x/docs.html similarity index 77% rename from docs/0.x/index.html rename to docs/0.x/docs.html index f58973b03..2d45a3248 100755 --- a/docs/0.x/index.html +++ b/docs/0.x/docs.html @@ -5,8 +5,8 @@ - - + + MicroApp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/0.x/home/assets/banzhuan.png b/docs/0.x/home/assets/banzhuan.png new file mode 100644 index 000000000..73e0b8c53 Binary files /dev/null and b/docs/0.x/home/assets/banzhuan.png differ diff --git a/docs/0.x/home/assets/github-logo.png b/docs/0.x/home/assets/github-logo.png new file mode 100644 index 000000000..60a3b3b37 Binary files /dev/null and b/docs/0.x/home/assets/github-logo.png differ diff --git a/docs/0.x/home/assets/logo.png b/docs/0.x/home/assets/logo.png new file mode 100644 index 000000000..75b27f831 Binary files /dev/null and b/docs/0.x/home/assets/logo.png differ diff --git a/docs/0.x/home/assets/one-line.png b/docs/0.x/home/assets/one-line.png new file mode 100644 index 000000000..4b3c63ae7 Binary files /dev/null and b/docs/0.x/home/assets/one-line.png differ diff --git a/docs/0.x/home/assets/react-code.png b/docs/0.x/home/assets/react-code.png new file mode 100644 index 000000000..be23b30f0 Binary files /dev/null and b/docs/0.x/home/assets/react-code.png differ diff --git a/docs/0.x/home/assets/react-logo.png b/docs/0.x/home/assets/react-logo.png new file mode 100644 index 000000000..aa3a2ecba Binary files /dev/null and b/docs/0.x/home/assets/react-logo.png differ diff --git a/docs/0.x/home/assets/vue-code.png b/docs/0.x/home/assets/vue-code.png new file mode 100644 index 000000000..317c46674 Binary files /dev/null and b/docs/0.x/home/assets/vue-code.png differ diff --git a/docs/0.x/home/assets/vue-logo.png b/docs/0.x/home/assets/vue-logo.png new file mode 100644 index 000000000..97b2f735d Binary files /dev/null and b/docs/0.x/home/assets/vue-logo.png differ diff --git a/docs/0.x/home/css/animation.css b/docs/0.x/home/css/animation.css new file mode 100644 index 000000000..9d2c66aad --- /dev/null +++ b/docs/0.x/home/css/animation.css @@ -0,0 +1,215 @@ +.home-show-main { + position: absolute; + top: 50%; + left: 45%; + margin: -270px 0 0 -350px; + height: 440px; + width: 650px; + border-radius: 10px; + transform-style: preserve-3d; + backface-visibility: hidden; + transform-origin: center; + animation: slope-con .4s 2.2s linear forwards; +} + +@keyframes slope-con { + to { + transform: rotateX(33deg); + } +} + +.home-show-main::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border: 2px solid #fff; + border-radius: 10px; + animation: bottom-line-move 1s linear forwards, bottom-line-show .8s 1.5s linear forwards; +} + +@keyframes bottom-line-move { + 0% { + clip-path: inset(0 0 95% 0); + opacity: 0; + } + 25% { + clip-path: inset(0 95% 0 0); + } + 50% { + clip-path: inset(95% 0 0 0); + } + 75% { + clip-path: inset(0 0 0 95%); + } + 90% { + opacity: 1; + } + 100% { + clip-path: inset(0 0 95% 0); + opacity: 0; + } +} + +@keyframes bottom-line-show { + 0% { + clip-path: inset(0 0 0 0); + opacity: 0; + } + + 100% { + clip-path: inset(0 0 0 0); + opacity: 1; + } +} + +.home-show-main-back { + position: absolute; + height: calc(100% - 4px); + width: calc(100% - 4px); + left: 2px; + top: 2px; + background-color: rgba(101, 119, 255, 1); + border-radius: 10px; + opacity: 0; + animation: home-show-main-back-mv .4s 3s linear forwards; +} + +@keyframes home-show-main-back-mv { + to { + opacity: 1; + } +} + +@keyframes home-show-main-back-mv2 { + to { + transform: translate(-20px, -20px); + } +} + +.home-show-top { + height: 17%; + width: 96%; + background-color: rgba(255, 255, 255, 0.3); + margin: 3% auto; + border-radius: 6px; + opacity: 0; + animation: top-left-show .6s 3.6s linear forwards; +} + +.home-show-left { + position: absolute; + left: 2%; + top: 25%; + width: 10%; + height: 72%; + border-radius: 6px; + opacity: 0; + background-color: rgba(255, 255, 255, 0.3); + animation: top-left-show .6s 4.2s linear forwards; +} + +@keyframes top-left-show { + to { + opacity: 1; + } +} + +.home-show-micro-con { + height: 74%; + width: 83%; + position: absolute; + top: 26%; + left: 15%; +} + +.home-show-micro { + height: 44%; + width: 100%; + position: absolute; + border-radius: 10px; + left: 0; + background-image: linear-gradient(302deg, #94a6ec 0%, #f4f6ff 100%); + box-shadow: -6px 6px 15px rgb(210 209 209 / 40%); + opacity: 0; + animation: middle-show-block .8s linear forwards; +} + +.home-show-micro:nth-child(1) { + top: 0%; + animation-delay: 4.8s; +} + +.home-show-micro:nth-child(2) { + top: 50%; + animation-delay: 5.4s; +} + +@keyframes middle-show-block { + from { + opacity: 0; + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + transform: translate3d(0, -20px, 0) scale(1.1); + } + + to, + 20% { + opacity: 1; + } + + 20%, + 53%, + to { + animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transform: translate3d(0, 0, 0); + } + + 40%, + 43% { + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + transform: translate3d(0, -10px, 0) scale(1.1); + } + + 70% { + animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); + transform: translate3d(0, -6px, 0) scale(1.05); + } + + 80% { + transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); + transform: translate3d(0, 0, 0) scale(0.95); + } + + 90% { + transform: translate3d(0, -2px, 0) scale(1.02); + } +} + +.home-show-logo { + position: absolute; + top: 55%; + left: 45%; + height: 80px; + width: 80px; + opacity: 0.3; + margin-top: -40px; + margin-left: -40px; + opacity: 0.01; + animation: home-show-logo-visible .8s linear forwards; +} + +@keyframes home-show-logo-visible { + to { + opacity: 0.1; + } +} + +.home-show-micro:nth-child(1) .home-show-logo { + animation-delay: 6.2s; +} + +.home-show-micro:nth-child(2) .home-show-logo { + animation-delay: 6.6s; +} diff --git a/docs/0.x/home/css/index.css b/docs/0.x/home/css/index.css new file mode 100644 index 000000000..ed75b0217 --- /dev/null +++ b/docs/0.x/home/css/index.css @@ -0,0 +1,562 @@ +body { + margin: 0; + -webkit-font-smoothing: antialiased; + font-family: -apple-system, BlinkMacSystemFont, Tahoma, Arial, "Hiragino Sans GB", "Microsoft YaHei", sans-serif; + width: 100%; + overflow-x: hidden; +} + +a { + text-decoration: none; +} + +dl, dd, dt { + padding: 0; + margin: 0; + list-style: none; +} + +.icon { + width: 1em; + height: 1em; + vertical-align: -0.15em; + fill: currentColor; + overflow: hidden; +} + +.main-page { + width: 100vw; + overflow-x: hidden; +} + +.top-container { + position: relative; + height: 1200px; + width: 100vw; + background-image: linear-gradient(117deg, #6B46E3 0%, #5264EE 50%, #55A0EB 100%); + overflow: hidden; +} + +.top-container::after { + content: ''; + position: absolute; + top: 85%; + width: 100%; + height: 350px; + background: #F8FAFF; + transform: skewY(-7deg); + z-index: 4; +} + +.home-header { + position: absolute; + top: 0; + left: 0; + height: 80px; + width: 100vw; + box-sizing: border-box; + padding: 0 120px; + display: flex; + justify-content: space-between; + z-index: 100; +} + +.logo-con { + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.logo-con a { + display: flex; + align-items: center; + justify-content: center; + height: 80px; +} + +.logo-con .logo-img { + margin-right: 5px; + width: 34px; + height: 34px; +} + +.logo-con .logo-title { + color: #FFF; + font-weight: bold; + font-style: italic; + font-size: 16px; + white-space: nowrap; +} + +.header-nav { + margin-right: 40px; + white-space: nowrap; +} + +.header-nav-title { + font-size: 16px; + color: #fff; + line-height: 80px; + margin-right: 30px; + white-space: nowrap; +} + +.github-icon { + width: 20px; + height: 20px; + vertical-align: text-bottom; +} + +.introduce { + position: relative; + margin: 0 auto; + padding-top: 260px; + width: 90%; + max-width: 1200px; + color: #fff; + text-align: left; + vertical-align: top; + box-sizing: border-box; + z-index: 5; +} + +.introduce .introduce-title { + color: #fff; + font-weight: 300; + font-size: 40px; + letter-spacing: 0; + -webkit-font-smoothing: auto; + animation: title-show .6s 2.4s forwards; + opacity: 0; +} + +.introduce .introduce-desc { + font-size: 24px; + color: #FFF; + letter-spacing: 0; + animation: title-show .6s 2.6s forwards; + opacity: 0; +} + +.introduce-btn-list { + margin-top: 30px; + animation: title-show .6s 2.8s forwards; + opacity: 0; +} + +@keyframes title-show { + 0% { + opacity: 0; + transform: translateX(-200px) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +.introduce-btn-list a { + display: inline-block; + text-align: center; + color: #fff; + width: 140px; + height: 40px; + font-size: 16px; + line-height: 40px; + border-radius: 20px; + cursor: pointer; + user-select: none; +} + +.introduce .btn-start { + background: #00DAA8; +} + +.introduce .btn-coding { + color: #fff; + margin-left: 20px; + border: 1px solid #fff; +} + +.home-show { + position: absolute; + top: 120px; + left: 40%; + height: 600px; + width: 900px; + z-index: 4; + perspective: 1000px; +} + +.decoration-top { + position: absolute; + top: -310px; + right: 80px; + height: 400px; + width: 400px; + background: rgba(255, 255, 255, 0.08); + transform: rotate(195deg); + border-radius: 30px; +} + +.decoration-top::before { + content: ''; + position: absolute; + height: 100%; + width: 100%; + bottom: -20px; + right: 20px; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 30px; +} + +.decoration-bottom { + position: absolute; + width: 540px; + height: 360px; + bottom: 30px; + left: -20px; + background: rgba(255, 255, 255, 0.08); + border-radius: 30px; + transform: skew(7deg, -7deg) rotate(-20deg); +} + +.decoration-bottom::before { + content: ''; + position: absolute; + height: 100%; + width: 100%; + bottom: 30px; + right: 30px; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 30px; +} + +.content-demo { + margin-top: -500px; + position: relative; + z-index: 5; +} + +.content-main-title { + text-align: center; + color: #fff; + font-size: 24px; + font-weight: normal; + -webkit-font-smoothing: auto; +} + +.content-common { + width: 86vw; + background: #fff; + box-shadow: 0 4px 30px 0 rgba(0, 0, 0, .1); + border-radius: 10px; + margin: 120px auto 0; + box-sizing: border-box; + padding: 10px 30px 30px; +} + +.content-common-title { + font-weight: normal; + font-size: 20px; + text-align: center; + -webkit-font-smoothing: auto; + padding-bottom: 40px; +} + +.content-common-detail { + display: flex; + align-items: center; + justify-content: center; +} + +.content-one-img { + width: 45%; + height: auto; + opacity: 0; +} + +.content-one-img-show { + animation: one-img-show .6s .2s linear forwards; +} + +@keyframes one-img-show { + 0% { + opacity: 0; + transform: translateY(-20px) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +.content-common-arrow-right { + width: 5%; + margin: 0 2%; + opacity: 0; +} + +.content-common-arrow-right-show { + animation: arrow-right-show .6s .6s ease-out forwards; +} + +@keyframes arrow-right-show { + 0% { + opacity: 0; + transform: translate3d(-300px, 0, 0) scaleX(3); + } + + 60% { + transform: translate3d(10px, 0, 0) scaleX(1); + } + + 75% { + transform: translate3d(-5px, 0, 0) scaleX(0.98); + } + + to { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +.micro-app-con { + position: relative; + width: 40%; + height: 400px; + border-radius: 10px; + opacity: 0; + box-shadow: 0 0 15px rgb(210 209 209 / 40%); +} + +.micro-app-con-show { + animation: micro-app-con-show-move .4s .6s linear forwards; +} + +@keyframes micro-app-con-show-move { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.micro-app-con-two { + height: 500px; +} + +.content-two-imgs-con { + width: 50%; +} + +.content-two-img-con { + display: flex; + margin-bottom: 10px; + align-items: center; + opacity: 0; +} + +.content-two-img-con-show { + animation: two-img-con-move .6s .2s linear forwards; +} + +@keyframes two-img-con-move { + 0% { + opacity: 0; + transform: translateY(-20px) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +.content-two-img-logo { + width: 80px; + height: 80px; + margin-right: 10px; + display: block; +} + +.content-two-img-code { + width: calc(100% - 90px); +} + +.loading-logo { + position: absolute; + top: 50%; + left: 50%; + transform: translate3d(-50%, -50%, 0); +} + +.footer { + padding: 30px 50px; + margin-top: 80px; + background: #303846; +} + +.footer-content { + display: flex; + justify-content: center; + color: #fff; +} + +.footer-content dl { + width: 300px; +} + +.footer-content a { + color: #fff; +} + +.footer-content a:hover { + color: #5264EE; + text-decoration: underline; +} + +.footer-content dt { + font-size: 17px; + font-weight: bold; + margin-bottom: 10px; +} + +.footer-content dd { + color: #fff; + line-height: 2; + font-size: 15px; +} + +.footer-copy { + text-align: center; + padding-top: 30px; + margin-top: 30px; + font-size: 14px; + color: #999; + border-top: 1px solid #555; +} + +.ability-list { + margin-top: 100px; +} + +.ability-list-title { + font-size: 28px; + text-align: center; + font-weight: 600; + -webkit-font-smoothing: auto; +} + +.ability-list-cont { + display: flex; + justify-content: center; + margin-top: 50px; +} + +.ability-item { + display: flex; + flex-direction: column; + align-items: center; + margin: 0 40px; +} + +.ability-item-icon-con { + height: 100px; + width: 100px; + border-radius: 16px; + background-color: #4581de; + display: flex; + justify-content: center; + align-items: center; +} + +.ability-icon-sandbox { + height: 40px; + width: 40px; +} + +.ability-item-icon-css { + background-color: #debd45f7; + position: relative; +} + +.ability-item-icon-element { + background-color: #6b45de; +} + +.ability-item-icon-tongxun { + background-color: #ec9b37; +} + +.ability-item-icon-plugin { + background-color: #45dec9; +} + +.ability-item-icon-prefetch { + background-color: #45d0de; +} + +.ability-icon-css { + height: 34px; + width: 34px; +} + +.ability-icon-css:nth-child(1) { + transform: translate3d(0, 10px, 0); +} + +.ability-icon-css:nth-child(2) { + position: absolute; + top: 50%; + left: 50%; + transform: translate3d(-16%, -64%, 0); +} + +.ability-icon-element { + height: 36px; + width: 36px; +} + +.ability-icon-tongxun { + height: 36px; + width: 36px; +} + +.ability-icon-plugin { + height: 36px; + width: 36px; +} + +.ability-icon-prefetch { + height: 36px; + width: 36px; +} + +.ability-item h4 { + font-weight: normal; + -webkit-font-smoothing: auto; + font-size: 18px; + line-height: 60px; + margin: 0; +} + +.content-thrid-btn { + text-align: center; + margin-top: 80px; +} + +.content-thrid-btn a { + display: inline-block; + text-align: center; + color: #fff; + width: 180px; + height: 40px; + font-size: 16px; + line-height: 40px; + border-radius: 20px; + cursor: pointer; + user-select: none; + background: #00DAA8;; +} diff --git a/docs/0.x/home/js/iconfont.js b/docs/0.x/home/js/iconfont.js new file mode 100644 index 000000000..7ab830729 --- /dev/null +++ b/docs/0.x/home/js/iconfont.js @@ -0,0 +1 @@ +!function(l){var c,a,t,f,h,p,i='',d=(d=document.getElementsByTagName("script"))[d.length-1].getAttribute("data-injectcss");if(d&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}function e(){h||(h=!0,t())}c=function(){var l,c,a;(a=document.createElement("div")).innerHTML=i,i=null,(c=a.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",l=c,(a=document.body).firstChild?(c=a.firstChild).parentNode.insertBefore(l,c):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(c,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),c()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(t=c,f=l.document,h=!1,(p=function(){try{f.documentElement.doScroll("left")}catch(l){return void setTimeout(p,50)}e()})(),f.onreadystatechange=function(){"complete"==f.readyState&&(f.onreadystatechange=null,e())})}(window); \ No newline at end of file diff --git a/docs/0.x/home/js/index.js b/docs/0.x/home/js/index.js new file mode 100644 index 000000000..365c64fb9 --- /dev/null +++ b/docs/0.x/home/js/index.js @@ -0,0 +1,71 @@ +const contentOneImg = document.querySelector('.content-one-img') +const contentTwoImg1 = document.querySelectorAll('.content-two-img-con')[0] +const contentTwoImg2 = document.querySelectorAll('.content-two-img-con')[1] + +const observer1 = new IntersectionObserver(res => { + if (res[0].intersectionRatio <= 0) return + observer1.disconnect() + contentOneImg.className = 'content-one-img content-one-img-show' + const microAppCon = document.querySelector('.micro-app-con-one') + microAppCon.className = 'micro-app-con micro-app-con-one micro-app-con-show' + + const arrowRight1 = document.querySelectorAll('.content-common-arrow-right')[0] + arrowRight1.className = 'content-common-arrow-right content-common-arrow-right-show' + + setTimeout(() => { + const LoadingLogo = document.createElement('micro-app-loading') + LoadingLogo.setAttribute('size', '0.3') + LoadingLogo.setAttribute('class', 'loading-logo') + microAppCon.appendChild(LoadingLogo) + }, 1100) + + // + setTimeout(() => { + const myApp = document.createElement('micro-app') + myApp.setAttribute('name', 'my-app1') + myApp.setAttribute('url', `https://zeroing.jd.com/micro-app/react17/`) + myApp.addEventListener('mounted', () => { + microAppCon.removeChild(microAppCon.children[0]) + }) + microAppCon.appendChild(myApp) + }, 3000) +}) +observer1.observe(contentOneImg) + + +const observer2 = new IntersectionObserver(res => { + if (res[0].intersectionRatio <= 0) return + observer2.disconnect() + contentTwoImg1.className = 'content-two-img-con content-two-img-con-show' +}) +observer2.observe(contentTwoImg1) + + +const observer3 = new IntersectionObserver(res => { + if (res[0].intersectionRatio <= 0) return + observer3.disconnect() + contentTwoImg2.className = 'content-two-img-con content-two-img-con-show' + const microAppCon = document.querySelector('.micro-app-con-two') + microAppCon.className = 'micro-app-con micro-app-con-two micro-app-con-show' + + const arrowRight2 = document.querySelectorAll('.content-common-arrow-right')[1] + arrowRight2.className = 'content-common-arrow-right content-common-arrow-right-show' + + setTimeout(() => { + const LoadingLogo = document.createElement('micro-app-loading') + LoadingLogo.setAttribute('size', '0.3') + LoadingLogo.setAttribute('class', 'loading-logo') + microAppCon.appendChild(LoadingLogo) + }, 1100) + + setTimeout(() => { + const myApp = document.createElement('micro-app') + myApp.setAttribute('name', 'my-app2') + myApp.setAttribute('url', `https://zeroing.jd.com/micro-app/react17/`) + myApp.addEventListener('mounted', () => { + microAppCon.removeChild(microAppCon.children[0]) + }) + microAppCon.appendChild(myApp) + }, 3000); +}) +observer3.observe(contentTwoImg2) diff --git a/docs/0.x/home/js/index.umd.js b/docs/0.x/home/js/index.umd.js new file mode 100644 index 000000000..1c3ac74b6 --- /dev/null +++ b/docs/0.x/home/js/index.umd.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@babel/runtime/helpers/typeof")):"function"==typeof define&&define.amd?define(["exports","@babel/runtime/helpers/typeof"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).microApp={})}(this,(function(e){"use strict";function t(e){return"string"==typeof e?`[micro-app] ${e}`:e}function n(e,...t){Promise.resolve().then(e.bind(null,...t))}function o(e){if("string"!=typeof e||!e)return"";try{const{origin:t,pathname:n}=new URL(e.startsWith("//")?`${location.protocol}${e}`:e),o=`${t}${n}/`.replace(/\/\/$/,"/");return/^https?:\/\//.test(o)?o:""}catch(e){return console.error(e),""}}function r(e,t){if(/^((((ht|f)tps?)|file):)?\/\//.test(e))return e;const{origin:n}=new URL(t);return new URL(e,n).toString()}function i(e,t,n,o){let r=0;function i(){++r===e.length&&o()}e.forEach(((e,o)=>{"[object Promise]"===toString.call(e)?e.then((e=>{t({data:e,index:o}),i()})).catch((e=>{n({error:e,index:o}),i()})):(t({data:e,index:o}),i())}))}const s=window.requestIdleCallback||function(e){const t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:()=>Math.max(0,50-(Date.now()-t))})}),1)};let c=null;function a(e){c=e}function l(){return c}function u(){return/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent)}function p(e,t){return a(null),document.createElement(e,t)}var d,h,m,f;function y(e,t,n,o){return new(n||(n=Promise))((function(r,i){function s(e){try{a(o.next(e))}catch(e){i(e)}}function c(e){try{a(o.throw(e))}catch(e){i(e)}}function a(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,c)}a((o=o.apply(e,t||[])).next())}))}function b(e){return fetch(e).then((e=>e.text())).catch((e=>{throw e}))}function g(e,t){const{selectorText:n,cssText:o}=e;if(/^(html[\s+>~,]+body)|(html|body|:root)$/.test(n))return o.replace(/^(html[\s+>~,]+body)|(html|body|:root)/,t);if("*"===n)return o.replace("*",`${t} *`);const r=/(^|\s+)((html[\s+>~]+body)|(html|body|:root))(?=[\s+>~]+|$)/;return o.replace(/^[\s\S]+{/,(e=>e.replace(/(^|,)([^,]+)/g,((e,n,o)=>r.test(o)?e.replace(r,t):`${n} ${t} ${o.replace(/^\s*/,"")}`))))}function w(e,t,n){const o=E(Array.from(e.cssRules),t);return`@${n} ${e.conditionText} {${o}}`}function E(e,t){let n="";for(const o of e)switch(o.type){case f.STYLE_RULE:n+=g(o,t);break;case f.MEDIA_RULE:n+=w(o,t,"media");break;case f.SUPPORTS_RULE:n+=w(o,t,"supports");break;default:n+=o.cssText}return n}function v(e,t,n,o,i){var s,c;e.textContent=n;let a=function(e,t,n){return e.replace(/url\(["']?([^)"']+)["']?\)/gm,((e,o)=>{if(/^data:/.test(o))return e;if(/^(https?:)?\/\//.test(o)){if(!u())return e;{const t=o.replace(/^https?:/,"");if(-1!==n.indexOf(t))return e;o=o.replace(window.location.origin,"")}}return`url("${r(o,t)}")`}))}(E(Array.from(null!==(c=null===(s=e.sheet)||void 0===s?void 0:s.cssRules)&&void 0!==c?c:[]),o),i,n);u()&&(a=a.replace(/([;{]\s*content:\s*)([^\s"][^";}]*)/gm,((e,t,n)=>"none"===n||/^(url\()|(counter\()|(attr\()|(open-quote)|(close-quote)/.test(n)?e:`${t}"${n}"`))),t.textContent=a,e.textContent=""}let O;function _(e,t){var n;const o=de.get(t);if(null==o?void 0:o.scopecss){const r=`micro-app[name=${t}]`;O||(O=p("style"),document.body.appendChild(O),O.sheet.disabled=!0);const i=null!==(n=e.textContent)&&void 0!==n?n:"";if(i)v(O,e,i,r,o.url);else{const t=new MutationObserver((function(){var n;v(O,e,null!==(n=e.textContent)&&void 0!==n?n:"",r,o.url),t.disconnect()}));t.observe(e,{childList:!0})}}return e}function D(e,t){Object.defineProperties(e,{currcurrentTarget:{get:()=>t},srcElement:{get:()=>t},target:{get:()=>t}})}function C(e){const t=new CustomEvent("load");D(t,e),"function"==typeof e.onload?e.onload(t):e.dispatchEvent(t)}function A(e){const t=new CustomEvent("error");D(t,e),"function"==typeof e.onerror?e.onerror(t):e.dispatchEvent(t)}!function(e){e.NAME="name",e.URL="url"}(d||(d={})),function(e){e.NOT_LOADED="NOT_LOADED",e.LOADING_SOURCE_CODE="LOADING_SOURCE_CODE",e.LOAD_SOURCE_FINISHED="LOAD_SOURCE_FINISHED",e.LOAD_SOURCE_ERROR="LOAD_SOURCE_ERROR",e.MOUNTING="MOUNTING",e.MOUNTED="MOUNTED",e.UNMOUNT="UNMOUNT"}(h||(h={})),function(e){e.BEFOREMOUNT="beforemount",e.MOUNTED="mounted",e.UNMOUNT="unmount",e.ERROR="error"}(m||(m={})),function(e){e[e.STYLE_RULE=1]="STYLE_RULE",e[e.MEDIA_RULE=4]="MEDIA_RULE",e[e.SUPPORTS_RULE=12]="SUPPORTS_RULE"}(f||(f={}));const S=new Map;function N(e,t,n,o,i=!1){const s=e.getAttribute("rel");let c=e.getAttribute("href"),a=null;if("stylesheet"===s&&c){if(c=r(c,n.url),i)return{url:c,info:{code:"",isGlobal:e.hasAttribute("global")}};{a=document.createComment(`the link with href=${c} move to micro-app-head as style element`);const t=document.createComment(`placeholder for link with href=${c}`);o.appendChild(t),n.source.links.set(c,{code:"",placeholder:t,isGlobal:e.hasAttribute("global")})}}else c&&e.setAttribute("href",r(c,n.url));return i?{replaceComment:a}:a?t.replaceChild(a,e):void 0}function x(e,n,o){const r=Array.from(n.source.links.entries()),s=[];for(const[e]of r){const t=S.get(e);t?s.push(t):s.push(b(e))}i(s,(e=>{!function(e,n,o,r,i){o||console.warn(t(`data fetch from url ${e} is empty`));n.isGlobal&&!S.has(e)&&S.set(e,o);const s=document.createElement("style");s.textContent=o,r.replaceChild(_(s,i.name),n.placeholder),n.placeholder=null,n.code=o}(r[e.index][0],r[e.index][1],e.data,o,n)}),(e=>{console.error("[micro-app]",e)}),(()=>{n.onLoad(e)}))}const R=new Map,L="noModule"in document.createElement("script");function M(e,t,n,o=!1){let i=null,s=e.getAttribute("src");if(e.hasAttribute("exclude"))i=document.createComment("script element with exclude attribute ignored by micro-app");else if(L&&e.noModule||!L&&"module"===e.type)i=document.createComment((e.noModule?"noModule":"module")+" script ignored by micro-app");else if(s){s=r(s,n.url);const t={code:"",isExternal:!0,isDynamic:o,async:e.hasAttribute("async"),defer:e.defer||"module"===e.type,module:"module"===e.type,isGlobal:e.hasAttribute("global")};if(o)return{url:s,info:t};n.source.scripts.set(s,t),i=document.createComment(`script with src='${s}' extract by micro-app`)}else if(e.textContent){const t=Math.random().toString(36).substr(2,15),r={code:e.textContent,isExternal:!1,isDynamic:o,async:!1,defer:"module"===e.type,module:"module"===e.type};if(o)return{url:t,info:r};n.source.scripts.set(t,r),i=document.createComment("inline script extract by micro-app")}else i=document.createComment("script ignored by micro-app");return o?{replaceComment:i}:t.replaceChild(i,e)}function P(e,n){const o=Array.from(n.source.scripts.entries()),r=[],s=[];for(const[e,t]of o)if(t.isExternal){const n=R.get(e);n?t.code=n:t.defer||t.async||(r.push(b(e)),s.push([e,t]))}r.length?i(r,(e=>{!function(e,n,o){o||console.warn(t(`data fetch from url ${e} is empty`));n.isGlobal&&!R.has(e)&&R.set(e,o);n.code=o}(s[e.index][0],s[e.index][1],e.data)}),(e=>{console.error("[micro-app]",e)}),(()=>{n.onLoad(e)})):n.onLoad(e)}function U(e,t,n,o){var r;try{if(e=T(e,t),t.inline){const n=p("script");if(n.textContent=e,o)return n;null===(r=t.container)||void 0===r||r.querySelector("micro-app-body").appendChild(n)}else if((0,eval)(e),o)return document.createComment("dynamic script extract by micro-app")}catch(e){console.error("[micro-app from runScript]",e)}}function T(e,t){if(t.useSandbox){return(0,eval)("window").proxyWindow=t.sandBox.proxyWindow,`;(function(window, self){with(window){;${e}\n}}).call(window.proxyWindow, window.proxyWindow, window.proxyWindow);`}return e}function $(e,t,n){const o=Array.from(e.children);o.length&&o.forEach((e=>{$(e,t,n)}));for(const i of o)i instanceof HTMLLinkElement?i.hasAttribute("exclude")?e.replaceChild(document.createComment("link element with exclude attribute ignored by micro-app"),i):t.scopecss?N(i,e,t,n):i.hasAttribute("href")&&i.setAttribute("href",r(i.getAttribute("href"),t.url)):i instanceof HTMLStyleElement?i.hasAttribute("exclude")?e.replaceChild(document.createComment("style element with exclude attribute ignored by micro-app"),i):t.scopecss&&n.appendChild(_(i,t.name)):i instanceof HTMLScriptElement?M(i,e,t):i instanceof HTMLMetaElement||i instanceof HTMLTitleElement?e.removeChild(i):/^(img|iframe)$/i.test(i.tagName)&&i.hasAttribute("src")?i.setAttribute("src",r(i.getAttribute("src"),t.url)):/^a$/i.test(i.tagName)&&i.hasAttribute("href")&&i.setAttribute("href",r(i.getAttribute("href"),t.url))}function j(e,n){const o=function(e){const t=document.createElement("div");return t.innerHTML=e,t}(e),r=o.querySelector("micro-app-head"),i=o.querySelector("micro-app-body");if(!r||!i){const e=`element ${r?"body":"head"} is missing`;return n.onerror(new Error(e)),console.error(t(e))}$(o,n,r),n.source.links.size?x(o,n,r):n.onLoad(o),n.source.scripts.size?P(o,n):n.onLoad(o)}const k=Object.defineProperty;const I="function"==typeof document.all&&void 0===document.all?e=>"function"==typeof e&&void 0!==e:e=>"function"==typeof e,W=new WeakMap;const B=new WeakMap;const G=new WeakMap;function q(e,t){const n=G.get(t);if(n)return n;if(I(t)&&!function(e){if(W.has(e))return W.get(e);const t=0===e.name.indexOf("bound ")&&!e.hasOwnProperty("prototype");return W.set(e,t),t}(t)&&!function(e){if(B.has(e))return B.get(e);const t=e.prototype&&e.prototype.constructor===e&&Object.getOwnPropertyNames(e.prototype).length>1||/^function\b\s[A-Z].*/.test(e.toString())||/^class\b/.test(e.toString());return B.set(e,t),t}(t)){const n=Function.prototype.bind.call(t,e);for(const e in t)n[e]=t[e];return t.hasOwnProperty("prototype")&&!n.hasOwnProperty("prototype")&&(n.prototype=t.prototype),G.set(t,n),n}return t}const H=window.addEventListener,F=window.removeEventListener,z=window.setInterval,K=window.setTimeout,Y=window.clearInterval,J=window.clearTimeout;function V(e,t){return"unmount"===e?`unmount-${t.__micro_app_name__}`:e}const Z=new class{constructor(){this.eventList=new Map}isLegalName(e){return!("string"!=typeof e||!e)||(console.error(t("event-center: Invalid name")),!1)}on(e,n){if(this.isLegalName(e)){if("function"!=typeof n)return console.error(t("event-center: Invalid callback function"));let o=this.eventList.get(e);o?Object.getOwnPropertyNames(o.data).length&&n(o.data):(o={data:{},callbacks:new Set},this.eventList.set(e,o)),o.callbacks.add(n)}}off(e,t){if(this.isLegalName(e)){const n=this.eventList.get(e);n&&("function"==typeof t?n.callbacks.delete(t):t||n.callbacks.clear())}}dispatch(e,n){if(this.isLegalName(e)){if("[object Object]"!==toString.call(n))return console.error(t("event-center: data must be object"));let o=this.eventList.get(e);if(o){if(o.data!==n){o.data=n;for(const e of o.callbacks)e(n)}}else o={data:n,callbacks:new Set},this.eventList.set(e,o)}}getData(e){var t;const n=this.eventList.get(e);return null!==(t=null==n?void 0:n.data)&&void 0!==t?t:null}};function Q(e,t){return"string"==typeof e&&e?t?`__from_base_app_${e}__`:`__from_micro_app_${e}__`:""}class X{addGlobalDataListener(e){Z.on("global",e)}removeGlobalDataListener(e){"function"==typeof e&&Z.off("global",e)}setGlobalData(e){Z.dispatch("global",e)}clearGlobalDataListener(){Z.off("global")}}class ee extends X{addDataListener(e,t){Z.on(Q(e,!1),t)}removeDataListener(e,t){"string"==typeof e&&"function"==typeof t&&Z.off(Q(e,!1),t)}getData(e,t=!1){return Z.getData(Q(e,t))}setData(e,t){Z.dispatch(Q(e,!0),t)}clearDataListener(e){Z.off(Q(e,!1))}}class te extends X{constructor(e){super(),this.appName=e}addDataListener(e){Z.on(Q(this.appName,!0),e)}removeDataListener(e){"function"==typeof e&&Z.off(Q(this.appName,!0),e)}getData(){return Z.getData(Q(this.appName,!0))}dispatch(e){n((()=>{Z.dispatch(Q(this.appName,!1),e);const t=de.get(this.appName);if((null==t?void 0:t.container)&&"[object Object]"===toString.call(e)){const n=new CustomEvent("datachange",{detail:{data:e}});t.container.dispatchEvent(n)}}))}clearDataListener(){Z.off(Q(this.appName,!0))}}const ne=["System","__cjsWrapper","__REACT_ERROR_OVERLAY_GLOBAL_HOOK__"],oe=["location"],re={undefined:!0,Array:!0,Object:!0,String:!0,Boolean:!0,Math:!0,Number:!0,Symbol:!0,parseFloat:!0,Float32Array:!0};let ie;function se(e){ie&&clearTimeout(ie),ie=setTimeout(e,0)}class ce{constructor(e,t,o){this.active=!1;const r=window,{clonedWindow:i,propertiesWithGetter:s}=function(e,t){const n={},o=new Map;return Object.getOwnPropertyNames(e).forEach((t=>{const r=Object.getOwnPropertyDescriptor(e,t);if(r&&!r.configurable){const e=Object.prototype.hasOwnProperty.call(r,"get");"top"!==t&&"parent"!==t&&"self"!==t&&"window"!==t||(r.configurable=!0,e||(r.writable=!0)),e&&o.set(t,!0),k(n,t,Object.freeze(r))}})),{clonedWindow:n,propertiesWithGetter:o}}(window),c=new Map,l=e=>i.hasOwnProperty(e)||r.hasOwnProperty(e);this.inject(i,e,t),this.releaseEffect=function(e){const t=new Map,n=new Set,o=new Set;return e.addEventListener=function(n,o,r){n=V(n,e);const i=t.get(n);return i?i.add(o):t.set(n,new Set([o])),H.call(window,n,o,r)},e.removeEventListener=function(n,o,r){n=V(n,e);const i=t.get(n);return(null==i?void 0:i.size)&&i.has(o)&&i.delete(o),F.call(window,n,o,r)},e.setInterval=function(e,t,...o){const r=z(e,t,...o);return n.add(r),r},e.setTimeout=function(e,t,...n){const r=K(e,t,...n);return o.add(r),r},e.clearInterval=function(e){n.delete(e),Y(e)},e.clearTimeout=function(e){o.delete(e),J(e)},()=>{t.size&&(t.forEach(((e,t)=>{if(e.size)for(const n of e)F.call(window,t,n)})),t.clear()),n.size&&(n.forEach((e=>{Y(e)})),n.clear()),o.size&&(o.forEach((e=>{J(e)})),o.clear())}}(i),this.proxyWindow=new Proxy(i,{get:(t,i)=>{if(i===Symbol.unscopables)return re;if("window"===i||"self"===i)return this.proxyWindow;if("top"===i||"parent"===i)return r===r.parent?this.proxyWindow:Reflect.get(r,i);if("hasOwnProperty"===i)return l;if("document"===i||"eval"===i)switch(a(e),(o?se:n)((()=>a(null))),i){case"document":return document;case"eval":return eval}if("webpackJsonp"===i)return Reflect.get(t,i);const c=s.get(i)?Reflect.get(r,i):i in t?Reflect.get(t,i):Reflect.get(r,i);return q(r,c)},set:(e,t,n)=>{if(this.active){if(oe.includes(t))Reflect.set(r,t,n);else if(!e.hasOwnProperty(t)&&r.hasOwnProperty(t)&&"webpackJsonp"!==t){const o=Object.getOwnPropertyDescriptor(r,t),{writable:i,configurable:s,enumerable:c}=o;i&&Object.defineProperty(e,t,{configurable:s,enumerable:c,writable:i,value:n})}else Reflect.set(e,t,n);ne.includes(t)&&Reflect.set(r,t,n)}return!0},has:(e,t)=>t in re||t in e||t in r,getOwnPropertyDescriptor(e,t){if(e.hasOwnProperty(t)){const n=Object.getOwnPropertyDescriptor(e,t);return c.set(t,"target"),n}if(r.hasOwnProperty(t)){const e=Object.getOwnPropertyDescriptor(r,t);return c.set(t,"rawWindow"),e&&!e.configurable&&(e.configurable=!0),e}},defineProperty:(e,t,n)=>"rawWindow"===c.get(t)?Reflect.defineProperty(r,t,n):Reflect.defineProperty(e,t,n),ownKeys:e=>Reflect.ownKeys(r).concat(Reflect.ownKeys(e)).filter((function(e){return!(e in this)&&(this[e]=!0)}),Object.create(null)),deleteProperty:(e,t)=>!e.hasOwnProperty(t)||Reflect.deleteProperty(e,t)})}start(){this.active||(this.active=!0,ce.activeCount++)}stop(){this.active&&(this.active=!1,this.releaseEffect(),this.proxyWindow.microApp.clearDataListener(),0==--ce.activeCount&&ne.forEach((e=>{this.proxyWindow.hasOwnProperty(e)&&delete window[e]})))}inject(e,t,n){e.__micro_app_environment__=!0,e.__micro_app_name__=t,e.__full_public_path__=n,e.microApp=new te(t)}}function ae(e,t){"[object Array]"===toString.call(e)&&e.forEach((e=>{"[object Object]"===toString.call(e)&&e.name&&"string"==typeof e.name&&e.url&&"string"==typeof e.url&&!de.has(e.name)&&t.push(e)}))}function le(e){s((()=>{const t=[];ae("function"==typeof e?e():e,t),t.forEach((e=>{var t,n,o;const r=new he({name:e.name,url:e.url,scopecss:!(null!==(t=e.disableScopecss)&&void 0!==t?t:ue.disableScopecss),useSandbox:!(null!==(n=e.disableSandbox)&&void 0!==n?n:ue.disableSandbox),macro:null!==(o=e.macro)&&void 0!==o?o:ue.macro});r.isPrefetch=!0,de.set(e.name,r)}))}))}ce.activeCount=0;var ue=new class extends ee{constructor(){super(...arguments),this.version="0.0.5",this.preFetch=le}use(e){"[object Object]"===toString.call(e)&&(this.shadowDOM=e.shadowDOM,this.destory=e.destory,this.inline=e.inline,this.disableScopecss=e.disableScopecss,this.disableSandbox=e.disableSandbox,this.macro=e.macro,"[object Object]"===toString.call(e.lifeCycles)&&(this.lifeCycles=e.lifeCycles),e.preFetchApps&&le(e.preFetchApps))}};function pe(e,n,o,r){var i;if(!e)return console.error(t(`element does not exist in lifecycle ${o},it seems to be something wrong`));const s=Object.assign({name:n,container:e},r&&{error:r}),c=new CustomEvent(o,{detail:s});!function(e,t){Object.defineProperties(e,{currcurrentTarget:{get:()=>t},target:{get:()=>t}})}(c,e),"function"==typeof(null===(i=ue.lifeCycles)||void 0===i?void 0:i[o])&&ue.lifeCycles[o](c),e.dispatchEvent(c)}const de=new Map;class he{constructor({name:e,url:t,container:n,inline:o,scopecss:r,useSandbox:i,macro:s}){this.status=h.NOT_LOADED,this.loadSourceLevel=0,this.isPrefetch=!1,this.container=null,this.scopecss=!0,this.useSandbox=!0,this.macro=!1,this.sandBox=null,this.container=null!=n?n:null,this.inline=null!=o&&o,this.name=e,this.url=t,this.useSandbox=null==i||i,this.scopecss=!!this.useSandbox&&(null==r||r),this.macro=null!=s&&s,this.source={links:new Map,scripts:new Map},this.loadSourceCode(),this.useSandbox&&(this.sandBox=new ce(e,t,this.macro))}loadSourceCode(){this.status=h.LOADING_SOURCE_CODE,function(e){y(this,void 0,void 0,(function*(){try{let n=yield b(e.url);if(!n){const n="html is empty, please check that the URL is correct";return e.onerror(new Error(n)),console.error(t(n))}n=n.replace(/]*>[\s\S]*?<\/head>/i,(e=>e.replace(//i,""))).replace(/]*>[\s\S]*?<\/body>/i,(e=>e.replace(//i,""))),j(n,e)}catch(n){e.onLoadError(n),console.error(t(`Failed to fetch data from ${e.url}, micro-app stop rendering`),n)}}))}(this)}onLoad(e){if(2==++this.loadSourceLevel){if(this.source.html=e,this.isPrefetch||this.status===h.UNMOUNT)return;this.status=h.LOAD_SOURCE_FINISHED,this.mount()}}onLoadError(e){this.loadSourceLevel=-1,this.status!==h.UNMOUNT&&(this.onerror(e),this.status=h.LOAD_SOURCE_ERROR)}mount(e,t){var n;if(!this.container&&e&&(this.container=e),"boolean"==typeof t&&t!==this.inline&&(this.inline=t),2!==this.loadSourceLevel)return void(this.status=h.LOADING_SOURCE_CODE);this.status=h.MOUNTING,pe(this.container,this.name,m.BEFOREMOUNT);const o=this.source.html.cloneNode(!0),r=document.createDocumentFragment();Array.from(o.childNodes).forEach((e=>{r.appendChild(e)})),this.container.appendChild(r),null===(n=this.sandBox)||void 0===n||n.start(),function(e,t){const n=Array.from(e.entries()),o=[],r=[];for(const[e,i]of n)i.isDynamic||(i.defer||i.async?(i.isExternal?o.push(b(e)):o.push(i.code),r.push(i)):U(i.code,t,i.module,!1));o.length&&Promise.all(o).then((e=>{e.forEach(((e,n)=>{U(e,t,r[n].module,!1)}))})).catch((e=>{console.error("[micro-app]",e)}))}(this.source.scripts,this),this.status=h.MOUNTED,pe(this.container,this.name,m.MOUNTED)}unmount(e){var t;this.status===h.LOAD_SOURCE_ERROR&&(e=!0),this.status=h.UNMOUNT,pe(this.container,this.name,m.UNMOUNT),function(e){const t=new CustomEvent(`unmount-${e}`);window.dispatchEvent(t)}(this.name),null===(t=this.sandBox)||void 0===t||t.stop(),a(null),this.container=null,e&&de.delete(this.name)}onerror(e){pe(this.container,this.name,m.ERROR,e)}getAppStatus(){return this.status}}const me=Element.prototype.setAttribute,fe=Node.prototype.appendChild,ye=Node.prototype.insertBefore,be=Node.prototype.replaceChild,ge=Node.prototype.removeChild,we=Document.prototype.createElement,Ee=Document.prototype.createElementNS,ve=Document.prototype.createDocumentFragment,Oe=Document.prototype.querySelector,_e=Document.prototype.querySelectorAll,De=Document.prototype.getElementById,Ce=Document.prototype.getElementsByClassName,Ae=Document.prototype.getElementsByName,Se=new WeakMap;function Ne(e,t,n){if(t instanceof HTMLStyleElement){if(t.hasAttribute("exclude")){const e=document.createComment("style element with exclude attribute ignored by micro-app");return Se.set(t,e),e}return n.scopecss?_(t,n.name):t}if(t instanceof HTMLLinkElement){if(t.hasAttribute("exclude")){const e=document.createComment("link element with exclude attribute ignored by micro-app");return Se.set(t,e),e}if(!n.scopecss)return t;const{replaceComment:o,url:r,info:i}=N(t,e,n,null,!0);if(r&&i){const e=p("style");return function(e,t,n,o,r){if(n.source.links.has(e))return r.textContent=n.source.links.get(e).code,void _(r,n.name);if(S.has(e)){const o=S.get(e);return t.code=o,n.source.links.set(e,t),r.textContent=o,void _(r,n.name)}b(e).then((i=>{t.code=i,n.source.links.set(e,t),t.isGlobal&&S.set(e,i),r.textContent=i,_(r,n.name),C(o)})).catch((e=>{console.error("[micro-app]",e),A(o)}))}(r,i,n,t,e),Se.set(t,e),e}return o?(Se.set(t,o),o):t}if(t instanceof HTMLScriptElement){const{replaceComment:o,url:r,info:i}=M(t,e,n,!0);if(r&&i){if(i.code){const e=U(i.code,n,i.module,!0);return Se.set(t,e),e}{const e=function(e,t,n,o){if(n.source.scripts.has(e))return U(n.source.scripts.get(e).code,n,t.module,!0);if(R.has(e)){const o=R.get(e);return t.code=o,n.source.scripts.set(e,t),U(o,n,t.module,!0)}let r;return r=n.inline?p("script"):document.createComment(`dynamic script with src='${e}' extract by micro-app`),b(e).then((i=>{t.code=i,n.source.scripts.set(e,t),t.isGlobal&&R.set(e,i);try{i=T(i,n),n.inline?r.textContent=i:(0,eval)(i)}catch(e){console.error("[micro-app from runDynamicScript]",e)}C(o)})).catch((e=>{console.error("[micro-app]",e),A(o)})),r}(r,i,n,t);return Se.set(t,e),e}}return Se.set(t,o),o}return t}function xe(e,t,n,o,r){if(n instanceof HTMLHeadElement){const n=e.container.querySelector("micro-app-head");return r&&!n.contains(r)?fe.call(n,o):t.call(n,o,r)}if(n instanceof HTMLBodyElement){const n=e.container.querySelector("micro-app-body");return r&&!n.contains(r)?fe.call(n,o):t.call(e.container.querySelector("micro-app-body"),o,r)}return t.call(n,o,r)}function Re(e){var t;return null!==(t=Se.get(e))&&void 0!==t?t:e}function Le(e,t,n,o,r){if(null==t?void 0:t._MICRO_APP_NAME_){const i=de.get(t._MICRO_APP_NAME_);return(null==i?void 0:i.container)?xe(i,r,e,Ne(e,t,i),n&&Re(n)):o}return r.call(e,t,n)}function Me(){!function(){function e(e){var t,n,o;const r=l();return r&&"head"!==e&&"body"!==e?null!==(o=null===(n=null===(t=de.get(r))||void 0===t?void 0:t.container)||void 0===n?void 0:n.querySelector(e))&&void 0!==o?o:null:Oe.call(document,e)}function t(e){var t,n,o;const r=l();return r&&"head"!==e&&"body"!==e?null!==(o=null===(n=null===(t=de.get(r))||void 0===t?void 0:t.container)||void 0===n?void 0:n.querySelectorAll(e))&&void 0!==o?o:[]:_e.call(document,e)}Document.prototype.createElement=function(e,t){return Pe(we.call(document,e,t))},Document.prototype.createElementNS=function(e,t,n){return Pe(Ee.call(document,e,t,n))},Document.prototype.createDocumentFragment=function(){return Pe(ve.call(document))},Document.prototype.querySelector=e,Document.prototype.querySelectorAll=t,Document.prototype.getElementById=function(t){return e(`#${t}`)},Document.prototype.getElementsByClassName=function(e){return t(`.${e}`)},Document.prototype.getElementsByName=function(e){return t(`[name=${e}]`)}}(),Element.prototype.setAttribute=function(e,n){if("MICRO-APP"===this.tagName&&"data"===e)if("[object Object]"===toString.call(n)){const e={};Object.getOwnPropertyNames(n).forEach((t=>{"string"==typeof t&&0===t.indexOf("__")||(e[t]=n[t])})),this.data=e}else"[object Object]"!==n&&console.warn(t("property data must be an object"));else if(("src"===e&&/^(img|iframe|script|style)$/i.test(this.tagName)||"href"===e&&/^(link|a)$/i.test(this.tagName))&&this._MICRO_APP_NAME_&&de.has(this._MICRO_APP_NAME_)){const t=de.get(this._MICRO_APP_NAME_);me.call(this,e,r(n,t.url))}else me.call(this,e,n)},Node.prototype.appendChild=function(e){return Le(this,e,null,e,fe)},Node.prototype.insertBefore=function(e,t){return Le(this,e,t,e,ye)},Node.prototype.replaceChild=function(e,t){return Le(this,e,t,t,be)},Node.prototype.removeChild=function(e){if(null==e?void 0:e._MICRO_APP_NAME_){const t=de.get(e._MICRO_APP_NAME_);return(null==t?void 0:t.container)?xe(t,ge,this,Re(e)):e}return ge.call(this,e)}}function Pe(e){const t=l();return t&&(e._MICRO_APP_NAME_=t),e}function Ue(){Document.prototype.createElement=we,Document.prototype.createElementNS=Ee,Document.prototype.createDocumentFragment=ve,Document.prototype.querySelector=Oe,Document.prototype.querySelectorAll=_e,Document.prototype.getElementById=De,Document.prototype.getElementsByClassName=Ce,Document.prototype.getElementsByName=Ae,Element.prototype.setAttribute=me,Node.prototype.appendChild=fe,Node.prototype.insertBefore=ye,Node.prototype.removeChild=ge,Node.prototype.replaceChild=be}let Te=!1;class $e extends HTMLElement{constructor(){super(),this.name="",this.url="",this.isWating=!1,this.cacheData=null,this.handleAttributeUpdate=()=>{this.isWating=!1;const e=this.getAttribute("name"),n=o(this.getAttribute("url"));if(this.legalAttribute("name",e)&&this.legalAttribute("url",n)){if(e!==this.name&&de.has(e)){if(de.get(e).getAppStatus()!==h.UNMOUNT)return this.setAttribute("name",this.name),console.error(t(`an app named ${this.name} already exists`))}e===this.name&&n===this.url||(this.handleUnmount(!0),this.name=e,this.url=n,this.innerHTML="",this.handleCreate())}else e!==this.name&&this.setAttribute("name",this.name)},1==++$e.microAppCount&&(Me(),function(){if(!Te){Te=!0;const e=document.createElement("style");e.setAttribute("type","text/css"),e.textContent="micro-app, micro-app-body { display: block; }",document.head.appendChild(e)}}())}static get observedAttributes(){return["name","url"]}connectedCallback(){if(!this.name||!this.url)return;const e=de.get(this.name);if(e)return e.url!==this.url||!e.isPrefetch&&e.getAppStatus()!==h.UNMOUNT?e.isPrefetch?console.error(t(`the url: ${this.url} is different from prefetch url: ${e.url}`)):console.error(t(`an app named ${this.name} already exists`)):(e.isPrefetch=!1,n((()=>{var t;return e.mount(null!==(t=this.shadowRoot)&&void 0!==t?t:this,this.getDisposeResult("inline"))})));this.getDisposeResult("shadowDOM")&&this.attachShadow({mode:"open"}),this.handleCreate()}disconnectedCallback(){this.handleUnmount(this.getDisposeResult("destory")),0==--$e.microAppCount&&Ue()}attributeChangedCallback(e,r,i){if(this.legalAttribute(e,i)&&this[e]!==i)if(e!==d.URL||this.url)e!==d.NAME||this.name?this.isWating||(this.isWating=!0,n(this.handleAttributeUpdate)):(this.cacheData&&(ue.setData(i,this.cacheData),this.cacheData=null),this.name=i);else{if(!(i=o(i)))return console.error(t("Invalid attribute url"));this.url=i}}legalAttribute(e,n){return!("string"!=typeof n||!n)||(console.error(t(`unexpected attribute ${e}, please check again`)),!1)}handleCreate(){var e;const t=new he({name:this.name,url:this.url,container:null!==(e=this.shadowRoot)&&void 0!==e?e:this,inline:this.getDisposeResult("inline"),scopecss:!this.getDisposeResult("disableScopecss"),useSandbox:!this.getDisposeResult("disableSandbox"),macro:this.getDisposeResult("macro")});de.set(this.name,t)}handleUnmount(e){const t=de.get(this.name);t&&t.unmount(e)}getDisposeResult(e){return(this.hasAttribute(e)||ue[e])&&"false"!==this.getAttribute(e)}set data(e){this.name?ue.setData(this.name,e):this.cacheData=e}get data(){return this.name?ue.getData(this.name,!0):this.cacheData?this.cacheData:null}}$e.microAppCount=0,customElements.get("micro-app")||customElements.define("micro-app",$e),e.default=ue,e.preFetch=le,e.removeDomScope=function(){a(null)},Object.defineProperty(e,"__esModule",{value:!0})})); +//# sourceMappingURL=index.umd.js.map diff --git a/docs/0.x/home/js/micro-app-loading.js b/docs/0.x/home/js/micro-app-loading.js new file mode 100644 index 000000000..4e6c22be1 --- /dev/null +++ b/docs/0.x/home/js/micro-app-loading.js @@ -0,0 +1,234 @@ +function getStyle(size = 1) { + const styleText = ` + .micro-app-logo { + width: 300px; + height: 300px; + transform: scale(${size}); + overflow: hidden; + animation: logo-spin .8s .8s linear infinite; + } + + @keyframes logo-spin { + 0% { + transform: scale(${size}) rotate(0); + } + 100% { + transform: scale(${size}) rotate(360deg); + } + } + + .logo-container { + display: flex; + height: 220px; + width: 220px; + position: relative; + margin: 160px auto 0; + } + + .logo-common-part-con { + height: 100px; + width: 110px; + flex-shrink: 0; + } + + .logo-common-part { + height: 100%; + width: 100%; + border-radius: 6px; + animation: logo-part-scale .8s .7s forwards; + } + + @keyframes logo-part-scale { + 0% { + height: 100%; + width: 100%; + } + 100% { + height: 60px; + width: 60px; + transform: skew(0); + border-radius: 50%; + } + } + + .logo-common-con-top { + position: absolute; + left: 50%; + margin-left: -55px; + top: -100px; + animation: shaking-top .8s ease-in-out; + } + + .logo-common-con-left { + animation: shaking-left .8s ease-in-out; + } + + .logo-common-con-right { + animation: shaking-right .8s ease-in-out; + } + + @keyframes shaking-left { + 10%, 90% { + transform: translate3d(-1px, 0, 0); + } + 25%, 85% { + transform: translate3d(-2px, 1px, 0); + } + 20%, 80% { + transform: translate3d(3px, 2px, 0); + } + 25%, 75% { + transform: translate3d(-1px, -2px, 0); + } + 30%, 70% { + transform: translate3d(-4px, -1px, 0); + } + 35%, 65% { + transform: translate3d(-2px, 1px, 0); + } + 40%, 60% { + transform: translate3d(3px, -2px, 0); + } + 45%, 55% { + transform: translate3d(0px, 2px, 0); + } + 50% { + transform: translate3d(-4px, 1px, 0); + } + } + + @keyframes shaking-right { + 10%, 90% { + transform: translate3d(1px, 2px, 0); + } + 20%, 80% { + transform: translate3d(-4px, -1px, 0); + } + 25%, 75% { + transform: translate3d(1px, 3px, 0); + } + 30%, 70% { + transform: translate3d(4px, -2px, 0); + } + 35%, 65% { + transform: translate3d(-1px, 3px, 0); + } + 40%, 60% { + transform: translate3d(-3px, -2px, 0); + } + 50% { + transform: translate3d(4px, -2px, 0); + } + } + + @keyframes shaking-top { + 10%, 90% { + transform: translate3d(-1px, 1px, 0); + } + 20%, 80% { + transform: translate3d(4px, -1px, 0); + } + 25%, 75% { + transform: translate3d(1px, -3px, 0); + } + 30%, 70% { + transform: translate3d(-3px, -3px, 0); + } + 35%, 65% { + transform: translate3d(1px, 4px, 0); + } + 40%, 60% { + transform: translate3d(-4px, 1px, 0); + } + 50% { + transform: translate3d(0px, -2px, 0); + } + } + + .logo-part-left-con { + transform: rotate(30deg); + animation: trans-part-left .8s 1s forwards; + } + + @keyframes trans-part-left { + to { + transform: rotate(7deg); + } + } + + .logo-part-left { + background-color: #59d6d2; + transform: skewX(30deg); + } + + .logo-part-right-con { + transform: rotate(90deg); + height: 96px; + width: 112px; + margin-left: 2px; + margin-top: 2px; + } + + .logo-part-right { + background-color: #2F3240; + transform: skewX(30deg); + } + + .logo-part-top-con { + transform: rotate(150deg); + animation: trans-part-top .8s 1s forwards; + } + + @keyframes trans-part-top { + to { + transform: rotate(50deg); + } + } + + .logo-part-top { + background-color: #2F3240; + transform: skewX(30deg); + } + ` + + const styleElement = document.createElement('style') + styleElement.textContent = styleText + return styleElement +} + +class MicroAppLoading extends HTMLElement { + constructor() { + super() + this.attachShadow({ mode: 'open' }) + } + + connectedCallback() { + this.shadowRoot.appendChild(getStyle(this.getAttribute('size') || 1)) + const container = document.createElement('div') + container.setAttribute('class', 'micro-app-logo') + container.innerHTML = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ` + this.shadowRoot.appendChild(container) + } +} + +if (!customElements.get('micro-app-loading')) { + customElements.define('micro-app-loading', MicroAppLoading) +} diff --git a/docs/0.x/media/logo.png b/docs/0.x/media/logo.png new file mode 100644 index 000000000..007851553 Binary files /dev/null and b/docs/0.x/media/logo.png differ diff --git a/docs/0.x/media/logo.svg b/docs/0.x/media/logo.svg new file mode 100755 index 000000000..3af7e03c4 --- /dev/null +++ b/docs/0.x/media/logo.svg @@ -0,0 +1 @@ + diff --git a/docs/0.x/media/qq.jpeg b/docs/0.x/media/qq.jpeg new file mode 100644 index 000000000..1501dec58 Binary files /dev/null and b/docs/0.x/media/qq.jpeg differ diff --git a/docs/0.x/static/docsify-copy-code.min.js b/docs/0.x/static/docsify-copy-code.min.js new file mode 100644 index 000000000..9766a7888 --- /dev/null +++ b/docs/0.x/static/docsify-copy-code.min.js @@ -0,0 +1,9 @@ +/*! + * docsify-copy-code + * v2.1.1 + * https://github.com/jperasmus/docsify-copy-code + * (c) 2017-2020 JP Erasmus + * MIT license + */ +!function(){"use strict";function s(o){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o})(o)}!function(o,e){void 0===e&&(e={});var t=e.insertAt;if(o&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.type="text/css","top"===t&&n.firstChild?n.insertBefore(c,n.firstChild):n.appendChild(c),c.styleSheet?c.styleSheet.cssText=o:c.appendChild(document.createTextNode(o))}}(".docsify-copy-code-button,.docsify-copy-code-button span{cursor:pointer;transition:all .25s ease}.docsify-copy-code-button{position:absolute;z-index:1;top:0;right:0;overflow:visible;padding:.65em .8em;border:0;border-radius:0;outline:0;font-size:1em;background:grey;background:var(--theme-color,grey);color:#fff;opacity:0}.docsify-copy-code-button span{border-radius:3px;background:inherit;pointer-events:none}.docsify-copy-code-button .error,.docsify-copy-code-button .success{position:absolute;z-index:-100;top:50%;right:0;padding:.5em .65em;font-size:.825em;opacity:0;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.docsify-copy-code-button.error .error,.docsify-copy-code-button.success .success{right:100%;opacity:1;-webkit-transform:translate(-115%,-50%);transform:translate(-115%,-50%)}.docsify-copy-code-button:focus,pre:hover .docsify-copy-code-button{opacity:1}"),document.querySelector('link[href*="docsify-copy-code"]')&&console.warn("[Deprecation] Link to external docsify-copy-code stylesheet is no longer necessary."),window.DocsifyCopyCodePlugin={init:function(){return function(o,e){o.ready(function(){console.warn("[Deprecation] Manually initializing docsify-copy-code using window.DocsifyCopyCodePlugin.init() is no longer necessary.")})}}},window.$docsify=window.$docsify||{},window.$docsify.plugins=[function(o,r){o.doneEach(function(){var o=Array.apply(null,document.querySelectorAll("pre[data-lang]")),c={buttonText:"Copy to clipboard",errorText:"Error",successText:"Copied"};r.config.copyCode&&Object.keys(c).forEach(function(t){var n=r.config.copyCode[t];"string"==typeof n?c[t]=n:"object"===s(n)&&Object.keys(n).some(function(o){var e=-1',''.concat(c.buttonText,""),''.concat(c.errorText,""),''.concat(c.successText,""),""].join("");o.forEach(function(o){o.insertAdjacentHTML("beforeend",e)})}),o.mounted(function(){document.querySelector(".content").addEventListener("click",function(o){if(o.target.classList.contains("docsify-copy-code-button")){var e="BUTTON"===o.target.tagName?o.target:o.target.parentNode,t=document.createRange(),n=e.parentNode.querySelector("code"),c=window.getSelection();t.selectNode(n),c.removeAllRanges(),c.addRange(t);try{document.execCommand("copy")&&(e.classList.add("success"),setTimeout(function(){e.classList.remove("success")},1e3))}catch(o){console.error("docsify-copy-code: ".concat(o)),e.classList.add("error"),setTimeout(function(){e.classList.remove("error")},1e3)}"function"==typeof(c=window.getSelection()).removeRange?c.removeRange(t):"function"==typeof c.removeAllRanges&&c.removeAllRanges()}})})}].concat(window.$docsify.plugins||[])}(); +//# sourceMappingURL=docsify-copy-code.min.js.map diff --git a/docs/0.x/static/docsify-pagination.min.js b/docs/0.x/static/docsify-pagination.min.js new file mode 100644 index 000000000..11b90291e --- /dev/null +++ b/docs/0.x/static/docsify-pagination.min.js @@ -0,0 +1 @@ +!function(t){("object"!=typeof exports||"undefined"==typeof module)&&"function"==typeof define&&define.amd?define(t):t()}(function(){"use strict";var i="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(t,e){return t(e={exports:{}},e.exports),e.exports}var c=t(function(t,e){function n(t,e){return e.querySelector(t)}(e=t.exports=function(t,e){return n(t,e=e||document)}).all=function(t,e){return(e=e||document).querySelectorAll(t)},e.engine=function(t){if(!t.one)throw new Error(".one callback required");if(t.all)return n=t.one,e.all=t.all,e;throw new Error(".all callback required")}}),e=(c.all,c.engine,t(function(e){var n=eval;try{n("export default global")}catch(t){try{n("export default self")}catch(t){try{e.exports=i}catch(t){try{self.global=self}catch(t){window.global=window}}}}}));try{var a=c}catch(t){a=c}var e=e.Element,e=e&&e.prototype||{},r=e.matches||e.webkitMatchesSelector||e.mozMatchesSelector||e.msMatchesSelector||e.oMatchesSelector,s=function(t,e){if(!t||1!==t.nodeType)return!1;if(r)return r.call(t,e);for(var n=a.all(e,t.parentNode),i=0;i ul > li"),c("p",e)),this.hyperlink=m(t))}var b=function(){return'
'},k=function(t,e){a=e,r=t.route.path,o={},["previousText","nextText"].forEach(function(n){var i=a[n];"string"==typeof i?o[n]=i:Object.keys(i).some(function(t){var e=r&&-1\n \n
\n \n \n \n '+i+'\n
\n
'+t.prev.name+"
\n ",t.prev&&e.crossChapterText&&'
'+t.prev.chapterName+"
",t.prev&&"
\n \n ",t.next&&'\n \n "].filter(Boolean).join("")};window.$docsify=window.$docsify||{},window.$docsify.plugins=[function(t,e){var n=d({},(e.config,{previousText:"PREVIOUS",nextText:"NEXT",crossChapter:!1,crossChapterText:!1}),e.config.pagination||{});function i(){var t=c("."+h);t&&(t.innerHTML=k(function(t,e){e=e.crossChapter;try{var n=t.router.toURL(t.route.path),i=g(c.all(".sidebar-nav li a")).filter(function(t){return!s(t,".section-link")}),a=i.find(x(n)),r=g((p(a,"ul")||{}).children).filter(function(t){return"LI"===t.tagName.toUpperCase()}),o=e?i.findIndex(x(n)):r.findIndex(function(t){t=m(t);return t&&x(n,t)}),l=e?i:r;return{route:t.route,prev:new y(l[o-1]).toJSON(),next:new y(l[o+1]).toJSON()}}catch(t){return{route:{}}}}(e,n),n))}t.afterEach(function(t){return t+b()}),t.doneEach(i)}].concat(window.$docsify.plugins||[])}); diff --git a/docs/0.x/static/docsify-plugin-flexible-alerts.min.js b/docs/0.x/static/docsify-plugin-flexible-alerts.min.js new file mode 100644 index 000000000..67566474b --- /dev/null +++ b/docs/0.x/static/docsify-plugin-flexible-alerts.min.js @@ -0,0 +1,9 @@ +/*! + * docsify-plugin-flexible-alerts + * v1.1.1 + * https://github.com/fzankl/docsify-plugin-flexible-alerts#readme + * (c) 2022 Fabian Zankl + * MIT license + */ +!function(){"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t(e)}!function(t,e){void 0===e&&(e={});var a=e.insertAt;if(t&&"undefined"!=typeof document){var o=document.head||document.getElementsByTagName("head")[0],l=document.createElement("style");l.type="text/css","top"===a&&o.firstChild?o.insertBefore(l,o.firstChild):o.appendChild(l),l.styleSheet?l.styleSheet.cssText=t:l.appendChild(document.createTextNode(t))}}(".alert{word-wrap:break-word;display:block;margin-bottom:1rem!important;padding:.75rem 1.25rem!important;position:relative;word-break:break-word}.alert>*{max-width:100%}.alert>:first-child{margin-top:0}.alert>:last-child{margin-bottom:0}.alert:before{content:unset!important}.alert+.alert{margin-top:-.25rem!important}.alert p{margin-bottom:.5rem;margin-top:.5rem}.alert .title{align-items:center;display:flex;flex-wrap:wrap;font-weight:600;margin:0}.icon{background-repeat:no-repeat;display:inline-block;height:16px;margin-right:.5rem;width:16px}.alert.callout{background:var(--background);border:1px solid #eee;border-left-width:.25rem;border-radius:.25rem}.alert.callout.note{border-left-color:#17a2b8!important}.alert.callout.note .title{color:#17a2b8}.alert.callout.note .icon-note{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 16 16' fill='%2317a2b8' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM8 5.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2z'/%3E%3C/svg%3E\")}.alert.callout.tip{border-left-color:#28a745!important}.alert.callout.tip .title{color:#28a745}.alert.callout.tip .icon-tip{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 352 512' fill='%2328a745' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M96.06 454.35c.01 6.29 1.87 12.45 5.36 17.69l17.09 25.69a31.99 31.99 0 0 0 26.64 14.28h61.71a31.99 31.99 0 0 0 26.64-14.28l17.09-25.69a31.989 31.989 0 0 0 5.36-17.69l.04-38.35H96.01l.05 38.35zM0 176c0 44.37 16.45 84.85 43.56 115.78 16.52 18.85 42.36 58.23 52.21 91.45.04.26.07.52.11.78h160.24c.04-.26.07-.51.11-.78 9.85-33.22 35.69-72.6 52.21-91.45C335.55 260.85 352 220.37 352 176 352 78.61 272.91-.3 175.45 0 73.44.31 0 82.97 0 176zm176-80c-44.11 0-80 35.89-80 80 0 8.84-7.16 16-16 16s-16-7.16-16-16c0-61.76 50.24-112 112-112 8.84 0 16 7.16 16 16s-7.16 16-16 16z'/%3E%3C/svg%3E\")}.alert.callout.warning{border-left-color:#f0ad4e!important}.alert.callout.warning .title{color:#f0ad4e}.alert.callout.warning .icon-warning{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 17 16' fill='%23f0ad4e' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 5zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/%3E%3C/svg%3E\")}.alert.callout.attention{border-left-color:#dc3545!important}.alert.callout.attention .title{color:#dc3545}.alert.callout.attention .icon-attention{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 16 16' fill='%23dc3545' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z'/%3E%3Cpath fill-rule='evenodd' d='M11.354 4.646a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E\")}.alert.flat{background-color:#e2e3e5;border:1px solid #d6d8db;border-radius:.125rem;color:#383d41}.alert.flat.note{background-color:#cdeefd;border-color:#b4e6fc;color:#02587f}.alert.flat.note .title{color:#01354d}.alert.flat.note .icon-note{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 16 16' fill='%2301354d' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM8 5.5a1 1 0 1 0 0-2 1 1 0 0 0 0 2z'/%3E%3C/svg%3E\")}.alert.flat.tip{background-color:#dbefdc;border-color:#c9e7cb;color:#285b2a}.alert.flat.tip .title{color:#18381a}.alert.flat.tip .icon-tip{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 352 512' fill='%2318381a' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M96.06 454.35c.01 6.29 1.87 12.45 5.36 17.69l17.09 25.69a31.99 31.99 0 0 0 26.64 14.28h61.71a31.99 31.99 0 0 0 26.64-14.28l17.09-25.69a31.989 31.989 0 0 0 5.36-17.69l.04-38.35H96.01l.05 38.35zM0 176c0 44.37 16.45 84.85 43.56 115.78 16.52 18.85 42.36 58.23 52.21 91.45.04.26.07.52.11.78h160.24c.04-.26.07-.51.11-.78 9.85-33.22 35.69-72.6 52.21-91.45C335.55 260.85 352 220.37 352 176 352 78.61 272.91-.3 175.45 0 73.44.31 0 82.97 0 176zm176-80c-44.11 0-80 35.89-80 80 0 8.84-7.16 16-16 16s-16-7.16-16-16c0-61.76 50.24-112 112-112 8.84 0 16 7.16 16 16s-7.16 16-16 16z'/%3E%3C/svg%3E\")}.alert.flat.warning{background-color:#ffddd3;border-color:#ffc9ba;color:#852d12}.alert.flat.warning .title{color:#581e0c}.alert.flat.warning .icon-warning{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 17 16' fill='%23581e0c' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5a.905.905 0 0 0-.9.995l.35 3.507a.552.552 0 0 0 1.1 0l.35-3.507A.905.905 0 0 0 8 5zm.002 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2z'/%3E%3C/svg%3E\")}.alert.flat.attention{background-color:#fdd9d7;border-color:#fcc2bf;color:#7f231c}.alert.flat.attention .title{color:#551713}.alert.flat.attention .icon-attention{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg width='1em' height='1em' viewBox='0 0 16 16' fill='%23551713' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z'/%3E%3Cpath fill-rule='evenodd' d='M11.354 4.646a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E\")}"),function(){var e={style:"callout",note:{label:"Note",icon:"icon-note",className:"note"},tip:{label:"Tip",icon:"icon-tip",className:"tip"},warning:{label:"Warning",icon:"icon-warning",className:"warning"},attention:{label:"Attention",icon:"icon-attention",className:"attention"},typeMappings:{info:"note",danger:"attention"}};function a(t,e){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;for(var l in e)try{e[l].constructor===Object&&o<1?t[l]=a(t[l],e[l],o+1):t[l]=e[l]}catch(a){t[l]=e[l]}return t}window.$docsify=window.$docsify||{},window.$docsify.plugins=[].concat((function(o,l){var r=a(e,l.config["flexible-alerts"]||l.config.flexibleAlerts),i=function(t,e,a,o){var l=(t||"").match(new RegExp("".concat(e,":(([\\s\\w\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF-]*))")));return l?o?o(l[1]):l[1]:o?o(a):a};o.afterEach((function(e,a){a(e.replace(/<\s*blockquote[^>]*>[\s]+?(?:

)?\[!(\w*)((?:\|[\w*:[\s\w\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF-]*)*?)\]([\s\S]*?)(?:<\/p>)?<\s*\/\s*blockquote>/g,(function(e,a,o,n){!r[a.toLowerCase()]&&r.typeMappings[a.toLowerCase()]&&(a=r.typeMappings[a.toLowerCase()]);var c=r[a.toLowerCase()];if(!c)return e;var d=i(o,"style",r.style),s=i(o,"iconVisibility","visible",(function(t){return"hidden"!==t})),g=i(o,"labelVisibility","visible",(function(t){return"hidden"!==t})),m=i(o,"label",c.label),u=i(o,"icon",c.icon),f=i(o,"className",c.className);if("object"===t(m)){var p=Object.keys(m).filter((function(t){return l.route.path.indexOf(t)>-1}));p&&p.length>0?m=m[p[0]]:(g=!1,s=!1)}var w=''),h='

'.concat(s?w:"").concat(g?m:"","

");return'
\n ').concat(s||g?h:"","\n

").concat(n,"

\n
")})))}))}),window.$docsify.plugins)}()}(); +//# sourceMappingURL=docsify-plugin-flexible-alerts.min.js.map diff --git a/docs/0.x/static/docsify-search.js b/docs/0.x/static/docsify-search.js new file mode 100644 index 000000000..63b5bc7e4 --- /dev/null +++ b/docs/0.x/static/docsify-search.js @@ -0,0 +1 @@ +!function(){function u(e){return e.replace(//,"").replace(/{docsify-ignore}/,"").replace(//,"").replace(/{docsify-ignore-all}/,"").trim()}var f={},m={EXPIRE_KEY:"docsify.search.expires",INDEX_KEY:"docsify.search.index"};function g(e){var n={"&":"&","<":"<",">":">",'"':""","'":"'"};return String(e).replace(/[&<>"']/g,function(e){return n[e]})}function y(e){return e.text||"table"!==e.type||(e.cells.unshift(e.header),e.text=e.cells.map(function(e){return e.join(" | ")}).join(" |\n ")),e.text}function v(e){return e.text||"list"!==e.type||(e.text=e.raw),e.text}function b(o,e,s,c){void 0===e&&(e="");var d,e=window.marked.lexer(e),l=window.Docsify.slugify,p={},h="";return e.forEach(function(e,n){var t,a,i,r;"heading"===e.type&&e.depth<=c?(t=(a=(i=e.text,r={},{str:i=(i=void 0===i?"":i)&&i.replace(/^('|")/,"").replace(/('|")$/,"").replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g,function(e,n,t){return-1===n.indexOf(":")?(r[n]=t&&t.replace(/"/g,"")||!0,""):e}).trim(),config:r})).str,i=a.config,a=u(e.text),d=i.id?s.toURL(o,{id:l(i.id)}):s.toURL(o,{id:l(g(a))}),t&&(h=u(t)),p[d]={slug:d,title:h,body:""}):(0===n&&(d=s.toURL(o),p[d]={slug:d,title:"/"!==o?o.slice(1):"Home Page",body:e.text||""}),d&&(p[d]?p[d].body?(e.text=y(e),e.text=v(e),p[d].body+="\n"+(e.text||"")):(e.text=y(e),e.text=v(e),p[d].body=e.text||""):p[d]={slug:d,title:"",body:""}))}),l.clear(),p}function p(e){return e&&e.normalize?e.normalize("NFD").replace(/[\u0300-\u036f]/g,""):e}function o(e){var n=[],t=[];Object.keys(f).forEach(function(n){t=t.concat(Object.keys(f[n]).map(function(e){return f[n][e]}))});var a=(e=e.trim()).split(/[\s\-,\\/]+/);1!==a.length&&(a=[].concat(e,a));for(var i=0;il.length&&(t=l.length),a=c&&"..."+c.substring(n,t).replace(a,function(e){return''+e+""})+"...",o+=a)}),0\n\n

'+e.title+"

\n

"+e.content+"

\n
\n"}),t.classList.add("show"),a.classList.add("show"),t.innerHTML=r||'

'+c+"

",s.hideOtherSidebarContent&&(i&&i.classList.add("hide"),n&&n.classList.add("hide"))}function l(e){s=e}function h(e,n){var t,a,i=n.router.parse().query.s;l(e),Docsify.dom.style("\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0.6em 7px;\n font-size: inherit;\n border: 1px solid transparent;\n}\n\n.search input:focus {\n box-shadow: 0 0 5px var(--theme-color, #42b983);\n border: 1px solid var(--theme-color, #42b983);\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n\n.search input::-ms-clear {\n display: none;\n height: 0;\n width: 0;\n}\n\n.search .clear-button {\n cursor: pointer;\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}\n\n.app-name.hide, .sidebar-nav.hide {\n display: none;\n}"),function(e){void 0===e&&(e="");var n=Docsify.dom.create("div",'
\n \n
\n \n \n \n \n \n
\n
\n
\n '),e=Docsify.dom.find("aside");Docsify.dom.toggleClass(n,"search"),Docsify.dom.before(e,n)}(i),n=Docsify.dom.find("div.search"),a=Docsify.dom.find(n,"input"),e=Docsify.dom.find(n,".input-wrap"),Docsify.dom.on(n,"click",function(e){return-1===["A","H2","P","EM"].indexOf(e.target.tagName)&&e.stopPropagation()}),Docsify.dom.on(a,"input",function(n){clearTimeout(t),t=setTimeout(function(e){return d(n.target.value.trim())},100)}),Docsify.dom.on(e,"click",function(e){"INPUT"!==e.target.tagName&&(a.value="",d())}),i&&setTimeout(function(e){return d(i)},500)}function x(e,n){var t,a,i,r,o;l(e),t=e.placeholder,a=n.route.path,(r=Docsify.dom.getNode('.search input[type="search"]'))&&("string"==typeof t?r.placeholder=t:(i=Object.keys(t).filter(function(e){return-1:first-child{margin-top:0}.docsify-tabs__content[class]>:last-child{margin-bottom:0}.docsify-tabs__tab--active+.docsify-tabs__content[class]{height:auto;overflow:auto;position:relative;visibility:visible}[class*=docsify-tabs--]{margin:1.5em 0;margin:var(--docsifytabs-margin)}[class*=docsify-tabs--]>.docsify-tabs__tab{background:#f8f8f8;background:var(--docsifytabs-tab-background);color:#999;color:var(--docsifytabs-tab-color);padding:.6em 1em;padding:var(--docsifytabs-tab-padding)}[class*=docsify-tabs--]>.docsify-tabs__tab--active{background:inherit;background:var(--docsifytabs-tab-background--active);color:inherit;color:var(--docsifytabs-tab-color--active)}[class*=docsify-tabs--]>.docsify-tabs__content{background:inherit;background:var(--docsifytabs-content-background)}[class*=docsify-tabs--]>.docsify-tabs__tab--active+.docsify-tabs__content{padding:1.5rem;padding:var(--docsifytabs-content-padding)}.docsify-tabs--classic:before,.docsify-tabs--classic>.docsify-tabs__content,.docsify-tabs--classic>.docsify-tabs__tab{border-color:#ededed;border-color:var(--docsifytabs-border-color);border-style:solid;border-width:1px;border-width:var(--docsifytabs-border-px)}.docsify-tabs--classic:before{border-left-width:0;border-right-width:0;border-top-width:0;margin-right:1px;margin-right:var(--docsifytabs-border-px)}.docsify-tabs--classic>.docsify-tabs__tab:first-of-type{border-top-left-radius:var(--docsifytabs-border-radius-px)}.docsify-tabs--classic>.docsify-tabs__tab:last-of-type{border-top-right-radius:var(--docsifytabs-border-radius-px)}.docsify-tabs--classic>.docsify-tabs__tab~.docsify-tabs__tab{margin-left:-1px;margin-left:calc(0px - var(--docsifytabs-border-px))}.docsify-tabs--classic>.docsify-tabs__tab--active{border-bottom-width:0;box-shadow:inset 0 3px 0 0 currentColor;box-shadow:inset 0 var(--docsifytabs-tab-highlight-px) 0 0 var(--docsifytabs-tab-highlight-color)}.docsify-tabs--classic>.docsify-tabs__content{border-radius:0;border-radius:0 var(--docsifytabs-border-radius-px) var(--docsifytabs-border-radius-px) var(--docsifytabs-border-radius-px);border-top:0;margin-top:-1px;margin-top:calc(0px - var(--docsifytabs-border-px))}.docsify-tabs--material>.docsify-tabs__tab{background:transparent;border:0;margin-bottom:2px;margin-bottom:calc(var(--docsifytabs-tab-highlight-px) - var(--docsifytabs-border-px))}.docsify-tabs--material>.docsify-tabs__tab--active{background:transparent;box-shadow:0 3px 0 0 currentColor;box-shadow:0 var(--docsifytabs-tab-highlight-px) 0 0 var(--docsifytabs-tab-highlight-color)}.docsify-tabs--material>.docsify-tabs__content{border-color:#ededed;border-color:var(--docsifytabs-border-color);border-style:solid;border-width:1px 0;border-width:var(--docsifytabs-border-px) 0}',{insertAt:"top"});var t="tabs:replace",a={tabsContainer:"content",tabBlock:"docsify-tabs",tabButton:"docsify-tabs__tab",tabButtonActive:"docsify-tabs__tab--active",tabContent:"docsify-tabs__content"},o={codeMarkup:/(```[\s\S]*?```)/gm,commentReplaceMarkup:new RegExp("\x3c!-- ".concat(t," (.*?) --\x3e")),tabBlockMarkup:/( *)()(?:(?!())[\s\S])*()/,tabCommentMarkup:/[\r\n]*(\s*)[\r\n]+([\s\S]*?)[\r\n]*\s*(?=)/m},c={persist:!0,sync:!0,theme:"classic",tabComments:!0,tabHeadings:!0},e={get persist(){return"docsify-tabs.persist.".concat(window.location.pathname)},sync:"docsify-tabs.sync"};function s(t,a){return(Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector).call(t,a)}function r(){var t=document.querySelector(".".concat(a.tabsContainer)),o=t?Array.apply(null,t.querySelectorAll(".".concat(a.tabBlock))):[],r=JSON.parse(sessionStorage.getItem(e.persist))||{},i=JSON.parse(sessionStorage.getItem(e.sync))||[];!function(){var t=window.location.hash||window.location.search,o=decodeURIComponent((t.match(/(?:id=)([^&]+)/)||[])[1]),c=o&&".".concat(a.tabBlock," #").concat(o);if(o&&document.querySelector(c)){var e,s=document.querySelector("#".concat(o));if(s.closest)e=s.closest(".".concat(a.tabContent));else for(e=s.parentNode;e!==document.body&&!e.classList.contains("".concat(a.tabContent));)e=e.parentNode;n(e.previousElementSibling)}}(),o.forEach((function(t,o){var e=Array.apply(null,t.children).filter((function(t){return s(t,".".concat(a.tabButtonActive))}))[0];e||(c.sync&&i.length&&(e=i.map((function(o){return Array.apply(null,t.children).filter((function(t){return s(t,".".concat(a.tabButton,'[data-tab="').concat(o,'"]'))}))[0]})).filter((function(t){return t}))[0]),!e&&c.persist&&(e=Array.apply(null,t.children).filter((function(t){return s(t,".".concat(a.tabButton,'[data-tab="').concat(r[o],'"]'))}))[0]),(e=e||t.querySelector(".".concat(a.tabButton)))&&e.classList.add(a.tabButtonActive))}))}function n(t){var o=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=function(t,a){if(Element.prototype.closest)return t.closest(a);for(;t;){if(s(t,a))return t;t=t.parentNode||null}return t}(t,".".concat(a.tabButton));if(r){var i=r.getAttribute("data-tab"),d=document.querySelector(".".concat(a.tabsContainer)),b=r.parentNode,f=Array.apply(null,b.children).filter((function(t){return s(t,"button")})),l=b.offsetTop;if(f.forEach((function(t){return t.classList.remove(a.tabButtonActive)})),r.classList.add(a.tabButtonActive),!o){if(c.persist){var u=(d?Array.apply(null,d.querySelectorAll(".".concat(a.tabBlock))):[]).indexOf(b),y=JSON.parse(sessionStorage.getItem(e.persist))||{};y[u]=i,sessionStorage.setItem(e.persist,JSON.stringify(y))}if(c.sync){var p=d?Array.apply(null,d.querySelectorAll(".".concat(a.tabButton,'[data-tab="').concat(i,'"]'))):[],m=JSON.parse(sessionStorage.getItem(e.sync))||[];p.forEach((function(t){n(t,!0)})),window.scrollBy(0,0-(l-b.offsetTop)),m.indexOf(i)>0&&m.splice(m.indexOf(i),1),0!==m.indexOf(i)&&(m.unshift(i),sessionStorage.setItem(e.sync,JSON.stringify(m)))}}}}window&&(window.$docsify=window.$docsify||{},window.$docsify.tabs=window.$docsify.tabs||{},Object.keys(window.$docsify.tabs).forEach((function(t){Object.prototype.hasOwnProperty.call(c,t)&&(c[t]=window.$docsify.tabs[t])})),window.$docsify.tabs.version="1.6.3",(c.tabComments||c.tabHeadings)&&(window.$docsify.plugins=[].concat(window.$docsify.plugins||[],(function(e,s){var i=!1;e.beforeEach((function(e){return(i=o.tabBlockMarkup.test(e))&&(e=function(e,s){for(var r=e.match(o.codeMarkup)||[],n=r.map((function(a,o){var c="\x3c!-- ".concat(t," CODEBLOCK").concat(o," --\x3e");return e=e.replace(a,(function(){return c})),c})),i=c.theme?"".concat(a.tabBlock,"--").concat(c.theme):"",d=document.createElement("div"),b=e.match(o.tabBlockMarkup),f=1,l=function(){var r,n=b[0],l=b[1],u=b[2],y=b[4],p=c.tabComments&&o.tabCommentMarkup.test(n),m=c.tabHeadings&&o.tabHeadingMarkup.test(n),h="",g="";if(p||m){h="\x3c!-- ".concat(t,'
--\x3e'),g="\n".concat(l,"\x3c!-- ").concat(t,"
--\x3e");for(var v=function(){d.innerHTML=r[2].trim()?s.compiler.compile(r[2]).replace(/<\/?p>/g,""):"Tab ".concat(f);var o=d.innerHTML,c=(r[3]||"").trim(),e=(d.textContent||d.firstChild.getAttribute("alt")||d.firstChild.getAttribute("src")).trim().toLowerCase();n=n.replace(r[0],(function(){return["\n".concat(l,"\x3c!-- ").concat(t,' --\x3e"),"\n".concat(l,"\x3c!-- ").concat(t,'
--\x3e'),"\n\n".concat(l).concat(c),"\n\n".concat(l,"\x3c!-- ").concat(t,"
--\x3e")].join("")})),f++};null!==(r=(c.tabComments?o.tabCommentMarkup.exec(n):null)||(c.tabHeadings?o.tabHeadingMarkup.exec(n):null));)v()}n=(n=n.replace(u,(function(){return h}))).replace(y,(function(){return g})),e=e.replace(b[0],(function(){return n})),b=e.match(o.tabBlockMarkup)};b;)l();return n.forEach((function(t,a){e=e.replace(t,(function(){return r[a]}))})),e}(e,s)),e})),e.afterEach((function(t,a){i&&(t=function(t){for(var a,c=function(){var o=a[0],c=a[1]||"";t=t.replace(o,(function(){return c}))};null!==(a=o.commentReplaceMarkup.exec(t));)c();return t}(t)),a(t)})),e.doneEach((function(){i&&r()})),e.mounted((function(){var t=document.querySelector(".".concat(a.tabsContainer));t&&t.addEventListener("click",(function(t){n(t.target)}))}))}))))}(); +//# sourceMappingURL=docsify-tabs.min.js.map diff --git a/docs/static/vue.css b/docs/0.x/static/docsify-vue.css similarity index 100% rename from docs/static/vue.css rename to docs/0.x/static/docsify-vue.css diff --git a/docs/0.x/static/docsify-zoom-image.js b/docs/0.x/static/docsify-zoom-image.js new file mode 100644 index 000000000..63153aefc --- /dev/null +++ b/docs/0.x/static/docsify-zoom-image.js @@ -0,0 +1 @@ +!function(){function t(e){return"IMG"===e.tagName}function d(e){function t(){for(var e=arguments,t=arguments.length,o=Array(t),n=0;nu.scrollOffset&&setTimeout(a,150))}),window.addEventListener("resize",a);var f={open:i,close:a,toggle:o,update:function(){var e=0=e||n.classList.contains("hidden")?S(h,"add","sticky"):S(h,"remove","sticky"))}function ee(e,n,o,i){var t=[];null!=(n=l(n))&&(t=k(n,"a"));var a,r=decodeURI(e.toURL(e.getCurrentPath()));return t.sort(function(e,n){return n.href.length-e.href.length}).forEach(function(e){var n=decodeURI(e.getAttribute("href")),i=o?e.parentNode:e;e.title=e.title||e.innerText,0!==r.indexOf(n)||a?S(i,"remove","active"):(a=e,S(i,"add","active"))}),i&&(v.title=a?a.title||a.innerText+" - "+J:J),a}function ne(e,n){for(var i=0;ithis.end&&e>=this.next}[this.direction]}},{key:"_defaultEase",value:function(e,n,i,o){return(e/=o/2)<1?i/2*e*e+n:-i/2*(--e*(e-2)-1)+n}}]),re);function re(){var e=0c){n=n||p;break}n=p}!n||(r=fe[ve(e,n.getAttribute("data-id"))])&&r!==a&&(a&&a.classList.remove("active"),r.classList.add("active"),a=r,!pe&&h.classList.contains("sticky")&&(e=i.clientHeight,r=a.offsetTop+a.clientHeight+40,a=a.offsetTop>=t.scrollTop&&r<=t.scrollTop+e,i.scrollTop=a?t.scrollTop:+r"']/),xe=/[&<>"']/g,Se=/[<>"']|&(?!#?\w+;)/,Ae=/[<>"']|&(?!#?\w+;)/g,$e={"&":"&","<":"<",">":">",'"':""","'":"'"};var ze=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function Fe(e){return e.replace(ze,function(e,n){return"colon"===(n=n.toLowerCase())?":":"#"===n.charAt(0)?"x"===n.charAt(1)?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1)):""})}var Ee=/(^|[^\[])\^/g;var Re=/[^\w:]/g,Te=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;var Ce={},je=/^[^:]+:\/*[^/]*$/,Le=/^([^:]+:)[\s\S]*$/,Oe=/^([^:]+:\/*[^/]*)[\s\S]*$/;function qe(e,n){Ce[" "+e]||(je.test(e)?Ce[" "+e]=e+"/":Ce[" "+e]=Pe(e,"/",!0));var i=-1===(e=Ce[" "+e]).indexOf(":");return"//"===n.substring(0,2)?i?n:e.replace(Le,"$1")+n:"/"===n.charAt(0)?i?n:e.replace(Oe,"$1")+n:e+n}function Pe(e,n,i){var o=e.length;if(0===o)return"";for(var t=0;tn)i.splice(n);else for(;i.length>=1,e+=e;return i+e},We=we.defaults,Xe=Be,Qe=Ze,Je=Me,Ke=Ve;function en(e,n,i){var o=n.href,t=n.title?Je(n.title):null,n=e[1].replace(/\\([\[\]])/g,"$1");return"!"!==e[0].charAt(0)?{type:"link",raw:i,href:o,title:t,text:n}:{type:"image",raw:i,href:o,title:t,text:Je(n)}}var nn=function(){function e(e){this.options=e||We}return e.prototype.space=function(e){e=this.rules.block.newline.exec(e);if(e)return 1=i.length?e.slice(i.length):e}).join("\n")}(i,n[3]||"");return{type:"code",raw:i,lang:n[2]&&n[2].trim(),text:e}}},e.prototype.heading=function(e){var n=this.rules.block.heading.exec(e);if(n){var i=n[2].trim();return/#$/.test(i)&&(e=Xe(i,"#"),!this.options.pedantic&&e&&!/ $/.test(e)||(i=e.trim())),{type:"heading",raw:n[0],depth:n[1].length,text:i}}},e.prototype.nptable=function(e){e=this.rules.block.nptable.exec(e);if(e){var n={type:"table",header:Qe(e[1].replace(/^ *| *\| *$/g,"")),align:e[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:e[3]?e[3].replace(/\n$/,"").split("\n"):[],raw:e[0]};if(n.header.length===n.align.length){for(var i=n.align.length,o=0;o ?/gm,"");return{type:"blockquote",raw:n[0],text:e}}},e.prototype.list=function(e){e=this.rules.block.list.exec(e);if(e){for(var n,i,o,t,a,r=e[0],c=e[2],u=1s[1].length:o[1].length>s[0].length||3/i.test(e[0])&&(n=!1),!i&&/^<(pre|code|kbd|script)(\s|>)/i.test(e[0])?i=!0:i&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(e[0])&&(i=!1),{type:this.options.sanitize?"text":"html",raw:e[0],inLink:n,inRawBlock:i,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):Je(e[0]):e[0]}},e.prototype.link=function(e){var n=this.rules.inline.link.exec(e);if(n){e=n[2].trim();if(!this.options.pedantic&&/^$/.test(e))return;var i=Xe(e.slice(0,-1),"\\");if((e.length-i.length)%2==0)return}else{var o=Ke(n[2],"()");-1$/.test(e)?i.slice(1):i.slice(1,-1):i)&&i.replace(this.rules.inline._escapes,"$1"),title:o&&o.replace(this.rules.inline._escapes,"$1")},n[0])}},e.prototype.reflink=function(e,n){if((i=this.rules.inline.reflink.exec(e))||(i=this.rules.inline.nolink.exec(e))){var e=(i[2]||i[1]).replace(/\s+/g," ");if((e=n[e.toLowerCase()])&&e.href)return en(i,e,i[0]);var i=i[0].charAt(0);return{type:"text",raw:i,text:i}}},e.prototype.strong=function(e,n,i){void 0===i&&(i="");var o=this.rules.inline.strong.start.exec(e);if(o&&(!o[1]||o[1]&&(""===i||this.rules.inline.punctuation.exec(i)))){n=n.slice(-1*e.length);var t,a="**"===o[0]?this.rules.inline.strong.endAst:this.rules.inline.strong.endUnd;for(a.lastIndex=0;null!=(o=a.exec(n));)if(t=this.rules.inline.strong.middle.exec(n.slice(0,o.index+3)))return{type:"strong",raw:e.slice(0,t[0].length),text:e.slice(2,t[0].length-2)}}},e.prototype.em=function(e,n,i){void 0===i&&(i="");var o=this.rules.inline.em.start.exec(e);if(o&&(!o[1]||o[1]&&(""===i||this.rules.inline.punctuation.exec(i)))){n=n.slice(-1*e.length);var t,a="*"===o[0]?this.rules.inline.em.endAst:this.rules.inline.em.endUnd;for(a.lastIndex=0;null!=(o=a.exec(n));)if(t=this.rules.inline.em.middle.exec(n.slice(0,o.index+2)))return{type:"em",raw:e.slice(0,t[0].length),text:e.slice(1,t[0].length-1)}}},e.prototype.codespan=function(e){var n=this.rules.inline.code.exec(e);if(n){var i=n[2].replace(/\n/g," "),o=/[^ ]/.test(i),e=/^ /.test(i)&&/ $/.test(i);return o&&e&&(i=i.substring(1,i.length-1)),i=Je(i,!0),{type:"codespan",raw:n[0],text:i}}},e.prototype.br=function(e){e=this.rules.inline.br.exec(e);if(e)return{type:"br",raw:e[0]}},e.prototype.del=function(e){e=this.rules.inline.del.exec(e);if(e)return{type:"del",raw:e[0],text:e[2]}},e.prototype.autolink=function(e,n){e=this.rules.inline.autolink.exec(e);if(e){var i,n="@"===e[2]?"mailto:"+(i=Je(this.options.mangle?n(e[1]):e[1])):i=Je(e[1]);return{type:"link",raw:e[0],text:i,href:n,tokens:[{type:"text",raw:i,text:i}]}}},e.prototype.url=function(e,n){var i,o,t,a;if(i=this.rules.inline.url.exec(e)){if("@"===i[2])t="mailto:"+(o=Je(this.options.mangle?n(i[0]):i[0]));else{for(;a=i[0],i[0]=this.rules.inline._backpedal.exec(i[0])[0],a!==i[0];);o=Je(i[0]),t="www."===i[1]?"http://"+o:o}return{type:"link",raw:i[0],text:o,href:t,tokens:[{type:"text",raw:o,text:o}]}}},e.prototype.inlineText=function(e,n,i){e=this.rules.inline.text.exec(e);if(e){i=n?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):Je(e[0]):e[0]:Je(this.options.smartypants?i(e[0]):e[0]);return{type:"text",raw:e[0],text:i}}},e}(),Ze=De,Ve=Ne,De=Ue,Ne={newline:/^(?: *(?:\n|$))+/,code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:Ze,table:Ze,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/};Ne.def=Ve(Ne.def).replace("label",Ne._label).replace("title",Ne._title).getRegex(),Ne.bullet=/(?:[*+-]|\d{1,9}[.)])/,Ne.item=/^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/,Ne.item=Ve(Ne.item,"gm").replace(/bull/g,Ne.bullet).getRegex(),Ne.listItemStart=Ve(/^( *)(bull)/).replace("bull",Ne.bullet).getRegex(),Ne.list=Ve(Ne.list).replace(/bull/g,Ne.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+Ne.def.source+")").getRegex(),Ne._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",Ne._comment=/|$)/,Ne.html=Ve(Ne.html,"i").replace("comment",Ne._comment).replace("tag",Ne._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Ne.paragraph=Ve(Ne._paragraph).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.blockquote=Ve(Ne.blockquote).replace("paragraph",Ne.paragraph).getRegex(),Ne.normal=De({},Ne),Ne.gfm=De({},Ne.normal,{nptable:"^ *([^|\\n ].*\\|.*)\\n {0,3}([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)",table:"^ *\\|(.+)\\n {0,3}\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),Ne.gfm.nptable=Ve(Ne.gfm.nptable).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.gfm.table=Ve(Ne.gfm.table).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.pedantic=De({},Ne.normal,{html:Ve("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",Ne._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Ze,paragraph:Ve(Ne.normal._paragraph).replace("hr",Ne.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",Ne.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});Ze={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:Ze,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",strong:{start:/^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/,middle:/^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,endAst:/[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/},em:{start:/^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/,middle:/^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,endAst:/[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:Ze,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~"};Ze.punctuation=Ve(Ze.punctuation).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze._blockSkip="\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>",Ze._overlapSkip="__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*",Ze._comment=Ve(Ne._comment).replace("(?:--\x3e|$)","--\x3e").getRegex(),Ze.em.start=Ve(Ze.em.start).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.em.middle=Ve(Ze.em.middle).replace(/punctuation/g,Ze._punctuation).replace(/overlapSkip/g,Ze._overlapSkip).getRegex(),Ze.em.endAst=Ve(Ze.em.endAst,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.em.endUnd=Ve(Ze.em.endUnd,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.start=Ve(Ze.strong.start).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.middle=Ve(Ze.strong.middle).replace(/punctuation/g,Ze._punctuation).replace(/overlapSkip/g,Ze._overlapSkip).getRegex(),Ze.strong.endAst=Ve(Ze.strong.endAst,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.endUnd=Ve(Ze.strong.endUnd,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.blockSkip=Ve(Ze._blockSkip,"g").getRegex(),Ze.overlapSkip=Ve(Ze._overlapSkip,"g").getRegex(),Ze._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,Ze._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,Ze._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,Ze.autolink=Ve(Ze.autolink).replace("scheme",Ze._scheme).replace("email",Ze._email).getRegex(),Ze._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,Ze.tag=Ve(Ze.tag).replace("comment",Ze._comment).replace("attribute",Ze._attribute).getRegex(),Ze._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Ze._href=/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/,Ze._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,Ze.link=Ve(Ze.link).replace("label",Ze._label).replace("href",Ze._href).replace("title",Ze._title).getRegex(),Ze.reflink=Ve(Ze.reflink).replace("label",Ze._label).getRegex(),Ze.reflinkSearch=Ve(Ze.reflinkSearch,"g").replace("reflink",Ze.reflink).replace("nolink",Ze.nolink).getRegex(),Ze.normal=De({},Ze),Ze.pedantic=De({},Ze.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:Ve(/^!?\[(label)\]\((.*?)\)/).replace("label",Ze._label).getRegex(),reflink:Ve(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Ze._label).getRegex()}),Ze.gfm=De({},Ze.normal,{escape:Ve(Ze.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\'+(i?e:gn(e,!0))+"\n":"
"+(i?e:gn(e,!0))+"
\n"},e.prototype.blockquote=function(e){return"
\n"+e+"
\n"},e.prototype.html=function(e){return e},e.prototype.heading=function(e,n,i,o){return this.options.headerIds?"'+e+"\n":""+e+"\n"},e.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},e.prototype.list=function(e,n,i){var o=n?"ol":"ul";return"<"+o+(n&&1!==i?' start="'+i+'"':"")+">\n"+e+"\n"},e.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},e.prototype.checkbox=function(e){return" "},e.prototype.paragraph=function(e){return"

    "+e+"

    \n"},e.prototype.table=function(e,n){return"\n\n"+e+"\n"+(n=n&&""+n+"")+"
    \n"},e.prototype.tablerow=function(e){return"\n"+e+"\n"},e.prototype.tablecell=function(e,n){var i=n.header?"th":"td";return(n.align?"<"+i+' align="'+n.align+'">':"<"+i+">")+e+"\n"},e.prototype.strong=function(e){return""+e+""},e.prototype.em=function(e){return""+e+""},e.prototype.codespan=function(e){return""+e+""},e.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},e.prototype.del=function(e){return""+e+""},e.prototype.link=function(e,n,i){if(null===(e=dn(this.options.sanitize,this.options.baseUrl,e)))return i;e='"},e.prototype.image=function(e,n,i){if(null===(e=dn(this.options.sanitize,this.options.baseUrl,e)))return i;i=''+i+'":">"},e.prototype.text=function(e){return e},e}(),ln=function(){function e(){}return e.prototype.strong=function(e){return e},e.prototype.em=function(e){return e},e.prototype.codespan=function(e){return e},e.prototype.del=function(e){return e},e.prototype.html=function(e){return e},e.prototype.text=function(e){return e},e.prototype.link=function(e,n,i){return""+i},e.prototype.image=function(e,n,i){return""+i},e.prototype.br=function(){return""},e}(),vn=function(){function e(){this.seen={}}return e.prototype.serialize=function(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")},e.prototype.getNextSafeSlug=function(e,n){var i=e,o=0;if(this.seen.hasOwnProperty(i))for(o=this.seen[e];i=e+"-"+ ++o,this.seen.hasOwnProperty(i););return n||(this.seen[e]=o,this.seen[i]=0),i},e.prototype.slug=function(e,n){void 0===n&&(n={});e=this.serialize(e);return this.getNextSafeSlug(e,n.dryrun)},e}(),hn=we.defaults,_n=Ie,mn=function(){function i(e){this.options=e||hn,this.options.renderer=this.options.renderer||new sn,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new ln,this.slugger=new vn}return i.parse=function(e,n){return new i(n).parse(e)},i.parseInline=function(e,n){return new i(n).parseInline(e)},i.prototype.parse=function(e,n){void 0===n&&(n=!0);for(var i,o,t,a,r,c,u,f,p,d,g,s,l,v,h,_="",m=e.length,b=0;bAn error occurred:

    "+wn(e.message+"",!0)+"
    ";throw e}}xn.options=xn.setOptions=function(e){return bn(xn.defaults,e),yn(xn.defaults),xn},xn.getDefaults=Me,xn.defaults=we,xn.use=function(a){var n,e=bn({},a);if(a.renderer){var i,r=xn.defaults.renderer||new sn;for(i in a.renderer)!function(o){var t=r[o];r[o]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var i=a.renderer[o].apply(r,e);return i=!1===i?t.apply(r,e):i}}(i);e.renderer=r}if(a.tokenizer){var t,c=xn.defaults.tokenizer||new nn;for(t in a.tokenizer)!function(){var o=c[t];c[t]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var i=a.tokenizer[t].apply(c,e);return i=!1===i?o.apply(c,e):i}}();e.tokenizer=c}a.walkTokens&&(n=xn.defaults.walkTokens,e.walkTokens=function(e){a.walkTokens(e),n&&n(e)}),xn.setOptions(e)},xn.walkTokens=function(e,n){for(var i=0,o=e;iAn error occurred:

    "+wn(e.message+"",!0)+"
    ";throw e}},xn.Parser=mn,xn.parser=mn.parse,xn.Renderer=sn,xn.TextRenderer=ln,xn.Lexer=fn,xn.lexer=fn.lex,xn.Tokenizer=nn,xn.Slugger=vn;var Sn=xn.parse=xn;function An(e,i){if(void 0===i&&(i='
      {inner}
    '),!e||!e.length)return"";var o="";return e.forEach(function(e){var n=e.title.replace(/(<([^>]+)>)/g,"");o+='
  • '+e.title+"
  • ",e.children&&(o+=An(e.children,i))}),i.replace("{inner}",o)}function $n(e,n){return'

    '+n.slice(5).trim()+"

    "}function zn(e,o){var t=[],a={};return e.forEach(function(e){var n=e.level||1,i=n-1;o?@[\]^`{|}~]/g;function Rn(e){return e.toLowerCase()}function Tn(e){if("string"!=typeof e)return"";var n=e.trim().replace(/[A-Z]+/g,Rn).replace(/<[^>]+>/g,"").replace(En,"").replace(/\s/g,"-").replace(/-+/g,"-").replace(/^(\d)/,"_$1"),e=Fn[n],e=u.call(Fn,n)?e+1:0;return n=(Fn[n]=e)?n+"-"+e:n}Tn.clear=function(){Fn={}};var Cn={baseURL:"https://github.githubassets.com/images/icons/emoji/",data:{100:"unicode/1f4af.png?v8",1234:"unicode/1f522.png?v8","+1":"unicode/1f44d.png?v8","-1":"unicode/1f44e.png?v8","1st_place_medal":"unicode/1f947.png?v8","2nd_place_medal":"unicode/1f948.png?v8","3rd_place_medal":"unicode/1f949.png?v8","8ball":"unicode/1f3b1.png?v8",a:"unicode/1f170.png?v8",ab:"unicode/1f18e.png?v8",abacus:"unicode/1f9ee.png?v8",abc:"unicode/1f524.png?v8",abcd:"unicode/1f521.png?v8",accept:"unicode/1f251.png?v8",accessibility:"accessibility.png?v8",accordion:"unicode/1fa97.png?v8",adhesive_bandage:"unicode/1fa79.png?v8",adult:"unicode/1f9d1.png?v8",aerial_tramway:"unicode/1f6a1.png?v8",afghanistan:"unicode/1f1e6-1f1eb.png?v8",airplane:"unicode/2708.png?v8",aland_islands:"unicode/1f1e6-1f1fd.png?v8",alarm_clock:"unicode/23f0.png?v8",albania:"unicode/1f1e6-1f1f1.png?v8",alembic:"unicode/2697.png?v8",algeria:"unicode/1f1e9-1f1ff.png?v8",alien:"unicode/1f47d.png?v8",ambulance:"unicode/1f691.png?v8",american_samoa:"unicode/1f1e6-1f1f8.png?v8",amphora:"unicode/1f3fa.png?v8",anatomical_heart:"unicode/1fac0.png?v8",anchor:"unicode/2693.png?v8",andorra:"unicode/1f1e6-1f1e9.png?v8",angel:"unicode/1f47c.png?v8",anger:"unicode/1f4a2.png?v8",angola:"unicode/1f1e6-1f1f4.png?v8",angry:"unicode/1f620.png?v8",anguilla:"unicode/1f1e6-1f1ee.png?v8",anguished:"unicode/1f627.png?v8",ant:"unicode/1f41c.png?v8",antarctica:"unicode/1f1e6-1f1f6.png?v8",antigua_barbuda:"unicode/1f1e6-1f1ec.png?v8",apple:"unicode/1f34e.png?v8",aquarius:"unicode/2652.png?v8",argentina:"unicode/1f1e6-1f1f7.png?v8",aries:"unicode/2648.png?v8",armenia:"unicode/1f1e6-1f1f2.png?v8",arrow_backward:"unicode/25c0.png?v8",arrow_double_down:"unicode/23ec.png?v8",arrow_double_up:"unicode/23eb.png?v8",arrow_down:"unicode/2b07.png?v8",arrow_down_small:"unicode/1f53d.png?v8",arrow_forward:"unicode/25b6.png?v8",arrow_heading_down:"unicode/2935.png?v8",arrow_heading_up:"unicode/2934.png?v8",arrow_left:"unicode/2b05.png?v8",arrow_lower_left:"unicode/2199.png?v8",arrow_lower_right:"unicode/2198.png?v8",arrow_right:"unicode/27a1.png?v8",arrow_right_hook:"unicode/21aa.png?v8",arrow_up:"unicode/2b06.png?v8",arrow_up_down:"unicode/2195.png?v8",arrow_up_small:"unicode/1f53c.png?v8",arrow_upper_left:"unicode/2196.png?v8",arrow_upper_right:"unicode/2197.png?v8",arrows_clockwise:"unicode/1f503.png?v8",arrows_counterclockwise:"unicode/1f504.png?v8",art:"unicode/1f3a8.png?v8",articulated_lorry:"unicode/1f69b.png?v8",artificial_satellite:"unicode/1f6f0.png?v8",artist:"unicode/1f9d1-1f3a8.png?v8",aruba:"unicode/1f1e6-1f1fc.png?v8",ascension_island:"unicode/1f1e6-1f1e8.png?v8",asterisk:"unicode/002a-20e3.png?v8",astonished:"unicode/1f632.png?v8",astronaut:"unicode/1f9d1-1f680.png?v8",athletic_shoe:"unicode/1f45f.png?v8",atm:"unicode/1f3e7.png?v8",atom:"atom.png?v8",atom_symbol:"unicode/269b.png?v8",australia:"unicode/1f1e6-1f1fa.png?v8",austria:"unicode/1f1e6-1f1f9.png?v8",auto_rickshaw:"unicode/1f6fa.png?v8",avocado:"unicode/1f951.png?v8",axe:"unicode/1fa93.png?v8",azerbaijan:"unicode/1f1e6-1f1ff.png?v8",b:"unicode/1f171.png?v8",baby:"unicode/1f476.png?v8",baby_bottle:"unicode/1f37c.png?v8",baby_chick:"unicode/1f424.png?v8",baby_symbol:"unicode/1f6bc.png?v8",back:"unicode/1f519.png?v8",bacon:"unicode/1f953.png?v8",badger:"unicode/1f9a1.png?v8",badminton:"unicode/1f3f8.png?v8",bagel:"unicode/1f96f.png?v8",baggage_claim:"unicode/1f6c4.png?v8",baguette_bread:"unicode/1f956.png?v8",bahamas:"unicode/1f1e7-1f1f8.png?v8",bahrain:"unicode/1f1e7-1f1ed.png?v8",balance_scale:"unicode/2696.png?v8",bald_man:"unicode/1f468-1f9b2.png?v8",bald_woman:"unicode/1f469-1f9b2.png?v8",ballet_shoes:"unicode/1fa70.png?v8",balloon:"unicode/1f388.png?v8",ballot_box:"unicode/1f5f3.png?v8",ballot_box_with_check:"unicode/2611.png?v8",bamboo:"unicode/1f38d.png?v8",banana:"unicode/1f34c.png?v8",bangbang:"unicode/203c.png?v8",bangladesh:"unicode/1f1e7-1f1e9.png?v8",banjo:"unicode/1fa95.png?v8",bank:"unicode/1f3e6.png?v8",bar_chart:"unicode/1f4ca.png?v8",barbados:"unicode/1f1e7-1f1e7.png?v8",barber:"unicode/1f488.png?v8",baseball:"unicode/26be.png?v8",basecamp:"basecamp.png?v8",basecampy:"basecampy.png?v8",basket:"unicode/1f9fa.png?v8",basketball:"unicode/1f3c0.png?v8",basketball_man:"unicode/26f9-2642.png?v8",basketball_woman:"unicode/26f9-2640.png?v8",bat:"unicode/1f987.png?v8",bath:"unicode/1f6c0.png?v8",bathtub:"unicode/1f6c1.png?v8",battery:"unicode/1f50b.png?v8",beach_umbrella:"unicode/1f3d6.png?v8",bear:"unicode/1f43b.png?v8",bearded_person:"unicode/1f9d4.png?v8",beaver:"unicode/1f9ab.png?v8",bed:"unicode/1f6cf.png?v8",bee:"unicode/1f41d.png?v8",beer:"unicode/1f37a.png?v8",beers:"unicode/1f37b.png?v8",beetle:"unicode/1fab2.png?v8",beginner:"unicode/1f530.png?v8",belarus:"unicode/1f1e7-1f1fe.png?v8",belgium:"unicode/1f1e7-1f1ea.png?v8",belize:"unicode/1f1e7-1f1ff.png?v8",bell:"unicode/1f514.png?v8",bell_pepper:"unicode/1fad1.png?v8",bellhop_bell:"unicode/1f6ce.png?v8",benin:"unicode/1f1e7-1f1ef.png?v8",bento:"unicode/1f371.png?v8",bermuda:"unicode/1f1e7-1f1f2.png?v8",beverage_box:"unicode/1f9c3.png?v8",bhutan:"unicode/1f1e7-1f1f9.png?v8",bicyclist:"unicode/1f6b4.png?v8",bike:"unicode/1f6b2.png?v8",biking_man:"unicode/1f6b4-2642.png?v8",biking_woman:"unicode/1f6b4-2640.png?v8",bikini:"unicode/1f459.png?v8",billed_cap:"unicode/1f9e2.png?v8",biohazard:"unicode/2623.png?v8",bird:"unicode/1f426.png?v8",birthday:"unicode/1f382.png?v8",bison:"unicode/1f9ac.png?v8",black_cat:"unicode/1f408-2b1b.png?v8",black_circle:"unicode/26ab.png?v8",black_flag:"unicode/1f3f4.png?v8",black_heart:"unicode/1f5a4.png?v8",black_joker:"unicode/1f0cf.png?v8",black_large_square:"unicode/2b1b.png?v8",black_medium_small_square:"unicode/25fe.png?v8",black_medium_square:"unicode/25fc.png?v8",black_nib:"unicode/2712.png?v8",black_small_square:"unicode/25aa.png?v8",black_square_button:"unicode/1f532.png?v8",blond_haired_man:"unicode/1f471-2642.png?v8",blond_haired_person:"unicode/1f471.png?v8",blond_haired_woman:"unicode/1f471-2640.png?v8",blonde_woman:"unicode/1f471-2640.png?v8",blossom:"unicode/1f33c.png?v8",blowfish:"unicode/1f421.png?v8",blue_book:"unicode/1f4d8.png?v8",blue_car:"unicode/1f699.png?v8",blue_heart:"unicode/1f499.png?v8",blue_square:"unicode/1f7e6.png?v8",blueberries:"unicode/1fad0.png?v8",blush:"unicode/1f60a.png?v8",boar:"unicode/1f417.png?v8",boat:"unicode/26f5.png?v8",bolivia:"unicode/1f1e7-1f1f4.png?v8",bomb:"unicode/1f4a3.png?v8",bone:"unicode/1f9b4.png?v8",book:"unicode/1f4d6.png?v8",bookmark:"unicode/1f516.png?v8",bookmark_tabs:"unicode/1f4d1.png?v8",books:"unicode/1f4da.png?v8",boom:"unicode/1f4a5.png?v8",boomerang:"unicode/1fa83.png?v8",boot:"unicode/1f462.png?v8",bosnia_herzegovina:"unicode/1f1e7-1f1e6.png?v8",botswana:"unicode/1f1e7-1f1fc.png?v8",bouncing_ball_man:"unicode/26f9-2642.png?v8",bouncing_ball_person:"unicode/26f9.png?v8",bouncing_ball_woman:"unicode/26f9-2640.png?v8",bouquet:"unicode/1f490.png?v8",bouvet_island:"unicode/1f1e7-1f1fb.png?v8",bow:"unicode/1f647.png?v8",bow_and_arrow:"unicode/1f3f9.png?v8",bowing_man:"unicode/1f647-2642.png?v8",bowing_woman:"unicode/1f647-2640.png?v8",bowl_with_spoon:"unicode/1f963.png?v8",bowling:"unicode/1f3b3.png?v8",bowtie:"bowtie.png?v8",boxing_glove:"unicode/1f94a.png?v8",boy:"unicode/1f466.png?v8",brain:"unicode/1f9e0.png?v8",brazil:"unicode/1f1e7-1f1f7.png?v8",bread:"unicode/1f35e.png?v8",breast_feeding:"unicode/1f931.png?v8",bricks:"unicode/1f9f1.png?v8",bride_with_veil:"unicode/1f470-2640.png?v8",bridge_at_night:"unicode/1f309.png?v8",briefcase:"unicode/1f4bc.png?v8",british_indian_ocean_territory:"unicode/1f1ee-1f1f4.png?v8",british_virgin_islands:"unicode/1f1fb-1f1ec.png?v8",broccoli:"unicode/1f966.png?v8",broken_heart:"unicode/1f494.png?v8",broom:"unicode/1f9f9.png?v8",brown_circle:"unicode/1f7e4.png?v8",brown_heart:"unicode/1f90e.png?v8",brown_square:"unicode/1f7eb.png?v8",brunei:"unicode/1f1e7-1f1f3.png?v8",bubble_tea:"unicode/1f9cb.png?v8",bucket:"unicode/1faa3.png?v8",bug:"unicode/1f41b.png?v8",building_construction:"unicode/1f3d7.png?v8",bulb:"unicode/1f4a1.png?v8",bulgaria:"unicode/1f1e7-1f1ec.png?v8",bullettrain_front:"unicode/1f685.png?v8",bullettrain_side:"unicode/1f684.png?v8",burkina_faso:"unicode/1f1e7-1f1eb.png?v8",burrito:"unicode/1f32f.png?v8",burundi:"unicode/1f1e7-1f1ee.png?v8",bus:"unicode/1f68c.png?v8",business_suit_levitating:"unicode/1f574.png?v8",busstop:"unicode/1f68f.png?v8",bust_in_silhouette:"unicode/1f464.png?v8",busts_in_silhouette:"unicode/1f465.png?v8",butter:"unicode/1f9c8.png?v8",butterfly:"unicode/1f98b.png?v8",cactus:"unicode/1f335.png?v8",cake:"unicode/1f370.png?v8",calendar:"unicode/1f4c6.png?v8",call_me_hand:"unicode/1f919.png?v8",calling:"unicode/1f4f2.png?v8",cambodia:"unicode/1f1f0-1f1ed.png?v8",camel:"unicode/1f42b.png?v8",camera:"unicode/1f4f7.png?v8",camera_flash:"unicode/1f4f8.png?v8",cameroon:"unicode/1f1e8-1f1f2.png?v8",camping:"unicode/1f3d5.png?v8",canada:"unicode/1f1e8-1f1e6.png?v8",canary_islands:"unicode/1f1ee-1f1e8.png?v8",cancer:"unicode/264b.png?v8",candle:"unicode/1f56f.png?v8",candy:"unicode/1f36c.png?v8",canned_food:"unicode/1f96b.png?v8",canoe:"unicode/1f6f6.png?v8",cape_verde:"unicode/1f1e8-1f1fb.png?v8",capital_abcd:"unicode/1f520.png?v8",capricorn:"unicode/2651.png?v8",car:"unicode/1f697.png?v8",card_file_box:"unicode/1f5c3.png?v8",card_index:"unicode/1f4c7.png?v8",card_index_dividers:"unicode/1f5c2.png?v8",caribbean_netherlands:"unicode/1f1e7-1f1f6.png?v8",carousel_horse:"unicode/1f3a0.png?v8",carpentry_saw:"unicode/1fa9a.png?v8",carrot:"unicode/1f955.png?v8",cartwheeling:"unicode/1f938.png?v8",cat:"unicode/1f431.png?v8",cat2:"unicode/1f408.png?v8",cayman_islands:"unicode/1f1f0-1f1fe.png?v8",cd:"unicode/1f4bf.png?v8",central_african_republic:"unicode/1f1e8-1f1eb.png?v8",ceuta_melilla:"unicode/1f1ea-1f1e6.png?v8",chad:"unicode/1f1f9-1f1e9.png?v8",chains:"unicode/26d3.png?v8",chair:"unicode/1fa91.png?v8",champagne:"unicode/1f37e.png?v8",chart:"unicode/1f4b9.png?v8",chart_with_downwards_trend:"unicode/1f4c9.png?v8",chart_with_upwards_trend:"unicode/1f4c8.png?v8",checkered_flag:"unicode/1f3c1.png?v8",cheese:"unicode/1f9c0.png?v8",cherries:"unicode/1f352.png?v8",cherry_blossom:"unicode/1f338.png?v8",chess_pawn:"unicode/265f.png?v8",chestnut:"unicode/1f330.png?v8",chicken:"unicode/1f414.png?v8",child:"unicode/1f9d2.png?v8",children_crossing:"unicode/1f6b8.png?v8",chile:"unicode/1f1e8-1f1f1.png?v8",chipmunk:"unicode/1f43f.png?v8",chocolate_bar:"unicode/1f36b.png?v8",chopsticks:"unicode/1f962.png?v8",christmas_island:"unicode/1f1e8-1f1fd.png?v8",christmas_tree:"unicode/1f384.png?v8",church:"unicode/26ea.png?v8",cinema:"unicode/1f3a6.png?v8",circus_tent:"unicode/1f3aa.png?v8",city_sunrise:"unicode/1f307.png?v8",city_sunset:"unicode/1f306.png?v8",cityscape:"unicode/1f3d9.png?v8",cl:"unicode/1f191.png?v8",clamp:"unicode/1f5dc.png?v8",clap:"unicode/1f44f.png?v8",clapper:"unicode/1f3ac.png?v8",classical_building:"unicode/1f3db.png?v8",climbing:"unicode/1f9d7.png?v8",climbing_man:"unicode/1f9d7-2642.png?v8",climbing_woman:"unicode/1f9d7-2640.png?v8",clinking_glasses:"unicode/1f942.png?v8",clipboard:"unicode/1f4cb.png?v8",clipperton_island:"unicode/1f1e8-1f1f5.png?v8",clock1:"unicode/1f550.png?v8",clock10:"unicode/1f559.png?v8",clock1030:"unicode/1f565.png?v8",clock11:"unicode/1f55a.png?v8",clock1130:"unicode/1f566.png?v8",clock12:"unicode/1f55b.png?v8",clock1230:"unicode/1f567.png?v8",clock130:"unicode/1f55c.png?v8",clock2:"unicode/1f551.png?v8",clock230:"unicode/1f55d.png?v8",clock3:"unicode/1f552.png?v8",clock330:"unicode/1f55e.png?v8",clock4:"unicode/1f553.png?v8",clock430:"unicode/1f55f.png?v8",clock5:"unicode/1f554.png?v8",clock530:"unicode/1f560.png?v8",clock6:"unicode/1f555.png?v8",clock630:"unicode/1f561.png?v8",clock7:"unicode/1f556.png?v8",clock730:"unicode/1f562.png?v8",clock8:"unicode/1f557.png?v8",clock830:"unicode/1f563.png?v8",clock9:"unicode/1f558.png?v8",clock930:"unicode/1f564.png?v8",closed_book:"unicode/1f4d5.png?v8",closed_lock_with_key:"unicode/1f510.png?v8",closed_umbrella:"unicode/1f302.png?v8",cloud:"unicode/2601.png?v8",cloud_with_lightning:"unicode/1f329.png?v8",cloud_with_lightning_and_rain:"unicode/26c8.png?v8",cloud_with_rain:"unicode/1f327.png?v8",cloud_with_snow:"unicode/1f328.png?v8",clown_face:"unicode/1f921.png?v8",clubs:"unicode/2663.png?v8",cn:"unicode/1f1e8-1f1f3.png?v8",coat:"unicode/1f9e5.png?v8",cockroach:"unicode/1fab3.png?v8",cocktail:"unicode/1f378.png?v8",coconut:"unicode/1f965.png?v8",cocos_islands:"unicode/1f1e8-1f1e8.png?v8",coffee:"unicode/2615.png?v8",coffin:"unicode/26b0.png?v8",coin:"unicode/1fa99.png?v8",cold_face:"unicode/1f976.png?v8",cold_sweat:"unicode/1f630.png?v8",collision:"unicode/1f4a5.png?v8",colombia:"unicode/1f1e8-1f1f4.png?v8",comet:"unicode/2604.png?v8",comoros:"unicode/1f1f0-1f1f2.png?v8",compass:"unicode/1f9ed.png?v8",computer:"unicode/1f4bb.png?v8",computer_mouse:"unicode/1f5b1.png?v8",confetti_ball:"unicode/1f38a.png?v8",confounded:"unicode/1f616.png?v8",confused:"unicode/1f615.png?v8",congo_brazzaville:"unicode/1f1e8-1f1ec.png?v8",congo_kinshasa:"unicode/1f1e8-1f1e9.png?v8",congratulations:"unicode/3297.png?v8",construction:"unicode/1f6a7.png?v8",construction_worker:"unicode/1f477.png?v8",construction_worker_man:"unicode/1f477-2642.png?v8",construction_worker_woman:"unicode/1f477-2640.png?v8",control_knobs:"unicode/1f39b.png?v8",convenience_store:"unicode/1f3ea.png?v8",cook:"unicode/1f9d1-1f373.png?v8",cook_islands:"unicode/1f1e8-1f1f0.png?v8",cookie:"unicode/1f36a.png?v8",cool:"unicode/1f192.png?v8",cop:"unicode/1f46e.png?v8",copyright:"unicode/00a9.png?v8",corn:"unicode/1f33d.png?v8",costa_rica:"unicode/1f1e8-1f1f7.png?v8",cote_divoire:"unicode/1f1e8-1f1ee.png?v8",couch_and_lamp:"unicode/1f6cb.png?v8",couple:"unicode/1f46b.png?v8",couple_with_heart:"unicode/1f491.png?v8",couple_with_heart_man_man:"unicode/1f468-2764-1f468.png?v8",couple_with_heart_woman_man:"unicode/1f469-2764-1f468.png?v8",couple_with_heart_woman_woman:"unicode/1f469-2764-1f469.png?v8",couplekiss:"unicode/1f48f.png?v8",couplekiss_man_man:"unicode/1f468-2764-1f48b-1f468.png?v8",couplekiss_man_woman:"unicode/1f469-2764-1f48b-1f468.png?v8",couplekiss_woman_woman:"unicode/1f469-2764-1f48b-1f469.png?v8",cow:"unicode/1f42e.png?v8",cow2:"unicode/1f404.png?v8",cowboy_hat_face:"unicode/1f920.png?v8",crab:"unicode/1f980.png?v8",crayon:"unicode/1f58d.png?v8",credit_card:"unicode/1f4b3.png?v8",crescent_moon:"unicode/1f319.png?v8",cricket:"unicode/1f997.png?v8",cricket_game:"unicode/1f3cf.png?v8",croatia:"unicode/1f1ed-1f1f7.png?v8",crocodile:"unicode/1f40a.png?v8",croissant:"unicode/1f950.png?v8",crossed_fingers:"unicode/1f91e.png?v8",crossed_flags:"unicode/1f38c.png?v8",crossed_swords:"unicode/2694.png?v8",crown:"unicode/1f451.png?v8",cry:"unicode/1f622.png?v8",crying_cat_face:"unicode/1f63f.png?v8",crystal_ball:"unicode/1f52e.png?v8",cuba:"unicode/1f1e8-1f1fa.png?v8",cucumber:"unicode/1f952.png?v8",cup_with_straw:"unicode/1f964.png?v8",cupcake:"unicode/1f9c1.png?v8",cupid:"unicode/1f498.png?v8",curacao:"unicode/1f1e8-1f1fc.png?v8",curling_stone:"unicode/1f94c.png?v8",curly_haired_man:"unicode/1f468-1f9b1.png?v8",curly_haired_woman:"unicode/1f469-1f9b1.png?v8",curly_loop:"unicode/27b0.png?v8",currency_exchange:"unicode/1f4b1.png?v8",curry:"unicode/1f35b.png?v8",cursing_face:"unicode/1f92c.png?v8",custard:"unicode/1f36e.png?v8",customs:"unicode/1f6c3.png?v8",cut_of_meat:"unicode/1f969.png?v8",cyclone:"unicode/1f300.png?v8",cyprus:"unicode/1f1e8-1f1fe.png?v8",czech_republic:"unicode/1f1e8-1f1ff.png?v8",dagger:"unicode/1f5e1.png?v8",dancer:"unicode/1f483.png?v8",dancers:"unicode/1f46f.png?v8",dancing_men:"unicode/1f46f-2642.png?v8",dancing_women:"unicode/1f46f-2640.png?v8",dango:"unicode/1f361.png?v8",dark_sunglasses:"unicode/1f576.png?v8",dart:"unicode/1f3af.png?v8",dash:"unicode/1f4a8.png?v8",date:"unicode/1f4c5.png?v8",de:"unicode/1f1e9-1f1ea.png?v8",deaf_man:"unicode/1f9cf-2642.png?v8",deaf_person:"unicode/1f9cf.png?v8",deaf_woman:"unicode/1f9cf-2640.png?v8",deciduous_tree:"unicode/1f333.png?v8",deer:"unicode/1f98c.png?v8",denmark:"unicode/1f1e9-1f1f0.png?v8",department_store:"unicode/1f3ec.png?v8",dependabot:"dependabot.png?v8",derelict_house:"unicode/1f3da.png?v8",desert:"unicode/1f3dc.png?v8",desert_island:"unicode/1f3dd.png?v8",desktop_computer:"unicode/1f5a5.png?v8",detective:"unicode/1f575.png?v8",diamond_shape_with_a_dot_inside:"unicode/1f4a0.png?v8",diamonds:"unicode/2666.png?v8",diego_garcia:"unicode/1f1e9-1f1ec.png?v8",disappointed:"unicode/1f61e.png?v8",disappointed_relieved:"unicode/1f625.png?v8",disguised_face:"unicode/1f978.png?v8",diving_mask:"unicode/1f93f.png?v8",diya_lamp:"unicode/1fa94.png?v8",dizzy:"unicode/1f4ab.png?v8",dizzy_face:"unicode/1f635.png?v8",djibouti:"unicode/1f1e9-1f1ef.png?v8",dna:"unicode/1f9ec.png?v8",do_not_litter:"unicode/1f6af.png?v8",dodo:"unicode/1f9a4.png?v8",dog:"unicode/1f436.png?v8",dog2:"unicode/1f415.png?v8",dollar:"unicode/1f4b5.png?v8",dolls:"unicode/1f38e.png?v8",dolphin:"unicode/1f42c.png?v8",dominica:"unicode/1f1e9-1f1f2.png?v8",dominican_republic:"unicode/1f1e9-1f1f4.png?v8",door:"unicode/1f6aa.png?v8",doughnut:"unicode/1f369.png?v8",dove:"unicode/1f54a.png?v8",dragon:"unicode/1f409.png?v8",dragon_face:"unicode/1f432.png?v8",dress:"unicode/1f457.png?v8",dromedary_camel:"unicode/1f42a.png?v8",drooling_face:"unicode/1f924.png?v8",drop_of_blood:"unicode/1fa78.png?v8",droplet:"unicode/1f4a7.png?v8",drum:"unicode/1f941.png?v8",duck:"unicode/1f986.png?v8",dumpling:"unicode/1f95f.png?v8",dvd:"unicode/1f4c0.png?v8","e-mail":"unicode/1f4e7.png?v8",eagle:"unicode/1f985.png?v8",ear:"unicode/1f442.png?v8",ear_of_rice:"unicode/1f33e.png?v8",ear_with_hearing_aid:"unicode/1f9bb.png?v8",earth_africa:"unicode/1f30d.png?v8",earth_americas:"unicode/1f30e.png?v8",earth_asia:"unicode/1f30f.png?v8",ecuador:"unicode/1f1ea-1f1e8.png?v8",egg:"unicode/1f95a.png?v8",eggplant:"unicode/1f346.png?v8",egypt:"unicode/1f1ea-1f1ec.png?v8",eight:"unicode/0038-20e3.png?v8",eight_pointed_black_star:"unicode/2734.png?v8",eight_spoked_asterisk:"unicode/2733.png?v8",eject_button:"unicode/23cf.png?v8",el_salvador:"unicode/1f1f8-1f1fb.png?v8",electric_plug:"unicode/1f50c.png?v8",electron:"electron.png?v8",elephant:"unicode/1f418.png?v8",elevator:"unicode/1f6d7.png?v8",elf:"unicode/1f9dd.png?v8",elf_man:"unicode/1f9dd-2642.png?v8",elf_woman:"unicode/1f9dd-2640.png?v8",email:"unicode/1f4e7.png?v8",end:"unicode/1f51a.png?v8",england:"unicode/1f3f4-e0067-e0062-e0065-e006e-e0067-e007f.png?v8",envelope:"unicode/2709.png?v8",envelope_with_arrow:"unicode/1f4e9.png?v8",equatorial_guinea:"unicode/1f1ec-1f1f6.png?v8",eritrea:"unicode/1f1ea-1f1f7.png?v8",es:"unicode/1f1ea-1f1f8.png?v8",estonia:"unicode/1f1ea-1f1ea.png?v8",ethiopia:"unicode/1f1ea-1f1f9.png?v8",eu:"unicode/1f1ea-1f1fa.png?v8",euro:"unicode/1f4b6.png?v8",european_castle:"unicode/1f3f0.png?v8",european_post_office:"unicode/1f3e4.png?v8",european_union:"unicode/1f1ea-1f1fa.png?v8",evergreen_tree:"unicode/1f332.png?v8",exclamation:"unicode/2757.png?v8",exploding_head:"unicode/1f92f.png?v8",expressionless:"unicode/1f611.png?v8",eye:"unicode/1f441.png?v8",eye_speech_bubble:"unicode/1f441-1f5e8.png?v8",eyeglasses:"unicode/1f453.png?v8",eyes:"unicode/1f440.png?v8",face_exhaling:"unicode/1f62e-1f4a8.png?v8",face_in_clouds:"unicode/1f636-1f32b.png?v8",face_with_head_bandage:"unicode/1f915.png?v8",face_with_spiral_eyes:"unicode/1f635-1f4ab.png?v8",face_with_thermometer:"unicode/1f912.png?v8",facepalm:"unicode/1f926.png?v8",facepunch:"unicode/1f44a.png?v8",factory:"unicode/1f3ed.png?v8",factory_worker:"unicode/1f9d1-1f3ed.png?v8",fairy:"unicode/1f9da.png?v8",fairy_man:"unicode/1f9da-2642.png?v8",fairy_woman:"unicode/1f9da-2640.png?v8",falafel:"unicode/1f9c6.png?v8",falkland_islands:"unicode/1f1eb-1f1f0.png?v8",fallen_leaf:"unicode/1f342.png?v8",family:"unicode/1f46a.png?v8",family_man_boy:"unicode/1f468-1f466.png?v8",family_man_boy_boy:"unicode/1f468-1f466-1f466.png?v8",family_man_girl:"unicode/1f468-1f467.png?v8",family_man_girl_boy:"unicode/1f468-1f467-1f466.png?v8",family_man_girl_girl:"unicode/1f468-1f467-1f467.png?v8",family_man_man_boy:"unicode/1f468-1f468-1f466.png?v8",family_man_man_boy_boy:"unicode/1f468-1f468-1f466-1f466.png?v8",family_man_man_girl:"unicode/1f468-1f468-1f467.png?v8",family_man_man_girl_boy:"unicode/1f468-1f468-1f467-1f466.png?v8",family_man_man_girl_girl:"unicode/1f468-1f468-1f467-1f467.png?v8",family_man_woman_boy:"unicode/1f468-1f469-1f466.png?v8",family_man_woman_boy_boy:"unicode/1f468-1f469-1f466-1f466.png?v8",family_man_woman_girl:"unicode/1f468-1f469-1f467.png?v8",family_man_woman_girl_boy:"unicode/1f468-1f469-1f467-1f466.png?v8",family_man_woman_girl_girl:"unicode/1f468-1f469-1f467-1f467.png?v8",family_woman_boy:"unicode/1f469-1f466.png?v8",family_woman_boy_boy:"unicode/1f469-1f466-1f466.png?v8",family_woman_girl:"unicode/1f469-1f467.png?v8",family_woman_girl_boy:"unicode/1f469-1f467-1f466.png?v8",family_woman_girl_girl:"unicode/1f469-1f467-1f467.png?v8",family_woman_woman_boy:"unicode/1f469-1f469-1f466.png?v8",family_woman_woman_boy_boy:"unicode/1f469-1f469-1f466-1f466.png?v8",family_woman_woman_girl:"unicode/1f469-1f469-1f467.png?v8",family_woman_woman_girl_boy:"unicode/1f469-1f469-1f467-1f466.png?v8",family_woman_woman_girl_girl:"unicode/1f469-1f469-1f467-1f467.png?v8",farmer:"unicode/1f9d1-1f33e.png?v8",faroe_islands:"unicode/1f1eb-1f1f4.png?v8",fast_forward:"unicode/23e9.png?v8",fax:"unicode/1f4e0.png?v8",fearful:"unicode/1f628.png?v8",feather:"unicode/1fab6.png?v8",feelsgood:"feelsgood.png?v8",feet:"unicode/1f43e.png?v8",female_detective:"unicode/1f575-2640.png?v8",female_sign:"unicode/2640.png?v8",ferris_wheel:"unicode/1f3a1.png?v8",ferry:"unicode/26f4.png?v8",field_hockey:"unicode/1f3d1.png?v8",fiji:"unicode/1f1eb-1f1ef.png?v8",file_cabinet:"unicode/1f5c4.png?v8",file_folder:"unicode/1f4c1.png?v8",film_projector:"unicode/1f4fd.png?v8",film_strip:"unicode/1f39e.png?v8",finland:"unicode/1f1eb-1f1ee.png?v8",finnadie:"finnadie.png?v8",fire:"unicode/1f525.png?v8",fire_engine:"unicode/1f692.png?v8",fire_extinguisher:"unicode/1f9ef.png?v8",firecracker:"unicode/1f9e8.png?v8",firefighter:"unicode/1f9d1-1f692.png?v8",fireworks:"unicode/1f386.png?v8",first_quarter_moon:"unicode/1f313.png?v8",first_quarter_moon_with_face:"unicode/1f31b.png?v8",fish:"unicode/1f41f.png?v8",fish_cake:"unicode/1f365.png?v8",fishing_pole_and_fish:"unicode/1f3a3.png?v8",fishsticks:"fishsticks.png?v8",fist:"unicode/270a.png?v8",fist_left:"unicode/1f91b.png?v8",fist_oncoming:"unicode/1f44a.png?v8",fist_raised:"unicode/270a.png?v8",fist_right:"unicode/1f91c.png?v8",five:"unicode/0035-20e3.png?v8",flags:"unicode/1f38f.png?v8",flamingo:"unicode/1f9a9.png?v8",flashlight:"unicode/1f526.png?v8",flat_shoe:"unicode/1f97f.png?v8",flatbread:"unicode/1fad3.png?v8",fleur_de_lis:"unicode/269c.png?v8",flight_arrival:"unicode/1f6ec.png?v8",flight_departure:"unicode/1f6eb.png?v8",flipper:"unicode/1f42c.png?v8",floppy_disk:"unicode/1f4be.png?v8",flower_playing_cards:"unicode/1f3b4.png?v8",flushed:"unicode/1f633.png?v8",fly:"unicode/1fab0.png?v8",flying_disc:"unicode/1f94f.png?v8",flying_saucer:"unicode/1f6f8.png?v8",fog:"unicode/1f32b.png?v8",foggy:"unicode/1f301.png?v8",fondue:"unicode/1fad5.png?v8",foot:"unicode/1f9b6.png?v8",football:"unicode/1f3c8.png?v8",footprints:"unicode/1f463.png?v8",fork_and_knife:"unicode/1f374.png?v8",fortune_cookie:"unicode/1f960.png?v8",fountain:"unicode/26f2.png?v8",fountain_pen:"unicode/1f58b.png?v8",four:"unicode/0034-20e3.png?v8",four_leaf_clover:"unicode/1f340.png?v8",fox_face:"unicode/1f98a.png?v8",fr:"unicode/1f1eb-1f1f7.png?v8",framed_picture:"unicode/1f5bc.png?v8",free:"unicode/1f193.png?v8",french_guiana:"unicode/1f1ec-1f1eb.png?v8",french_polynesia:"unicode/1f1f5-1f1eb.png?v8",french_southern_territories:"unicode/1f1f9-1f1eb.png?v8",fried_egg:"unicode/1f373.png?v8",fried_shrimp:"unicode/1f364.png?v8",fries:"unicode/1f35f.png?v8",frog:"unicode/1f438.png?v8",frowning:"unicode/1f626.png?v8",frowning_face:"unicode/2639.png?v8",frowning_man:"unicode/1f64d-2642.png?v8",frowning_person:"unicode/1f64d.png?v8",frowning_woman:"unicode/1f64d-2640.png?v8",fu:"unicode/1f595.png?v8",fuelpump:"unicode/26fd.png?v8",full_moon:"unicode/1f315.png?v8",full_moon_with_face:"unicode/1f31d.png?v8",funeral_urn:"unicode/26b1.png?v8",gabon:"unicode/1f1ec-1f1e6.png?v8",gambia:"unicode/1f1ec-1f1f2.png?v8",game_die:"unicode/1f3b2.png?v8",garlic:"unicode/1f9c4.png?v8",gb:"unicode/1f1ec-1f1e7.png?v8",gear:"unicode/2699.png?v8",gem:"unicode/1f48e.png?v8",gemini:"unicode/264a.png?v8",genie:"unicode/1f9de.png?v8",genie_man:"unicode/1f9de-2642.png?v8",genie_woman:"unicode/1f9de-2640.png?v8",georgia:"unicode/1f1ec-1f1ea.png?v8",ghana:"unicode/1f1ec-1f1ed.png?v8",ghost:"unicode/1f47b.png?v8",gibraltar:"unicode/1f1ec-1f1ee.png?v8",gift:"unicode/1f381.png?v8",gift_heart:"unicode/1f49d.png?v8",giraffe:"unicode/1f992.png?v8",girl:"unicode/1f467.png?v8",globe_with_meridians:"unicode/1f310.png?v8",gloves:"unicode/1f9e4.png?v8",goal_net:"unicode/1f945.png?v8",goat:"unicode/1f410.png?v8",goberserk:"goberserk.png?v8",godmode:"godmode.png?v8",goggles:"unicode/1f97d.png?v8",golf:"unicode/26f3.png?v8",golfing:"unicode/1f3cc.png?v8",golfing_man:"unicode/1f3cc-2642.png?v8",golfing_woman:"unicode/1f3cc-2640.png?v8",gorilla:"unicode/1f98d.png?v8",grapes:"unicode/1f347.png?v8",greece:"unicode/1f1ec-1f1f7.png?v8",green_apple:"unicode/1f34f.png?v8",green_book:"unicode/1f4d7.png?v8",green_circle:"unicode/1f7e2.png?v8",green_heart:"unicode/1f49a.png?v8",green_salad:"unicode/1f957.png?v8",green_square:"unicode/1f7e9.png?v8",greenland:"unicode/1f1ec-1f1f1.png?v8",grenada:"unicode/1f1ec-1f1e9.png?v8",grey_exclamation:"unicode/2755.png?v8",grey_question:"unicode/2754.png?v8",grimacing:"unicode/1f62c.png?v8",grin:"unicode/1f601.png?v8",grinning:"unicode/1f600.png?v8",guadeloupe:"unicode/1f1ec-1f1f5.png?v8",guam:"unicode/1f1ec-1f1fa.png?v8",guard:"unicode/1f482.png?v8",guardsman:"unicode/1f482-2642.png?v8",guardswoman:"unicode/1f482-2640.png?v8",guatemala:"unicode/1f1ec-1f1f9.png?v8",guernsey:"unicode/1f1ec-1f1ec.png?v8",guide_dog:"unicode/1f9ae.png?v8",guinea:"unicode/1f1ec-1f1f3.png?v8",guinea_bissau:"unicode/1f1ec-1f1fc.png?v8",guitar:"unicode/1f3b8.png?v8",gun:"unicode/1f52b.png?v8",guyana:"unicode/1f1ec-1f1fe.png?v8",haircut:"unicode/1f487.png?v8",haircut_man:"unicode/1f487-2642.png?v8",haircut_woman:"unicode/1f487-2640.png?v8",haiti:"unicode/1f1ed-1f1f9.png?v8",hamburger:"unicode/1f354.png?v8",hammer:"unicode/1f528.png?v8",hammer_and_pick:"unicode/2692.png?v8",hammer_and_wrench:"unicode/1f6e0.png?v8",hamster:"unicode/1f439.png?v8",hand:"unicode/270b.png?v8",hand_over_mouth:"unicode/1f92d.png?v8",handbag:"unicode/1f45c.png?v8",handball_person:"unicode/1f93e.png?v8",handshake:"unicode/1f91d.png?v8",hankey:"unicode/1f4a9.png?v8",hash:"unicode/0023-20e3.png?v8",hatched_chick:"unicode/1f425.png?v8",hatching_chick:"unicode/1f423.png?v8",headphones:"unicode/1f3a7.png?v8",headstone:"unicode/1faa6.png?v8",health_worker:"unicode/1f9d1-2695.png?v8",hear_no_evil:"unicode/1f649.png?v8",heard_mcdonald_islands:"unicode/1f1ed-1f1f2.png?v8",heart:"unicode/2764.png?v8",heart_decoration:"unicode/1f49f.png?v8",heart_eyes:"unicode/1f60d.png?v8",heart_eyes_cat:"unicode/1f63b.png?v8",heart_on_fire:"unicode/2764-1f525.png?v8",heartbeat:"unicode/1f493.png?v8",heartpulse:"unicode/1f497.png?v8",hearts:"unicode/2665.png?v8",heavy_check_mark:"unicode/2714.png?v8",heavy_division_sign:"unicode/2797.png?v8",heavy_dollar_sign:"unicode/1f4b2.png?v8",heavy_exclamation_mark:"unicode/2757.png?v8",heavy_heart_exclamation:"unicode/2763.png?v8",heavy_minus_sign:"unicode/2796.png?v8",heavy_multiplication_x:"unicode/2716.png?v8",heavy_plus_sign:"unicode/2795.png?v8",hedgehog:"unicode/1f994.png?v8",helicopter:"unicode/1f681.png?v8",herb:"unicode/1f33f.png?v8",hibiscus:"unicode/1f33a.png?v8",high_brightness:"unicode/1f506.png?v8",high_heel:"unicode/1f460.png?v8",hiking_boot:"unicode/1f97e.png?v8",hindu_temple:"unicode/1f6d5.png?v8",hippopotamus:"unicode/1f99b.png?v8",hocho:"unicode/1f52a.png?v8",hole:"unicode/1f573.png?v8",honduras:"unicode/1f1ed-1f1f3.png?v8",honey_pot:"unicode/1f36f.png?v8",honeybee:"unicode/1f41d.png?v8",hong_kong:"unicode/1f1ed-1f1f0.png?v8",hook:"unicode/1fa9d.png?v8",horse:"unicode/1f434.png?v8",horse_racing:"unicode/1f3c7.png?v8",hospital:"unicode/1f3e5.png?v8",hot_face:"unicode/1f975.png?v8",hot_pepper:"unicode/1f336.png?v8",hotdog:"unicode/1f32d.png?v8",hotel:"unicode/1f3e8.png?v8",hotsprings:"unicode/2668.png?v8",hourglass:"unicode/231b.png?v8",hourglass_flowing_sand:"unicode/23f3.png?v8",house:"unicode/1f3e0.png?v8",house_with_garden:"unicode/1f3e1.png?v8",houses:"unicode/1f3d8.png?v8",hugs:"unicode/1f917.png?v8",hungary:"unicode/1f1ed-1f1fa.png?v8",hurtrealbad:"hurtrealbad.png?v8",hushed:"unicode/1f62f.png?v8",hut:"unicode/1f6d6.png?v8",ice_cream:"unicode/1f368.png?v8",ice_cube:"unicode/1f9ca.png?v8",ice_hockey:"unicode/1f3d2.png?v8",ice_skate:"unicode/26f8.png?v8",icecream:"unicode/1f366.png?v8",iceland:"unicode/1f1ee-1f1f8.png?v8",id:"unicode/1f194.png?v8",ideograph_advantage:"unicode/1f250.png?v8",imp:"unicode/1f47f.png?v8",inbox_tray:"unicode/1f4e5.png?v8",incoming_envelope:"unicode/1f4e8.png?v8",india:"unicode/1f1ee-1f1f3.png?v8",indonesia:"unicode/1f1ee-1f1e9.png?v8",infinity:"unicode/267e.png?v8",information_desk_person:"unicode/1f481.png?v8",information_source:"unicode/2139.png?v8",innocent:"unicode/1f607.png?v8",interrobang:"unicode/2049.png?v8",iphone:"unicode/1f4f1.png?v8",iran:"unicode/1f1ee-1f1f7.png?v8",iraq:"unicode/1f1ee-1f1f6.png?v8",ireland:"unicode/1f1ee-1f1ea.png?v8",isle_of_man:"unicode/1f1ee-1f1f2.png?v8",israel:"unicode/1f1ee-1f1f1.png?v8",it:"unicode/1f1ee-1f1f9.png?v8",izakaya_lantern:"unicode/1f3ee.png?v8",jack_o_lantern:"unicode/1f383.png?v8",jamaica:"unicode/1f1ef-1f1f2.png?v8",japan:"unicode/1f5fe.png?v8",japanese_castle:"unicode/1f3ef.png?v8",japanese_goblin:"unicode/1f47a.png?v8",japanese_ogre:"unicode/1f479.png?v8",jeans:"unicode/1f456.png?v8",jersey:"unicode/1f1ef-1f1ea.png?v8",jigsaw:"unicode/1f9e9.png?v8",jordan:"unicode/1f1ef-1f1f4.png?v8",joy:"unicode/1f602.png?v8",joy_cat:"unicode/1f639.png?v8",joystick:"unicode/1f579.png?v8",jp:"unicode/1f1ef-1f1f5.png?v8",judge:"unicode/1f9d1-2696.png?v8",juggling_person:"unicode/1f939.png?v8",kaaba:"unicode/1f54b.png?v8",kangaroo:"unicode/1f998.png?v8",kazakhstan:"unicode/1f1f0-1f1ff.png?v8",kenya:"unicode/1f1f0-1f1ea.png?v8",key:"unicode/1f511.png?v8",keyboard:"unicode/2328.png?v8",keycap_ten:"unicode/1f51f.png?v8",kick_scooter:"unicode/1f6f4.png?v8",kimono:"unicode/1f458.png?v8",kiribati:"unicode/1f1f0-1f1ee.png?v8",kiss:"unicode/1f48b.png?v8",kissing:"unicode/1f617.png?v8",kissing_cat:"unicode/1f63d.png?v8",kissing_closed_eyes:"unicode/1f61a.png?v8",kissing_heart:"unicode/1f618.png?v8",kissing_smiling_eyes:"unicode/1f619.png?v8",kite:"unicode/1fa81.png?v8",kiwi_fruit:"unicode/1f95d.png?v8",kneeling_man:"unicode/1f9ce-2642.png?v8",kneeling_person:"unicode/1f9ce.png?v8",kneeling_woman:"unicode/1f9ce-2640.png?v8",knife:"unicode/1f52a.png?v8",knot:"unicode/1faa2.png?v8",koala:"unicode/1f428.png?v8",koko:"unicode/1f201.png?v8",kosovo:"unicode/1f1fd-1f1f0.png?v8",kr:"unicode/1f1f0-1f1f7.png?v8",kuwait:"unicode/1f1f0-1f1fc.png?v8",kyrgyzstan:"unicode/1f1f0-1f1ec.png?v8",lab_coat:"unicode/1f97c.png?v8",label:"unicode/1f3f7.png?v8",lacrosse:"unicode/1f94d.png?v8",ladder:"unicode/1fa9c.png?v8",lady_beetle:"unicode/1f41e.png?v8",lantern:"unicode/1f3ee.png?v8",laos:"unicode/1f1f1-1f1e6.png?v8",large_blue_circle:"unicode/1f535.png?v8",large_blue_diamond:"unicode/1f537.png?v8",large_orange_diamond:"unicode/1f536.png?v8",last_quarter_moon:"unicode/1f317.png?v8",last_quarter_moon_with_face:"unicode/1f31c.png?v8",latin_cross:"unicode/271d.png?v8",latvia:"unicode/1f1f1-1f1fb.png?v8",laughing:"unicode/1f606.png?v8",leafy_green:"unicode/1f96c.png?v8",leaves:"unicode/1f343.png?v8",lebanon:"unicode/1f1f1-1f1e7.png?v8",ledger:"unicode/1f4d2.png?v8",left_luggage:"unicode/1f6c5.png?v8",left_right_arrow:"unicode/2194.png?v8",left_speech_bubble:"unicode/1f5e8.png?v8",leftwards_arrow_with_hook:"unicode/21a9.png?v8",leg:"unicode/1f9b5.png?v8",lemon:"unicode/1f34b.png?v8",leo:"unicode/264c.png?v8",leopard:"unicode/1f406.png?v8",lesotho:"unicode/1f1f1-1f1f8.png?v8",level_slider:"unicode/1f39a.png?v8",liberia:"unicode/1f1f1-1f1f7.png?v8",libra:"unicode/264e.png?v8",libya:"unicode/1f1f1-1f1fe.png?v8",liechtenstein:"unicode/1f1f1-1f1ee.png?v8",light_rail:"unicode/1f688.png?v8",link:"unicode/1f517.png?v8",lion:"unicode/1f981.png?v8",lips:"unicode/1f444.png?v8",lipstick:"unicode/1f484.png?v8",lithuania:"unicode/1f1f1-1f1f9.png?v8",lizard:"unicode/1f98e.png?v8",llama:"unicode/1f999.png?v8",lobster:"unicode/1f99e.png?v8",lock:"unicode/1f512.png?v8",lock_with_ink_pen:"unicode/1f50f.png?v8",lollipop:"unicode/1f36d.png?v8",long_drum:"unicode/1fa98.png?v8",loop:"unicode/27bf.png?v8",lotion_bottle:"unicode/1f9f4.png?v8",lotus_position:"unicode/1f9d8.png?v8",lotus_position_man:"unicode/1f9d8-2642.png?v8",lotus_position_woman:"unicode/1f9d8-2640.png?v8",loud_sound:"unicode/1f50a.png?v8",loudspeaker:"unicode/1f4e2.png?v8",love_hotel:"unicode/1f3e9.png?v8",love_letter:"unicode/1f48c.png?v8",love_you_gesture:"unicode/1f91f.png?v8",low_brightness:"unicode/1f505.png?v8",luggage:"unicode/1f9f3.png?v8",lungs:"unicode/1fac1.png?v8",luxembourg:"unicode/1f1f1-1f1fa.png?v8",lying_face:"unicode/1f925.png?v8",m:"unicode/24c2.png?v8",macau:"unicode/1f1f2-1f1f4.png?v8",macedonia:"unicode/1f1f2-1f1f0.png?v8",madagascar:"unicode/1f1f2-1f1ec.png?v8",mag:"unicode/1f50d.png?v8",mag_right:"unicode/1f50e.png?v8",mage:"unicode/1f9d9.png?v8",mage_man:"unicode/1f9d9-2642.png?v8",mage_woman:"unicode/1f9d9-2640.png?v8",magic_wand:"unicode/1fa84.png?v8",magnet:"unicode/1f9f2.png?v8",mahjong:"unicode/1f004.png?v8",mailbox:"unicode/1f4eb.png?v8",mailbox_closed:"unicode/1f4ea.png?v8",mailbox_with_mail:"unicode/1f4ec.png?v8",mailbox_with_no_mail:"unicode/1f4ed.png?v8",malawi:"unicode/1f1f2-1f1fc.png?v8",malaysia:"unicode/1f1f2-1f1fe.png?v8",maldives:"unicode/1f1f2-1f1fb.png?v8",male_detective:"unicode/1f575-2642.png?v8",male_sign:"unicode/2642.png?v8",mali:"unicode/1f1f2-1f1f1.png?v8",malta:"unicode/1f1f2-1f1f9.png?v8",mammoth:"unicode/1f9a3.png?v8",man:"unicode/1f468.png?v8",man_artist:"unicode/1f468-1f3a8.png?v8",man_astronaut:"unicode/1f468-1f680.png?v8",man_beard:"unicode/1f9d4-2642.png?v8",man_cartwheeling:"unicode/1f938-2642.png?v8",man_cook:"unicode/1f468-1f373.png?v8",man_dancing:"unicode/1f57a.png?v8",man_facepalming:"unicode/1f926-2642.png?v8",man_factory_worker:"unicode/1f468-1f3ed.png?v8",man_farmer:"unicode/1f468-1f33e.png?v8",man_feeding_baby:"unicode/1f468-1f37c.png?v8",man_firefighter:"unicode/1f468-1f692.png?v8",man_health_worker:"unicode/1f468-2695.png?v8",man_in_manual_wheelchair:"unicode/1f468-1f9bd.png?v8",man_in_motorized_wheelchair:"unicode/1f468-1f9bc.png?v8",man_in_tuxedo:"unicode/1f935-2642.png?v8",man_judge:"unicode/1f468-2696.png?v8",man_juggling:"unicode/1f939-2642.png?v8",man_mechanic:"unicode/1f468-1f527.png?v8",man_office_worker:"unicode/1f468-1f4bc.png?v8",man_pilot:"unicode/1f468-2708.png?v8",man_playing_handball:"unicode/1f93e-2642.png?v8",man_playing_water_polo:"unicode/1f93d-2642.png?v8",man_scientist:"unicode/1f468-1f52c.png?v8",man_shrugging:"unicode/1f937-2642.png?v8",man_singer:"unicode/1f468-1f3a4.png?v8",man_student:"unicode/1f468-1f393.png?v8",man_teacher:"unicode/1f468-1f3eb.png?v8",man_technologist:"unicode/1f468-1f4bb.png?v8",man_with_gua_pi_mao:"unicode/1f472.png?v8",man_with_probing_cane:"unicode/1f468-1f9af.png?v8",man_with_turban:"unicode/1f473-2642.png?v8",man_with_veil:"unicode/1f470-2642.png?v8",mandarin:"unicode/1f34a.png?v8",mango:"unicode/1f96d.png?v8",mans_shoe:"unicode/1f45e.png?v8",mantelpiece_clock:"unicode/1f570.png?v8",manual_wheelchair:"unicode/1f9bd.png?v8",maple_leaf:"unicode/1f341.png?v8",marshall_islands:"unicode/1f1f2-1f1ed.png?v8",martial_arts_uniform:"unicode/1f94b.png?v8",martinique:"unicode/1f1f2-1f1f6.png?v8",mask:"unicode/1f637.png?v8",massage:"unicode/1f486.png?v8",massage_man:"unicode/1f486-2642.png?v8",massage_woman:"unicode/1f486-2640.png?v8",mate:"unicode/1f9c9.png?v8",mauritania:"unicode/1f1f2-1f1f7.png?v8",mauritius:"unicode/1f1f2-1f1fa.png?v8",mayotte:"unicode/1f1fe-1f1f9.png?v8",meat_on_bone:"unicode/1f356.png?v8",mechanic:"unicode/1f9d1-1f527.png?v8",mechanical_arm:"unicode/1f9be.png?v8",mechanical_leg:"unicode/1f9bf.png?v8",medal_military:"unicode/1f396.png?v8",medal_sports:"unicode/1f3c5.png?v8",medical_symbol:"unicode/2695.png?v8",mega:"unicode/1f4e3.png?v8",melon:"unicode/1f348.png?v8",memo:"unicode/1f4dd.png?v8",men_wrestling:"unicode/1f93c-2642.png?v8",mending_heart:"unicode/2764-1fa79.png?v8",menorah:"unicode/1f54e.png?v8",mens:"unicode/1f6b9.png?v8",mermaid:"unicode/1f9dc-2640.png?v8",merman:"unicode/1f9dc-2642.png?v8",merperson:"unicode/1f9dc.png?v8",metal:"unicode/1f918.png?v8",metro:"unicode/1f687.png?v8",mexico:"unicode/1f1f2-1f1fd.png?v8",microbe:"unicode/1f9a0.png?v8",micronesia:"unicode/1f1eb-1f1f2.png?v8",microphone:"unicode/1f3a4.png?v8",microscope:"unicode/1f52c.png?v8",middle_finger:"unicode/1f595.png?v8",military_helmet:"unicode/1fa96.png?v8",milk_glass:"unicode/1f95b.png?v8",milky_way:"unicode/1f30c.png?v8",minibus:"unicode/1f690.png?v8",minidisc:"unicode/1f4bd.png?v8",mirror:"unicode/1fa9e.png?v8",mobile_phone_off:"unicode/1f4f4.png?v8",moldova:"unicode/1f1f2-1f1e9.png?v8",monaco:"unicode/1f1f2-1f1e8.png?v8",money_mouth_face:"unicode/1f911.png?v8",money_with_wings:"unicode/1f4b8.png?v8",moneybag:"unicode/1f4b0.png?v8",mongolia:"unicode/1f1f2-1f1f3.png?v8",monkey:"unicode/1f412.png?v8",monkey_face:"unicode/1f435.png?v8",monocle_face:"unicode/1f9d0.png?v8",monorail:"unicode/1f69d.png?v8",montenegro:"unicode/1f1f2-1f1ea.png?v8",montserrat:"unicode/1f1f2-1f1f8.png?v8",moon:"unicode/1f314.png?v8",moon_cake:"unicode/1f96e.png?v8",morocco:"unicode/1f1f2-1f1e6.png?v8",mortar_board:"unicode/1f393.png?v8",mosque:"unicode/1f54c.png?v8",mosquito:"unicode/1f99f.png?v8",motor_boat:"unicode/1f6e5.png?v8",motor_scooter:"unicode/1f6f5.png?v8",motorcycle:"unicode/1f3cd.png?v8",motorized_wheelchair:"unicode/1f9bc.png?v8",motorway:"unicode/1f6e3.png?v8",mount_fuji:"unicode/1f5fb.png?v8",mountain:"unicode/26f0.png?v8",mountain_bicyclist:"unicode/1f6b5.png?v8",mountain_biking_man:"unicode/1f6b5-2642.png?v8",mountain_biking_woman:"unicode/1f6b5-2640.png?v8",mountain_cableway:"unicode/1f6a0.png?v8",mountain_railway:"unicode/1f69e.png?v8",mountain_snow:"unicode/1f3d4.png?v8",mouse:"unicode/1f42d.png?v8",mouse2:"unicode/1f401.png?v8",mouse_trap:"unicode/1faa4.png?v8",movie_camera:"unicode/1f3a5.png?v8",moyai:"unicode/1f5ff.png?v8",mozambique:"unicode/1f1f2-1f1ff.png?v8",mrs_claus:"unicode/1f936.png?v8",muscle:"unicode/1f4aa.png?v8",mushroom:"unicode/1f344.png?v8",musical_keyboard:"unicode/1f3b9.png?v8",musical_note:"unicode/1f3b5.png?v8",musical_score:"unicode/1f3bc.png?v8",mute:"unicode/1f507.png?v8",mx_claus:"unicode/1f9d1-1f384.png?v8",myanmar:"unicode/1f1f2-1f1f2.png?v8",nail_care:"unicode/1f485.png?v8",name_badge:"unicode/1f4db.png?v8",namibia:"unicode/1f1f3-1f1e6.png?v8",national_park:"unicode/1f3de.png?v8",nauru:"unicode/1f1f3-1f1f7.png?v8",nauseated_face:"unicode/1f922.png?v8",nazar_amulet:"unicode/1f9ff.png?v8",neckbeard:"neckbeard.png?v8",necktie:"unicode/1f454.png?v8",negative_squared_cross_mark:"unicode/274e.png?v8",nepal:"unicode/1f1f3-1f1f5.png?v8",nerd_face:"unicode/1f913.png?v8",nesting_dolls:"unicode/1fa86.png?v8",netherlands:"unicode/1f1f3-1f1f1.png?v8",neutral_face:"unicode/1f610.png?v8",new:"unicode/1f195.png?v8",new_caledonia:"unicode/1f1f3-1f1e8.png?v8",new_moon:"unicode/1f311.png?v8",new_moon_with_face:"unicode/1f31a.png?v8",new_zealand:"unicode/1f1f3-1f1ff.png?v8",newspaper:"unicode/1f4f0.png?v8",newspaper_roll:"unicode/1f5de.png?v8",next_track_button:"unicode/23ed.png?v8",ng:"unicode/1f196.png?v8",ng_man:"unicode/1f645-2642.png?v8",ng_woman:"unicode/1f645-2640.png?v8",nicaragua:"unicode/1f1f3-1f1ee.png?v8",niger:"unicode/1f1f3-1f1ea.png?v8",nigeria:"unicode/1f1f3-1f1ec.png?v8",night_with_stars:"unicode/1f303.png?v8",nine:"unicode/0039-20e3.png?v8",ninja:"unicode/1f977.png?v8",niue:"unicode/1f1f3-1f1fa.png?v8",no_bell:"unicode/1f515.png?v8",no_bicycles:"unicode/1f6b3.png?v8",no_entry:"unicode/26d4.png?v8",no_entry_sign:"unicode/1f6ab.png?v8",no_good:"unicode/1f645.png?v8",no_good_man:"unicode/1f645-2642.png?v8",no_good_woman:"unicode/1f645-2640.png?v8",no_mobile_phones:"unicode/1f4f5.png?v8",no_mouth:"unicode/1f636.png?v8",no_pedestrians:"unicode/1f6b7.png?v8",no_smoking:"unicode/1f6ad.png?v8","non-potable_water":"unicode/1f6b1.png?v8",norfolk_island:"unicode/1f1f3-1f1eb.png?v8",north_korea:"unicode/1f1f0-1f1f5.png?v8",northern_mariana_islands:"unicode/1f1f2-1f1f5.png?v8",norway:"unicode/1f1f3-1f1f4.png?v8",nose:"unicode/1f443.png?v8",notebook:"unicode/1f4d3.png?v8",notebook_with_decorative_cover:"unicode/1f4d4.png?v8",notes:"unicode/1f3b6.png?v8",nut_and_bolt:"unicode/1f529.png?v8",o:"unicode/2b55.png?v8",o2:"unicode/1f17e.png?v8",ocean:"unicode/1f30a.png?v8",octocat:"octocat.png?v8",octopus:"unicode/1f419.png?v8",oden:"unicode/1f362.png?v8",office:"unicode/1f3e2.png?v8",office_worker:"unicode/1f9d1-1f4bc.png?v8",oil_drum:"unicode/1f6e2.png?v8",ok:"unicode/1f197.png?v8",ok_hand:"unicode/1f44c.png?v8",ok_man:"unicode/1f646-2642.png?v8",ok_person:"unicode/1f646.png?v8",ok_woman:"unicode/1f646-2640.png?v8",old_key:"unicode/1f5dd.png?v8",older_adult:"unicode/1f9d3.png?v8",older_man:"unicode/1f474.png?v8",older_woman:"unicode/1f475.png?v8",olive:"unicode/1fad2.png?v8",om:"unicode/1f549.png?v8",oman:"unicode/1f1f4-1f1f2.png?v8",on:"unicode/1f51b.png?v8",oncoming_automobile:"unicode/1f698.png?v8",oncoming_bus:"unicode/1f68d.png?v8",oncoming_police_car:"unicode/1f694.png?v8",oncoming_taxi:"unicode/1f696.png?v8",one:"unicode/0031-20e3.png?v8",one_piece_swimsuit:"unicode/1fa71.png?v8",onion:"unicode/1f9c5.png?v8",open_book:"unicode/1f4d6.png?v8",open_file_folder:"unicode/1f4c2.png?v8",open_hands:"unicode/1f450.png?v8",open_mouth:"unicode/1f62e.png?v8",open_umbrella:"unicode/2602.png?v8",ophiuchus:"unicode/26ce.png?v8",orange:"unicode/1f34a.png?v8",orange_book:"unicode/1f4d9.png?v8",orange_circle:"unicode/1f7e0.png?v8",orange_heart:"unicode/1f9e1.png?v8",orange_square:"unicode/1f7e7.png?v8",orangutan:"unicode/1f9a7.png?v8",orthodox_cross:"unicode/2626.png?v8",otter:"unicode/1f9a6.png?v8",outbox_tray:"unicode/1f4e4.png?v8",owl:"unicode/1f989.png?v8",ox:"unicode/1f402.png?v8",oyster:"unicode/1f9aa.png?v8",package:"unicode/1f4e6.png?v8",page_facing_up:"unicode/1f4c4.png?v8",page_with_curl:"unicode/1f4c3.png?v8",pager:"unicode/1f4df.png?v8",paintbrush:"unicode/1f58c.png?v8",pakistan:"unicode/1f1f5-1f1f0.png?v8",palau:"unicode/1f1f5-1f1fc.png?v8",palestinian_territories:"unicode/1f1f5-1f1f8.png?v8",palm_tree:"unicode/1f334.png?v8",palms_up_together:"unicode/1f932.png?v8",panama:"unicode/1f1f5-1f1e6.png?v8",pancakes:"unicode/1f95e.png?v8",panda_face:"unicode/1f43c.png?v8",paperclip:"unicode/1f4ce.png?v8",paperclips:"unicode/1f587.png?v8",papua_new_guinea:"unicode/1f1f5-1f1ec.png?v8",parachute:"unicode/1fa82.png?v8",paraguay:"unicode/1f1f5-1f1fe.png?v8",parasol_on_ground:"unicode/26f1.png?v8",parking:"unicode/1f17f.png?v8",parrot:"unicode/1f99c.png?v8",part_alternation_mark:"unicode/303d.png?v8",partly_sunny:"unicode/26c5.png?v8",partying_face:"unicode/1f973.png?v8",passenger_ship:"unicode/1f6f3.png?v8",passport_control:"unicode/1f6c2.png?v8",pause_button:"unicode/23f8.png?v8",paw_prints:"unicode/1f43e.png?v8",peace_symbol:"unicode/262e.png?v8",peach:"unicode/1f351.png?v8",peacock:"unicode/1f99a.png?v8",peanuts:"unicode/1f95c.png?v8",pear:"unicode/1f350.png?v8",pen:"unicode/1f58a.png?v8",pencil:"unicode/1f4dd.png?v8",pencil2:"unicode/270f.png?v8",penguin:"unicode/1f427.png?v8",pensive:"unicode/1f614.png?v8",people_holding_hands:"unicode/1f9d1-1f91d-1f9d1.png?v8",people_hugging:"unicode/1fac2.png?v8",performing_arts:"unicode/1f3ad.png?v8",persevere:"unicode/1f623.png?v8",person_bald:"unicode/1f9d1-1f9b2.png?v8",person_curly_hair:"unicode/1f9d1-1f9b1.png?v8",person_feeding_baby:"unicode/1f9d1-1f37c.png?v8",person_fencing:"unicode/1f93a.png?v8",person_in_manual_wheelchair:"unicode/1f9d1-1f9bd.png?v8",person_in_motorized_wheelchair:"unicode/1f9d1-1f9bc.png?v8",person_in_tuxedo:"unicode/1f935.png?v8",person_red_hair:"unicode/1f9d1-1f9b0.png?v8",person_white_hair:"unicode/1f9d1-1f9b3.png?v8",person_with_probing_cane:"unicode/1f9d1-1f9af.png?v8",person_with_turban:"unicode/1f473.png?v8",person_with_veil:"unicode/1f470.png?v8",peru:"unicode/1f1f5-1f1ea.png?v8",petri_dish:"unicode/1f9eb.png?v8",philippines:"unicode/1f1f5-1f1ed.png?v8",phone:"unicode/260e.png?v8",pick:"unicode/26cf.png?v8",pickup_truck:"unicode/1f6fb.png?v8",pie:"unicode/1f967.png?v8",pig:"unicode/1f437.png?v8",pig2:"unicode/1f416.png?v8",pig_nose:"unicode/1f43d.png?v8",pill:"unicode/1f48a.png?v8",pilot:"unicode/1f9d1-2708.png?v8",pinata:"unicode/1fa85.png?v8",pinched_fingers:"unicode/1f90c.png?v8",pinching_hand:"unicode/1f90f.png?v8",pineapple:"unicode/1f34d.png?v8",ping_pong:"unicode/1f3d3.png?v8",pirate_flag:"unicode/1f3f4-2620.png?v8",pisces:"unicode/2653.png?v8",pitcairn_islands:"unicode/1f1f5-1f1f3.png?v8",pizza:"unicode/1f355.png?v8",placard:"unicode/1faa7.png?v8",place_of_worship:"unicode/1f6d0.png?v8",plate_with_cutlery:"unicode/1f37d.png?v8",play_or_pause_button:"unicode/23ef.png?v8",pleading_face:"unicode/1f97a.png?v8",plunger:"unicode/1faa0.png?v8",point_down:"unicode/1f447.png?v8",point_left:"unicode/1f448.png?v8",point_right:"unicode/1f449.png?v8",point_up:"unicode/261d.png?v8",point_up_2:"unicode/1f446.png?v8",poland:"unicode/1f1f5-1f1f1.png?v8",polar_bear:"unicode/1f43b-2744.png?v8",police_car:"unicode/1f693.png?v8",police_officer:"unicode/1f46e.png?v8",policeman:"unicode/1f46e-2642.png?v8",policewoman:"unicode/1f46e-2640.png?v8",poodle:"unicode/1f429.png?v8",poop:"unicode/1f4a9.png?v8",popcorn:"unicode/1f37f.png?v8",portugal:"unicode/1f1f5-1f1f9.png?v8",post_office:"unicode/1f3e3.png?v8",postal_horn:"unicode/1f4ef.png?v8",postbox:"unicode/1f4ee.png?v8",potable_water:"unicode/1f6b0.png?v8",potato:"unicode/1f954.png?v8",potted_plant:"unicode/1fab4.png?v8",pouch:"unicode/1f45d.png?v8",poultry_leg:"unicode/1f357.png?v8",pound:"unicode/1f4b7.png?v8",pout:"unicode/1f621.png?v8",pouting_cat:"unicode/1f63e.png?v8",pouting_face:"unicode/1f64e.png?v8",pouting_man:"unicode/1f64e-2642.png?v8",pouting_woman:"unicode/1f64e-2640.png?v8",pray:"unicode/1f64f.png?v8",prayer_beads:"unicode/1f4ff.png?v8",pregnant_woman:"unicode/1f930.png?v8",pretzel:"unicode/1f968.png?v8",previous_track_button:"unicode/23ee.png?v8",prince:"unicode/1f934.png?v8",princess:"unicode/1f478.png?v8",printer:"unicode/1f5a8.png?v8",probing_cane:"unicode/1f9af.png?v8",puerto_rico:"unicode/1f1f5-1f1f7.png?v8",punch:"unicode/1f44a.png?v8",purple_circle:"unicode/1f7e3.png?v8",purple_heart:"unicode/1f49c.png?v8",purple_square:"unicode/1f7ea.png?v8",purse:"unicode/1f45b.png?v8",pushpin:"unicode/1f4cc.png?v8",put_litter_in_its_place:"unicode/1f6ae.png?v8",qatar:"unicode/1f1f6-1f1e6.png?v8",question:"unicode/2753.png?v8",rabbit:"unicode/1f430.png?v8",rabbit2:"unicode/1f407.png?v8",raccoon:"unicode/1f99d.png?v8",racehorse:"unicode/1f40e.png?v8",racing_car:"unicode/1f3ce.png?v8",radio:"unicode/1f4fb.png?v8",radio_button:"unicode/1f518.png?v8",radioactive:"unicode/2622.png?v8",rage:"unicode/1f621.png?v8",rage1:"rage1.png?v8",rage2:"rage2.png?v8",rage3:"rage3.png?v8",rage4:"rage4.png?v8",railway_car:"unicode/1f683.png?v8",railway_track:"unicode/1f6e4.png?v8",rainbow:"unicode/1f308.png?v8",rainbow_flag:"unicode/1f3f3-1f308.png?v8",raised_back_of_hand:"unicode/1f91a.png?v8",raised_eyebrow:"unicode/1f928.png?v8",raised_hand:"unicode/270b.png?v8",raised_hand_with_fingers_splayed:"unicode/1f590.png?v8",raised_hands:"unicode/1f64c.png?v8",raising_hand:"unicode/1f64b.png?v8",raising_hand_man:"unicode/1f64b-2642.png?v8",raising_hand_woman:"unicode/1f64b-2640.png?v8",ram:"unicode/1f40f.png?v8",ramen:"unicode/1f35c.png?v8",rat:"unicode/1f400.png?v8",razor:"unicode/1fa92.png?v8",receipt:"unicode/1f9fe.png?v8",record_button:"unicode/23fa.png?v8",recycle:"unicode/267b.png?v8",red_car:"unicode/1f697.png?v8",red_circle:"unicode/1f534.png?v8",red_envelope:"unicode/1f9e7.png?v8",red_haired_man:"unicode/1f468-1f9b0.png?v8",red_haired_woman:"unicode/1f469-1f9b0.png?v8",red_square:"unicode/1f7e5.png?v8",registered:"unicode/00ae.png?v8",relaxed:"unicode/263a.png?v8",relieved:"unicode/1f60c.png?v8",reminder_ribbon:"unicode/1f397.png?v8",repeat:"unicode/1f501.png?v8",repeat_one:"unicode/1f502.png?v8",rescue_worker_helmet:"unicode/26d1.png?v8",restroom:"unicode/1f6bb.png?v8",reunion:"unicode/1f1f7-1f1ea.png?v8",revolving_hearts:"unicode/1f49e.png?v8",rewind:"unicode/23ea.png?v8",rhinoceros:"unicode/1f98f.png?v8",ribbon:"unicode/1f380.png?v8",rice:"unicode/1f35a.png?v8",rice_ball:"unicode/1f359.png?v8",rice_cracker:"unicode/1f358.png?v8",rice_scene:"unicode/1f391.png?v8",right_anger_bubble:"unicode/1f5ef.png?v8",ring:"unicode/1f48d.png?v8",ringed_planet:"unicode/1fa90.png?v8",robot:"unicode/1f916.png?v8",rock:"unicode/1faa8.png?v8",rocket:"unicode/1f680.png?v8",rofl:"unicode/1f923.png?v8",roll_eyes:"unicode/1f644.png?v8",roll_of_paper:"unicode/1f9fb.png?v8",roller_coaster:"unicode/1f3a2.png?v8",roller_skate:"unicode/1f6fc.png?v8",romania:"unicode/1f1f7-1f1f4.png?v8",rooster:"unicode/1f413.png?v8",rose:"unicode/1f339.png?v8",rosette:"unicode/1f3f5.png?v8",rotating_light:"unicode/1f6a8.png?v8",round_pushpin:"unicode/1f4cd.png?v8",rowboat:"unicode/1f6a3.png?v8",rowing_man:"unicode/1f6a3-2642.png?v8",rowing_woman:"unicode/1f6a3-2640.png?v8",ru:"unicode/1f1f7-1f1fa.png?v8",rugby_football:"unicode/1f3c9.png?v8",runner:"unicode/1f3c3.png?v8",running:"unicode/1f3c3.png?v8",running_man:"unicode/1f3c3-2642.png?v8",running_shirt_with_sash:"unicode/1f3bd.png?v8",running_woman:"unicode/1f3c3-2640.png?v8",rwanda:"unicode/1f1f7-1f1fc.png?v8",sa:"unicode/1f202.png?v8",safety_pin:"unicode/1f9f7.png?v8",safety_vest:"unicode/1f9ba.png?v8",sagittarius:"unicode/2650.png?v8",sailboat:"unicode/26f5.png?v8",sake:"unicode/1f376.png?v8",salt:"unicode/1f9c2.png?v8",samoa:"unicode/1f1fc-1f1f8.png?v8",san_marino:"unicode/1f1f8-1f1f2.png?v8",sandal:"unicode/1f461.png?v8",sandwich:"unicode/1f96a.png?v8",santa:"unicode/1f385.png?v8",sao_tome_principe:"unicode/1f1f8-1f1f9.png?v8",sari:"unicode/1f97b.png?v8",sassy_man:"unicode/1f481-2642.png?v8",sassy_woman:"unicode/1f481-2640.png?v8",satellite:"unicode/1f4e1.png?v8",satisfied:"unicode/1f606.png?v8",saudi_arabia:"unicode/1f1f8-1f1e6.png?v8",sauna_man:"unicode/1f9d6-2642.png?v8",sauna_person:"unicode/1f9d6.png?v8",sauna_woman:"unicode/1f9d6-2640.png?v8",sauropod:"unicode/1f995.png?v8",saxophone:"unicode/1f3b7.png?v8",scarf:"unicode/1f9e3.png?v8",school:"unicode/1f3eb.png?v8",school_satchel:"unicode/1f392.png?v8",scientist:"unicode/1f9d1-1f52c.png?v8",scissors:"unicode/2702.png?v8",scorpion:"unicode/1f982.png?v8",scorpius:"unicode/264f.png?v8",scotland:"unicode/1f3f4-e0067-e0062-e0073-e0063-e0074-e007f.png?v8",scream:"unicode/1f631.png?v8",scream_cat:"unicode/1f640.png?v8",screwdriver:"unicode/1fa9b.png?v8",scroll:"unicode/1f4dc.png?v8",seal:"unicode/1f9ad.png?v8",seat:"unicode/1f4ba.png?v8",secret:"unicode/3299.png?v8",see_no_evil:"unicode/1f648.png?v8",seedling:"unicode/1f331.png?v8",selfie:"unicode/1f933.png?v8",senegal:"unicode/1f1f8-1f1f3.png?v8",serbia:"unicode/1f1f7-1f1f8.png?v8",service_dog:"unicode/1f415-1f9ba.png?v8",seven:"unicode/0037-20e3.png?v8",sewing_needle:"unicode/1faa1.png?v8",seychelles:"unicode/1f1f8-1f1e8.png?v8",shallow_pan_of_food:"unicode/1f958.png?v8",shamrock:"unicode/2618.png?v8",shark:"unicode/1f988.png?v8",shaved_ice:"unicode/1f367.png?v8",sheep:"unicode/1f411.png?v8",shell:"unicode/1f41a.png?v8",shield:"unicode/1f6e1.png?v8",shinto_shrine:"unicode/26e9.png?v8",ship:"unicode/1f6a2.png?v8",shipit:"shipit.png?v8",shirt:"unicode/1f455.png?v8",shit:"unicode/1f4a9.png?v8",shoe:"unicode/1f45e.png?v8",shopping:"unicode/1f6cd.png?v8",shopping_cart:"unicode/1f6d2.png?v8",shorts:"unicode/1fa73.png?v8",shower:"unicode/1f6bf.png?v8",shrimp:"unicode/1f990.png?v8",shrug:"unicode/1f937.png?v8",shushing_face:"unicode/1f92b.png?v8",sierra_leone:"unicode/1f1f8-1f1f1.png?v8",signal_strength:"unicode/1f4f6.png?v8",singapore:"unicode/1f1f8-1f1ec.png?v8",singer:"unicode/1f9d1-1f3a4.png?v8",sint_maarten:"unicode/1f1f8-1f1fd.png?v8",six:"unicode/0036-20e3.png?v8",six_pointed_star:"unicode/1f52f.png?v8",skateboard:"unicode/1f6f9.png?v8",ski:"unicode/1f3bf.png?v8",skier:"unicode/26f7.png?v8",skull:"unicode/1f480.png?v8",skull_and_crossbones:"unicode/2620.png?v8",skunk:"unicode/1f9a8.png?v8",sled:"unicode/1f6f7.png?v8",sleeping:"unicode/1f634.png?v8",sleeping_bed:"unicode/1f6cc.png?v8",sleepy:"unicode/1f62a.png?v8",slightly_frowning_face:"unicode/1f641.png?v8",slightly_smiling_face:"unicode/1f642.png?v8",slot_machine:"unicode/1f3b0.png?v8",sloth:"unicode/1f9a5.png?v8",slovakia:"unicode/1f1f8-1f1f0.png?v8",slovenia:"unicode/1f1f8-1f1ee.png?v8",small_airplane:"unicode/1f6e9.png?v8",small_blue_diamond:"unicode/1f539.png?v8",small_orange_diamond:"unicode/1f538.png?v8",small_red_triangle:"unicode/1f53a.png?v8",small_red_triangle_down:"unicode/1f53b.png?v8",smile:"unicode/1f604.png?v8",smile_cat:"unicode/1f638.png?v8",smiley:"unicode/1f603.png?v8",smiley_cat:"unicode/1f63a.png?v8",smiling_face_with_tear:"unicode/1f972.png?v8",smiling_face_with_three_hearts:"unicode/1f970.png?v8",smiling_imp:"unicode/1f608.png?v8",smirk:"unicode/1f60f.png?v8",smirk_cat:"unicode/1f63c.png?v8",smoking:"unicode/1f6ac.png?v8",snail:"unicode/1f40c.png?v8",snake:"unicode/1f40d.png?v8",sneezing_face:"unicode/1f927.png?v8",snowboarder:"unicode/1f3c2.png?v8",snowflake:"unicode/2744.png?v8",snowman:"unicode/26c4.png?v8",snowman_with_snow:"unicode/2603.png?v8",soap:"unicode/1f9fc.png?v8",sob:"unicode/1f62d.png?v8",soccer:"unicode/26bd.png?v8",socks:"unicode/1f9e6.png?v8",softball:"unicode/1f94e.png?v8",solomon_islands:"unicode/1f1f8-1f1e7.png?v8",somalia:"unicode/1f1f8-1f1f4.png?v8",soon:"unicode/1f51c.png?v8",sos:"unicode/1f198.png?v8",sound:"unicode/1f509.png?v8",south_africa:"unicode/1f1ff-1f1e6.png?v8",south_georgia_south_sandwich_islands:"unicode/1f1ec-1f1f8.png?v8",south_sudan:"unicode/1f1f8-1f1f8.png?v8",space_invader:"unicode/1f47e.png?v8",spades:"unicode/2660.png?v8",spaghetti:"unicode/1f35d.png?v8",sparkle:"unicode/2747.png?v8",sparkler:"unicode/1f387.png?v8",sparkles:"unicode/2728.png?v8",sparkling_heart:"unicode/1f496.png?v8",speak_no_evil:"unicode/1f64a.png?v8",speaker:"unicode/1f508.png?v8",speaking_head:"unicode/1f5e3.png?v8",speech_balloon:"unicode/1f4ac.png?v8",speedboat:"unicode/1f6a4.png?v8",spider:"unicode/1f577.png?v8",spider_web:"unicode/1f578.png?v8",spiral_calendar:"unicode/1f5d3.png?v8",spiral_notepad:"unicode/1f5d2.png?v8",sponge:"unicode/1f9fd.png?v8",spoon:"unicode/1f944.png?v8",squid:"unicode/1f991.png?v8",sri_lanka:"unicode/1f1f1-1f1f0.png?v8",st_barthelemy:"unicode/1f1e7-1f1f1.png?v8",st_helena:"unicode/1f1f8-1f1ed.png?v8",st_kitts_nevis:"unicode/1f1f0-1f1f3.png?v8",st_lucia:"unicode/1f1f1-1f1e8.png?v8",st_martin:"unicode/1f1f2-1f1eb.png?v8",st_pierre_miquelon:"unicode/1f1f5-1f1f2.png?v8",st_vincent_grenadines:"unicode/1f1fb-1f1e8.png?v8",stadium:"unicode/1f3df.png?v8",standing_man:"unicode/1f9cd-2642.png?v8",standing_person:"unicode/1f9cd.png?v8",standing_woman:"unicode/1f9cd-2640.png?v8",star:"unicode/2b50.png?v8",star2:"unicode/1f31f.png?v8",star_and_crescent:"unicode/262a.png?v8",star_of_david:"unicode/2721.png?v8",star_struck:"unicode/1f929.png?v8",stars:"unicode/1f320.png?v8",station:"unicode/1f689.png?v8",statue_of_liberty:"unicode/1f5fd.png?v8",steam_locomotive:"unicode/1f682.png?v8",stethoscope:"unicode/1fa7a.png?v8",stew:"unicode/1f372.png?v8",stop_button:"unicode/23f9.png?v8",stop_sign:"unicode/1f6d1.png?v8",stopwatch:"unicode/23f1.png?v8",straight_ruler:"unicode/1f4cf.png?v8",strawberry:"unicode/1f353.png?v8",stuck_out_tongue:"unicode/1f61b.png?v8",stuck_out_tongue_closed_eyes:"unicode/1f61d.png?v8",stuck_out_tongue_winking_eye:"unicode/1f61c.png?v8",student:"unicode/1f9d1-1f393.png?v8",studio_microphone:"unicode/1f399.png?v8",stuffed_flatbread:"unicode/1f959.png?v8",sudan:"unicode/1f1f8-1f1e9.png?v8",sun_behind_large_cloud:"unicode/1f325.png?v8",sun_behind_rain_cloud:"unicode/1f326.png?v8",sun_behind_small_cloud:"unicode/1f324.png?v8",sun_with_face:"unicode/1f31e.png?v8",sunflower:"unicode/1f33b.png?v8",sunglasses:"unicode/1f60e.png?v8",sunny:"unicode/2600.png?v8",sunrise:"unicode/1f305.png?v8",sunrise_over_mountains:"unicode/1f304.png?v8",superhero:"unicode/1f9b8.png?v8",superhero_man:"unicode/1f9b8-2642.png?v8",superhero_woman:"unicode/1f9b8-2640.png?v8",supervillain:"unicode/1f9b9.png?v8",supervillain_man:"unicode/1f9b9-2642.png?v8",supervillain_woman:"unicode/1f9b9-2640.png?v8",surfer:"unicode/1f3c4.png?v8",surfing_man:"unicode/1f3c4-2642.png?v8",surfing_woman:"unicode/1f3c4-2640.png?v8",suriname:"unicode/1f1f8-1f1f7.png?v8",sushi:"unicode/1f363.png?v8",suspect:"suspect.png?v8",suspension_railway:"unicode/1f69f.png?v8",svalbard_jan_mayen:"unicode/1f1f8-1f1ef.png?v8",swan:"unicode/1f9a2.png?v8",swaziland:"unicode/1f1f8-1f1ff.png?v8",sweat:"unicode/1f613.png?v8",sweat_drops:"unicode/1f4a6.png?v8",sweat_smile:"unicode/1f605.png?v8",sweden:"unicode/1f1f8-1f1ea.png?v8",sweet_potato:"unicode/1f360.png?v8",swim_brief:"unicode/1fa72.png?v8",swimmer:"unicode/1f3ca.png?v8",swimming_man:"unicode/1f3ca-2642.png?v8",swimming_woman:"unicode/1f3ca-2640.png?v8",switzerland:"unicode/1f1e8-1f1ed.png?v8",symbols:"unicode/1f523.png?v8",synagogue:"unicode/1f54d.png?v8",syria:"unicode/1f1f8-1f1fe.png?v8",syringe:"unicode/1f489.png?v8","t-rex":"unicode/1f996.png?v8",taco:"unicode/1f32e.png?v8",tada:"unicode/1f389.png?v8",taiwan:"unicode/1f1f9-1f1fc.png?v8",tajikistan:"unicode/1f1f9-1f1ef.png?v8",takeout_box:"unicode/1f961.png?v8",tamale:"unicode/1fad4.png?v8",tanabata_tree:"unicode/1f38b.png?v8",tangerine:"unicode/1f34a.png?v8",tanzania:"unicode/1f1f9-1f1ff.png?v8",taurus:"unicode/2649.png?v8",taxi:"unicode/1f695.png?v8",tea:"unicode/1f375.png?v8",teacher:"unicode/1f9d1-1f3eb.png?v8",teapot:"unicode/1fad6.png?v8",technologist:"unicode/1f9d1-1f4bb.png?v8",teddy_bear:"unicode/1f9f8.png?v8",telephone:"unicode/260e.png?v8",telephone_receiver:"unicode/1f4de.png?v8",telescope:"unicode/1f52d.png?v8",tennis:"unicode/1f3be.png?v8",tent:"unicode/26fa.png?v8",test_tube:"unicode/1f9ea.png?v8",thailand:"unicode/1f1f9-1f1ed.png?v8",thermometer:"unicode/1f321.png?v8",thinking:"unicode/1f914.png?v8",thong_sandal:"unicode/1fa74.png?v8",thought_balloon:"unicode/1f4ad.png?v8",thread:"unicode/1f9f5.png?v8",three:"unicode/0033-20e3.png?v8",thumbsdown:"unicode/1f44e.png?v8",thumbsup:"unicode/1f44d.png?v8",ticket:"unicode/1f3ab.png?v8",tickets:"unicode/1f39f.png?v8",tiger:"unicode/1f42f.png?v8",tiger2:"unicode/1f405.png?v8",timer_clock:"unicode/23f2.png?v8",timor_leste:"unicode/1f1f9-1f1f1.png?v8",tipping_hand_man:"unicode/1f481-2642.png?v8",tipping_hand_person:"unicode/1f481.png?v8",tipping_hand_woman:"unicode/1f481-2640.png?v8",tired_face:"unicode/1f62b.png?v8",tm:"unicode/2122.png?v8",togo:"unicode/1f1f9-1f1ec.png?v8",toilet:"unicode/1f6bd.png?v8",tokelau:"unicode/1f1f9-1f1f0.png?v8",tokyo_tower:"unicode/1f5fc.png?v8",tomato:"unicode/1f345.png?v8",tonga:"unicode/1f1f9-1f1f4.png?v8",tongue:"unicode/1f445.png?v8",toolbox:"unicode/1f9f0.png?v8",tooth:"unicode/1f9b7.png?v8",toothbrush:"unicode/1faa5.png?v8",top:"unicode/1f51d.png?v8",tophat:"unicode/1f3a9.png?v8",tornado:"unicode/1f32a.png?v8",tr:"unicode/1f1f9-1f1f7.png?v8",trackball:"unicode/1f5b2.png?v8",tractor:"unicode/1f69c.png?v8",traffic_light:"unicode/1f6a5.png?v8",train:"unicode/1f68b.png?v8",train2:"unicode/1f686.png?v8",tram:"unicode/1f68a.png?v8",transgender_flag:"unicode/1f3f3-26a7.png?v8",transgender_symbol:"unicode/26a7.png?v8",triangular_flag_on_post:"unicode/1f6a9.png?v8",triangular_ruler:"unicode/1f4d0.png?v8",trident:"unicode/1f531.png?v8",trinidad_tobago:"unicode/1f1f9-1f1f9.png?v8",tristan_da_cunha:"unicode/1f1f9-1f1e6.png?v8",triumph:"unicode/1f624.png?v8",trolleybus:"unicode/1f68e.png?v8",trollface:"trollface.png?v8",trophy:"unicode/1f3c6.png?v8",tropical_drink:"unicode/1f379.png?v8",tropical_fish:"unicode/1f420.png?v8",truck:"unicode/1f69a.png?v8",trumpet:"unicode/1f3ba.png?v8",tshirt:"unicode/1f455.png?v8",tulip:"unicode/1f337.png?v8",tumbler_glass:"unicode/1f943.png?v8",tunisia:"unicode/1f1f9-1f1f3.png?v8",turkey:"unicode/1f983.png?v8",turkmenistan:"unicode/1f1f9-1f1f2.png?v8",turks_caicos_islands:"unicode/1f1f9-1f1e8.png?v8",turtle:"unicode/1f422.png?v8",tuvalu:"unicode/1f1f9-1f1fb.png?v8",tv:"unicode/1f4fa.png?v8",twisted_rightwards_arrows:"unicode/1f500.png?v8",two:"unicode/0032-20e3.png?v8",two_hearts:"unicode/1f495.png?v8",two_men_holding_hands:"unicode/1f46c.png?v8",two_women_holding_hands:"unicode/1f46d.png?v8",u5272:"unicode/1f239.png?v8",u5408:"unicode/1f234.png?v8",u55b6:"unicode/1f23a.png?v8",u6307:"unicode/1f22f.png?v8",u6708:"unicode/1f237.png?v8",u6709:"unicode/1f236.png?v8",u6e80:"unicode/1f235.png?v8",u7121:"unicode/1f21a.png?v8",u7533:"unicode/1f238.png?v8",u7981:"unicode/1f232.png?v8",u7a7a:"unicode/1f233.png?v8",uganda:"unicode/1f1fa-1f1ec.png?v8",uk:"unicode/1f1ec-1f1e7.png?v8",ukraine:"unicode/1f1fa-1f1e6.png?v8",umbrella:"unicode/2614.png?v8",unamused:"unicode/1f612.png?v8",underage:"unicode/1f51e.png?v8",unicorn:"unicode/1f984.png?v8",united_arab_emirates:"unicode/1f1e6-1f1ea.png?v8",united_nations:"unicode/1f1fa-1f1f3.png?v8",unlock:"unicode/1f513.png?v8",up:"unicode/1f199.png?v8",upside_down_face:"unicode/1f643.png?v8",uruguay:"unicode/1f1fa-1f1fe.png?v8",us:"unicode/1f1fa-1f1f8.png?v8",us_outlying_islands:"unicode/1f1fa-1f1f2.png?v8",us_virgin_islands:"unicode/1f1fb-1f1ee.png?v8",uzbekistan:"unicode/1f1fa-1f1ff.png?v8",v:"unicode/270c.png?v8",vampire:"unicode/1f9db.png?v8",vampire_man:"unicode/1f9db-2642.png?v8",vampire_woman:"unicode/1f9db-2640.png?v8",vanuatu:"unicode/1f1fb-1f1fa.png?v8",vatican_city:"unicode/1f1fb-1f1e6.png?v8",venezuela:"unicode/1f1fb-1f1ea.png?v8",vertical_traffic_light:"unicode/1f6a6.png?v8",vhs:"unicode/1f4fc.png?v8",vibration_mode:"unicode/1f4f3.png?v8",video_camera:"unicode/1f4f9.png?v8",video_game:"unicode/1f3ae.png?v8",vietnam:"unicode/1f1fb-1f1f3.png?v8",violin:"unicode/1f3bb.png?v8",virgo:"unicode/264d.png?v8",volcano:"unicode/1f30b.png?v8",volleyball:"unicode/1f3d0.png?v8",vomiting_face:"unicode/1f92e.png?v8",vs:"unicode/1f19a.png?v8",vulcan_salute:"unicode/1f596.png?v8",waffle:"unicode/1f9c7.png?v8",wales:"unicode/1f3f4-e0067-e0062-e0077-e006c-e0073-e007f.png?v8",walking:"unicode/1f6b6.png?v8",walking_man:"unicode/1f6b6-2642.png?v8",walking_woman:"unicode/1f6b6-2640.png?v8",wallis_futuna:"unicode/1f1fc-1f1eb.png?v8",waning_crescent_moon:"unicode/1f318.png?v8",waning_gibbous_moon:"unicode/1f316.png?v8",warning:"unicode/26a0.png?v8",wastebasket:"unicode/1f5d1.png?v8",watch:"unicode/231a.png?v8",water_buffalo:"unicode/1f403.png?v8",water_polo:"unicode/1f93d.png?v8",watermelon:"unicode/1f349.png?v8",wave:"unicode/1f44b.png?v8",wavy_dash:"unicode/3030.png?v8",waxing_crescent_moon:"unicode/1f312.png?v8",waxing_gibbous_moon:"unicode/1f314.png?v8",wc:"unicode/1f6be.png?v8",weary:"unicode/1f629.png?v8",wedding:"unicode/1f492.png?v8",weight_lifting:"unicode/1f3cb.png?v8",weight_lifting_man:"unicode/1f3cb-2642.png?v8",weight_lifting_woman:"unicode/1f3cb-2640.png?v8",western_sahara:"unicode/1f1ea-1f1ed.png?v8",whale:"unicode/1f433.png?v8",whale2:"unicode/1f40b.png?v8",wheel_of_dharma:"unicode/2638.png?v8",wheelchair:"unicode/267f.png?v8",white_check_mark:"unicode/2705.png?v8",white_circle:"unicode/26aa.png?v8",white_flag:"unicode/1f3f3.png?v8",white_flower:"unicode/1f4ae.png?v8",white_haired_man:"unicode/1f468-1f9b3.png?v8",white_haired_woman:"unicode/1f469-1f9b3.png?v8",white_heart:"unicode/1f90d.png?v8",white_large_square:"unicode/2b1c.png?v8",white_medium_small_square:"unicode/25fd.png?v8",white_medium_square:"unicode/25fb.png?v8",white_small_square:"unicode/25ab.png?v8",white_square_button:"unicode/1f533.png?v8",wilted_flower:"unicode/1f940.png?v8",wind_chime:"unicode/1f390.png?v8",wind_face:"unicode/1f32c.png?v8",window:"unicode/1fa9f.png?v8",wine_glass:"unicode/1f377.png?v8",wink:"unicode/1f609.png?v8",wolf:"unicode/1f43a.png?v8",woman:"unicode/1f469.png?v8",woman_artist:"unicode/1f469-1f3a8.png?v8",woman_astronaut:"unicode/1f469-1f680.png?v8",woman_beard:"unicode/1f9d4-2640.png?v8",woman_cartwheeling:"unicode/1f938-2640.png?v8",woman_cook:"unicode/1f469-1f373.png?v8",woman_dancing:"unicode/1f483.png?v8",woman_facepalming:"unicode/1f926-2640.png?v8",woman_factory_worker:"unicode/1f469-1f3ed.png?v8",woman_farmer:"unicode/1f469-1f33e.png?v8",woman_feeding_baby:"unicode/1f469-1f37c.png?v8",woman_firefighter:"unicode/1f469-1f692.png?v8",woman_health_worker:"unicode/1f469-2695.png?v8",woman_in_manual_wheelchair:"unicode/1f469-1f9bd.png?v8",woman_in_motorized_wheelchair:"unicode/1f469-1f9bc.png?v8",woman_in_tuxedo:"unicode/1f935-2640.png?v8",woman_judge:"unicode/1f469-2696.png?v8",woman_juggling:"unicode/1f939-2640.png?v8",woman_mechanic:"unicode/1f469-1f527.png?v8",woman_office_worker:"unicode/1f469-1f4bc.png?v8",woman_pilot:"unicode/1f469-2708.png?v8",woman_playing_handball:"unicode/1f93e-2640.png?v8",woman_playing_water_polo:"unicode/1f93d-2640.png?v8",woman_scientist:"unicode/1f469-1f52c.png?v8",woman_shrugging:"unicode/1f937-2640.png?v8",woman_singer:"unicode/1f469-1f3a4.png?v8",woman_student:"unicode/1f469-1f393.png?v8",woman_teacher:"unicode/1f469-1f3eb.png?v8",woman_technologist:"unicode/1f469-1f4bb.png?v8",woman_with_headscarf:"unicode/1f9d5.png?v8",woman_with_probing_cane:"unicode/1f469-1f9af.png?v8",woman_with_turban:"unicode/1f473-2640.png?v8",woman_with_veil:"unicode/1f470-2640.png?v8",womans_clothes:"unicode/1f45a.png?v8",womans_hat:"unicode/1f452.png?v8",women_wrestling:"unicode/1f93c-2640.png?v8",womens:"unicode/1f6ba.png?v8",wood:"unicode/1fab5.png?v8",woozy_face:"unicode/1f974.png?v8",world_map:"unicode/1f5fa.png?v8",worm:"unicode/1fab1.png?v8",worried:"unicode/1f61f.png?v8",wrench:"unicode/1f527.png?v8",wrestling:"unicode/1f93c.png?v8",writing_hand:"unicode/270d.png?v8",x:"unicode/274c.png?v8",yarn:"unicode/1f9f6.png?v8",yawning_face:"unicode/1f971.png?v8",yellow_circle:"unicode/1f7e1.png?v8",yellow_heart:"unicode/1f49b.png?v8",yellow_square:"unicode/1f7e8.png?v8",yemen:"unicode/1f1fe-1f1ea.png?v8",yen:"unicode/1f4b4.png?v8",yin_yang:"unicode/262f.png?v8",yo_yo:"unicode/1fa80.png?v8",yum:"unicode/1f60b.png?v8",zambia:"unicode/1f1ff-1f1f2.png?v8",zany_face:"unicode/1f92a.png?v8",zap:"unicode/26a1.png?v8",zebra:"unicode/1f993.png?v8",zero:"unicode/0030-20e3.png?v8",zimbabwe:"unicode/1f1ff-1f1fc.png?v8",zipper_mouth_face:"unicode/1f910.png?v8",zombie:"unicode/1f9df.png?v8",zombie_man:"unicode/1f9df-2642.png?v8",zombie_woman:"unicode/1f9df-2640.png?v8",zzz:"unicode/1f4a4.png?v8"}};function jn(e,t){return e.replace(/<(code|pre|script|template)[^>]*?>[\s\S]+?<\/(code|pre|script|template)>/g,function(e){return e.replace(/:/g,"__colon__")}).replace(//g,function(e){return e.replace(/:/g,"__colon__")}).replace(/([a-z]{2,}:)?\/\/[^\s'">)]+/gi,function(e){return e.replace(/:/g,"__colon__")}).replace(/:([a-z0-9_\-+]+?):/g,function(e,n){return i=e,o=n,e=t,n=Cn.data[o],i,i=n?e&&/unicode/.test(n)?''+n.replace("unicode/","").replace(/\.png.*/,"").split("-").map(function(e){return"&#x"+e+";"}).join("‍").concat("︎")+"":''+o+'':i;var i,o}).replace(/__colon__/g,":")}function Ln(e){var o={};return{str:e=(e=void 0===e?"":e)&&e.replace(/^('|")/,"").replace(/('|")$/,"").replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g,function(e,n,i){return-1===n.indexOf(":")?(o[n]=i&&i.replace(/"/g,"")||!0,""):e}).trim(),config:o}}function On(e){return(e=void 0===e?"":e).replace(/(<\/?a.*?>)/gi,"")}var qn,Pn=be(function(e){var u,f,p,d,n,g=function(u){var i=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,e={},R={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof T?new T(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=r.reach);m+=_.value.length,_=_.next){var b=_.value;if(i.length>n.length)return;if(!(b instanceof T)){var k,w=1;if(l){if(!(k=C(h,m,n,s))||k.index>=n.length)break;var y=k.index,x=k.index+k[0].length,S=m;for(S+=_.value.length;S<=y;)_=_.next,S+=_.value.length;if(S-=_.value.length,m=S,_.value instanceof T)continue;for(var A=_;A!==i.tail&&(Sr.reach&&(r.reach=E);b=_.prev;z&&(b=j(i,b,z),m+=z.length),L(i,b,w);$=new T(c,g?R.tokenize($,g):$,v,$);_=j(i,b,$),F&&j(i,_,F),1r.reach&&(r.reach=E.reach))}}}}}(e,t,n,t.head,0),function(e){var n=[],i=e.head.next;for(;i!==e.tail;)n.push(i.value),i=i.next;return n}(t)},hooks:{all:{},add:function(e,n){var i=R.hooks.all;i[e]=i[e]||[],i[e].push(n)},run:function(e,n){var i=R.hooks.all[e];if(i&&i.length)for(var o,t=0;o=i[t++];)o(n)}},Token:T};function T(e,n,i,o){this.type=e,this.content=n,this.alias=i,this.length=0|(o||"").length}function C(e,n,i,o){e.lastIndex=n;i=e.exec(i);return i&&o&&i[1]&&(o=i[1].length,i.index+=o,i[0]=i[0].slice(o)),i}function a(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function j(e,n,i){var o=n.next,i={value:i,prev:n,next:o};return n.next=i,o.prev=i,e.length++,i}function L(e,n,i){for(var o=n.next,t=0;t"+t.content+""},!u.document)return u.addEventListener&&(R.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),i=n.language,e=n.code,n=n.immediateClose;u.postMessage(R.highlight(e,R.languages[i],i)),n&&u.close()},!1)),R;var o=R.util.currentScript();function t(){R.manual||R.highlightAll()}return o&&(R.filename=o.src,o.hasAttribute("data-manual")&&(R.manual=!0)),R.manual||("loading"===(e=document.readyState)||"interactive"===e&&o&&o.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)),R}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=g),void 0!==me&&(me.Prism=g),g.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},g.languages.markup.tag.inside["attr-value"].inside.entity=g.languages.markup.entity,g.languages.markup.doctype.inside["internal-subset"].inside=g.languages.markup,g.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(g.languages.markup.tag,"addInlined",{value:function(e,n){var i={};i["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:g.languages[n]},i.cdata=/^$/i;i={"included-cdata":{pattern://i,inside:i}};i["language-"+n]={pattern:/[\s\S]+/,inside:g.languages[n]};n={};n[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:i},g.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(g.languages.markup.tag,"addAttribute",{value:function(e,n){g.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:g.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),g.languages.html=g.languages.markup,g.languages.mathml=g.languages.markup,g.languages.svg=g.languages.markup,g.languages.xml=g.languages.extend("markup",{}),g.languages.ssml=g.languages.xml,g.languages.atom=g.languages.xml,g.languages.rss=g.languages.xml,function(e){var n=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+n.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+n.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+n.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+n.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:n,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;e=e.languages.markup;e&&(e.tag.addInlined("style","css"),e.tag.addAttribute("style","css"))}(g),g.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},g.languages.javascript=g.languages.extend("clike",{"class-name":[g.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),g.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,g.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:g.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:g.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:g.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:g.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:g.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),g.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:g.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),g.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),g.languages.markup&&(g.languages.markup.tag.addInlined("script","javascript"),g.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),g.languages.js=g.languages.javascript,void 0!==g&&"undefined"!=typeof document&&(Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),u={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"},d="pre[data-src]:not(["+(f="data-src-status")+'="loaded"]):not(['+f+'="'+(p="loading")+'"])',g.hooks.add("before-highlightall",function(e){e.selector+=", "+d}),g.hooks.add("before-sanity-check",function(e){var t,n,i,o,a,r,c=e.element;c.matches(d)&&(e.code="",c.setAttribute(f,p),(t=c.appendChild(document.createElement("CODE"))).textContent="Loading…",i=c.getAttribute("data-src"),"none"===(e=e.language)&&(n=(/\.(\w+)$/.exec(i)||[,"none"])[1],e=u[n]||n),g.util.setLanguage(t,e),g.util.setLanguage(c,e),(n=g.plugins.autoloader)&&n.loadLanguages(e),i=i,o=function(e){c.setAttribute(f,"loaded");var n,i,o=function(e){if(i=/^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(e||"")){var n=Number(i[1]),e=i[2],i=i[3];return e?i?[n,Number(i)]:[n,void 0]:[n,n]}}(c.getAttribute("data-range"));o&&(n=e.split(/\r\n?|\n/g),i=o[0],o=null==o[1]?n.length:o[1],i<0&&(i+=n.length),i=Math.max(0,Math.min(i-1,n.length)),o<0&&(o+=n.length),o=Math.max(0,Math.min(o,n.length)),e=n.slice(i,o).join("\n"),c.hasAttribute("data-start")||c.setAttribute("data-start",String(i+1))),t.textContent=e,g.highlightElement(t)},a=function(e){c.setAttribute(f,"failed"),t.textContent=e},(r=new XMLHttpRequest).open("GET",i,!0),r.onreadystatechange=function(){4==r.readyState&&(r.status<400&&r.responseText?o(r.responseText):400<=r.status?a("✖ Error "+r.status+" while fetching file: "+r.statusText):a("✖ Error: File does not exist or is empty"))},r.send(null))}),n=!(g.plugins.fileHighlight={highlight:function(e){for(var n,i=(e||document).querySelectorAll(d),o=0;n=i[o++];)g.highlightElement(n)}}),g.fileHighlight=function(){n||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),n=!0),g.plugins.fileHighlight.highlight.apply(this,arguments)})});function Mn(e,n){return"___"+e.toUpperCase()+n+"___"}qn=Prism,Object.defineProperties(qn.languages["markup-templating"]={},{buildPlaceholders:{value:function(o,t,e,a){var r;o.language===t&&(r=o.tokenStack=[],o.code=o.code.replace(e,function(e){if("function"==typeof a&&!a(e))return e;for(var n,i=r.length;-1!==o.code.indexOf(n=Mn(t,i));)++i;return r[i]=e,n}),o.grammar=qn.languages.markup)}},tokenizePlaceholders:{value:function(f,p){var d,g;f.language===p&&f.tokenStack&&(f.grammar=qn.languages[p],d=0,g=Object.keys(f.tokenStack),function e(n){for(var i=0;i=g.length);i++){var o,t,a,r,c,u=n[i];"string"==typeof u||u.content&&"string"==typeof u.content?(t=g[d],a=f.tokenStack[t],o="string"==typeof u?u:u.content,c=Mn(p,t),-1<(r=o.indexOf(c))&&(++d,t=o.substring(0,r),a=new qn.Token(p,qn.tokenize(a,f.grammar),"language-"+p,a),r=o.substring(r+c.length),c=[],t&&c.push.apply(c,e([t])),c.push(a),r&&c.push.apply(c,e([r])),"string"==typeof u?n.splice.apply(n,[i,1].concat(c)):u.content=c)):u.content&&e(u.content)}return n}(f.tokens))}}});function In(t,e){var a=this;this.config=t,this.router=e,this.cacheTree={},this.toc=[],this.cacheTOC={},this.linkTarget=t.externalLinkTarget||"_blank",this.linkRel="_blank"===this.linkTarget?t.externalLinkRel||"noopener":"",this.contentBase=e.getBasePath();var n=this._initRenderer();this.heading=n.heading;var r=o(e=t.markdown||{})?e(Sn,n):(Sn.setOptions(m(e,{renderer:m(n,e.renderer)})),Sn);this._marked=r,this.compile=function(i){var o=!0,e=c(function(e){o=!1;var n="";return i&&(n=f(i)?r(i):r.parser(i),n=t.noEmoji?n:jn(n,t.nativeEmoji),Tn.clear(),n)})(i),n=a.router.parse().file;return o?a.toc=a.cacheTOC[n]:a.cacheTOC[n]=[].concat(a.toc),e}}var Nn={},Hn={markdown:function(e){return{url:e}},mermaid:function(e){return{url:e}},iframe:function(e,n){return{html:'"}},video:function(e,n){return{html:'"}},audio:function(e,n){return{html:'"}},code:function(e,n){var i=e.match(/\.(\w+)$/);return{url:e,lang:i="md"===(i=n||i&&i[1])?"markdown":i}}};In.prototype.compileEmbed=function(e,n){var i,o,t=Ln(n),a=t.str,t=t.config;if(n=a,t.include)return R(e)||(e=q(this.contentBase,C(this.router.getCurrentPath()),e)),t.type&&(o=Hn[t.type])?(i=o.call(this,e,n)).type=t.type:(o="code",/\.(md|markdown)/.test(e)?o="markdown":/\.mmd/.test(e)?o="mermaid":/\.html?/.test(e)?o="iframe":/\.(mp4|ogg)/.test(e)?o="video":/\.mp3/.test(e)&&(o="audio"),(i=Hn[o].call(this,e,n)).type=o),i.fragment=t.fragment,i},In.prototype._matchNotCompileLink=function(e){for(var n=this.config.noCompileLinks||[],i=0;i/g.test(o)&&(o=o.replace("\x3c!-- {docsify-ignore} --\x3e",""),e.title=On(o),e.ignoreSubHeading=!0),/{docsify-ignore}/g.test(o)&&(o=o.replace("{docsify-ignore}",""),e.title=On(o),e.ignoreSubHeading=!0),//g.test(o)&&(o=o.replace("\x3c!-- {docsify-ignore-all} --\x3e",""),e.title=On(o),e.ignoreAllSubs=!0),/{docsify-ignore-all}/g.test(o)&&(o=o.replace("{docsify-ignore-all}",""),e.title=On(o),e.ignoreAllSubs=!0);i=Tn(t.id||o),t=a.toURL(a.getCurrentPath(),{id:i});return e.slug=t,g.toc.push(e),"'+o+""},t.code={renderer:e}.renderer.code=function(e,n){var i=Pn.languages[n=void 0===n?"markup":n]||Pn.languages.markup;return'
    '+Pn.highlight(e.replace(/@DOCSIFY_QM@/g,"`"),i,n)+"
    "},t.link=(i=(n={renderer:e,router:a,linkTarget:n,linkRel:i,compilerClass:g}).renderer,c=n.router,u=n.linkTarget,n.linkRel,f=n.compilerClass,i.link=function(e,n,i){var o=[],t=Ln(n=void 0===n?"":n),a=t.str,t=t.config;return u=t.target||u,r="_blank"===u?f.config.externalLinkRel||"noopener":"",n=a,R(e)||f._matchNotCompileLink(e)||t.ignore?(R(e)||"./"!==e.slice(0,2)||(e=document.URL.replace(/\/(?!.*\/).*/,"/").replace("#/./","")+e),o.push(0===e.indexOf("mailto:")?"":'target="'+u+'"'),o.push(0!==e.indexOf("mailto:")&&""!==r?' rel="'+r+'"':"")):(e===f.config.homepage&&(e="README"),e=c.toURL(e,null,c.getCurrentPath())),t.disabled&&(o.push("disabled"),e="javascript:void(0)"),t.class&&o.push('class="'+t.class+'"'),t.id&&o.push('id="'+t.id+'"'),n&&o.push('title="'+n+'"'),'"+i+""}),t.paragraph={renderer:e}.renderer.paragraph=function(e){e=/^!>/.test(e)?$n("tip",e):/^\?>/.test(e)?$n("warn",e):"

    "+e+"

    ";return e},t.image=(o=(i={renderer:e,contentBase:o,router:a}).renderer,p=i.contentBase,d=i.router,o.image=function(e,n,i){var o=e,t=[],a=Ln(n),r=a.str,a=a.config;return n=r,a["no-zoom"]&&t.push("data-no-zoom"),n&&t.push('title="'+n+'"'),a.size&&(n=(r=a.size.split("x"))[0],(r=r[1])?t.push('width="'+n+'" height="'+r+'"'):t.push('width="'+n+'"')),a.class&&t.push('class="'+a.class+'"'),a.id&&t.push('id="'+a.id+'"'),R(e)||(o=q(p,C(d.getCurrentPath()),e)),0":''+i+'"}),t.list={renderer:e}.renderer.list=function(e,n,i){n=n?"ol":"ul";return"<"+n+" "+[/
  • /.test(e.split('class="task-list"')[0])?'class="task-list"':"",i&&1"+e+""},t.listitem={renderer:e}.renderer.listitem=function(e){return/^(]*>)/.test(e)?'
  • ":"
  • "+e+"
  • "},e.origin=t,e},In.prototype.sidebar=function(e,n){var i=this.toc,o=this.router.getCurrentPath(),t="";if(e)t=this.compile(e);else{for(var a=0;a{inner}");this.cacheTree[o]=n}return t},In.prototype.subSidebar=function(e){if(e){var n=this.router.getCurrentPath(),i=this.cacheTree,o=this.toc;o[0]&&o[0].ignoreAllSubs&&o.splice(0),o[0]&&1===o[0].level&&o.shift();for(var t=0;t\n'+e+"\n"}]).links={}:(n=[{type:"html",text:e}]).links={}),a({token:t,embedToken:n}),++u>=c&&a({})}}(n);n.embed.url?X(n.embed.url).then(o):o(n.embed.html)}}({compile:i,embedTokens:c,fetch:n},function(e){var n,i=e.embedToken,e=e.token;e?(n=e.index,p.forEach(function(e){n>e.start&&(n+=e.length)}),m(f,i.links),r=r.slice(0,n).concat(i,r.slice(n+1)),p.push({start:n,length:i.length-1})):(Bn[t]=r.concat(),r.links=Bn[t].links=f,o(r))})}function Yn(e,n,i){var o,t,a,r;return n="function"==typeof i?i(n):"string"==typeof i?(a=[],r=0,(o=i).replace(V,function(n,e,i){a.push(o.substring(r,i-1)),r=i+=n.length+1,a.push(t&&t[n]||function(e){return("00"+("string"==typeof Y[n]?e[Y[n]]():Y[n](e))).slice(-n.length)})}),r!==o.length&&a.push(o.substring(r)),function(e){for(var n="",i=0,o=e||new Date;i404 - Not found","Vue"in window)for(var a=0,r=k(".markdown-section > *").filter(n);ascript").filter(function(e){return!/template/.test(e.type)})[0])||(e=e.innerText.trim())&&new Function(e)()),"Vue"in window){var u,f,p=[],d=Object.keys(i.vueComponents||{});2===t&&d.length&&d.forEach(function(e){window.Vue.options.components[e]||window.Vue.component(e,i.vueComponents[e])}),!Un&&i.vueGlobalOptions&&"function"==typeof i.vueGlobalOptions.data&&(Un=i.vueGlobalOptions.data()),p.push.apply(p,Object.keys(i.vueMounts||{}).map(function(e){return[b(o,e),i.vueMounts[e]]}).filter(function(e){var n=e[0];e[1];return n})),(i.vueGlobalOptions||d.length)&&(u=/{{2}[^{}]*}{2}/,f=/<[^>/]+\s([@:]|v-)[\w-:.[\]]+[=>\s]/,p.push.apply(p,k(".markdown-section > *").filter(function(i){return!p.some(function(e){var n=e[0];e[1];return n===i})}).filter(function(e){return e.tagName.toLowerCase()in(i.vueComponents||{})||e.querySelector(d.join(",")||null)||u.test(e.outerHTML)||f.test(e.outerHTML)}).map(function(e){var n=m({},i.vueGlobalOptions||{});return Un&&(n.data=function(){return Un}),[e,n]})));for(var g=0,s=p;g([^<]*?)

    $'))&&("color"===n[2]?o.style.background=n[1]+(n[3]||""):(e=n[1],S(o,"add","has-mask"),R(n[1])||(e=q(this.router.getBasePath(),n[1])),o.style.backgroundImage="url("+e+")",o.style.backgroundSize="cover",o.style.backgroundPosition="center center"),i=i.replace(n[0],"")),this._renderTo(".cover-main",i),K()):S(o,"remove","show")},n.prototype._updateRender=function(){var e,n,i,o;e=this,n=l(".app-name-link"),i=e.config.nameLink,o=e.route.path,n&&(f(e.config.nameLink)?n.setAttribute("href",i):"object"==typeof i&&(e=Object.keys(i).filter(function(e){return-1':"")),e.coverpage&&(f+=(o=", 100%, 85%",'
    \x3c!--cover--\x3e
    ')),e.logo&&(o=/^data:image/.test(e.logo),n=/(?:http[s]?:)?\/\//.test(e.logo),i=/^\./.test(e.logo),o||n||i||(e.logo=q(this.router.getBasePath(),e.logo))),f+=(i=(n=e).name||"","
    "+('')+'
    \x3c!--main--\x3e
    '),this._renderTo(u,f,!0)):this.rendered=!0,e.mergeNavbar&&s?p=b(".sidebar"):(c.classList.add("app-nav"),e.repo||c.classList.add("no-badge")),e.loadNavbar&&y(p,c),e.themeColor&&(v.head.appendChild(w("div","").firstElementChild),a=e.themeColor,window.CSS&&window.CSS.supports&&window.CSS.supports("(--v:red)")||(e=k("style:not(.inserted),link"),[].forEach.call(e,function(e){"STYLE"===e.nodeName?Q(e,a):"LINK"===e.nodeName&&(e=e.getAttribute("href"),/\.css$/.test(e)&&X(e).then(function(e){e=w("style",e);_.appendChild(e),Q(e,a)}))}))),this._updateRender(),S(h,"ready")},n}(function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),((n.prototype=Object.create(e&&e.prototype)).constructor=n).prototype.routes=function(){return this.config.routes||{}},n.prototype.matchVirtualRoute=function(t){var a=this.routes(),r=Object.keys(a),c=function(){return null};function u(){var e=r.shift();if(!e)return c(null);var n=A(o=(i="^",0===(o=e).indexOf(i)?o:"^"+o),"$")?o:o+"$",i=t.match(n);if(!i)return u();var o=a[e];if("string"==typeof o)return c(o);if("function"!=typeof o)return u();n=o,e=Xn(),o=e[0];return(0,e[1])(function(e){return"string"==typeof e?c(e):!1===e?c(null):u()}),n.length<=2?o(n(t,i)):n(t,i,o)}return{then:function(e){c=e,u()}}},n}(function(i){function e(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];i.apply(this,e),this.route={}}return i&&(e.__proto__=i),((e.prototype=Object.create(i&&i.prototype)).constructor=e).prototype.updateRender=function(){this.router.normalize(),this.route=this.router.parse(),h.setAttribute("data-page",this.route.file)},e.prototype.initRouter=function(){var n=this,e=this.config,e=new("history"===(e.routerMode||"hash")&&t?D:H)(e);this.router=e,this.updateRender(),U=this.route,e.onchange(function(e){n.updateRender(),n._updateRender(),U.path!==n.route.path?(n.$fetch(d,n.$resetEvents.bind(n,e.source)),U=n.route):n.$resetEvents(e.source)})},e}(function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),((n.prototype=Object.create(e&&e.prototype)).constructor=n).prototype.initLifecycle=function(){var i=this;this._hooks={},this._lifecycle={},["init","mounted","beforeEach","afterEach","doneEach","ready"].forEach(function(e){var n=i._hooks[e]=[];i._lifecycle[e]=function(e){return n.push(e)}})},n.prototype.callHook=function(e,t,a){void 0===a&&(a=d);var r=this._hooks[e],c=this.config.catchPluginErrors,u=function(n){var e=r[n];if(n>=r.length)a(t);else if("function"==typeof e){var i="Docsify plugin error";if(2===e.length)try{e(t,function(e){t=e,u(n+1)})}catch(e){if(!c)throw e;console.error(i,e),u(n+1)}else try{var o=e(t);t=void 0===o?t:o,u(n+1)}catch(e){if(!c)throw e;console.error(i,e),u(n+1)}}else u(n+1)};u(0)},n}(we))))))));function Kn(e,n,i){return Qn&&Qn.abort&&Qn.abort(),Qn=X(e,!0,i)}window.Docsify={util:Me,dom:n,get:X,slugify:Tn,version:"4.13.1"},window.DocsifyCompiler=In,window.marked=Sn,window.Prism=Pn,e(function(e){return new Jn})}(); diff --git a/docs/docs.html b/docs/docs.html index 1bfa350b2..85bd61566 100644 --- a/docs/docs.html +++ b/docs/docs.html @@ -6,7 +6,7 @@ - + MicroApp ").firstElementChild),o=t.themeColor,window.CSS&&window.CSS.supports&&window.CSS.supports("(--v:red)")||(t=w("style:not(.inserted),link"),[].forEach.call(t,function(e){if("STYLE"===e.nodeName)W(e,o);else if("LINK"===e.nodeName){e=e.getAttribute("href");if(!/\.css$/.test(e))return;G(e).then(function(e){e=x("style",e);y.appendChild(e),W(e,o)})}}))),e._updateRender(),T(v,"ready")}var Mn={};pt=function(e){this.config=e};function Nn(e){var t=location.href.indexOf("#");location.replace(location.href.slice(0,0<=t?t:0)+"#"+e)}pt.prototype.getBasePath=function(){return this.config.basePath},pt.prototype.getFile=function(e,t){void 0===e&&(e=this.getCurrentPath());var n,r,i=this.config,a=this.getBasePath(),o="string"==typeof i.ext?i.ext:".md";return e=i.alias?function e(t,n,r){var i=Object.keys(n).filter(function(e){return(Mn[e]||(Mn[e]=new RegExp("^"+e+"$"))).test(t)&&t!==r})[0];return i?e(t.replace(Mn[i],n[i]),n,t):t}(e,i.alias):e,n=e,r=o,e=(e=new RegExp("\\.("+r.replace(/^\./,"")+"|html)$","g").test(n)?n:/\/$/g.test(n)?n+"README"+r:""+n+r)==="/README"+o&&i.homepage||e,e=ne(e)?e:le(a,e),t&&(e=e.replace(new RegExp("^"+a),"")),e},pt.prototype.onchange=function(e){void 0===e&&(e=u),e()},pt.prototype.getCurrentPath=function(){},pt.prototype.normalize=function(){},pt.prototype.parse=function(){},pt.prototype.toURL=function(e,t,n){var r=n&&"#"===e[0],i=this.parse(ce(e));if(i.query=b({},i.query,t),e=(e=i.path+te(i.query)).replace(/\.md(\?)|\.md$/,"$1"),r&&(e=(0<(r=n.indexOf("?"))?n.substring(0,r):n)+e),this.config.relativePath&&0!==e.indexOf("/")){n=n.substring(0,n.lastIndexOf("/")+1);return ae(oe(n+e))}return ae("/"+e)};var Pn=function(r){function e(e){r.call(this,e),this.mode="hash"}return r&&(e.__proto__=r),((e.prototype=Object.create(r&&r.prototype)).constructor=e).prototype.getBasePath=function(){var e=window.location.pathname||"",t=this.config.basePath,e=ue(e,".html")?e+"#/"+t:e+"/"+t;return/^(\/|https?:)/g.test(t)?t:ae(e)},e.prototype.getCurrentPath=function(){var e=location.href,t=e.indexOf("#");return-1===t?"":e.slice(t+1)},e.prototype.onchange=function(n){void 0===n&&(n=u);var r=!1;S("click",function(e){e="A"===e.target.tagName?e.target:e.target.parentNode;e&&"A"===e.tagName&&!/_blank/.test(e.target)&&(r=!0)}),S("hashchange",function(e){var t=r?"navigate":"history";r=!1,n({event:e,source:t})})},e.prototype.normalize=function(){var e=this.getCurrentPath();if("/"===(e=ce(e)).charAt(0))return Nn(e);Nn("/"+e)},e.prototype.parse=function(e){void 0===e&&(e=location.href);var t="",n=e.indexOf("#");0<=n&&(e=e.slice(n+1));n=e.indexOf("?");return 0<=n&&(t=e.slice(n+1),e=e.slice(0,n)),{path:e,file:this.getFile(e,!0),query:ee(t)}},e.prototype.toURL=function(e,t,n){return"#"+r.prototype.toURL.call(this,e,t,n)},e}(pt),Dn=function(t){function e(e){t.call(this,e),this.mode="history"}return t&&(e.__proto__=t),((e.prototype=Object.create(t&&t.prototype)).constructor=e).prototype.getCurrentPath=function(){var e=this.getBasePath(),t=window.location.pathname;return e&&0===t.indexOf(e)&&(t=t.slice(e.length)),(t||"/")+window.location.search+window.location.hash},e.prototype.onchange=function(n){var r=this;void 0===n&&(n=u),S("click",function(e){var t="A"===e.target.tagName?e.target:e.target.parentNode;"A"!==t.tagName||/_blank/.test(t.target)||(e.preventDefault(),t=t.href,-1!==r.config.crossOriginLinks.indexOf(t)?window.open(t,"_self"):window.history.pushState({key:t},"",t),n({event:e,source:"navigate"}))}),S("popstate",function(e){n({event:e,source:"history"})})},e.prototype.parse=function(e){void 0===e&&(e=location.href);var t="",n=e.indexOf("?");0<=n&&(t=e.slice(n+1),e=e.slice(0,n));var r=le(location.origin),n=e.indexOf(r);return-1([^<]*?)

    $'))&&("color"===t[2]?r.style.background=t[1]+(t[3]||""):(e=t[1],T(r,"add","has-mask"),ne(t[1])||(e=le(this.router.getBasePath(),t[1])),r.style.backgroundImage="url("+e+")",r.style.backgroundSize="cover",r.style.backgroundPosition="center center"),n=n.replace(t[0],"")),this._renderTo(".cover-main",n),X()):T(r,"remove","show")},Zn._updateRender=function(){var e,t,n,r;e=this,t=g(".app-name-link"),n=e.config.nameLink,r=e.route.path,t&&(c(e.config.nameLink)?t.setAttribute("href",n):"object"==typeof n&&(e=Object.keys(n).filter(function(e){return-1=e||n.classList.contains("hidden")?S(h,"add","sticky"):S(h,"remove","sticky"))}function ee(e,n,o,i){var t=[];null!=(n=l(n))&&(t=k(n,"a"));var a,r=decodeURI(e.toURL(e.getCurrentPath()));return t.sort(function(e,n){return n.href.length-e.href.length}).forEach(function(e){var n=decodeURI(e.getAttribute("href")),i=o?e.parentNode:e;e.title=e.title||e.innerText,0!==r.indexOf(n)||a?S(i,"remove","active"):(a=e,S(i,"add","active"))}),i&&(v.title=a?a.title||a.innerText+" - "+J:J),a}function ne(e,n){for(var i=0;ithis.end&&e>=this.next}[this.direction]}},{key:"_defaultEase",value:function(e,n,i,o){return(e/=o/2)<1?i/2*e*e+n:-i/2*(--e*(e-2)-1)+n}}]),re);function re(){var e=0c){n=n||p;break}n=p}!n||(r=fe[ve(e,n.getAttribute("data-id"))])&&r!==a&&(a&&a.classList.remove("active"),r.classList.add("active"),a=r,!pe&&h.classList.contains("sticky")&&(e=i.clientHeight,r=a.offsetTop+a.clientHeight+40,a=a.offsetTop>=t.scrollTop&&r<=t.scrollTop+e,i.scrollTop=a?t.scrollTop:+r"']/),xe=/[&<>"']/g,Se=/[<>"']|&(?!#?\w+;)/,Ae=/[<>"']|&(?!#?\w+;)/g,$e={"&":"&","<":"<",">":">",'"':""","'":"'"};var ze=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function Fe(e){return e.replace(ze,function(e,n){return"colon"===(n=n.toLowerCase())?":":"#"===n.charAt(0)?"x"===n.charAt(1)?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1)):""})}var Ee=/(^|[^\[])\^/g;var Re=/[^\w:]/g,Te=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;var Ce={},je=/^[^:]+:\/*[^/]*$/,Le=/^([^:]+:)[\s\S]*$/,Oe=/^([^:]+:\/*[^/]*)[\s\S]*$/;function qe(e,n){Ce[" "+e]||(je.test(e)?Ce[" "+e]=e+"/":Ce[" "+e]=Pe(e,"/",!0));var i=-1===(e=Ce[" "+e]).indexOf(":");return"//"===n.substring(0,2)?i?n:e.replace(Le,"$1")+n:"/"===n.charAt(0)?i?n:e.replace(Oe,"$1")+n:e+n}function Pe(e,n,i){var o=e.length;if(0===o)return"";for(var t=0;tn)i.splice(n);else for(;i.length>=1,e+=e;return i+e},We=we.defaults,Xe=Be,Qe=Ze,Je=Me,Ke=Ve;function en(e,n,i){var o=n.href,t=n.title?Je(n.title):null,n=e[1].replace(/\\([\[\]])/g,"$1");return"!"!==e[0].charAt(0)?{type:"link",raw:i,href:o,title:t,text:n}:{type:"image",raw:i,href:o,title:t,text:Je(n)}}var nn=function(){function e(e){this.options=e||We}return e.prototype.space=function(e){e=this.rules.block.newline.exec(e);if(e)return 1=i.length?e.slice(i.length):e}).join("\n")}(i,n[3]||"");return{type:"code",raw:i,lang:n[2]&&n[2].trim(),text:e}}},e.prototype.heading=function(e){var n=this.rules.block.heading.exec(e);if(n){var i=n[2].trim();return/#$/.test(i)&&(e=Xe(i,"#"),!this.options.pedantic&&e&&!/ $/.test(e)||(i=e.trim())),{type:"heading",raw:n[0],depth:n[1].length,text:i}}},e.prototype.nptable=function(e){e=this.rules.block.nptable.exec(e);if(e){var n={type:"table",header:Qe(e[1].replace(/^ *| *\| *$/g,"")),align:e[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:e[3]?e[3].replace(/\n$/,"").split("\n"):[],raw:e[0]};if(n.header.length===n.align.length){for(var i=n.align.length,o=0;o ?/gm,"");return{type:"blockquote",raw:n[0],text:e}}},e.prototype.list=function(e){e=this.rules.block.list.exec(e);if(e){for(var n,i,o,t,a,r=e[0],c=e[2],u=1s[1].length:o[1].length>s[0].length||3/i.test(e[0])&&(n=!1),!i&&/^<(pre|code|kbd|script)(\s|>)/i.test(e[0])?i=!0:i&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(e[0])&&(i=!1),{type:this.options.sanitize?"text":"html",raw:e[0],inLink:n,inRawBlock:i,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):Je(e[0]):e[0]}},e.prototype.link=function(e){var n=this.rules.inline.link.exec(e);if(n){e=n[2].trim();if(!this.options.pedantic&&/^$/.test(e))return;var i=Xe(e.slice(0,-1),"\\");if((e.length-i.length)%2==0)return}else{var o=Ke(n[2],"()");-1$/.test(e)?i.slice(1):i.slice(1,-1):i)&&i.replace(this.rules.inline._escapes,"$1"),title:o&&o.replace(this.rules.inline._escapes,"$1")},n[0])}},e.prototype.reflink=function(e,n){if((i=this.rules.inline.reflink.exec(e))||(i=this.rules.inline.nolink.exec(e))){var e=(i[2]||i[1]).replace(/\s+/g," ");if((e=n[e.toLowerCase()])&&e.href)return en(i,e,i[0]);var i=i[0].charAt(0);return{type:"text",raw:i,text:i}}},e.prototype.strong=function(e,n,i){void 0===i&&(i="");var o=this.rules.inline.strong.start.exec(e);if(o&&(!o[1]||o[1]&&(""===i||this.rules.inline.punctuation.exec(i)))){n=n.slice(-1*e.length);var t,a="**"===o[0]?this.rules.inline.strong.endAst:this.rules.inline.strong.endUnd;for(a.lastIndex=0;null!=(o=a.exec(n));)if(t=this.rules.inline.strong.middle.exec(n.slice(0,o.index+3)))return{type:"strong",raw:e.slice(0,t[0].length),text:e.slice(2,t[0].length-2)}}},e.prototype.em=function(e,n,i){void 0===i&&(i="");var o=this.rules.inline.em.start.exec(e);if(o&&(!o[1]||o[1]&&(""===i||this.rules.inline.punctuation.exec(i)))){n=n.slice(-1*e.length);var t,a="*"===o[0]?this.rules.inline.em.endAst:this.rules.inline.em.endUnd;for(a.lastIndex=0;null!=(o=a.exec(n));)if(t=this.rules.inline.em.middle.exec(n.slice(0,o.index+2)))return{type:"em",raw:e.slice(0,t[0].length),text:e.slice(1,t[0].length-1)}}},e.prototype.codespan=function(e){var n=this.rules.inline.code.exec(e);if(n){var i=n[2].replace(/\n/g," "),o=/[^ ]/.test(i),e=/^ /.test(i)&&/ $/.test(i);return o&&e&&(i=i.substring(1,i.length-1)),i=Je(i,!0),{type:"codespan",raw:n[0],text:i}}},e.prototype.br=function(e){e=this.rules.inline.br.exec(e);if(e)return{type:"br",raw:e[0]}},e.prototype.del=function(e){e=this.rules.inline.del.exec(e);if(e)return{type:"del",raw:e[0],text:e[2]}},e.prototype.autolink=function(e,n){e=this.rules.inline.autolink.exec(e);if(e){var i,n="@"===e[2]?"mailto:"+(i=Je(this.options.mangle?n(e[1]):e[1])):i=Je(e[1]);return{type:"link",raw:e[0],text:i,href:n,tokens:[{type:"text",raw:i,text:i}]}}},e.prototype.url=function(e,n){var i,o,t,a;if(i=this.rules.inline.url.exec(e)){if("@"===i[2])t="mailto:"+(o=Je(this.options.mangle?n(i[0]):i[0]));else{for(;a=i[0],i[0]=this.rules.inline._backpedal.exec(i[0])[0],a!==i[0];);o=Je(i[0]),t="www."===i[1]?"http://"+o:o}return{type:"link",raw:i[0],text:o,href:t,tokens:[{type:"text",raw:o,text:o}]}}},e.prototype.inlineText=function(e,n,i){e=this.rules.inline.text.exec(e);if(e){i=n?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):Je(e[0]):e[0]:Je(this.options.smartypants?i(e[0]):e[0]);return{type:"text",raw:e[0],text:i}}},e}(),Ze=De,Ve=Ne,De=Ue,Ne={newline:/^(?: *(?:\n|$))+/,code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,nptable:Ze,table:Ze,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/};Ne.def=Ve(Ne.def).replace("label",Ne._label).replace("title",Ne._title).getRegex(),Ne.bullet=/(?:[*+-]|\d{1,9}[.)])/,Ne.item=/^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/,Ne.item=Ve(Ne.item,"gm").replace(/bull/g,Ne.bullet).getRegex(),Ne.listItemStart=Ve(/^( *)(bull)/).replace("bull",Ne.bullet).getRegex(),Ne.list=Ve(Ne.list).replace(/bull/g,Ne.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+Ne.def.source+")").getRegex(),Ne._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",Ne._comment=/|$)/,Ne.html=Ve(Ne.html,"i").replace("comment",Ne._comment).replace("tag",Ne._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Ne.paragraph=Ve(Ne._paragraph).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.blockquote=Ve(Ne.blockquote).replace("paragraph",Ne.paragraph).getRegex(),Ne.normal=De({},Ne),Ne.gfm=De({},Ne.normal,{nptable:"^ *([^|\\n ].*\\|.*)\\n {0,3}([-:]+ *\\|[-| :]*)(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)",table:"^ *\\|(.+)\\n {0,3}\\|?( *[-:]+[-| :]*)(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),Ne.gfm.nptable=Ve(Ne.gfm.nptable).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.gfm.table=Ve(Ne.gfm.table).replace("hr",Ne.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|!--)").replace("tag",Ne._tag).getRegex(),Ne.pedantic=De({},Ne.normal,{html:Ve("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",Ne._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:Ze,paragraph:Ve(Ne.normal._paragraph).replace("hr",Ne.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",Ne.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()});Ze={escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:Ze,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",strong:{start:/^(?:(\*\*(?=[*punctuation]))|\*\*)(?![\s])|__/,middle:/^\*\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*\*$|^__(?![\s])((?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?)__$/,endAst:/[^punctuation\s]\*\*(?!\*)|[punctuation]\*\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]__(?!_)(?:(?=[punctuation*\s])|$)/},em:{start:/^(?:(\*(?=[punctuation]))|\*)(?![*\s])|_/,middle:/^\*(?:(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)|\*(?:(?!overlapSkip)(?:[^*]|\\\*)|overlapSkip)*?\*)+?\*$|^_(?![_\s])(?:(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)|_(?:(?!overlapSkip)(?:[^_]|\\_)|overlapSkip)*?_)+?_$/,endAst:/[^punctuation\s]\*(?!\*)|[punctuation]\*(?!\*)(?:(?=[punctuation_\s]|$))/,endUnd:/[^\s]_(?!_)(?:(?=[punctuation*\s])|$)/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:Ze,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~"};Ze.punctuation=Ve(Ze.punctuation).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze._blockSkip="\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>",Ze._overlapSkip="__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*",Ze._comment=Ve(Ne._comment).replace("(?:--\x3e|$)","--\x3e").getRegex(),Ze.em.start=Ve(Ze.em.start).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.em.middle=Ve(Ze.em.middle).replace(/punctuation/g,Ze._punctuation).replace(/overlapSkip/g,Ze._overlapSkip).getRegex(),Ze.em.endAst=Ve(Ze.em.endAst,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.em.endUnd=Ve(Ze.em.endUnd,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.start=Ve(Ze.strong.start).replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.middle=Ve(Ze.strong.middle).replace(/punctuation/g,Ze._punctuation).replace(/overlapSkip/g,Ze._overlapSkip).getRegex(),Ze.strong.endAst=Ve(Ze.strong.endAst,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.strong.endUnd=Ve(Ze.strong.endUnd,"g").replace(/punctuation/g,Ze._punctuation).getRegex(),Ze.blockSkip=Ve(Ze._blockSkip,"g").getRegex(),Ze.overlapSkip=Ve(Ze._overlapSkip,"g").getRegex(),Ze._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,Ze._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,Ze._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,Ze.autolink=Ve(Ze.autolink).replace("scheme",Ze._scheme).replace("email",Ze._email).getRegex(),Ze._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,Ze.tag=Ve(Ze.tag).replace("comment",Ze._comment).replace("attribute",Ze._attribute).getRegex(),Ze._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Ze._href=/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/,Ze._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,Ze.link=Ve(Ze.link).replace("label",Ze._label).replace("href",Ze._href).replace("title",Ze._title).getRegex(),Ze.reflink=Ve(Ze.reflink).replace("label",Ze._label).getRegex(),Ze.reflinkSearch=Ve(Ze.reflinkSearch,"g").replace("reflink",Ze.reflink).replace("nolink",Ze.nolink).getRegex(),Ze.normal=De({},Ze),Ze.pedantic=De({},Ze.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:Ve(/^!?\[(label)\]\((.*?)\)/).replace("label",Ze._label).getRegex(),reflink:Ve(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Ze._label).getRegex()}),Ze.gfm=De({},Ze.normal,{escape:Ve(Ze.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\'+(i?e:gn(e,!0))+"\n":"
    "+(i?e:gn(e,!0))+"
    \n"},e.prototype.blockquote=function(e){return"
    \n"+e+"
    \n"},e.prototype.html=function(e){return e},e.prototype.heading=function(e,n,i,o){return this.options.headerIds?"'+e+"\n":""+e+"\n"},e.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"},e.prototype.list=function(e,n,i){var o=n?"ol":"ul";return"<"+o+(n&&1!==i?' start="'+i+'"':"")+">\n"+e+"\n"},e.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},e.prototype.checkbox=function(e){return" "},e.prototype.paragraph=function(e){return"

    "+e+"

    \n"},e.prototype.table=function(e,n){return"\n\n"+e+"\n"+(n=n&&""+n+"")+"
    \n"},e.prototype.tablerow=function(e){return"\n"+e+"\n"},e.prototype.tablecell=function(e,n){var i=n.header?"th":"td";return(n.align?"<"+i+' align="'+n.align+'">':"<"+i+">")+e+"\n"},e.prototype.strong=function(e){return""+e+""},e.prototype.em=function(e){return""+e+""},e.prototype.codespan=function(e){return""+e+""},e.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},e.prototype.del=function(e){return""+e+""},e.prototype.link=function(e,n,i){if(null===(e=dn(this.options.sanitize,this.options.baseUrl,e)))return i;e='
    "},e.prototype.image=function(e,n,i){if(null===(e=dn(this.options.sanitize,this.options.baseUrl,e)))return i;i=''+i+'":">"},e.prototype.text=function(e){return e},e}(),ln=function(){function e(){}return e.prototype.strong=function(e){return e},e.prototype.em=function(e){return e},e.prototype.codespan=function(e){return e},e.prototype.del=function(e){return e},e.prototype.html=function(e){return e},e.prototype.text=function(e){return e},e.prototype.link=function(e,n,i){return""+i},e.prototype.image=function(e,n,i){return""+i},e.prototype.br=function(){return""},e}(),vn=function(){function e(){this.seen={}}return e.prototype.serialize=function(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")},e.prototype.getNextSafeSlug=function(e,n){var i=e,o=0;if(this.seen.hasOwnProperty(i))for(o=this.seen[e];i=e+"-"+ ++o,this.seen.hasOwnProperty(i););return n||(this.seen[e]=o,this.seen[i]=0),i},e.prototype.slug=function(e,n){void 0===n&&(n={});e=this.serialize(e);return this.getNextSafeSlug(e,n.dryrun)},e}(),hn=we.defaults,_n=Ie,mn=function(){function i(e){this.options=e||hn,this.options.renderer=this.options.renderer||new sn,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new ln,this.slugger=new vn}return i.parse=function(e,n){return new i(n).parse(e)},i.parseInline=function(e,n){return new i(n).parseInline(e)},i.prototype.parse=function(e,n){void 0===n&&(n=!0);for(var i,o,t,a,r,c,u,f,p,d,g,s,l,v,h,_="",m=e.length,b=0;bAn error occurred:

    "+wn(e.message+"",!0)+"
    ";throw e}}xn.options=xn.setOptions=function(e){return bn(xn.defaults,e),yn(xn.defaults),xn},xn.getDefaults=Me,xn.defaults=we,xn.use=function(a){var n,e=bn({},a);if(a.renderer){var i,r=xn.defaults.renderer||new sn;for(i in a.renderer)!function(o){var t=r[o];r[o]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var i=a.renderer[o].apply(r,e);return i=!1===i?t.apply(r,e):i}}(i);e.renderer=r}if(a.tokenizer){var t,c=xn.defaults.tokenizer||new nn;for(t in a.tokenizer)!function(){var o=c[t];c[t]=function(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];var i=a.tokenizer[t].apply(c,e);return i=!1===i?o.apply(c,e):i}}();e.tokenizer=c}a.walkTokens&&(n=xn.defaults.walkTokens,e.walkTokens=function(e){a.walkTokens(e),n&&n(e)}),xn.setOptions(e)},xn.walkTokens=function(e,n){for(var i=0,o=e;iAn error occurred:

    "+wn(e.message+"",!0)+"
    ";throw e}},xn.Parser=mn,xn.parser=mn.parse,xn.Renderer=sn,xn.TextRenderer=ln,xn.Lexer=fn,xn.lexer=fn.lex,xn.Tokenizer=nn,xn.Slugger=vn;var Sn=xn.parse=xn;function An(e,i){if(void 0===i&&(i='
      {inner}
    '),!e||!e.length)return"";var o="";return e.forEach(function(e){var n=e.title.replace(/(<([^>]+)>)/g,"");o+='
  • '+e.title+"
  • ",e.children&&(o+=An(e.children,i))}),i.replace("{inner}",o)}function $n(e,n){return'

    '+n.slice(5).trim()+"

    "}function zn(e,o){var t=[],a={};return e.forEach(function(e){var n=e.level||1,i=n-1;o?@[\]^`{|}~]/g;function Rn(e){return e.toLowerCase()}function Tn(e){if("string"!=typeof e)return"";var n=e.trim().replace(/[A-Z]+/g,Rn).replace(/<[^>]+>/g,"").replace(En,"").replace(/\s/g,"-").replace(/-+/g,"-").replace(/^(\d)/,"_$1"),e=Fn[n],e=u.call(Fn,n)?e+1:0;return n=(Fn[n]=e)?n+"-"+e:n}Tn.clear=function(){Fn={}};var Cn={baseURL:"https://github.githubassets.com/images/icons/emoji/",data:{100:"unicode/1f4af.png?v8",1234:"unicode/1f522.png?v8","+1":"unicode/1f44d.png?v8","-1":"unicode/1f44e.png?v8","1st_place_medal":"unicode/1f947.png?v8","2nd_place_medal":"unicode/1f948.png?v8","3rd_place_medal":"unicode/1f949.png?v8","8ball":"unicode/1f3b1.png?v8",a:"unicode/1f170.png?v8",ab:"unicode/1f18e.png?v8",abacus:"unicode/1f9ee.png?v8",abc:"unicode/1f524.png?v8",abcd:"unicode/1f521.png?v8",accept:"unicode/1f251.png?v8",accessibility:"accessibility.png?v8",accordion:"unicode/1fa97.png?v8",adhesive_bandage:"unicode/1fa79.png?v8",adult:"unicode/1f9d1.png?v8",aerial_tramway:"unicode/1f6a1.png?v8",afghanistan:"unicode/1f1e6-1f1eb.png?v8",airplane:"unicode/2708.png?v8",aland_islands:"unicode/1f1e6-1f1fd.png?v8",alarm_clock:"unicode/23f0.png?v8",albania:"unicode/1f1e6-1f1f1.png?v8",alembic:"unicode/2697.png?v8",algeria:"unicode/1f1e9-1f1ff.png?v8",alien:"unicode/1f47d.png?v8",ambulance:"unicode/1f691.png?v8",american_samoa:"unicode/1f1e6-1f1f8.png?v8",amphora:"unicode/1f3fa.png?v8",anatomical_heart:"unicode/1fac0.png?v8",anchor:"unicode/2693.png?v8",andorra:"unicode/1f1e6-1f1e9.png?v8",angel:"unicode/1f47c.png?v8",anger:"unicode/1f4a2.png?v8",angola:"unicode/1f1e6-1f1f4.png?v8",angry:"unicode/1f620.png?v8",anguilla:"unicode/1f1e6-1f1ee.png?v8",anguished:"unicode/1f627.png?v8",ant:"unicode/1f41c.png?v8",antarctica:"unicode/1f1e6-1f1f6.png?v8",antigua_barbuda:"unicode/1f1e6-1f1ec.png?v8",apple:"unicode/1f34e.png?v8",aquarius:"unicode/2652.png?v8",argentina:"unicode/1f1e6-1f1f7.png?v8",aries:"unicode/2648.png?v8",armenia:"unicode/1f1e6-1f1f2.png?v8",arrow_backward:"unicode/25c0.png?v8",arrow_double_down:"unicode/23ec.png?v8",arrow_double_up:"unicode/23eb.png?v8",arrow_down:"unicode/2b07.png?v8",arrow_down_small:"unicode/1f53d.png?v8",arrow_forward:"unicode/25b6.png?v8",arrow_heading_down:"unicode/2935.png?v8",arrow_heading_up:"unicode/2934.png?v8",arrow_left:"unicode/2b05.png?v8",arrow_lower_left:"unicode/2199.png?v8",arrow_lower_right:"unicode/2198.png?v8",arrow_right:"unicode/27a1.png?v8",arrow_right_hook:"unicode/21aa.png?v8",arrow_up:"unicode/2b06.png?v8",arrow_up_down:"unicode/2195.png?v8",arrow_up_small:"unicode/1f53c.png?v8",arrow_upper_left:"unicode/2196.png?v8",arrow_upper_right:"unicode/2197.png?v8",arrows_clockwise:"unicode/1f503.png?v8",arrows_counterclockwise:"unicode/1f504.png?v8",art:"unicode/1f3a8.png?v8",articulated_lorry:"unicode/1f69b.png?v8",artificial_satellite:"unicode/1f6f0.png?v8",artist:"unicode/1f9d1-1f3a8.png?v8",aruba:"unicode/1f1e6-1f1fc.png?v8",ascension_island:"unicode/1f1e6-1f1e8.png?v8",asterisk:"unicode/002a-20e3.png?v8",astonished:"unicode/1f632.png?v8",astronaut:"unicode/1f9d1-1f680.png?v8",athletic_shoe:"unicode/1f45f.png?v8",atm:"unicode/1f3e7.png?v8",atom:"atom.png?v8",atom_symbol:"unicode/269b.png?v8",australia:"unicode/1f1e6-1f1fa.png?v8",austria:"unicode/1f1e6-1f1f9.png?v8",auto_rickshaw:"unicode/1f6fa.png?v8",avocado:"unicode/1f951.png?v8",axe:"unicode/1fa93.png?v8",azerbaijan:"unicode/1f1e6-1f1ff.png?v8",b:"unicode/1f171.png?v8",baby:"unicode/1f476.png?v8",baby_bottle:"unicode/1f37c.png?v8",baby_chick:"unicode/1f424.png?v8",baby_symbol:"unicode/1f6bc.png?v8",back:"unicode/1f519.png?v8",bacon:"unicode/1f953.png?v8",badger:"unicode/1f9a1.png?v8",badminton:"unicode/1f3f8.png?v8",bagel:"unicode/1f96f.png?v8",baggage_claim:"unicode/1f6c4.png?v8",baguette_bread:"unicode/1f956.png?v8",bahamas:"unicode/1f1e7-1f1f8.png?v8",bahrain:"unicode/1f1e7-1f1ed.png?v8",balance_scale:"unicode/2696.png?v8",bald_man:"unicode/1f468-1f9b2.png?v8",bald_woman:"unicode/1f469-1f9b2.png?v8",ballet_shoes:"unicode/1fa70.png?v8",balloon:"unicode/1f388.png?v8",ballot_box:"unicode/1f5f3.png?v8",ballot_box_with_check:"unicode/2611.png?v8",bamboo:"unicode/1f38d.png?v8",banana:"unicode/1f34c.png?v8",bangbang:"unicode/203c.png?v8",bangladesh:"unicode/1f1e7-1f1e9.png?v8",banjo:"unicode/1fa95.png?v8",bank:"unicode/1f3e6.png?v8",bar_chart:"unicode/1f4ca.png?v8",barbados:"unicode/1f1e7-1f1e7.png?v8",barber:"unicode/1f488.png?v8",baseball:"unicode/26be.png?v8",basecamp:"basecamp.png?v8",basecampy:"basecampy.png?v8",basket:"unicode/1f9fa.png?v8",basketball:"unicode/1f3c0.png?v8",basketball_man:"unicode/26f9-2642.png?v8",basketball_woman:"unicode/26f9-2640.png?v8",bat:"unicode/1f987.png?v8",bath:"unicode/1f6c0.png?v8",bathtub:"unicode/1f6c1.png?v8",battery:"unicode/1f50b.png?v8",beach_umbrella:"unicode/1f3d6.png?v8",bear:"unicode/1f43b.png?v8",bearded_person:"unicode/1f9d4.png?v8",beaver:"unicode/1f9ab.png?v8",bed:"unicode/1f6cf.png?v8",bee:"unicode/1f41d.png?v8",beer:"unicode/1f37a.png?v8",beers:"unicode/1f37b.png?v8",beetle:"unicode/1fab2.png?v8",beginner:"unicode/1f530.png?v8",belarus:"unicode/1f1e7-1f1fe.png?v8",belgium:"unicode/1f1e7-1f1ea.png?v8",belize:"unicode/1f1e7-1f1ff.png?v8",bell:"unicode/1f514.png?v8",bell_pepper:"unicode/1fad1.png?v8",bellhop_bell:"unicode/1f6ce.png?v8",benin:"unicode/1f1e7-1f1ef.png?v8",bento:"unicode/1f371.png?v8",bermuda:"unicode/1f1e7-1f1f2.png?v8",beverage_box:"unicode/1f9c3.png?v8",bhutan:"unicode/1f1e7-1f1f9.png?v8",bicyclist:"unicode/1f6b4.png?v8",bike:"unicode/1f6b2.png?v8",biking_man:"unicode/1f6b4-2642.png?v8",biking_woman:"unicode/1f6b4-2640.png?v8",bikini:"unicode/1f459.png?v8",billed_cap:"unicode/1f9e2.png?v8",biohazard:"unicode/2623.png?v8",bird:"unicode/1f426.png?v8",birthday:"unicode/1f382.png?v8",bison:"unicode/1f9ac.png?v8",black_cat:"unicode/1f408-2b1b.png?v8",black_circle:"unicode/26ab.png?v8",black_flag:"unicode/1f3f4.png?v8",black_heart:"unicode/1f5a4.png?v8",black_joker:"unicode/1f0cf.png?v8",black_large_square:"unicode/2b1b.png?v8",black_medium_small_square:"unicode/25fe.png?v8",black_medium_square:"unicode/25fc.png?v8",black_nib:"unicode/2712.png?v8",black_small_square:"unicode/25aa.png?v8",black_square_button:"unicode/1f532.png?v8",blond_haired_man:"unicode/1f471-2642.png?v8",blond_haired_person:"unicode/1f471.png?v8",blond_haired_woman:"unicode/1f471-2640.png?v8",blonde_woman:"unicode/1f471-2640.png?v8",blossom:"unicode/1f33c.png?v8",blowfish:"unicode/1f421.png?v8",blue_book:"unicode/1f4d8.png?v8",blue_car:"unicode/1f699.png?v8",blue_heart:"unicode/1f499.png?v8",blue_square:"unicode/1f7e6.png?v8",blueberries:"unicode/1fad0.png?v8",blush:"unicode/1f60a.png?v8",boar:"unicode/1f417.png?v8",boat:"unicode/26f5.png?v8",bolivia:"unicode/1f1e7-1f1f4.png?v8",bomb:"unicode/1f4a3.png?v8",bone:"unicode/1f9b4.png?v8",book:"unicode/1f4d6.png?v8",bookmark:"unicode/1f516.png?v8",bookmark_tabs:"unicode/1f4d1.png?v8",books:"unicode/1f4da.png?v8",boom:"unicode/1f4a5.png?v8",boomerang:"unicode/1fa83.png?v8",boot:"unicode/1f462.png?v8",bosnia_herzegovina:"unicode/1f1e7-1f1e6.png?v8",botswana:"unicode/1f1e7-1f1fc.png?v8",bouncing_ball_man:"unicode/26f9-2642.png?v8",bouncing_ball_person:"unicode/26f9.png?v8",bouncing_ball_woman:"unicode/26f9-2640.png?v8",bouquet:"unicode/1f490.png?v8",bouvet_island:"unicode/1f1e7-1f1fb.png?v8",bow:"unicode/1f647.png?v8",bow_and_arrow:"unicode/1f3f9.png?v8",bowing_man:"unicode/1f647-2642.png?v8",bowing_woman:"unicode/1f647-2640.png?v8",bowl_with_spoon:"unicode/1f963.png?v8",bowling:"unicode/1f3b3.png?v8",bowtie:"bowtie.png?v8",boxing_glove:"unicode/1f94a.png?v8",boy:"unicode/1f466.png?v8",brain:"unicode/1f9e0.png?v8",brazil:"unicode/1f1e7-1f1f7.png?v8",bread:"unicode/1f35e.png?v8",breast_feeding:"unicode/1f931.png?v8",bricks:"unicode/1f9f1.png?v8",bride_with_veil:"unicode/1f470-2640.png?v8",bridge_at_night:"unicode/1f309.png?v8",briefcase:"unicode/1f4bc.png?v8",british_indian_ocean_territory:"unicode/1f1ee-1f1f4.png?v8",british_virgin_islands:"unicode/1f1fb-1f1ec.png?v8",broccoli:"unicode/1f966.png?v8",broken_heart:"unicode/1f494.png?v8",broom:"unicode/1f9f9.png?v8",brown_circle:"unicode/1f7e4.png?v8",brown_heart:"unicode/1f90e.png?v8",brown_square:"unicode/1f7eb.png?v8",brunei:"unicode/1f1e7-1f1f3.png?v8",bubble_tea:"unicode/1f9cb.png?v8",bucket:"unicode/1faa3.png?v8",bug:"unicode/1f41b.png?v8",building_construction:"unicode/1f3d7.png?v8",bulb:"unicode/1f4a1.png?v8",bulgaria:"unicode/1f1e7-1f1ec.png?v8",bullettrain_front:"unicode/1f685.png?v8",bullettrain_side:"unicode/1f684.png?v8",burkina_faso:"unicode/1f1e7-1f1eb.png?v8",burrito:"unicode/1f32f.png?v8",burundi:"unicode/1f1e7-1f1ee.png?v8",bus:"unicode/1f68c.png?v8",business_suit_levitating:"unicode/1f574.png?v8",busstop:"unicode/1f68f.png?v8",bust_in_silhouette:"unicode/1f464.png?v8",busts_in_silhouette:"unicode/1f465.png?v8",butter:"unicode/1f9c8.png?v8",butterfly:"unicode/1f98b.png?v8",cactus:"unicode/1f335.png?v8",cake:"unicode/1f370.png?v8",calendar:"unicode/1f4c6.png?v8",call_me_hand:"unicode/1f919.png?v8",calling:"unicode/1f4f2.png?v8",cambodia:"unicode/1f1f0-1f1ed.png?v8",camel:"unicode/1f42b.png?v8",camera:"unicode/1f4f7.png?v8",camera_flash:"unicode/1f4f8.png?v8",cameroon:"unicode/1f1e8-1f1f2.png?v8",camping:"unicode/1f3d5.png?v8",canada:"unicode/1f1e8-1f1e6.png?v8",canary_islands:"unicode/1f1ee-1f1e8.png?v8",cancer:"unicode/264b.png?v8",candle:"unicode/1f56f.png?v8",candy:"unicode/1f36c.png?v8",canned_food:"unicode/1f96b.png?v8",canoe:"unicode/1f6f6.png?v8",cape_verde:"unicode/1f1e8-1f1fb.png?v8",capital_abcd:"unicode/1f520.png?v8",capricorn:"unicode/2651.png?v8",car:"unicode/1f697.png?v8",card_file_box:"unicode/1f5c3.png?v8",card_index:"unicode/1f4c7.png?v8",card_index_dividers:"unicode/1f5c2.png?v8",caribbean_netherlands:"unicode/1f1e7-1f1f6.png?v8",carousel_horse:"unicode/1f3a0.png?v8",carpentry_saw:"unicode/1fa9a.png?v8",carrot:"unicode/1f955.png?v8",cartwheeling:"unicode/1f938.png?v8",cat:"unicode/1f431.png?v8",cat2:"unicode/1f408.png?v8",cayman_islands:"unicode/1f1f0-1f1fe.png?v8",cd:"unicode/1f4bf.png?v8",central_african_republic:"unicode/1f1e8-1f1eb.png?v8",ceuta_melilla:"unicode/1f1ea-1f1e6.png?v8",chad:"unicode/1f1f9-1f1e9.png?v8",chains:"unicode/26d3.png?v8",chair:"unicode/1fa91.png?v8",champagne:"unicode/1f37e.png?v8",chart:"unicode/1f4b9.png?v8",chart_with_downwards_trend:"unicode/1f4c9.png?v8",chart_with_upwards_trend:"unicode/1f4c8.png?v8",checkered_flag:"unicode/1f3c1.png?v8",cheese:"unicode/1f9c0.png?v8",cherries:"unicode/1f352.png?v8",cherry_blossom:"unicode/1f338.png?v8",chess_pawn:"unicode/265f.png?v8",chestnut:"unicode/1f330.png?v8",chicken:"unicode/1f414.png?v8",child:"unicode/1f9d2.png?v8",children_crossing:"unicode/1f6b8.png?v8",chile:"unicode/1f1e8-1f1f1.png?v8",chipmunk:"unicode/1f43f.png?v8",chocolate_bar:"unicode/1f36b.png?v8",chopsticks:"unicode/1f962.png?v8",christmas_island:"unicode/1f1e8-1f1fd.png?v8",christmas_tree:"unicode/1f384.png?v8",church:"unicode/26ea.png?v8",cinema:"unicode/1f3a6.png?v8",circus_tent:"unicode/1f3aa.png?v8",city_sunrise:"unicode/1f307.png?v8",city_sunset:"unicode/1f306.png?v8",cityscape:"unicode/1f3d9.png?v8",cl:"unicode/1f191.png?v8",clamp:"unicode/1f5dc.png?v8",clap:"unicode/1f44f.png?v8",clapper:"unicode/1f3ac.png?v8",classical_building:"unicode/1f3db.png?v8",climbing:"unicode/1f9d7.png?v8",climbing_man:"unicode/1f9d7-2642.png?v8",climbing_woman:"unicode/1f9d7-2640.png?v8",clinking_glasses:"unicode/1f942.png?v8",clipboard:"unicode/1f4cb.png?v8",clipperton_island:"unicode/1f1e8-1f1f5.png?v8",clock1:"unicode/1f550.png?v8",clock10:"unicode/1f559.png?v8",clock1030:"unicode/1f565.png?v8",clock11:"unicode/1f55a.png?v8",clock1130:"unicode/1f566.png?v8",clock12:"unicode/1f55b.png?v8",clock1230:"unicode/1f567.png?v8",clock130:"unicode/1f55c.png?v8",clock2:"unicode/1f551.png?v8",clock230:"unicode/1f55d.png?v8",clock3:"unicode/1f552.png?v8",clock330:"unicode/1f55e.png?v8",clock4:"unicode/1f553.png?v8",clock430:"unicode/1f55f.png?v8",clock5:"unicode/1f554.png?v8",clock530:"unicode/1f560.png?v8",clock6:"unicode/1f555.png?v8",clock630:"unicode/1f561.png?v8",clock7:"unicode/1f556.png?v8",clock730:"unicode/1f562.png?v8",clock8:"unicode/1f557.png?v8",clock830:"unicode/1f563.png?v8",clock9:"unicode/1f558.png?v8",clock930:"unicode/1f564.png?v8",closed_book:"unicode/1f4d5.png?v8",closed_lock_with_key:"unicode/1f510.png?v8",closed_umbrella:"unicode/1f302.png?v8",cloud:"unicode/2601.png?v8",cloud_with_lightning:"unicode/1f329.png?v8",cloud_with_lightning_and_rain:"unicode/26c8.png?v8",cloud_with_rain:"unicode/1f327.png?v8",cloud_with_snow:"unicode/1f328.png?v8",clown_face:"unicode/1f921.png?v8",clubs:"unicode/2663.png?v8",cn:"unicode/1f1e8-1f1f3.png?v8",coat:"unicode/1f9e5.png?v8",cockroach:"unicode/1fab3.png?v8",cocktail:"unicode/1f378.png?v8",coconut:"unicode/1f965.png?v8",cocos_islands:"unicode/1f1e8-1f1e8.png?v8",coffee:"unicode/2615.png?v8",coffin:"unicode/26b0.png?v8",coin:"unicode/1fa99.png?v8",cold_face:"unicode/1f976.png?v8",cold_sweat:"unicode/1f630.png?v8",collision:"unicode/1f4a5.png?v8",colombia:"unicode/1f1e8-1f1f4.png?v8",comet:"unicode/2604.png?v8",comoros:"unicode/1f1f0-1f1f2.png?v8",compass:"unicode/1f9ed.png?v8",computer:"unicode/1f4bb.png?v8",computer_mouse:"unicode/1f5b1.png?v8",confetti_ball:"unicode/1f38a.png?v8",confounded:"unicode/1f616.png?v8",confused:"unicode/1f615.png?v8",congo_brazzaville:"unicode/1f1e8-1f1ec.png?v8",congo_kinshasa:"unicode/1f1e8-1f1e9.png?v8",congratulations:"unicode/3297.png?v8",construction:"unicode/1f6a7.png?v8",construction_worker:"unicode/1f477.png?v8",construction_worker_man:"unicode/1f477-2642.png?v8",construction_worker_woman:"unicode/1f477-2640.png?v8",control_knobs:"unicode/1f39b.png?v8",convenience_store:"unicode/1f3ea.png?v8",cook:"unicode/1f9d1-1f373.png?v8",cook_islands:"unicode/1f1e8-1f1f0.png?v8",cookie:"unicode/1f36a.png?v8",cool:"unicode/1f192.png?v8",cop:"unicode/1f46e.png?v8",copyright:"unicode/00a9.png?v8",corn:"unicode/1f33d.png?v8",costa_rica:"unicode/1f1e8-1f1f7.png?v8",cote_divoire:"unicode/1f1e8-1f1ee.png?v8",couch_and_lamp:"unicode/1f6cb.png?v8",couple:"unicode/1f46b.png?v8",couple_with_heart:"unicode/1f491.png?v8",couple_with_heart_man_man:"unicode/1f468-2764-1f468.png?v8",couple_with_heart_woman_man:"unicode/1f469-2764-1f468.png?v8",couple_with_heart_woman_woman:"unicode/1f469-2764-1f469.png?v8",couplekiss:"unicode/1f48f.png?v8",couplekiss_man_man:"unicode/1f468-2764-1f48b-1f468.png?v8",couplekiss_man_woman:"unicode/1f469-2764-1f48b-1f468.png?v8",couplekiss_woman_woman:"unicode/1f469-2764-1f48b-1f469.png?v8",cow:"unicode/1f42e.png?v8",cow2:"unicode/1f404.png?v8",cowboy_hat_face:"unicode/1f920.png?v8",crab:"unicode/1f980.png?v8",crayon:"unicode/1f58d.png?v8",credit_card:"unicode/1f4b3.png?v8",crescent_moon:"unicode/1f319.png?v8",cricket:"unicode/1f997.png?v8",cricket_game:"unicode/1f3cf.png?v8",croatia:"unicode/1f1ed-1f1f7.png?v8",crocodile:"unicode/1f40a.png?v8",croissant:"unicode/1f950.png?v8",crossed_fingers:"unicode/1f91e.png?v8",crossed_flags:"unicode/1f38c.png?v8",crossed_swords:"unicode/2694.png?v8",crown:"unicode/1f451.png?v8",cry:"unicode/1f622.png?v8",crying_cat_face:"unicode/1f63f.png?v8",crystal_ball:"unicode/1f52e.png?v8",cuba:"unicode/1f1e8-1f1fa.png?v8",cucumber:"unicode/1f952.png?v8",cup_with_straw:"unicode/1f964.png?v8",cupcake:"unicode/1f9c1.png?v8",cupid:"unicode/1f498.png?v8",curacao:"unicode/1f1e8-1f1fc.png?v8",curling_stone:"unicode/1f94c.png?v8",curly_haired_man:"unicode/1f468-1f9b1.png?v8",curly_haired_woman:"unicode/1f469-1f9b1.png?v8",curly_loop:"unicode/27b0.png?v8",currency_exchange:"unicode/1f4b1.png?v8",curry:"unicode/1f35b.png?v8",cursing_face:"unicode/1f92c.png?v8",custard:"unicode/1f36e.png?v8",customs:"unicode/1f6c3.png?v8",cut_of_meat:"unicode/1f969.png?v8",cyclone:"unicode/1f300.png?v8",cyprus:"unicode/1f1e8-1f1fe.png?v8",czech_republic:"unicode/1f1e8-1f1ff.png?v8",dagger:"unicode/1f5e1.png?v8",dancer:"unicode/1f483.png?v8",dancers:"unicode/1f46f.png?v8",dancing_men:"unicode/1f46f-2642.png?v8",dancing_women:"unicode/1f46f-2640.png?v8",dango:"unicode/1f361.png?v8",dark_sunglasses:"unicode/1f576.png?v8",dart:"unicode/1f3af.png?v8",dash:"unicode/1f4a8.png?v8",date:"unicode/1f4c5.png?v8",de:"unicode/1f1e9-1f1ea.png?v8",deaf_man:"unicode/1f9cf-2642.png?v8",deaf_person:"unicode/1f9cf.png?v8",deaf_woman:"unicode/1f9cf-2640.png?v8",deciduous_tree:"unicode/1f333.png?v8",deer:"unicode/1f98c.png?v8",denmark:"unicode/1f1e9-1f1f0.png?v8",department_store:"unicode/1f3ec.png?v8",dependabot:"dependabot.png?v8",derelict_house:"unicode/1f3da.png?v8",desert:"unicode/1f3dc.png?v8",desert_island:"unicode/1f3dd.png?v8",desktop_computer:"unicode/1f5a5.png?v8",detective:"unicode/1f575.png?v8",diamond_shape_with_a_dot_inside:"unicode/1f4a0.png?v8",diamonds:"unicode/2666.png?v8",diego_garcia:"unicode/1f1e9-1f1ec.png?v8",disappointed:"unicode/1f61e.png?v8",disappointed_relieved:"unicode/1f625.png?v8",disguised_face:"unicode/1f978.png?v8",diving_mask:"unicode/1f93f.png?v8",diya_lamp:"unicode/1fa94.png?v8",dizzy:"unicode/1f4ab.png?v8",dizzy_face:"unicode/1f635.png?v8",djibouti:"unicode/1f1e9-1f1ef.png?v8",dna:"unicode/1f9ec.png?v8",do_not_litter:"unicode/1f6af.png?v8",dodo:"unicode/1f9a4.png?v8",dog:"unicode/1f436.png?v8",dog2:"unicode/1f415.png?v8",dollar:"unicode/1f4b5.png?v8",dolls:"unicode/1f38e.png?v8",dolphin:"unicode/1f42c.png?v8",dominica:"unicode/1f1e9-1f1f2.png?v8",dominican_republic:"unicode/1f1e9-1f1f4.png?v8",door:"unicode/1f6aa.png?v8",doughnut:"unicode/1f369.png?v8",dove:"unicode/1f54a.png?v8",dragon:"unicode/1f409.png?v8",dragon_face:"unicode/1f432.png?v8",dress:"unicode/1f457.png?v8",dromedary_camel:"unicode/1f42a.png?v8",drooling_face:"unicode/1f924.png?v8",drop_of_blood:"unicode/1fa78.png?v8",droplet:"unicode/1f4a7.png?v8",drum:"unicode/1f941.png?v8",duck:"unicode/1f986.png?v8",dumpling:"unicode/1f95f.png?v8",dvd:"unicode/1f4c0.png?v8","e-mail":"unicode/1f4e7.png?v8",eagle:"unicode/1f985.png?v8",ear:"unicode/1f442.png?v8",ear_of_rice:"unicode/1f33e.png?v8",ear_with_hearing_aid:"unicode/1f9bb.png?v8",earth_africa:"unicode/1f30d.png?v8",earth_americas:"unicode/1f30e.png?v8",earth_asia:"unicode/1f30f.png?v8",ecuador:"unicode/1f1ea-1f1e8.png?v8",egg:"unicode/1f95a.png?v8",eggplant:"unicode/1f346.png?v8",egypt:"unicode/1f1ea-1f1ec.png?v8",eight:"unicode/0038-20e3.png?v8",eight_pointed_black_star:"unicode/2734.png?v8",eight_spoked_asterisk:"unicode/2733.png?v8",eject_button:"unicode/23cf.png?v8",el_salvador:"unicode/1f1f8-1f1fb.png?v8",electric_plug:"unicode/1f50c.png?v8",electron:"electron.png?v8",elephant:"unicode/1f418.png?v8",elevator:"unicode/1f6d7.png?v8",elf:"unicode/1f9dd.png?v8",elf_man:"unicode/1f9dd-2642.png?v8",elf_woman:"unicode/1f9dd-2640.png?v8",email:"unicode/1f4e7.png?v8",end:"unicode/1f51a.png?v8",england:"unicode/1f3f4-e0067-e0062-e0065-e006e-e0067-e007f.png?v8",envelope:"unicode/2709.png?v8",envelope_with_arrow:"unicode/1f4e9.png?v8",equatorial_guinea:"unicode/1f1ec-1f1f6.png?v8",eritrea:"unicode/1f1ea-1f1f7.png?v8",es:"unicode/1f1ea-1f1f8.png?v8",estonia:"unicode/1f1ea-1f1ea.png?v8",ethiopia:"unicode/1f1ea-1f1f9.png?v8",eu:"unicode/1f1ea-1f1fa.png?v8",euro:"unicode/1f4b6.png?v8",european_castle:"unicode/1f3f0.png?v8",european_post_office:"unicode/1f3e4.png?v8",european_union:"unicode/1f1ea-1f1fa.png?v8",evergreen_tree:"unicode/1f332.png?v8",exclamation:"unicode/2757.png?v8",exploding_head:"unicode/1f92f.png?v8",expressionless:"unicode/1f611.png?v8",eye:"unicode/1f441.png?v8",eye_speech_bubble:"unicode/1f441-1f5e8.png?v8",eyeglasses:"unicode/1f453.png?v8",eyes:"unicode/1f440.png?v8",face_exhaling:"unicode/1f62e-1f4a8.png?v8",face_in_clouds:"unicode/1f636-1f32b.png?v8",face_with_head_bandage:"unicode/1f915.png?v8",face_with_spiral_eyes:"unicode/1f635-1f4ab.png?v8",face_with_thermometer:"unicode/1f912.png?v8",facepalm:"unicode/1f926.png?v8",facepunch:"unicode/1f44a.png?v8",factory:"unicode/1f3ed.png?v8",factory_worker:"unicode/1f9d1-1f3ed.png?v8",fairy:"unicode/1f9da.png?v8",fairy_man:"unicode/1f9da-2642.png?v8",fairy_woman:"unicode/1f9da-2640.png?v8",falafel:"unicode/1f9c6.png?v8",falkland_islands:"unicode/1f1eb-1f1f0.png?v8",fallen_leaf:"unicode/1f342.png?v8",family:"unicode/1f46a.png?v8",family_man_boy:"unicode/1f468-1f466.png?v8",family_man_boy_boy:"unicode/1f468-1f466-1f466.png?v8",family_man_girl:"unicode/1f468-1f467.png?v8",family_man_girl_boy:"unicode/1f468-1f467-1f466.png?v8",family_man_girl_girl:"unicode/1f468-1f467-1f467.png?v8",family_man_man_boy:"unicode/1f468-1f468-1f466.png?v8",family_man_man_boy_boy:"unicode/1f468-1f468-1f466-1f466.png?v8",family_man_man_girl:"unicode/1f468-1f468-1f467.png?v8",family_man_man_girl_boy:"unicode/1f468-1f468-1f467-1f466.png?v8",family_man_man_girl_girl:"unicode/1f468-1f468-1f467-1f467.png?v8",family_man_woman_boy:"unicode/1f468-1f469-1f466.png?v8",family_man_woman_boy_boy:"unicode/1f468-1f469-1f466-1f466.png?v8",family_man_woman_girl:"unicode/1f468-1f469-1f467.png?v8",family_man_woman_girl_boy:"unicode/1f468-1f469-1f467-1f466.png?v8",family_man_woman_girl_girl:"unicode/1f468-1f469-1f467-1f467.png?v8",family_woman_boy:"unicode/1f469-1f466.png?v8",family_woman_boy_boy:"unicode/1f469-1f466-1f466.png?v8",family_woman_girl:"unicode/1f469-1f467.png?v8",family_woman_girl_boy:"unicode/1f469-1f467-1f466.png?v8",family_woman_girl_girl:"unicode/1f469-1f467-1f467.png?v8",family_woman_woman_boy:"unicode/1f469-1f469-1f466.png?v8",family_woman_woman_boy_boy:"unicode/1f469-1f469-1f466-1f466.png?v8",family_woman_woman_girl:"unicode/1f469-1f469-1f467.png?v8",family_woman_woman_girl_boy:"unicode/1f469-1f469-1f467-1f466.png?v8",family_woman_woman_girl_girl:"unicode/1f469-1f469-1f467-1f467.png?v8",farmer:"unicode/1f9d1-1f33e.png?v8",faroe_islands:"unicode/1f1eb-1f1f4.png?v8",fast_forward:"unicode/23e9.png?v8",fax:"unicode/1f4e0.png?v8",fearful:"unicode/1f628.png?v8",feather:"unicode/1fab6.png?v8",feelsgood:"feelsgood.png?v8",feet:"unicode/1f43e.png?v8",female_detective:"unicode/1f575-2640.png?v8",female_sign:"unicode/2640.png?v8",ferris_wheel:"unicode/1f3a1.png?v8",ferry:"unicode/26f4.png?v8",field_hockey:"unicode/1f3d1.png?v8",fiji:"unicode/1f1eb-1f1ef.png?v8",file_cabinet:"unicode/1f5c4.png?v8",file_folder:"unicode/1f4c1.png?v8",film_projector:"unicode/1f4fd.png?v8",film_strip:"unicode/1f39e.png?v8",finland:"unicode/1f1eb-1f1ee.png?v8",finnadie:"finnadie.png?v8",fire:"unicode/1f525.png?v8",fire_engine:"unicode/1f692.png?v8",fire_extinguisher:"unicode/1f9ef.png?v8",firecracker:"unicode/1f9e8.png?v8",firefighter:"unicode/1f9d1-1f692.png?v8",fireworks:"unicode/1f386.png?v8",first_quarter_moon:"unicode/1f313.png?v8",first_quarter_moon_with_face:"unicode/1f31b.png?v8",fish:"unicode/1f41f.png?v8",fish_cake:"unicode/1f365.png?v8",fishing_pole_and_fish:"unicode/1f3a3.png?v8",fishsticks:"fishsticks.png?v8",fist:"unicode/270a.png?v8",fist_left:"unicode/1f91b.png?v8",fist_oncoming:"unicode/1f44a.png?v8",fist_raised:"unicode/270a.png?v8",fist_right:"unicode/1f91c.png?v8",five:"unicode/0035-20e3.png?v8",flags:"unicode/1f38f.png?v8",flamingo:"unicode/1f9a9.png?v8",flashlight:"unicode/1f526.png?v8",flat_shoe:"unicode/1f97f.png?v8",flatbread:"unicode/1fad3.png?v8",fleur_de_lis:"unicode/269c.png?v8",flight_arrival:"unicode/1f6ec.png?v8",flight_departure:"unicode/1f6eb.png?v8",flipper:"unicode/1f42c.png?v8",floppy_disk:"unicode/1f4be.png?v8",flower_playing_cards:"unicode/1f3b4.png?v8",flushed:"unicode/1f633.png?v8",fly:"unicode/1fab0.png?v8",flying_disc:"unicode/1f94f.png?v8",flying_saucer:"unicode/1f6f8.png?v8",fog:"unicode/1f32b.png?v8",foggy:"unicode/1f301.png?v8",fondue:"unicode/1fad5.png?v8",foot:"unicode/1f9b6.png?v8",football:"unicode/1f3c8.png?v8",footprints:"unicode/1f463.png?v8",fork_and_knife:"unicode/1f374.png?v8",fortune_cookie:"unicode/1f960.png?v8",fountain:"unicode/26f2.png?v8",fountain_pen:"unicode/1f58b.png?v8",four:"unicode/0034-20e3.png?v8",four_leaf_clover:"unicode/1f340.png?v8",fox_face:"unicode/1f98a.png?v8",fr:"unicode/1f1eb-1f1f7.png?v8",framed_picture:"unicode/1f5bc.png?v8",free:"unicode/1f193.png?v8",french_guiana:"unicode/1f1ec-1f1eb.png?v8",french_polynesia:"unicode/1f1f5-1f1eb.png?v8",french_southern_territories:"unicode/1f1f9-1f1eb.png?v8",fried_egg:"unicode/1f373.png?v8",fried_shrimp:"unicode/1f364.png?v8",fries:"unicode/1f35f.png?v8",frog:"unicode/1f438.png?v8",frowning:"unicode/1f626.png?v8",frowning_face:"unicode/2639.png?v8",frowning_man:"unicode/1f64d-2642.png?v8",frowning_person:"unicode/1f64d.png?v8",frowning_woman:"unicode/1f64d-2640.png?v8",fu:"unicode/1f595.png?v8",fuelpump:"unicode/26fd.png?v8",full_moon:"unicode/1f315.png?v8",full_moon_with_face:"unicode/1f31d.png?v8",funeral_urn:"unicode/26b1.png?v8",gabon:"unicode/1f1ec-1f1e6.png?v8",gambia:"unicode/1f1ec-1f1f2.png?v8",game_die:"unicode/1f3b2.png?v8",garlic:"unicode/1f9c4.png?v8",gb:"unicode/1f1ec-1f1e7.png?v8",gear:"unicode/2699.png?v8",gem:"unicode/1f48e.png?v8",gemini:"unicode/264a.png?v8",genie:"unicode/1f9de.png?v8",genie_man:"unicode/1f9de-2642.png?v8",genie_woman:"unicode/1f9de-2640.png?v8",georgia:"unicode/1f1ec-1f1ea.png?v8",ghana:"unicode/1f1ec-1f1ed.png?v8",ghost:"unicode/1f47b.png?v8",gibraltar:"unicode/1f1ec-1f1ee.png?v8",gift:"unicode/1f381.png?v8",gift_heart:"unicode/1f49d.png?v8",giraffe:"unicode/1f992.png?v8",girl:"unicode/1f467.png?v8",globe_with_meridians:"unicode/1f310.png?v8",gloves:"unicode/1f9e4.png?v8",goal_net:"unicode/1f945.png?v8",goat:"unicode/1f410.png?v8",goberserk:"goberserk.png?v8",godmode:"godmode.png?v8",goggles:"unicode/1f97d.png?v8",golf:"unicode/26f3.png?v8",golfing:"unicode/1f3cc.png?v8",golfing_man:"unicode/1f3cc-2642.png?v8",golfing_woman:"unicode/1f3cc-2640.png?v8",gorilla:"unicode/1f98d.png?v8",grapes:"unicode/1f347.png?v8",greece:"unicode/1f1ec-1f1f7.png?v8",green_apple:"unicode/1f34f.png?v8",green_book:"unicode/1f4d7.png?v8",green_circle:"unicode/1f7e2.png?v8",green_heart:"unicode/1f49a.png?v8",green_salad:"unicode/1f957.png?v8",green_square:"unicode/1f7e9.png?v8",greenland:"unicode/1f1ec-1f1f1.png?v8",grenada:"unicode/1f1ec-1f1e9.png?v8",grey_exclamation:"unicode/2755.png?v8",grey_question:"unicode/2754.png?v8",grimacing:"unicode/1f62c.png?v8",grin:"unicode/1f601.png?v8",grinning:"unicode/1f600.png?v8",guadeloupe:"unicode/1f1ec-1f1f5.png?v8",guam:"unicode/1f1ec-1f1fa.png?v8",guard:"unicode/1f482.png?v8",guardsman:"unicode/1f482-2642.png?v8",guardswoman:"unicode/1f482-2640.png?v8",guatemala:"unicode/1f1ec-1f1f9.png?v8",guernsey:"unicode/1f1ec-1f1ec.png?v8",guide_dog:"unicode/1f9ae.png?v8",guinea:"unicode/1f1ec-1f1f3.png?v8",guinea_bissau:"unicode/1f1ec-1f1fc.png?v8",guitar:"unicode/1f3b8.png?v8",gun:"unicode/1f52b.png?v8",guyana:"unicode/1f1ec-1f1fe.png?v8",haircut:"unicode/1f487.png?v8",haircut_man:"unicode/1f487-2642.png?v8",haircut_woman:"unicode/1f487-2640.png?v8",haiti:"unicode/1f1ed-1f1f9.png?v8",hamburger:"unicode/1f354.png?v8",hammer:"unicode/1f528.png?v8",hammer_and_pick:"unicode/2692.png?v8",hammer_and_wrench:"unicode/1f6e0.png?v8",hamster:"unicode/1f439.png?v8",hand:"unicode/270b.png?v8",hand_over_mouth:"unicode/1f92d.png?v8",handbag:"unicode/1f45c.png?v8",handball_person:"unicode/1f93e.png?v8",handshake:"unicode/1f91d.png?v8",hankey:"unicode/1f4a9.png?v8",hash:"unicode/0023-20e3.png?v8",hatched_chick:"unicode/1f425.png?v8",hatching_chick:"unicode/1f423.png?v8",headphones:"unicode/1f3a7.png?v8",headstone:"unicode/1faa6.png?v8",health_worker:"unicode/1f9d1-2695.png?v8",hear_no_evil:"unicode/1f649.png?v8",heard_mcdonald_islands:"unicode/1f1ed-1f1f2.png?v8",heart:"unicode/2764.png?v8",heart_decoration:"unicode/1f49f.png?v8",heart_eyes:"unicode/1f60d.png?v8",heart_eyes_cat:"unicode/1f63b.png?v8",heart_on_fire:"unicode/2764-1f525.png?v8",heartbeat:"unicode/1f493.png?v8",heartpulse:"unicode/1f497.png?v8",hearts:"unicode/2665.png?v8",heavy_check_mark:"unicode/2714.png?v8",heavy_division_sign:"unicode/2797.png?v8",heavy_dollar_sign:"unicode/1f4b2.png?v8",heavy_exclamation_mark:"unicode/2757.png?v8",heavy_heart_exclamation:"unicode/2763.png?v8",heavy_minus_sign:"unicode/2796.png?v8",heavy_multiplication_x:"unicode/2716.png?v8",heavy_plus_sign:"unicode/2795.png?v8",hedgehog:"unicode/1f994.png?v8",helicopter:"unicode/1f681.png?v8",herb:"unicode/1f33f.png?v8",hibiscus:"unicode/1f33a.png?v8",high_brightness:"unicode/1f506.png?v8",high_heel:"unicode/1f460.png?v8",hiking_boot:"unicode/1f97e.png?v8",hindu_temple:"unicode/1f6d5.png?v8",hippopotamus:"unicode/1f99b.png?v8",hocho:"unicode/1f52a.png?v8",hole:"unicode/1f573.png?v8",honduras:"unicode/1f1ed-1f1f3.png?v8",honey_pot:"unicode/1f36f.png?v8",honeybee:"unicode/1f41d.png?v8",hong_kong:"unicode/1f1ed-1f1f0.png?v8",hook:"unicode/1fa9d.png?v8",horse:"unicode/1f434.png?v8",horse_racing:"unicode/1f3c7.png?v8",hospital:"unicode/1f3e5.png?v8",hot_face:"unicode/1f975.png?v8",hot_pepper:"unicode/1f336.png?v8",hotdog:"unicode/1f32d.png?v8",hotel:"unicode/1f3e8.png?v8",hotsprings:"unicode/2668.png?v8",hourglass:"unicode/231b.png?v8",hourglass_flowing_sand:"unicode/23f3.png?v8",house:"unicode/1f3e0.png?v8",house_with_garden:"unicode/1f3e1.png?v8",houses:"unicode/1f3d8.png?v8",hugs:"unicode/1f917.png?v8",hungary:"unicode/1f1ed-1f1fa.png?v8",hurtrealbad:"hurtrealbad.png?v8",hushed:"unicode/1f62f.png?v8",hut:"unicode/1f6d6.png?v8",ice_cream:"unicode/1f368.png?v8",ice_cube:"unicode/1f9ca.png?v8",ice_hockey:"unicode/1f3d2.png?v8",ice_skate:"unicode/26f8.png?v8",icecream:"unicode/1f366.png?v8",iceland:"unicode/1f1ee-1f1f8.png?v8",id:"unicode/1f194.png?v8",ideograph_advantage:"unicode/1f250.png?v8",imp:"unicode/1f47f.png?v8",inbox_tray:"unicode/1f4e5.png?v8",incoming_envelope:"unicode/1f4e8.png?v8",india:"unicode/1f1ee-1f1f3.png?v8",indonesia:"unicode/1f1ee-1f1e9.png?v8",infinity:"unicode/267e.png?v8",information_desk_person:"unicode/1f481.png?v8",information_source:"unicode/2139.png?v8",innocent:"unicode/1f607.png?v8",interrobang:"unicode/2049.png?v8",iphone:"unicode/1f4f1.png?v8",iran:"unicode/1f1ee-1f1f7.png?v8",iraq:"unicode/1f1ee-1f1f6.png?v8",ireland:"unicode/1f1ee-1f1ea.png?v8",isle_of_man:"unicode/1f1ee-1f1f2.png?v8",israel:"unicode/1f1ee-1f1f1.png?v8",it:"unicode/1f1ee-1f1f9.png?v8",izakaya_lantern:"unicode/1f3ee.png?v8",jack_o_lantern:"unicode/1f383.png?v8",jamaica:"unicode/1f1ef-1f1f2.png?v8",japan:"unicode/1f5fe.png?v8",japanese_castle:"unicode/1f3ef.png?v8",japanese_goblin:"unicode/1f47a.png?v8",japanese_ogre:"unicode/1f479.png?v8",jeans:"unicode/1f456.png?v8",jersey:"unicode/1f1ef-1f1ea.png?v8",jigsaw:"unicode/1f9e9.png?v8",jordan:"unicode/1f1ef-1f1f4.png?v8",joy:"unicode/1f602.png?v8",joy_cat:"unicode/1f639.png?v8",joystick:"unicode/1f579.png?v8",jp:"unicode/1f1ef-1f1f5.png?v8",judge:"unicode/1f9d1-2696.png?v8",juggling_person:"unicode/1f939.png?v8",kaaba:"unicode/1f54b.png?v8",kangaroo:"unicode/1f998.png?v8",kazakhstan:"unicode/1f1f0-1f1ff.png?v8",kenya:"unicode/1f1f0-1f1ea.png?v8",key:"unicode/1f511.png?v8",keyboard:"unicode/2328.png?v8",keycap_ten:"unicode/1f51f.png?v8",kick_scooter:"unicode/1f6f4.png?v8",kimono:"unicode/1f458.png?v8",kiribati:"unicode/1f1f0-1f1ee.png?v8",kiss:"unicode/1f48b.png?v8",kissing:"unicode/1f617.png?v8",kissing_cat:"unicode/1f63d.png?v8",kissing_closed_eyes:"unicode/1f61a.png?v8",kissing_heart:"unicode/1f618.png?v8",kissing_smiling_eyes:"unicode/1f619.png?v8",kite:"unicode/1fa81.png?v8",kiwi_fruit:"unicode/1f95d.png?v8",kneeling_man:"unicode/1f9ce-2642.png?v8",kneeling_person:"unicode/1f9ce.png?v8",kneeling_woman:"unicode/1f9ce-2640.png?v8",knife:"unicode/1f52a.png?v8",knot:"unicode/1faa2.png?v8",koala:"unicode/1f428.png?v8",koko:"unicode/1f201.png?v8",kosovo:"unicode/1f1fd-1f1f0.png?v8",kr:"unicode/1f1f0-1f1f7.png?v8",kuwait:"unicode/1f1f0-1f1fc.png?v8",kyrgyzstan:"unicode/1f1f0-1f1ec.png?v8",lab_coat:"unicode/1f97c.png?v8",label:"unicode/1f3f7.png?v8",lacrosse:"unicode/1f94d.png?v8",ladder:"unicode/1fa9c.png?v8",lady_beetle:"unicode/1f41e.png?v8",lantern:"unicode/1f3ee.png?v8",laos:"unicode/1f1f1-1f1e6.png?v8",large_blue_circle:"unicode/1f535.png?v8",large_blue_diamond:"unicode/1f537.png?v8",large_orange_diamond:"unicode/1f536.png?v8",last_quarter_moon:"unicode/1f317.png?v8",last_quarter_moon_with_face:"unicode/1f31c.png?v8",latin_cross:"unicode/271d.png?v8",latvia:"unicode/1f1f1-1f1fb.png?v8",laughing:"unicode/1f606.png?v8",leafy_green:"unicode/1f96c.png?v8",leaves:"unicode/1f343.png?v8",lebanon:"unicode/1f1f1-1f1e7.png?v8",ledger:"unicode/1f4d2.png?v8",left_luggage:"unicode/1f6c5.png?v8",left_right_arrow:"unicode/2194.png?v8",left_speech_bubble:"unicode/1f5e8.png?v8",leftwards_arrow_with_hook:"unicode/21a9.png?v8",leg:"unicode/1f9b5.png?v8",lemon:"unicode/1f34b.png?v8",leo:"unicode/264c.png?v8",leopard:"unicode/1f406.png?v8",lesotho:"unicode/1f1f1-1f1f8.png?v8",level_slider:"unicode/1f39a.png?v8",liberia:"unicode/1f1f1-1f1f7.png?v8",libra:"unicode/264e.png?v8",libya:"unicode/1f1f1-1f1fe.png?v8",liechtenstein:"unicode/1f1f1-1f1ee.png?v8",light_rail:"unicode/1f688.png?v8",link:"unicode/1f517.png?v8",lion:"unicode/1f981.png?v8",lips:"unicode/1f444.png?v8",lipstick:"unicode/1f484.png?v8",lithuania:"unicode/1f1f1-1f1f9.png?v8",lizard:"unicode/1f98e.png?v8",llama:"unicode/1f999.png?v8",lobster:"unicode/1f99e.png?v8",lock:"unicode/1f512.png?v8",lock_with_ink_pen:"unicode/1f50f.png?v8",lollipop:"unicode/1f36d.png?v8",long_drum:"unicode/1fa98.png?v8",loop:"unicode/27bf.png?v8",lotion_bottle:"unicode/1f9f4.png?v8",lotus_position:"unicode/1f9d8.png?v8",lotus_position_man:"unicode/1f9d8-2642.png?v8",lotus_position_woman:"unicode/1f9d8-2640.png?v8",loud_sound:"unicode/1f50a.png?v8",loudspeaker:"unicode/1f4e2.png?v8",love_hotel:"unicode/1f3e9.png?v8",love_letter:"unicode/1f48c.png?v8",love_you_gesture:"unicode/1f91f.png?v8",low_brightness:"unicode/1f505.png?v8",luggage:"unicode/1f9f3.png?v8",lungs:"unicode/1fac1.png?v8",luxembourg:"unicode/1f1f1-1f1fa.png?v8",lying_face:"unicode/1f925.png?v8",m:"unicode/24c2.png?v8",macau:"unicode/1f1f2-1f1f4.png?v8",macedonia:"unicode/1f1f2-1f1f0.png?v8",madagascar:"unicode/1f1f2-1f1ec.png?v8",mag:"unicode/1f50d.png?v8",mag_right:"unicode/1f50e.png?v8",mage:"unicode/1f9d9.png?v8",mage_man:"unicode/1f9d9-2642.png?v8",mage_woman:"unicode/1f9d9-2640.png?v8",magic_wand:"unicode/1fa84.png?v8",magnet:"unicode/1f9f2.png?v8",mahjong:"unicode/1f004.png?v8",mailbox:"unicode/1f4eb.png?v8",mailbox_closed:"unicode/1f4ea.png?v8",mailbox_with_mail:"unicode/1f4ec.png?v8",mailbox_with_no_mail:"unicode/1f4ed.png?v8",malawi:"unicode/1f1f2-1f1fc.png?v8",malaysia:"unicode/1f1f2-1f1fe.png?v8",maldives:"unicode/1f1f2-1f1fb.png?v8",male_detective:"unicode/1f575-2642.png?v8",male_sign:"unicode/2642.png?v8",mali:"unicode/1f1f2-1f1f1.png?v8",malta:"unicode/1f1f2-1f1f9.png?v8",mammoth:"unicode/1f9a3.png?v8",man:"unicode/1f468.png?v8",man_artist:"unicode/1f468-1f3a8.png?v8",man_astronaut:"unicode/1f468-1f680.png?v8",man_beard:"unicode/1f9d4-2642.png?v8",man_cartwheeling:"unicode/1f938-2642.png?v8",man_cook:"unicode/1f468-1f373.png?v8",man_dancing:"unicode/1f57a.png?v8",man_facepalming:"unicode/1f926-2642.png?v8",man_factory_worker:"unicode/1f468-1f3ed.png?v8",man_farmer:"unicode/1f468-1f33e.png?v8",man_feeding_baby:"unicode/1f468-1f37c.png?v8",man_firefighter:"unicode/1f468-1f692.png?v8",man_health_worker:"unicode/1f468-2695.png?v8",man_in_manual_wheelchair:"unicode/1f468-1f9bd.png?v8",man_in_motorized_wheelchair:"unicode/1f468-1f9bc.png?v8",man_in_tuxedo:"unicode/1f935-2642.png?v8",man_judge:"unicode/1f468-2696.png?v8",man_juggling:"unicode/1f939-2642.png?v8",man_mechanic:"unicode/1f468-1f527.png?v8",man_office_worker:"unicode/1f468-1f4bc.png?v8",man_pilot:"unicode/1f468-2708.png?v8",man_playing_handball:"unicode/1f93e-2642.png?v8",man_playing_water_polo:"unicode/1f93d-2642.png?v8",man_scientist:"unicode/1f468-1f52c.png?v8",man_shrugging:"unicode/1f937-2642.png?v8",man_singer:"unicode/1f468-1f3a4.png?v8",man_student:"unicode/1f468-1f393.png?v8",man_teacher:"unicode/1f468-1f3eb.png?v8",man_technologist:"unicode/1f468-1f4bb.png?v8",man_with_gua_pi_mao:"unicode/1f472.png?v8",man_with_probing_cane:"unicode/1f468-1f9af.png?v8",man_with_turban:"unicode/1f473-2642.png?v8",man_with_veil:"unicode/1f470-2642.png?v8",mandarin:"unicode/1f34a.png?v8",mango:"unicode/1f96d.png?v8",mans_shoe:"unicode/1f45e.png?v8",mantelpiece_clock:"unicode/1f570.png?v8",manual_wheelchair:"unicode/1f9bd.png?v8",maple_leaf:"unicode/1f341.png?v8",marshall_islands:"unicode/1f1f2-1f1ed.png?v8",martial_arts_uniform:"unicode/1f94b.png?v8",martinique:"unicode/1f1f2-1f1f6.png?v8",mask:"unicode/1f637.png?v8",massage:"unicode/1f486.png?v8",massage_man:"unicode/1f486-2642.png?v8",massage_woman:"unicode/1f486-2640.png?v8",mate:"unicode/1f9c9.png?v8",mauritania:"unicode/1f1f2-1f1f7.png?v8",mauritius:"unicode/1f1f2-1f1fa.png?v8",mayotte:"unicode/1f1fe-1f1f9.png?v8",meat_on_bone:"unicode/1f356.png?v8",mechanic:"unicode/1f9d1-1f527.png?v8",mechanical_arm:"unicode/1f9be.png?v8",mechanical_leg:"unicode/1f9bf.png?v8",medal_military:"unicode/1f396.png?v8",medal_sports:"unicode/1f3c5.png?v8",medical_symbol:"unicode/2695.png?v8",mega:"unicode/1f4e3.png?v8",melon:"unicode/1f348.png?v8",memo:"unicode/1f4dd.png?v8",men_wrestling:"unicode/1f93c-2642.png?v8",mending_heart:"unicode/2764-1fa79.png?v8",menorah:"unicode/1f54e.png?v8",mens:"unicode/1f6b9.png?v8",mermaid:"unicode/1f9dc-2640.png?v8",merman:"unicode/1f9dc-2642.png?v8",merperson:"unicode/1f9dc.png?v8",metal:"unicode/1f918.png?v8",metro:"unicode/1f687.png?v8",mexico:"unicode/1f1f2-1f1fd.png?v8",microbe:"unicode/1f9a0.png?v8",micronesia:"unicode/1f1eb-1f1f2.png?v8",microphone:"unicode/1f3a4.png?v8",microscope:"unicode/1f52c.png?v8",middle_finger:"unicode/1f595.png?v8",military_helmet:"unicode/1fa96.png?v8",milk_glass:"unicode/1f95b.png?v8",milky_way:"unicode/1f30c.png?v8",minibus:"unicode/1f690.png?v8",minidisc:"unicode/1f4bd.png?v8",mirror:"unicode/1fa9e.png?v8",mobile_phone_off:"unicode/1f4f4.png?v8",moldova:"unicode/1f1f2-1f1e9.png?v8",monaco:"unicode/1f1f2-1f1e8.png?v8",money_mouth_face:"unicode/1f911.png?v8",money_with_wings:"unicode/1f4b8.png?v8",moneybag:"unicode/1f4b0.png?v8",mongolia:"unicode/1f1f2-1f1f3.png?v8",monkey:"unicode/1f412.png?v8",monkey_face:"unicode/1f435.png?v8",monocle_face:"unicode/1f9d0.png?v8",monorail:"unicode/1f69d.png?v8",montenegro:"unicode/1f1f2-1f1ea.png?v8",montserrat:"unicode/1f1f2-1f1f8.png?v8",moon:"unicode/1f314.png?v8",moon_cake:"unicode/1f96e.png?v8",morocco:"unicode/1f1f2-1f1e6.png?v8",mortar_board:"unicode/1f393.png?v8",mosque:"unicode/1f54c.png?v8",mosquito:"unicode/1f99f.png?v8",motor_boat:"unicode/1f6e5.png?v8",motor_scooter:"unicode/1f6f5.png?v8",motorcycle:"unicode/1f3cd.png?v8",motorized_wheelchair:"unicode/1f9bc.png?v8",motorway:"unicode/1f6e3.png?v8",mount_fuji:"unicode/1f5fb.png?v8",mountain:"unicode/26f0.png?v8",mountain_bicyclist:"unicode/1f6b5.png?v8",mountain_biking_man:"unicode/1f6b5-2642.png?v8",mountain_biking_woman:"unicode/1f6b5-2640.png?v8",mountain_cableway:"unicode/1f6a0.png?v8",mountain_railway:"unicode/1f69e.png?v8",mountain_snow:"unicode/1f3d4.png?v8",mouse:"unicode/1f42d.png?v8",mouse2:"unicode/1f401.png?v8",mouse_trap:"unicode/1faa4.png?v8",movie_camera:"unicode/1f3a5.png?v8",moyai:"unicode/1f5ff.png?v8",mozambique:"unicode/1f1f2-1f1ff.png?v8",mrs_claus:"unicode/1f936.png?v8",muscle:"unicode/1f4aa.png?v8",mushroom:"unicode/1f344.png?v8",musical_keyboard:"unicode/1f3b9.png?v8",musical_note:"unicode/1f3b5.png?v8",musical_score:"unicode/1f3bc.png?v8",mute:"unicode/1f507.png?v8",mx_claus:"unicode/1f9d1-1f384.png?v8",myanmar:"unicode/1f1f2-1f1f2.png?v8",nail_care:"unicode/1f485.png?v8",name_badge:"unicode/1f4db.png?v8",namibia:"unicode/1f1f3-1f1e6.png?v8",national_park:"unicode/1f3de.png?v8",nauru:"unicode/1f1f3-1f1f7.png?v8",nauseated_face:"unicode/1f922.png?v8",nazar_amulet:"unicode/1f9ff.png?v8",neckbeard:"neckbeard.png?v8",necktie:"unicode/1f454.png?v8",negative_squared_cross_mark:"unicode/274e.png?v8",nepal:"unicode/1f1f3-1f1f5.png?v8",nerd_face:"unicode/1f913.png?v8",nesting_dolls:"unicode/1fa86.png?v8",netherlands:"unicode/1f1f3-1f1f1.png?v8",neutral_face:"unicode/1f610.png?v8",new:"unicode/1f195.png?v8",new_caledonia:"unicode/1f1f3-1f1e8.png?v8",new_moon:"unicode/1f311.png?v8",new_moon_with_face:"unicode/1f31a.png?v8",new_zealand:"unicode/1f1f3-1f1ff.png?v8",newspaper:"unicode/1f4f0.png?v8",newspaper_roll:"unicode/1f5de.png?v8",next_track_button:"unicode/23ed.png?v8",ng:"unicode/1f196.png?v8",ng_man:"unicode/1f645-2642.png?v8",ng_woman:"unicode/1f645-2640.png?v8",nicaragua:"unicode/1f1f3-1f1ee.png?v8",niger:"unicode/1f1f3-1f1ea.png?v8",nigeria:"unicode/1f1f3-1f1ec.png?v8",night_with_stars:"unicode/1f303.png?v8",nine:"unicode/0039-20e3.png?v8",ninja:"unicode/1f977.png?v8",niue:"unicode/1f1f3-1f1fa.png?v8",no_bell:"unicode/1f515.png?v8",no_bicycles:"unicode/1f6b3.png?v8",no_entry:"unicode/26d4.png?v8",no_entry_sign:"unicode/1f6ab.png?v8",no_good:"unicode/1f645.png?v8",no_good_man:"unicode/1f645-2642.png?v8",no_good_woman:"unicode/1f645-2640.png?v8",no_mobile_phones:"unicode/1f4f5.png?v8",no_mouth:"unicode/1f636.png?v8",no_pedestrians:"unicode/1f6b7.png?v8",no_smoking:"unicode/1f6ad.png?v8","non-potable_water":"unicode/1f6b1.png?v8",norfolk_island:"unicode/1f1f3-1f1eb.png?v8",north_korea:"unicode/1f1f0-1f1f5.png?v8",northern_mariana_islands:"unicode/1f1f2-1f1f5.png?v8",norway:"unicode/1f1f3-1f1f4.png?v8",nose:"unicode/1f443.png?v8",notebook:"unicode/1f4d3.png?v8",notebook_with_decorative_cover:"unicode/1f4d4.png?v8",notes:"unicode/1f3b6.png?v8",nut_and_bolt:"unicode/1f529.png?v8",o:"unicode/2b55.png?v8",o2:"unicode/1f17e.png?v8",ocean:"unicode/1f30a.png?v8",octocat:"octocat.png?v8",octopus:"unicode/1f419.png?v8",oden:"unicode/1f362.png?v8",office:"unicode/1f3e2.png?v8",office_worker:"unicode/1f9d1-1f4bc.png?v8",oil_drum:"unicode/1f6e2.png?v8",ok:"unicode/1f197.png?v8",ok_hand:"unicode/1f44c.png?v8",ok_man:"unicode/1f646-2642.png?v8",ok_person:"unicode/1f646.png?v8",ok_woman:"unicode/1f646-2640.png?v8",old_key:"unicode/1f5dd.png?v8",older_adult:"unicode/1f9d3.png?v8",older_man:"unicode/1f474.png?v8",older_woman:"unicode/1f475.png?v8",olive:"unicode/1fad2.png?v8",om:"unicode/1f549.png?v8",oman:"unicode/1f1f4-1f1f2.png?v8",on:"unicode/1f51b.png?v8",oncoming_automobile:"unicode/1f698.png?v8",oncoming_bus:"unicode/1f68d.png?v8",oncoming_police_car:"unicode/1f694.png?v8",oncoming_taxi:"unicode/1f696.png?v8",one:"unicode/0031-20e3.png?v8",one_piece_swimsuit:"unicode/1fa71.png?v8",onion:"unicode/1f9c5.png?v8",open_book:"unicode/1f4d6.png?v8",open_file_folder:"unicode/1f4c2.png?v8",open_hands:"unicode/1f450.png?v8",open_mouth:"unicode/1f62e.png?v8",open_umbrella:"unicode/2602.png?v8",ophiuchus:"unicode/26ce.png?v8",orange:"unicode/1f34a.png?v8",orange_book:"unicode/1f4d9.png?v8",orange_circle:"unicode/1f7e0.png?v8",orange_heart:"unicode/1f9e1.png?v8",orange_square:"unicode/1f7e7.png?v8",orangutan:"unicode/1f9a7.png?v8",orthodox_cross:"unicode/2626.png?v8",otter:"unicode/1f9a6.png?v8",outbox_tray:"unicode/1f4e4.png?v8",owl:"unicode/1f989.png?v8",ox:"unicode/1f402.png?v8",oyster:"unicode/1f9aa.png?v8",package:"unicode/1f4e6.png?v8",page_facing_up:"unicode/1f4c4.png?v8",page_with_curl:"unicode/1f4c3.png?v8",pager:"unicode/1f4df.png?v8",paintbrush:"unicode/1f58c.png?v8",pakistan:"unicode/1f1f5-1f1f0.png?v8",palau:"unicode/1f1f5-1f1fc.png?v8",palestinian_territories:"unicode/1f1f5-1f1f8.png?v8",palm_tree:"unicode/1f334.png?v8",palms_up_together:"unicode/1f932.png?v8",panama:"unicode/1f1f5-1f1e6.png?v8",pancakes:"unicode/1f95e.png?v8",panda_face:"unicode/1f43c.png?v8",paperclip:"unicode/1f4ce.png?v8",paperclips:"unicode/1f587.png?v8",papua_new_guinea:"unicode/1f1f5-1f1ec.png?v8",parachute:"unicode/1fa82.png?v8",paraguay:"unicode/1f1f5-1f1fe.png?v8",parasol_on_ground:"unicode/26f1.png?v8",parking:"unicode/1f17f.png?v8",parrot:"unicode/1f99c.png?v8",part_alternation_mark:"unicode/303d.png?v8",partly_sunny:"unicode/26c5.png?v8",partying_face:"unicode/1f973.png?v8",passenger_ship:"unicode/1f6f3.png?v8",passport_control:"unicode/1f6c2.png?v8",pause_button:"unicode/23f8.png?v8",paw_prints:"unicode/1f43e.png?v8",peace_symbol:"unicode/262e.png?v8",peach:"unicode/1f351.png?v8",peacock:"unicode/1f99a.png?v8",peanuts:"unicode/1f95c.png?v8",pear:"unicode/1f350.png?v8",pen:"unicode/1f58a.png?v8",pencil:"unicode/1f4dd.png?v8",pencil2:"unicode/270f.png?v8",penguin:"unicode/1f427.png?v8",pensive:"unicode/1f614.png?v8",people_holding_hands:"unicode/1f9d1-1f91d-1f9d1.png?v8",people_hugging:"unicode/1fac2.png?v8",performing_arts:"unicode/1f3ad.png?v8",persevere:"unicode/1f623.png?v8",person_bald:"unicode/1f9d1-1f9b2.png?v8",person_curly_hair:"unicode/1f9d1-1f9b1.png?v8",person_feeding_baby:"unicode/1f9d1-1f37c.png?v8",person_fencing:"unicode/1f93a.png?v8",person_in_manual_wheelchair:"unicode/1f9d1-1f9bd.png?v8",person_in_motorized_wheelchair:"unicode/1f9d1-1f9bc.png?v8",person_in_tuxedo:"unicode/1f935.png?v8",person_red_hair:"unicode/1f9d1-1f9b0.png?v8",person_white_hair:"unicode/1f9d1-1f9b3.png?v8",person_with_probing_cane:"unicode/1f9d1-1f9af.png?v8",person_with_turban:"unicode/1f473.png?v8",person_with_veil:"unicode/1f470.png?v8",peru:"unicode/1f1f5-1f1ea.png?v8",petri_dish:"unicode/1f9eb.png?v8",philippines:"unicode/1f1f5-1f1ed.png?v8",phone:"unicode/260e.png?v8",pick:"unicode/26cf.png?v8",pickup_truck:"unicode/1f6fb.png?v8",pie:"unicode/1f967.png?v8",pig:"unicode/1f437.png?v8",pig2:"unicode/1f416.png?v8",pig_nose:"unicode/1f43d.png?v8",pill:"unicode/1f48a.png?v8",pilot:"unicode/1f9d1-2708.png?v8",pinata:"unicode/1fa85.png?v8",pinched_fingers:"unicode/1f90c.png?v8",pinching_hand:"unicode/1f90f.png?v8",pineapple:"unicode/1f34d.png?v8",ping_pong:"unicode/1f3d3.png?v8",pirate_flag:"unicode/1f3f4-2620.png?v8",pisces:"unicode/2653.png?v8",pitcairn_islands:"unicode/1f1f5-1f1f3.png?v8",pizza:"unicode/1f355.png?v8",placard:"unicode/1faa7.png?v8",place_of_worship:"unicode/1f6d0.png?v8",plate_with_cutlery:"unicode/1f37d.png?v8",play_or_pause_button:"unicode/23ef.png?v8",pleading_face:"unicode/1f97a.png?v8",plunger:"unicode/1faa0.png?v8",point_down:"unicode/1f447.png?v8",point_left:"unicode/1f448.png?v8",point_right:"unicode/1f449.png?v8",point_up:"unicode/261d.png?v8",point_up_2:"unicode/1f446.png?v8",poland:"unicode/1f1f5-1f1f1.png?v8",polar_bear:"unicode/1f43b-2744.png?v8",police_car:"unicode/1f693.png?v8",police_officer:"unicode/1f46e.png?v8",policeman:"unicode/1f46e-2642.png?v8",policewoman:"unicode/1f46e-2640.png?v8",poodle:"unicode/1f429.png?v8",poop:"unicode/1f4a9.png?v8",popcorn:"unicode/1f37f.png?v8",portugal:"unicode/1f1f5-1f1f9.png?v8",post_office:"unicode/1f3e3.png?v8",postal_horn:"unicode/1f4ef.png?v8",postbox:"unicode/1f4ee.png?v8",potable_water:"unicode/1f6b0.png?v8",potato:"unicode/1f954.png?v8",potted_plant:"unicode/1fab4.png?v8",pouch:"unicode/1f45d.png?v8",poultry_leg:"unicode/1f357.png?v8",pound:"unicode/1f4b7.png?v8",pout:"unicode/1f621.png?v8",pouting_cat:"unicode/1f63e.png?v8",pouting_face:"unicode/1f64e.png?v8",pouting_man:"unicode/1f64e-2642.png?v8",pouting_woman:"unicode/1f64e-2640.png?v8",pray:"unicode/1f64f.png?v8",prayer_beads:"unicode/1f4ff.png?v8",pregnant_woman:"unicode/1f930.png?v8",pretzel:"unicode/1f968.png?v8",previous_track_button:"unicode/23ee.png?v8",prince:"unicode/1f934.png?v8",princess:"unicode/1f478.png?v8",printer:"unicode/1f5a8.png?v8",probing_cane:"unicode/1f9af.png?v8",puerto_rico:"unicode/1f1f5-1f1f7.png?v8",punch:"unicode/1f44a.png?v8",purple_circle:"unicode/1f7e3.png?v8",purple_heart:"unicode/1f49c.png?v8",purple_square:"unicode/1f7ea.png?v8",purse:"unicode/1f45b.png?v8",pushpin:"unicode/1f4cc.png?v8",put_litter_in_its_place:"unicode/1f6ae.png?v8",qatar:"unicode/1f1f6-1f1e6.png?v8",question:"unicode/2753.png?v8",rabbit:"unicode/1f430.png?v8",rabbit2:"unicode/1f407.png?v8",raccoon:"unicode/1f99d.png?v8",racehorse:"unicode/1f40e.png?v8",racing_car:"unicode/1f3ce.png?v8",radio:"unicode/1f4fb.png?v8",radio_button:"unicode/1f518.png?v8",radioactive:"unicode/2622.png?v8",rage:"unicode/1f621.png?v8",rage1:"rage1.png?v8",rage2:"rage2.png?v8",rage3:"rage3.png?v8",rage4:"rage4.png?v8",railway_car:"unicode/1f683.png?v8",railway_track:"unicode/1f6e4.png?v8",rainbow:"unicode/1f308.png?v8",rainbow_flag:"unicode/1f3f3-1f308.png?v8",raised_back_of_hand:"unicode/1f91a.png?v8",raised_eyebrow:"unicode/1f928.png?v8",raised_hand:"unicode/270b.png?v8",raised_hand_with_fingers_splayed:"unicode/1f590.png?v8",raised_hands:"unicode/1f64c.png?v8",raising_hand:"unicode/1f64b.png?v8",raising_hand_man:"unicode/1f64b-2642.png?v8",raising_hand_woman:"unicode/1f64b-2640.png?v8",ram:"unicode/1f40f.png?v8",ramen:"unicode/1f35c.png?v8",rat:"unicode/1f400.png?v8",razor:"unicode/1fa92.png?v8",receipt:"unicode/1f9fe.png?v8",record_button:"unicode/23fa.png?v8",recycle:"unicode/267b.png?v8",red_car:"unicode/1f697.png?v8",red_circle:"unicode/1f534.png?v8",red_envelope:"unicode/1f9e7.png?v8",red_haired_man:"unicode/1f468-1f9b0.png?v8",red_haired_woman:"unicode/1f469-1f9b0.png?v8",red_square:"unicode/1f7e5.png?v8",registered:"unicode/00ae.png?v8",relaxed:"unicode/263a.png?v8",relieved:"unicode/1f60c.png?v8",reminder_ribbon:"unicode/1f397.png?v8",repeat:"unicode/1f501.png?v8",repeat_one:"unicode/1f502.png?v8",rescue_worker_helmet:"unicode/26d1.png?v8",restroom:"unicode/1f6bb.png?v8",reunion:"unicode/1f1f7-1f1ea.png?v8",revolving_hearts:"unicode/1f49e.png?v8",rewind:"unicode/23ea.png?v8",rhinoceros:"unicode/1f98f.png?v8",ribbon:"unicode/1f380.png?v8",rice:"unicode/1f35a.png?v8",rice_ball:"unicode/1f359.png?v8",rice_cracker:"unicode/1f358.png?v8",rice_scene:"unicode/1f391.png?v8",right_anger_bubble:"unicode/1f5ef.png?v8",ring:"unicode/1f48d.png?v8",ringed_planet:"unicode/1fa90.png?v8",robot:"unicode/1f916.png?v8",rock:"unicode/1faa8.png?v8",rocket:"unicode/1f680.png?v8",rofl:"unicode/1f923.png?v8",roll_eyes:"unicode/1f644.png?v8",roll_of_paper:"unicode/1f9fb.png?v8",roller_coaster:"unicode/1f3a2.png?v8",roller_skate:"unicode/1f6fc.png?v8",romania:"unicode/1f1f7-1f1f4.png?v8",rooster:"unicode/1f413.png?v8",rose:"unicode/1f339.png?v8",rosette:"unicode/1f3f5.png?v8",rotating_light:"unicode/1f6a8.png?v8",round_pushpin:"unicode/1f4cd.png?v8",rowboat:"unicode/1f6a3.png?v8",rowing_man:"unicode/1f6a3-2642.png?v8",rowing_woman:"unicode/1f6a3-2640.png?v8",ru:"unicode/1f1f7-1f1fa.png?v8",rugby_football:"unicode/1f3c9.png?v8",runner:"unicode/1f3c3.png?v8",running:"unicode/1f3c3.png?v8",running_man:"unicode/1f3c3-2642.png?v8",running_shirt_with_sash:"unicode/1f3bd.png?v8",running_woman:"unicode/1f3c3-2640.png?v8",rwanda:"unicode/1f1f7-1f1fc.png?v8",sa:"unicode/1f202.png?v8",safety_pin:"unicode/1f9f7.png?v8",safety_vest:"unicode/1f9ba.png?v8",sagittarius:"unicode/2650.png?v8",sailboat:"unicode/26f5.png?v8",sake:"unicode/1f376.png?v8",salt:"unicode/1f9c2.png?v8",samoa:"unicode/1f1fc-1f1f8.png?v8",san_marino:"unicode/1f1f8-1f1f2.png?v8",sandal:"unicode/1f461.png?v8",sandwich:"unicode/1f96a.png?v8",santa:"unicode/1f385.png?v8",sao_tome_principe:"unicode/1f1f8-1f1f9.png?v8",sari:"unicode/1f97b.png?v8",sassy_man:"unicode/1f481-2642.png?v8",sassy_woman:"unicode/1f481-2640.png?v8",satellite:"unicode/1f4e1.png?v8",satisfied:"unicode/1f606.png?v8",saudi_arabia:"unicode/1f1f8-1f1e6.png?v8",sauna_man:"unicode/1f9d6-2642.png?v8",sauna_person:"unicode/1f9d6.png?v8",sauna_woman:"unicode/1f9d6-2640.png?v8",sauropod:"unicode/1f995.png?v8",saxophone:"unicode/1f3b7.png?v8",scarf:"unicode/1f9e3.png?v8",school:"unicode/1f3eb.png?v8",school_satchel:"unicode/1f392.png?v8",scientist:"unicode/1f9d1-1f52c.png?v8",scissors:"unicode/2702.png?v8",scorpion:"unicode/1f982.png?v8",scorpius:"unicode/264f.png?v8",scotland:"unicode/1f3f4-e0067-e0062-e0073-e0063-e0074-e007f.png?v8",scream:"unicode/1f631.png?v8",scream_cat:"unicode/1f640.png?v8",screwdriver:"unicode/1fa9b.png?v8",scroll:"unicode/1f4dc.png?v8",seal:"unicode/1f9ad.png?v8",seat:"unicode/1f4ba.png?v8",secret:"unicode/3299.png?v8",see_no_evil:"unicode/1f648.png?v8",seedling:"unicode/1f331.png?v8",selfie:"unicode/1f933.png?v8",senegal:"unicode/1f1f8-1f1f3.png?v8",serbia:"unicode/1f1f7-1f1f8.png?v8",service_dog:"unicode/1f415-1f9ba.png?v8",seven:"unicode/0037-20e3.png?v8",sewing_needle:"unicode/1faa1.png?v8",seychelles:"unicode/1f1f8-1f1e8.png?v8",shallow_pan_of_food:"unicode/1f958.png?v8",shamrock:"unicode/2618.png?v8",shark:"unicode/1f988.png?v8",shaved_ice:"unicode/1f367.png?v8",sheep:"unicode/1f411.png?v8",shell:"unicode/1f41a.png?v8",shield:"unicode/1f6e1.png?v8",shinto_shrine:"unicode/26e9.png?v8",ship:"unicode/1f6a2.png?v8",shipit:"shipit.png?v8",shirt:"unicode/1f455.png?v8",shit:"unicode/1f4a9.png?v8",shoe:"unicode/1f45e.png?v8",shopping:"unicode/1f6cd.png?v8",shopping_cart:"unicode/1f6d2.png?v8",shorts:"unicode/1fa73.png?v8",shower:"unicode/1f6bf.png?v8",shrimp:"unicode/1f990.png?v8",shrug:"unicode/1f937.png?v8",shushing_face:"unicode/1f92b.png?v8",sierra_leone:"unicode/1f1f8-1f1f1.png?v8",signal_strength:"unicode/1f4f6.png?v8",singapore:"unicode/1f1f8-1f1ec.png?v8",singer:"unicode/1f9d1-1f3a4.png?v8",sint_maarten:"unicode/1f1f8-1f1fd.png?v8",six:"unicode/0036-20e3.png?v8",six_pointed_star:"unicode/1f52f.png?v8",skateboard:"unicode/1f6f9.png?v8",ski:"unicode/1f3bf.png?v8",skier:"unicode/26f7.png?v8",skull:"unicode/1f480.png?v8",skull_and_crossbones:"unicode/2620.png?v8",skunk:"unicode/1f9a8.png?v8",sled:"unicode/1f6f7.png?v8",sleeping:"unicode/1f634.png?v8",sleeping_bed:"unicode/1f6cc.png?v8",sleepy:"unicode/1f62a.png?v8",slightly_frowning_face:"unicode/1f641.png?v8",slightly_smiling_face:"unicode/1f642.png?v8",slot_machine:"unicode/1f3b0.png?v8",sloth:"unicode/1f9a5.png?v8",slovakia:"unicode/1f1f8-1f1f0.png?v8",slovenia:"unicode/1f1f8-1f1ee.png?v8",small_airplane:"unicode/1f6e9.png?v8",small_blue_diamond:"unicode/1f539.png?v8",small_orange_diamond:"unicode/1f538.png?v8",small_red_triangle:"unicode/1f53a.png?v8",small_red_triangle_down:"unicode/1f53b.png?v8",smile:"unicode/1f604.png?v8",smile_cat:"unicode/1f638.png?v8",smiley:"unicode/1f603.png?v8",smiley_cat:"unicode/1f63a.png?v8",smiling_face_with_tear:"unicode/1f972.png?v8",smiling_face_with_three_hearts:"unicode/1f970.png?v8",smiling_imp:"unicode/1f608.png?v8",smirk:"unicode/1f60f.png?v8",smirk_cat:"unicode/1f63c.png?v8",smoking:"unicode/1f6ac.png?v8",snail:"unicode/1f40c.png?v8",snake:"unicode/1f40d.png?v8",sneezing_face:"unicode/1f927.png?v8",snowboarder:"unicode/1f3c2.png?v8",snowflake:"unicode/2744.png?v8",snowman:"unicode/26c4.png?v8",snowman_with_snow:"unicode/2603.png?v8",soap:"unicode/1f9fc.png?v8",sob:"unicode/1f62d.png?v8",soccer:"unicode/26bd.png?v8",socks:"unicode/1f9e6.png?v8",softball:"unicode/1f94e.png?v8",solomon_islands:"unicode/1f1f8-1f1e7.png?v8",somalia:"unicode/1f1f8-1f1f4.png?v8",soon:"unicode/1f51c.png?v8",sos:"unicode/1f198.png?v8",sound:"unicode/1f509.png?v8",south_africa:"unicode/1f1ff-1f1e6.png?v8",south_georgia_south_sandwich_islands:"unicode/1f1ec-1f1f8.png?v8",south_sudan:"unicode/1f1f8-1f1f8.png?v8",space_invader:"unicode/1f47e.png?v8",spades:"unicode/2660.png?v8",spaghetti:"unicode/1f35d.png?v8",sparkle:"unicode/2747.png?v8",sparkler:"unicode/1f387.png?v8",sparkles:"unicode/2728.png?v8",sparkling_heart:"unicode/1f496.png?v8",speak_no_evil:"unicode/1f64a.png?v8",speaker:"unicode/1f508.png?v8",speaking_head:"unicode/1f5e3.png?v8",speech_balloon:"unicode/1f4ac.png?v8",speedboat:"unicode/1f6a4.png?v8",spider:"unicode/1f577.png?v8",spider_web:"unicode/1f578.png?v8",spiral_calendar:"unicode/1f5d3.png?v8",spiral_notepad:"unicode/1f5d2.png?v8",sponge:"unicode/1f9fd.png?v8",spoon:"unicode/1f944.png?v8",squid:"unicode/1f991.png?v8",sri_lanka:"unicode/1f1f1-1f1f0.png?v8",st_barthelemy:"unicode/1f1e7-1f1f1.png?v8",st_helena:"unicode/1f1f8-1f1ed.png?v8",st_kitts_nevis:"unicode/1f1f0-1f1f3.png?v8",st_lucia:"unicode/1f1f1-1f1e8.png?v8",st_martin:"unicode/1f1f2-1f1eb.png?v8",st_pierre_miquelon:"unicode/1f1f5-1f1f2.png?v8",st_vincent_grenadines:"unicode/1f1fb-1f1e8.png?v8",stadium:"unicode/1f3df.png?v8",standing_man:"unicode/1f9cd-2642.png?v8",standing_person:"unicode/1f9cd.png?v8",standing_woman:"unicode/1f9cd-2640.png?v8",star:"unicode/2b50.png?v8",star2:"unicode/1f31f.png?v8",star_and_crescent:"unicode/262a.png?v8",star_of_david:"unicode/2721.png?v8",star_struck:"unicode/1f929.png?v8",stars:"unicode/1f320.png?v8",station:"unicode/1f689.png?v8",statue_of_liberty:"unicode/1f5fd.png?v8",steam_locomotive:"unicode/1f682.png?v8",stethoscope:"unicode/1fa7a.png?v8",stew:"unicode/1f372.png?v8",stop_button:"unicode/23f9.png?v8",stop_sign:"unicode/1f6d1.png?v8",stopwatch:"unicode/23f1.png?v8",straight_ruler:"unicode/1f4cf.png?v8",strawberry:"unicode/1f353.png?v8",stuck_out_tongue:"unicode/1f61b.png?v8",stuck_out_tongue_closed_eyes:"unicode/1f61d.png?v8",stuck_out_tongue_winking_eye:"unicode/1f61c.png?v8",student:"unicode/1f9d1-1f393.png?v8",studio_microphone:"unicode/1f399.png?v8",stuffed_flatbread:"unicode/1f959.png?v8",sudan:"unicode/1f1f8-1f1e9.png?v8",sun_behind_large_cloud:"unicode/1f325.png?v8",sun_behind_rain_cloud:"unicode/1f326.png?v8",sun_behind_small_cloud:"unicode/1f324.png?v8",sun_with_face:"unicode/1f31e.png?v8",sunflower:"unicode/1f33b.png?v8",sunglasses:"unicode/1f60e.png?v8",sunny:"unicode/2600.png?v8",sunrise:"unicode/1f305.png?v8",sunrise_over_mountains:"unicode/1f304.png?v8",superhero:"unicode/1f9b8.png?v8",superhero_man:"unicode/1f9b8-2642.png?v8",superhero_woman:"unicode/1f9b8-2640.png?v8",supervillain:"unicode/1f9b9.png?v8",supervillain_man:"unicode/1f9b9-2642.png?v8",supervillain_woman:"unicode/1f9b9-2640.png?v8",surfer:"unicode/1f3c4.png?v8",surfing_man:"unicode/1f3c4-2642.png?v8",surfing_woman:"unicode/1f3c4-2640.png?v8",suriname:"unicode/1f1f8-1f1f7.png?v8",sushi:"unicode/1f363.png?v8",suspect:"suspect.png?v8",suspension_railway:"unicode/1f69f.png?v8",svalbard_jan_mayen:"unicode/1f1f8-1f1ef.png?v8",swan:"unicode/1f9a2.png?v8",swaziland:"unicode/1f1f8-1f1ff.png?v8",sweat:"unicode/1f613.png?v8",sweat_drops:"unicode/1f4a6.png?v8",sweat_smile:"unicode/1f605.png?v8",sweden:"unicode/1f1f8-1f1ea.png?v8",sweet_potato:"unicode/1f360.png?v8",swim_brief:"unicode/1fa72.png?v8",swimmer:"unicode/1f3ca.png?v8",swimming_man:"unicode/1f3ca-2642.png?v8",swimming_woman:"unicode/1f3ca-2640.png?v8",switzerland:"unicode/1f1e8-1f1ed.png?v8",symbols:"unicode/1f523.png?v8",synagogue:"unicode/1f54d.png?v8",syria:"unicode/1f1f8-1f1fe.png?v8",syringe:"unicode/1f489.png?v8","t-rex":"unicode/1f996.png?v8",taco:"unicode/1f32e.png?v8",tada:"unicode/1f389.png?v8",taiwan:"unicode/1f1f9-1f1fc.png?v8",tajikistan:"unicode/1f1f9-1f1ef.png?v8",takeout_box:"unicode/1f961.png?v8",tamale:"unicode/1fad4.png?v8",tanabata_tree:"unicode/1f38b.png?v8",tangerine:"unicode/1f34a.png?v8",tanzania:"unicode/1f1f9-1f1ff.png?v8",taurus:"unicode/2649.png?v8",taxi:"unicode/1f695.png?v8",tea:"unicode/1f375.png?v8",teacher:"unicode/1f9d1-1f3eb.png?v8",teapot:"unicode/1fad6.png?v8",technologist:"unicode/1f9d1-1f4bb.png?v8",teddy_bear:"unicode/1f9f8.png?v8",telephone:"unicode/260e.png?v8",telephone_receiver:"unicode/1f4de.png?v8",telescope:"unicode/1f52d.png?v8",tennis:"unicode/1f3be.png?v8",tent:"unicode/26fa.png?v8",test_tube:"unicode/1f9ea.png?v8",thailand:"unicode/1f1f9-1f1ed.png?v8",thermometer:"unicode/1f321.png?v8",thinking:"unicode/1f914.png?v8",thong_sandal:"unicode/1fa74.png?v8",thought_balloon:"unicode/1f4ad.png?v8",thread:"unicode/1f9f5.png?v8",three:"unicode/0033-20e3.png?v8",thumbsdown:"unicode/1f44e.png?v8",thumbsup:"unicode/1f44d.png?v8",ticket:"unicode/1f3ab.png?v8",tickets:"unicode/1f39f.png?v8",tiger:"unicode/1f42f.png?v8",tiger2:"unicode/1f405.png?v8",timer_clock:"unicode/23f2.png?v8",timor_leste:"unicode/1f1f9-1f1f1.png?v8",tipping_hand_man:"unicode/1f481-2642.png?v8",tipping_hand_person:"unicode/1f481.png?v8",tipping_hand_woman:"unicode/1f481-2640.png?v8",tired_face:"unicode/1f62b.png?v8",tm:"unicode/2122.png?v8",togo:"unicode/1f1f9-1f1ec.png?v8",toilet:"unicode/1f6bd.png?v8",tokelau:"unicode/1f1f9-1f1f0.png?v8",tokyo_tower:"unicode/1f5fc.png?v8",tomato:"unicode/1f345.png?v8",tonga:"unicode/1f1f9-1f1f4.png?v8",tongue:"unicode/1f445.png?v8",toolbox:"unicode/1f9f0.png?v8",tooth:"unicode/1f9b7.png?v8",toothbrush:"unicode/1faa5.png?v8",top:"unicode/1f51d.png?v8",tophat:"unicode/1f3a9.png?v8",tornado:"unicode/1f32a.png?v8",tr:"unicode/1f1f9-1f1f7.png?v8",trackball:"unicode/1f5b2.png?v8",tractor:"unicode/1f69c.png?v8",traffic_light:"unicode/1f6a5.png?v8",train:"unicode/1f68b.png?v8",train2:"unicode/1f686.png?v8",tram:"unicode/1f68a.png?v8",transgender_flag:"unicode/1f3f3-26a7.png?v8",transgender_symbol:"unicode/26a7.png?v8",triangular_flag_on_post:"unicode/1f6a9.png?v8",triangular_ruler:"unicode/1f4d0.png?v8",trident:"unicode/1f531.png?v8",trinidad_tobago:"unicode/1f1f9-1f1f9.png?v8",tristan_da_cunha:"unicode/1f1f9-1f1e6.png?v8",triumph:"unicode/1f624.png?v8",trolleybus:"unicode/1f68e.png?v8",trollface:"trollface.png?v8",trophy:"unicode/1f3c6.png?v8",tropical_drink:"unicode/1f379.png?v8",tropical_fish:"unicode/1f420.png?v8",truck:"unicode/1f69a.png?v8",trumpet:"unicode/1f3ba.png?v8",tshirt:"unicode/1f455.png?v8",tulip:"unicode/1f337.png?v8",tumbler_glass:"unicode/1f943.png?v8",tunisia:"unicode/1f1f9-1f1f3.png?v8",turkey:"unicode/1f983.png?v8",turkmenistan:"unicode/1f1f9-1f1f2.png?v8",turks_caicos_islands:"unicode/1f1f9-1f1e8.png?v8",turtle:"unicode/1f422.png?v8",tuvalu:"unicode/1f1f9-1f1fb.png?v8",tv:"unicode/1f4fa.png?v8",twisted_rightwards_arrows:"unicode/1f500.png?v8",two:"unicode/0032-20e3.png?v8",two_hearts:"unicode/1f495.png?v8",two_men_holding_hands:"unicode/1f46c.png?v8",two_women_holding_hands:"unicode/1f46d.png?v8",u5272:"unicode/1f239.png?v8",u5408:"unicode/1f234.png?v8",u55b6:"unicode/1f23a.png?v8",u6307:"unicode/1f22f.png?v8",u6708:"unicode/1f237.png?v8",u6709:"unicode/1f236.png?v8",u6e80:"unicode/1f235.png?v8",u7121:"unicode/1f21a.png?v8",u7533:"unicode/1f238.png?v8",u7981:"unicode/1f232.png?v8",u7a7a:"unicode/1f233.png?v8",uganda:"unicode/1f1fa-1f1ec.png?v8",uk:"unicode/1f1ec-1f1e7.png?v8",ukraine:"unicode/1f1fa-1f1e6.png?v8",umbrella:"unicode/2614.png?v8",unamused:"unicode/1f612.png?v8",underage:"unicode/1f51e.png?v8",unicorn:"unicode/1f984.png?v8",united_arab_emirates:"unicode/1f1e6-1f1ea.png?v8",united_nations:"unicode/1f1fa-1f1f3.png?v8",unlock:"unicode/1f513.png?v8",up:"unicode/1f199.png?v8",upside_down_face:"unicode/1f643.png?v8",uruguay:"unicode/1f1fa-1f1fe.png?v8",us:"unicode/1f1fa-1f1f8.png?v8",us_outlying_islands:"unicode/1f1fa-1f1f2.png?v8",us_virgin_islands:"unicode/1f1fb-1f1ee.png?v8",uzbekistan:"unicode/1f1fa-1f1ff.png?v8",v:"unicode/270c.png?v8",vampire:"unicode/1f9db.png?v8",vampire_man:"unicode/1f9db-2642.png?v8",vampire_woman:"unicode/1f9db-2640.png?v8",vanuatu:"unicode/1f1fb-1f1fa.png?v8",vatican_city:"unicode/1f1fb-1f1e6.png?v8",venezuela:"unicode/1f1fb-1f1ea.png?v8",vertical_traffic_light:"unicode/1f6a6.png?v8",vhs:"unicode/1f4fc.png?v8",vibration_mode:"unicode/1f4f3.png?v8",video_camera:"unicode/1f4f9.png?v8",video_game:"unicode/1f3ae.png?v8",vietnam:"unicode/1f1fb-1f1f3.png?v8",violin:"unicode/1f3bb.png?v8",virgo:"unicode/264d.png?v8",volcano:"unicode/1f30b.png?v8",volleyball:"unicode/1f3d0.png?v8",vomiting_face:"unicode/1f92e.png?v8",vs:"unicode/1f19a.png?v8",vulcan_salute:"unicode/1f596.png?v8",waffle:"unicode/1f9c7.png?v8",wales:"unicode/1f3f4-e0067-e0062-e0077-e006c-e0073-e007f.png?v8",walking:"unicode/1f6b6.png?v8",walking_man:"unicode/1f6b6-2642.png?v8",walking_woman:"unicode/1f6b6-2640.png?v8",wallis_futuna:"unicode/1f1fc-1f1eb.png?v8",waning_crescent_moon:"unicode/1f318.png?v8",waning_gibbous_moon:"unicode/1f316.png?v8",warning:"unicode/26a0.png?v8",wastebasket:"unicode/1f5d1.png?v8",watch:"unicode/231a.png?v8",water_buffalo:"unicode/1f403.png?v8",water_polo:"unicode/1f93d.png?v8",watermelon:"unicode/1f349.png?v8",wave:"unicode/1f44b.png?v8",wavy_dash:"unicode/3030.png?v8",waxing_crescent_moon:"unicode/1f312.png?v8",waxing_gibbous_moon:"unicode/1f314.png?v8",wc:"unicode/1f6be.png?v8",weary:"unicode/1f629.png?v8",wedding:"unicode/1f492.png?v8",weight_lifting:"unicode/1f3cb.png?v8",weight_lifting_man:"unicode/1f3cb-2642.png?v8",weight_lifting_woman:"unicode/1f3cb-2640.png?v8",western_sahara:"unicode/1f1ea-1f1ed.png?v8",whale:"unicode/1f433.png?v8",whale2:"unicode/1f40b.png?v8",wheel_of_dharma:"unicode/2638.png?v8",wheelchair:"unicode/267f.png?v8",white_check_mark:"unicode/2705.png?v8",white_circle:"unicode/26aa.png?v8",white_flag:"unicode/1f3f3.png?v8",white_flower:"unicode/1f4ae.png?v8",white_haired_man:"unicode/1f468-1f9b3.png?v8",white_haired_woman:"unicode/1f469-1f9b3.png?v8",white_heart:"unicode/1f90d.png?v8",white_large_square:"unicode/2b1c.png?v8",white_medium_small_square:"unicode/25fd.png?v8",white_medium_square:"unicode/25fb.png?v8",white_small_square:"unicode/25ab.png?v8",white_square_button:"unicode/1f533.png?v8",wilted_flower:"unicode/1f940.png?v8",wind_chime:"unicode/1f390.png?v8",wind_face:"unicode/1f32c.png?v8",window:"unicode/1fa9f.png?v8",wine_glass:"unicode/1f377.png?v8",wink:"unicode/1f609.png?v8",wolf:"unicode/1f43a.png?v8",woman:"unicode/1f469.png?v8",woman_artist:"unicode/1f469-1f3a8.png?v8",woman_astronaut:"unicode/1f469-1f680.png?v8",woman_beard:"unicode/1f9d4-2640.png?v8",woman_cartwheeling:"unicode/1f938-2640.png?v8",woman_cook:"unicode/1f469-1f373.png?v8",woman_dancing:"unicode/1f483.png?v8",woman_facepalming:"unicode/1f926-2640.png?v8",woman_factory_worker:"unicode/1f469-1f3ed.png?v8",woman_farmer:"unicode/1f469-1f33e.png?v8",woman_feeding_baby:"unicode/1f469-1f37c.png?v8",woman_firefighter:"unicode/1f469-1f692.png?v8",woman_health_worker:"unicode/1f469-2695.png?v8",woman_in_manual_wheelchair:"unicode/1f469-1f9bd.png?v8",woman_in_motorized_wheelchair:"unicode/1f469-1f9bc.png?v8",woman_in_tuxedo:"unicode/1f935-2640.png?v8",woman_judge:"unicode/1f469-2696.png?v8",woman_juggling:"unicode/1f939-2640.png?v8",woman_mechanic:"unicode/1f469-1f527.png?v8",woman_office_worker:"unicode/1f469-1f4bc.png?v8",woman_pilot:"unicode/1f469-2708.png?v8",woman_playing_handball:"unicode/1f93e-2640.png?v8",woman_playing_water_polo:"unicode/1f93d-2640.png?v8",woman_scientist:"unicode/1f469-1f52c.png?v8",woman_shrugging:"unicode/1f937-2640.png?v8",woman_singer:"unicode/1f469-1f3a4.png?v8",woman_student:"unicode/1f469-1f393.png?v8",woman_teacher:"unicode/1f469-1f3eb.png?v8",woman_technologist:"unicode/1f469-1f4bb.png?v8",woman_with_headscarf:"unicode/1f9d5.png?v8",woman_with_probing_cane:"unicode/1f469-1f9af.png?v8",woman_with_turban:"unicode/1f473-2640.png?v8",woman_with_veil:"unicode/1f470-2640.png?v8",womans_clothes:"unicode/1f45a.png?v8",womans_hat:"unicode/1f452.png?v8",women_wrestling:"unicode/1f93c-2640.png?v8",womens:"unicode/1f6ba.png?v8",wood:"unicode/1fab5.png?v8",woozy_face:"unicode/1f974.png?v8",world_map:"unicode/1f5fa.png?v8",worm:"unicode/1fab1.png?v8",worried:"unicode/1f61f.png?v8",wrench:"unicode/1f527.png?v8",wrestling:"unicode/1f93c.png?v8",writing_hand:"unicode/270d.png?v8",x:"unicode/274c.png?v8",yarn:"unicode/1f9f6.png?v8",yawning_face:"unicode/1f971.png?v8",yellow_circle:"unicode/1f7e1.png?v8",yellow_heart:"unicode/1f49b.png?v8",yellow_square:"unicode/1f7e8.png?v8",yemen:"unicode/1f1fe-1f1ea.png?v8",yen:"unicode/1f4b4.png?v8",yin_yang:"unicode/262f.png?v8",yo_yo:"unicode/1fa80.png?v8",yum:"unicode/1f60b.png?v8",zambia:"unicode/1f1ff-1f1f2.png?v8",zany_face:"unicode/1f92a.png?v8",zap:"unicode/26a1.png?v8",zebra:"unicode/1f993.png?v8",zero:"unicode/0030-20e3.png?v8",zimbabwe:"unicode/1f1ff-1f1fc.png?v8",zipper_mouth_face:"unicode/1f910.png?v8",zombie:"unicode/1f9df.png?v8",zombie_man:"unicode/1f9df-2642.png?v8",zombie_woman:"unicode/1f9df-2640.png?v8",zzz:"unicode/1f4a4.png?v8"}};function jn(e,t){return e.replace(/<(code|pre|script|template)[^>]*?>[\s\S]+?<\/(code|pre|script|template)>/g,function(e){return e.replace(/:/g,"__colon__")}).replace(//g,function(e){return e.replace(/:/g,"__colon__")}).replace(/([a-z]{2,}:)?\/\/[^\s'">)]+/gi,function(e){return e.replace(/:/g,"__colon__")}).replace(/:([a-z0-9_\-+]+?):/g,function(e,n){return i=e,o=n,e=t,n=Cn.data[o],i,i=n?e&&/unicode/.test(n)?''+n.replace("unicode/","").replace(/\.png.*/,"").split("-").map(function(e){return"&#x"+e+";"}).join("‍").concat("︎")+"":''+o+'':i;var i,o}).replace(/__colon__/g,":")}function Ln(e){var o={};return{str:e=(e=void 0===e?"":e)&&e.replace(/^('|")/,"").replace(/('|")$/,"").replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g,function(e,n,i){return-1===n.indexOf(":")?(o[n]=i&&i.replace(/"/g,"")||!0,""):e}).trim(),config:o}}function On(e){return(e=void 0===e?"":e).replace(/(<\/?a.*?>)/gi,"")}var qn,Pn=be(function(e){var u,f,p,d,n,g=function(u){var i=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,e={},R={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof T?new T(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=r.reach);m+=_.value.length,_=_.next){var b=_.value;if(i.length>n.length)return;if(!(b instanceof T)){var k,w=1;if(l){if(!(k=C(h,m,n,s))||k.index>=n.length)break;var y=k.index,x=k.index+k[0].length,S=m;for(S+=_.value.length;S<=y;)_=_.next,S+=_.value.length;if(S-=_.value.length,m=S,_.value instanceof T)continue;for(var A=_;A!==i.tail&&(Sr.reach&&(r.reach=E);b=_.prev;z&&(b=j(i,b,z),m+=z.length),L(i,b,w);$=new T(c,g?R.tokenize($,g):$,v,$);_=j(i,b,$),F&&j(i,_,F),1r.reach&&(r.reach=E.reach))}}}}}(e,t,n,t.head,0),function(e){var n=[],i=e.head.next;for(;i!==e.tail;)n.push(i.value),i=i.next;return n}(t)},hooks:{all:{},add:function(e,n){var i=R.hooks.all;i[e]=i[e]||[],i[e].push(n)},run:function(e,n){var i=R.hooks.all[e];if(i&&i.length)for(var o,t=0;o=i[t++];)o(n)}},Token:T};function T(e,n,i,o){this.type=e,this.content=n,this.alias=i,this.length=0|(o||"").length}function C(e,n,i,o){e.lastIndex=n;i=e.exec(i);return i&&o&&i[1]&&(o=i[1].length,i.index+=o,i[0]=i[0].slice(o)),i}function a(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function j(e,n,i){var o=n.next,i={value:i,prev:n,next:o};return n.next=i,o.prev=i,e.length++,i}function L(e,n,i){for(var o=n.next,t=0;t"+t.content+""},!u.document)return u.addEventListener&&(R.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),i=n.language,e=n.code,n=n.immediateClose;u.postMessage(R.highlight(e,R.languages[i],i)),n&&u.close()},!1)),R;var o=R.util.currentScript();function t(){R.manual||R.highlightAll()}return o&&(R.filename=o.src,o.hasAttribute("data-manual")&&(R.manual=!0)),R.manual||("loading"===(e=document.readyState)||"interactive"===e&&o&&o.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)),R}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});e.exports&&(e.exports=g),void 0!==me&&(me.Prism=g),g.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},g.languages.markup.tag.inside["attr-value"].inside.entity=g.languages.markup.entity,g.languages.markup.doctype.inside["internal-subset"].inside=g.languages.markup,g.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(g.languages.markup.tag,"addInlined",{value:function(e,n){var i={};i["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:g.languages[n]},i.cdata=/^$/i;i={"included-cdata":{pattern://i,inside:i}};i["language-"+n]={pattern:/[\s\S]+/,inside:g.languages[n]};n={};n[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:i},g.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(g.languages.markup.tag,"addAttribute",{value:function(e,n){g.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:g.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),g.languages.html=g.languages.markup,g.languages.mathml=g.languages.markup,g.languages.svg=g.languages.markup,g.languages.xml=g.languages.extend("markup",{}),g.languages.ssml=g.languages.xml,g.languages.atom=g.languages.xml,g.languages.rss=g.languages.xml,function(e){var n=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+n.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+n.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+n.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+n.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:n,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;e=e.languages.markup;e&&(e.tag.addInlined("style","css"),e.tag.addAttribute("style","css"))}(g),g.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},g.languages.javascript=g.languages.extend("clike",{"class-name":[g.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),g.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,g.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:g.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:g.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:g.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:g.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:g.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),g.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:g.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),g.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),g.languages.markup&&(g.languages.markup.tag.addInlined("script","javascript"),g.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),g.languages.js=g.languages.javascript,void 0!==g&&"undefined"!=typeof document&&(Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),u={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"},d="pre[data-src]:not(["+(f="data-src-status")+'="loaded"]):not(['+f+'="'+(p="loading")+'"])',g.hooks.add("before-highlightall",function(e){e.selector+=", "+d}),g.hooks.add("before-sanity-check",function(e){var t,n,i,o,a,r,c=e.element;c.matches(d)&&(e.code="",c.setAttribute(f,p),(t=c.appendChild(document.createElement("CODE"))).textContent="Loading…",i=c.getAttribute("data-src"),"none"===(e=e.language)&&(n=(/\.(\w+)$/.exec(i)||[,"none"])[1],e=u[n]||n),g.util.setLanguage(t,e),g.util.setLanguage(c,e),(n=g.plugins.autoloader)&&n.loadLanguages(e),i=i,o=function(e){c.setAttribute(f,"loaded");var n,i,o=function(e){if(i=/^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(e||"")){var n=Number(i[1]),e=i[2],i=i[3];return e?i?[n,Number(i)]:[n,void 0]:[n,n]}}(c.getAttribute("data-range"));o&&(n=e.split(/\r\n?|\n/g),i=o[0],o=null==o[1]?n.length:o[1],i<0&&(i+=n.length),i=Math.max(0,Math.min(i-1,n.length)),o<0&&(o+=n.length),o=Math.max(0,Math.min(o,n.length)),e=n.slice(i,o).join("\n"),c.hasAttribute("data-start")||c.setAttribute("data-start",String(i+1))),t.textContent=e,g.highlightElement(t)},a=function(e){c.setAttribute(f,"failed"),t.textContent=e},(r=new XMLHttpRequest).open("GET",i,!0),r.onreadystatechange=function(){4==r.readyState&&(r.status<400&&r.responseText?o(r.responseText):400<=r.status?a("✖ Error "+r.status+" while fetching file: "+r.statusText):a("✖ Error: File does not exist or is empty"))},r.send(null))}),n=!(g.plugins.fileHighlight={highlight:function(e){for(var n,i=(e||document).querySelectorAll(d),o=0;n=i[o++];)g.highlightElement(n)}}),g.fileHighlight=function(){n||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),n=!0),g.plugins.fileHighlight.highlight.apply(this,arguments)})});function Mn(e,n){return"___"+e.toUpperCase()+n+"___"}qn=Prism,Object.defineProperties(qn.languages["markup-templating"]={},{buildPlaceholders:{value:function(o,t,e,a){var r;o.language===t&&(r=o.tokenStack=[],o.code=o.code.replace(e,function(e){if("function"==typeof a&&!a(e))return e;for(var n,i=r.length;-1!==o.code.indexOf(n=Mn(t,i));)++i;return r[i]=e,n}),o.grammar=qn.languages.markup)}},tokenizePlaceholders:{value:function(f,p){var d,g;f.language===p&&f.tokenStack&&(f.grammar=qn.languages[p],d=0,g=Object.keys(f.tokenStack),function e(n){for(var i=0;i=g.length);i++){var o,t,a,r,c,u=n[i];"string"==typeof u||u.content&&"string"==typeof u.content?(t=g[d],a=f.tokenStack[t],o="string"==typeof u?u:u.content,c=Mn(p,t),-1<(r=o.indexOf(c))&&(++d,t=o.substring(0,r),a=new qn.Token(p,qn.tokenize(a,f.grammar),"language-"+p,a),r=o.substring(r+c.length),c=[],t&&c.push.apply(c,e([t])),c.push(a),r&&c.push.apply(c,e([r])),"string"==typeof u?n.splice.apply(n,[i,1].concat(c)):u.content=c)):u.content&&e(u.content)}return n}(f.tokens))}}});function In(t,e){var a=this;this.config=t,this.router=e,this.cacheTree={},this.toc=[],this.cacheTOC={},this.linkTarget=t.externalLinkTarget||"_blank",this.linkRel="_blank"===this.linkTarget?t.externalLinkRel||"noopener":"",this.contentBase=e.getBasePath();var n=this._initRenderer();this.heading=n.heading;var r=o(e=t.markdown||{})?e(Sn,n):(Sn.setOptions(m(e,{renderer:m(n,e.renderer)})),Sn);this._marked=r,this.compile=function(i){var o=!0,e=c(function(e){o=!1;var n="";return i&&(n=f(i)?r(i):r.parser(i),n=t.noEmoji?n:jn(n,t.nativeEmoji),Tn.clear(),n)})(i),n=a.router.parse().file;return o?a.toc=a.cacheTOC[n]:a.cacheTOC[n]=[].concat(a.toc),e}}var Nn={},Hn={markdown:function(e){return{url:e}},mermaid:function(e){return{url:e}},iframe:function(e,n){return{html:'"}},video:function(e,n){return{html:'"}},audio:function(e,n){return{html:'"}},code:function(e,n){var i=e.match(/\.(\w+)$/);return{url:e,lang:i="md"===(i=n||i&&i[1])?"markdown":i}}};In.prototype.compileEmbed=function(e,n){var i,o,t=Ln(n),a=t.str,t=t.config;if(n=a,t.include)return R(e)||(e=q(this.contentBase,C(this.router.getCurrentPath()),e)),t.type&&(o=Hn[t.type])?(i=o.call(this,e,n)).type=t.type:(o="code",/\.(md|markdown)/.test(e)?o="markdown":/\.mmd/.test(e)?o="mermaid":/\.html?/.test(e)?o="iframe":/\.(mp4|ogg)/.test(e)?o="video":/\.mp3/.test(e)&&(o="audio"),(i=Hn[o].call(this,e,n)).type=o),i.fragment=t.fragment,i},In.prototype._matchNotCompileLink=function(e){for(var n=this.config.noCompileLinks||[],i=0;i/g.test(o)&&(o=o.replace("\x3c!-- {docsify-ignore} --\x3e",""),e.title=On(o),e.ignoreSubHeading=!0),/{docsify-ignore}/g.test(o)&&(o=o.replace("{docsify-ignore}",""),e.title=On(o),e.ignoreSubHeading=!0),//g.test(o)&&(o=o.replace("\x3c!-- {docsify-ignore-all} --\x3e",""),e.title=On(o),e.ignoreAllSubs=!0),/{docsify-ignore-all}/g.test(o)&&(o=o.replace("{docsify-ignore-all}",""),e.title=On(o),e.ignoreAllSubs=!0);i=Tn(t.id||o),t=a.toURL(a.getCurrentPath(),{id:i});return e.slug=t,g.toc.push(e),"'+o+""},t.code={renderer:e}.renderer.code=function(e,n){var i=Pn.languages[n=void 0===n?"markup":n]||Pn.languages.markup;return'
    '+Pn.highlight(e.replace(/@DOCSIFY_QM@/g,"`"),i,n)+"
    "},t.link=(i=(n={renderer:e,router:a,linkTarget:n,linkRel:i,compilerClass:g}).renderer,c=n.router,u=n.linkTarget,n.linkRel,f=n.compilerClass,i.link=function(e,n,i){var o=[],t=Ln(n=void 0===n?"":n),a=t.str,t=t.config;return u=t.target||u,r="_blank"===u?f.config.externalLinkRel||"noopener":"",n=a,R(e)||f._matchNotCompileLink(e)||t.ignore?(R(e)||"./"!==e.slice(0,2)||(e=document.URL.replace(/\/(?!.*\/).*/,"/").replace("#/./","")+e),o.push(0===e.indexOf("mailto:")?"":'target="'+u+'"'),o.push(0!==e.indexOf("mailto:")&&""!==r?' rel="'+r+'"':"")):(e===f.config.homepage&&(e="README"),e=c.toURL(e,null,c.getCurrentPath())),t.disabled&&(o.push("disabled"),e="javascript:void(0)"),t.class&&o.push('class="'+t.class+'"'),t.id&&o.push('id="'+t.id+'"'),n&&o.push('title="'+n+'"'),'"+i+""}),t.paragraph={renderer:e}.renderer.paragraph=function(e){e=/^!>/.test(e)?$n("tip",e):/^\?>/.test(e)?$n("warn",e):"

    "+e+"

    ";return e},t.image=(o=(i={renderer:e,contentBase:o,router:a}).renderer,p=i.contentBase,d=i.router,o.image=function(e,n,i){var o=e,t=[],a=Ln(n),r=a.str,a=a.config;return n=r,a["no-zoom"]&&t.push("data-no-zoom"),n&&t.push('title="'+n+'"'),a.size&&(n=(r=a.size.split("x"))[0],(r=r[1])?t.push('width="'+n+'" height="'+r+'"'):t.push('width="'+n+'"')),a.class&&t.push('class="'+a.class+'"'),a.id&&t.push('id="'+a.id+'"'),R(e)||(o=q(p,C(d.getCurrentPath()),e)),0":''+i+'"}),t.list={renderer:e}.renderer.list=function(e,n,i){n=n?"ol":"ul";return"<"+n+" "+[/
  • /.test(e.split('class="task-list"')[0])?'class="task-list"':"",i&&1"+e+""},t.listitem={renderer:e}.renderer.listitem=function(e){return/^(]*>)/.test(e)?'
  • ":"
  • "+e+"
  • "},e.origin=t,e},In.prototype.sidebar=function(e,n){var i=this.toc,o=this.router.getCurrentPath(),t="";if(e)t=this.compile(e);else{for(var a=0;a{inner}");this.cacheTree[o]=n}return t},In.prototype.subSidebar=function(e){if(e){var n=this.router.getCurrentPath(),i=this.cacheTree,o=this.toc;o[0]&&o[0].ignoreAllSubs&&o.splice(0),o[0]&&1===o[0].level&&o.shift();for(var t=0;t\n'+e+"\n"}]).links={}:(n=[{type:"html",text:e}]).links={}),a({token:t,embedToken:n}),++u>=c&&a({})}}(n);n.embed.url?X(n.embed.url).then(o):o(n.embed.html)}}({compile:i,embedTokens:c,fetch:n},function(e){var n,i=e.embedToken,e=e.token;e?(n=e.index,p.forEach(function(e){n>e.start&&(n+=e.length)}),m(f,i.links),r=r.slice(0,n).concat(i,r.slice(n+1)),p.push({start:n,length:i.length-1})):(Bn[t]=r.concat(),r.links=Bn[t].links=f,o(r))})}function Yn(e,n,i){var o,t,a,r;return n="function"==typeof i?i(n):"string"==typeof i?(a=[],r=0,(o=i).replace(V,function(n,e,i){a.push(o.substring(r,i-1)),r=i+=n.length+1,a.push(t&&t[n]||function(e){return("00"+("string"==typeof Y[n]?e[Y[n]]():Y[n](e))).slice(-n.length)})}),r!==o.length&&a.push(o.substring(r)),function(e){for(var n="",i=0,o=e||new Date;i404 - Not found","Vue"in window)for(var a=0,r=k(".markdown-section > *").filter(n);ascript").filter(function(e){return!/template/.test(e.type)})[0])||(e=e.innerText.trim())&&new Function(e)()),"Vue"in window){var u,f,p=[],d=Object.keys(i.vueComponents||{});2===t&&d.length&&d.forEach(function(e){window.Vue.options.components[e]||window.Vue.component(e,i.vueComponents[e])}),!Un&&i.vueGlobalOptions&&"function"==typeof i.vueGlobalOptions.data&&(Un=i.vueGlobalOptions.data()),p.push.apply(p,Object.keys(i.vueMounts||{}).map(function(e){return[b(o,e),i.vueMounts[e]]}).filter(function(e){var n=e[0];e[1];return n})),(i.vueGlobalOptions||d.length)&&(u=/{{2}[^{}]*}{2}/,f=/<[^>/]+\s([@:]|v-)[\w-:.[\]]+[=>\s]/,p.push.apply(p,k(".markdown-section > *").filter(function(i){return!p.some(function(e){var n=e[0];e[1];return n===i})}).filter(function(e){return e.tagName.toLowerCase()in(i.vueComponents||{})||e.querySelector(d.join(",")||null)||u.test(e.outerHTML)||f.test(e.outerHTML)}).map(function(e){var n=m({},i.vueGlobalOptions||{});return Un&&(n.data=function(){return Un}),[e,n]})));for(var g=0,s=p;g([^<]*?)

    $'))&&("color"===n[2]?o.style.background=n[1]+(n[3]||""):(e=n[1],S(o,"add","has-mask"),R(n[1])||(e=q(this.router.getBasePath(),n[1])),o.style.backgroundImage="url("+e+")",o.style.backgroundSize="cover",o.style.backgroundPosition="center center"),i=i.replace(n[0],"")),this._renderTo(".cover-main",i),K()):S(o,"remove","show")},n.prototype._updateRender=function(){var e,n,i,o;e=this,n=l(".app-name-link"),i=e.config.nameLink,o=e.route.path,n&&(f(e.config.nameLink)?n.setAttribute("href",i):"object"==typeof i&&(e=Object.keys(i).filter(function(e){return-1':"")),e.coverpage&&(f+=(o=", 100%, 85%",'
    \x3c!--cover--\x3e
    ')),e.logo&&(o=/^data:image/.test(e.logo),n=/(?:http[s]?:)?\/\//.test(e.logo),i=/^\./.test(e.logo),o||n||i||(e.logo=q(this.router.getBasePath(),e.logo))),f+=(i=(n=e).name||"","
    "+('')+'
    \x3c!--main--\x3e
    '),this._renderTo(u,f,!0)):this.rendered=!0,e.mergeNavbar&&s?p=b(".sidebar"):(c.classList.add("app-nav"),e.repo||c.classList.add("no-badge")),e.loadNavbar&&y(p,c),e.themeColor&&(v.head.appendChild(w("div","").firstElementChild),a=e.themeColor,window.CSS&&window.CSS.supports&&window.CSS.supports("(--v:red)")||(e=k("style:not(.inserted),link"),[].forEach.call(e,function(e){"STYLE"===e.nodeName?Q(e,a):"LINK"===e.nodeName&&(e=e.getAttribute("href"),/\.css$/.test(e)&&X(e).then(function(e){e=w("style",e);_.appendChild(e),Q(e,a)}))}))),this._updateRender(),S(h,"ready")},n}(function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),((n.prototype=Object.create(e&&e.prototype)).constructor=n).prototype.routes=function(){return this.config.routes||{}},n.prototype.matchVirtualRoute=function(t){var a=this.routes(),r=Object.keys(a),c=function(){return null};function u(){var e=r.shift();if(!e)return c(null);var n=A(o=(i="^",0===(o=e).indexOf(i)?o:"^"+o),"$")?o:o+"$",i=t.match(n);if(!i)return u();var o=a[e];if("string"==typeof o)return c(o);if("function"!=typeof o)return u();n=o,e=Xn(),o=e[0];return(0,e[1])(function(e){return"string"==typeof e?c(e):!1===e?c(null):u()}),n.length<=2?o(n(t,i)):n(t,i,o)}return{then:function(e){c=e,u()}}},n}(function(i){function e(){for(var e=[],n=arguments.length;n--;)e[n]=arguments[n];i.apply(this,e),this.route={}}return i&&(e.__proto__=i),((e.prototype=Object.create(i&&i.prototype)).constructor=e).prototype.updateRender=function(){this.router.normalize(),this.route=this.router.parse(),h.setAttribute("data-page",this.route.file)},e.prototype.initRouter=function(){var n=this,e=this.config,e=new("history"===(e.routerMode||"hash")&&t?D:H)(e);this.router=e,this.updateRender(),U=this.route,e.onchange(function(e){n.updateRender(),n._updateRender(),U.path!==n.route.path?(n.$fetch(d,n.$resetEvents.bind(n,e.source)),U=n.route):n.$resetEvents(e.source)})},e}(function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),((n.prototype=Object.create(e&&e.prototype)).constructor=n).prototype.initLifecycle=function(){var i=this;this._hooks={},this._lifecycle={},["init","mounted","beforeEach","afterEach","doneEach","ready"].forEach(function(e){var n=i._hooks[e]=[];i._lifecycle[e]=function(e){return n.push(e)}})},n.prototype.callHook=function(e,t,a){void 0===a&&(a=d);var r=this._hooks[e],c=this.config.catchPluginErrors,u=function(n){var e=r[n];if(n>=r.length)a(t);else if("function"==typeof e){var i="Docsify plugin error";if(2===e.length)try{e(t,function(e){t=e,u(n+1)})}catch(e){if(!c)throw e;console.error(i,e),u(n+1)}else try{var o=e(t);t=void 0===o?t:o,u(n+1)}catch(e){if(!c)throw e;console.error(i,e),u(n+1)}}else u(n+1)};u(0)},n}(we))))))));function Kn(e,n,i){return Qn&&Qn.abort&&Qn.abort(),Qn=X(e,!0,i)}window.Docsify={util:Me,dom:n,get:X,slugify:Tn,version:"4.13.1"},window.DocsifyCompiler=In,window.marked=Sn,window.Prism=Pn,e(function(e){return new Jn})}(); diff --git a/docs/static/search.js b/docs/static/search.js deleted file mode 100644 index 9db7c761d..000000000 --- a/docs/static/search.js +++ /dev/null @@ -1,535 +0,0 @@ -(function () { - /** - * Converts a colon formatted string to a object with properties. - * - * This is process a provided string and look for any tokens in the format - * of `:name[=value]` and then convert it to a object and return. - * An example of this is ':include :type=code :fragment=demo' is taken and - * then converted to: - * - * ``` - * { - * include: '', - * type: 'code', - * fragment: 'demo' - * } - * ``` - * - * @param {string} str The string to parse. - * - * @return {object} The original string and parsed object, { str, config }. - */ - function getAndRemoveConfig(str) { - if ( str === void 0 ) str = ''; - - var config = {}; - - if (str) { - str = str - .replace(/^'/, '') - .replace(/'$/, '') - .replace(/(?:^|\s):([\w-]+:?)=?([\w-%]+)?/g, function (m, key, value) { - if (key.indexOf(':') === -1) { - config[key] = (value && value.replace(/"/g, '')) || true; - return ''; - } - - return m; - }) - .trim(); - } - - return { str: str, config: config }; - } - - /* eslint-disable no-unused-vars */ - - var INDEXS = {}; - - var LOCAL_STORAGE = { - EXPIRE_KEY: 'docsify.search.expires', - INDEX_KEY: 'docsify.search.index', - }; - - function resolveExpireKey(namespace) { - return namespace - ? ((LOCAL_STORAGE.EXPIRE_KEY) + "/" + namespace) - : LOCAL_STORAGE.EXPIRE_KEY; - } - - function resolveIndexKey(namespace) { - return namespace - ? ((LOCAL_STORAGE.INDEX_KEY) + "/" + namespace) - : LOCAL_STORAGE.INDEX_KEY; - } - - function escapeHtml(string) { - var entityMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - }; - - return String(string).replace(/[&<>"']/g, function (s) { return entityMap[s]; }); - } - - function getAllPaths(router) { - var paths = []; - - Docsify.dom - .findAll('.sidebar-nav a:not(.section-link):not([data-nosearch])') - .forEach(function (node) { - var href = node.href; - var originHref = node.getAttribute('href'); - var path = router.parse(href).path; - - if ( - path && - paths.indexOf(path) === -1 && - !Docsify.util.isAbsolutePath(originHref) - ) { - paths.push(path); - } - }); - - return paths; - } - - function getTableData(token) { - if (!token.text && token.type === 'table') { - token.cells.unshift(token.header); - token.text = token.cells - .map(function(rows) { - return rows.join(' | '); - }) - .join(' |\n '); - } - return token.text; - } - - function getListData(token) { - if (!token.text && token.type === 'list') { - token.text = token.raw; - } - return token.text; - } - - function saveData(maxAge, expireKey, indexKey) { - localStorage.setItem(expireKey, Date.now() + maxAge); - localStorage.setItem(indexKey, JSON.stringify(INDEXS)); - } - - function genIndex(path, content, router, depth) { - if ( content === void 0 ) content = ''; - - var tokens = window.marked.lexer(content); - var slugify = window.Docsify.slugify; - var index = {}; - var slug; - var title = ''; - - tokens.forEach(function(token, tokenIndex) { - if (token.type === 'heading' && token.depth <= depth) { - var ref = getAndRemoveConfig(token.text); - var str = ref.str; - var config = ref.config; - - if (config.id) { - slug = router.toURL(path, { id: slugify(config.id) }); - } else { - slug = router.toURL(path, { id: slugify(escapeHtml(token.text)) }); - } - - if (str) { - title = str - .replace(//, '') - .replace(/{docsify-ignore}/, '') - .replace(//, '') - .replace(/{docsify-ignore-all}/, '') - .trim(); - } - - index[slug] = { slug: slug, title: title, body: '' }; - } else { - if (tokenIndex === 0) { - slug = router.toURL(path); - index[slug] = { - slug: slug, - title: path !== '/' ? path.slice(1) : 'Home Page', - body: token.text || '', - }; - } - - if (!slug) { - return; - } - - if (!index[slug]) { - index[slug] = { slug: slug, title: '', body: '' }; - } else if (index[slug].body) { - token.text = getTableData(token); - token.text = getListData(token); - - index[slug].body += '\n' + (token.text || ''); - } else { - token.text = getTableData(token); - token.text = getListData(token); - - index[slug].body = index[slug].body - ? index[slug].body + token.text - : token.text; - } - } - }); - slugify.clear(); - return index; - } - - function ignoreDiacriticalMarks(keyword) { - if (keyword && keyword.normalize) { - return keyword.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); - } - return keyword; - } - - /** - * @param {String} query Search query - * @returns {Array} Array of results - */ - function search(query) { - var matchingResults = []; - var data = []; - Object.keys(INDEXS).forEach(function (key) { - data = data.concat(Object.keys(INDEXS[key]).map(function (page) { return INDEXS[key][page]; })); - }); - - query = query.trim(); - var keywords = query.split(/[\s\-,\\/]+/); - if (keywords.length !== 1) { - keywords = [].concat(query, keywords); - } - - var loop = function ( i ) { - var post = data[i]; - var matchesScore = 0; - var resultStr = ''; - var handlePostTitle = ''; - var handlePostContent = ''; - var postTitle = post.title && post.title.trim(); - var postContent = post.body && post.body.trim(); - var postUrl = post.slug || ''; - - if (postTitle) { - keywords.forEach(function (keyword) { - // From https://github.com/sindresorhus/escape-string-regexp - var regEx = new RegExp( - ignoreDiacriticalMarks(keyword).replace( - /[|\\{}()[\]^$+*?.]/g, - '\\$&' - ), - 'gi' - ); - var indexTitle = -1; - var indexContent = -1; - handlePostTitle = postTitle - ? ignoreDiacriticalMarks(postTitle) - : postTitle; - handlePostContent = postContent - ? ignoreDiacriticalMarks(postContent) - : postContent; - - indexTitle = postTitle ? handlePostTitle.search(regEx) : -1; - indexContent = postContent ? handlePostContent.search(regEx) : -1; - - if (indexTitle >= 0 || indexContent >= 0) { - matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0; - if (indexContent < 0) { - indexContent = 0; - } - - var start = 0; - var end = 0; - - start = indexContent < 11 ? 0 : indexContent - 10; - end = start === 0 ? 70 : indexContent + keyword.length + 60; - - if (postContent && end > postContent.length) { - end = postContent.length; - } - - var matchContent = - '...' + - handlePostContent - .substring(start, end) - .replace( - regEx, - function (word) { return ("" + word + ""); } - ) + - '...'; - - resultStr += matchContent; - } - }); - - if (matchesScore > 0) { - var matchingPost = { - title: handlePostTitle, - content: postContent ? resultStr : '', - url: postUrl, - score: matchesScore, - }; - - matchingResults.push(matchingPost); - } - } - }; - - for (var i = 0; i < data.length; i++) loop( i ); - - return matchingResults.sort(function (r1, r2) { return r2.score - r1.score; }); - } - - function init(config, vm) { - var isAuto = config.paths === 'auto'; - var paths = isAuto ? getAllPaths(vm.router) : config.paths; - - var namespaceSuffix = ''; - - // only in auto mode - if (paths.length && isAuto && config.pathNamespaces) { - var path = paths[0]; - - if (Array.isArray(config.pathNamespaces)) { - namespaceSuffix = - config.pathNamespaces.filter( - function (prefix) { return path.slice(0, prefix.length) === prefix; } - )[0] || namespaceSuffix; - } else if (config.pathNamespaces instanceof RegExp) { - var matches = path.match(config.pathNamespaces); - - if (matches) { - namespaceSuffix = matches[0]; - } - } - var isExistHome = paths.indexOf(namespaceSuffix + '/') === -1; - var isExistReadme = paths.indexOf(namespaceSuffix + '/README') === -1; - if (isExistHome && isExistReadme) { - paths.unshift(namespaceSuffix + '/'); - } - } else if (paths.indexOf('/') === -1 && paths.indexOf('/README') === -1) { - paths.unshift('/'); - } - - var expireKey = resolveExpireKey(config.namespace) + namespaceSuffix; - var indexKey = resolveIndexKey(config.namespace) + namespaceSuffix; - - var isExpired = localStorage.getItem(expireKey) < Date.now(); - - INDEXS = JSON.parse(localStorage.getItem(indexKey)); - - if (isExpired) { - INDEXS = {}; - } else if (!isAuto) { - return; - } - - var len = paths.length; - var count = 0; - - paths.forEach(function (path) { - if (INDEXS[path]) { - return count++; - } - - Docsify.get(vm.router.getFile(path), false, vm.config.requestHeaders).then( - function (result) { - INDEXS[path] = genIndex(path, result, vm.router, config.depth); - len === ++count && saveData(config.maxAge, expireKey, indexKey); - } - ); - }); - } - - /* eslint-disable no-unused-vars */ - - var NO_DATA_TEXT = ''; - var options; - - function style() { - var code = "\n.sidebar {\n padding-top: 0;\n}\n\n.search {\n margin-bottom: 20px;\n padding: 6px;\n border-bottom: 1px solid #eee;\n}\n\n.search .input-wrap {\n display: flex;\n align-items: center;\n}\n\n.search .results-panel {\n display: none;\n}\n\n.search .results-panel.show {\n display: block;\n}\n\n.search input {\n outline: none;\n border: none;\n width: 100%;\n padding: 0 7px;\n line-height: 36px;\n font-size: 14px;\n border: 1px solid transparent;\n}\n\n.search input:focus {\n box-shadow: 0 0 5px var(--theme-color, #42b983);\n border: 1px solid var(--theme-color, #42b983);\n}\n\n.search input::-webkit-search-decoration,\n.search input::-webkit-search-cancel-button,\n.search input {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.search .clear-button {\n cursor: pointer;\n width: 36px;\n text-align: right;\n display: none;\n}\n\n.search .clear-button.show {\n display: block;\n}\n\n.search .clear-button svg {\n transform: scale(.5);\n}\n\n.search h2 {\n font-size: 17px;\n margin: 10px 0;\n}\n\n.search a {\n text-decoration: none;\n color: inherit;\n}\n\n.search .matching-post {\n border-bottom: 1px solid #eee;\n}\n\n.search .matching-post:last-child {\n border-bottom: 0;\n}\n\n.search p {\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n\n.search p.empty {\n text-align: center;\n}\n\n.app-name.hide, .sidebar-nav.hide {\n display: none;\n}"; - - Docsify.dom.style(code); - } - - function tpl(defaultValue) { - if ( defaultValue === void 0 ) defaultValue = ''; - - var html = "
    \n \n
    \n \n \n \n \n \n
    \n
    \n
    \n "; - var el = Docsify.dom.create('div', html); - var aside = Docsify.dom.find('aside'); - - Docsify.dom.toggleClass(el, 'search'); - Docsify.dom.before(aside, el); - } - - function doSearch(value) { - var $search = Docsify.dom.find('div.search'); - var $panel = Docsify.dom.find($search, '.results-panel'); - var $clearBtn = Docsify.dom.find($search, '.clear-button'); - var $sidebarNav = Docsify.dom.find('.sidebar-nav'); - var $appName = Docsify.dom.find('.app-name'); - - if (!value) { - $panel.classList.remove('show'); - $clearBtn.classList.remove('show'); - $panel.innerHTML = ''; - - if (options.hideOtherSidebarContent) { - $sidebarNav.classList.remove('hide'); - $appName.classList.remove('hide'); - } - - return; - } - - var matchs = search(value); - - var html = ''; - matchs.forEach(function (post) { - html += "
    "; - }); - - $panel.classList.add('show'); - $clearBtn.classList.add('show'); - $panel.innerHTML = html || ("

    " + NO_DATA_TEXT + "

    "); - if (options.hideOtherSidebarContent) { - $sidebarNav.classList.add('hide'); - $appName.classList.add('hide'); - } - } - - function bindEvents() { - var $search = Docsify.dom.find('div.search'); - var $input = Docsify.dom.find($search, 'input'); - var $inputWrap = Docsify.dom.find($search, '.input-wrap'); - - var timeId; - - /** - Prevent to Fold sidebar. - - When searching on the mobile end, - the sidebar is collapsed when you click the INPUT box, - making it impossible to search. - */ - Docsify.dom.on( - $search, - 'click', - function (e) { return ['A', 'H2', 'P', 'EM'].indexOf(e.target.tagName) === -1 && - e.stopPropagation(); } - ); - Docsify.dom.on($input, 'input', function (e) { - clearTimeout(timeId); - timeId = setTimeout(function (_) { return doSearch(e.target.value.trim()); }, 100); - }); - Docsify.dom.on($inputWrap, 'click', function (e) { - // Click input outside - if (e.target.tagName !== 'INPUT') { - $input.value = ''; - doSearch(); - } - }); - } - - function updatePlaceholder(text, path) { - var $input = Docsify.dom.getNode('.search input[type="search"]'); - - if (!$input) { - return; - } - - if (typeof text === 'string') { - $input.placeholder = text; - } else { - var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0]; - $input.placeholder = text[match]; - } - } - - function updateNoData(text, path) { - if (typeof text === 'string') { - NO_DATA_TEXT = text; - } else { - var match = Object.keys(text).filter(function (key) { return path.indexOf(key) > -1; })[0]; - NO_DATA_TEXT = text[match]; - } - } - - function updateOptions(opts) { - options = opts; - } - - function init$1(opts, vm) { - var keywords = vm.router.parse().query.s; - - updateOptions(opts); - style(); - tpl(keywords); - bindEvents(); - keywords && setTimeout(function (_) { return doSearch(keywords); }, 500); - } - - function update(opts, vm) { - updateOptions(opts); - updatePlaceholder(opts.placeholder, vm.route.path); - updateNoData(opts.noData, vm.route.path); - } - - /* eslint-disable no-unused-vars */ - - var CONFIG = { - placeholder: 'Type to search', - noData: 'No Results!', - paths: 'auto', - depth: 2, - maxAge: 86400000, // 1 day - hideOtherSidebarContent: false, - namespace: undefined, - pathNamespaces: undefined, - }; - - var install = function(hook, vm) { - var util = Docsify.util; - var opts = vm.config.search || CONFIG; - - if (Array.isArray(opts)) { - CONFIG.paths = opts; - } else if (typeof opts === 'object') { - CONFIG.paths = Array.isArray(opts.paths) ? opts.paths : 'auto'; - CONFIG.maxAge = util.isPrimitive(opts.maxAge) ? opts.maxAge : CONFIG.maxAge; - CONFIG.placeholder = opts.placeholder || CONFIG.placeholder; - CONFIG.noData = opts.noData || CONFIG.noData; - CONFIG.depth = opts.depth || CONFIG.depth; - CONFIG.hideOtherSidebarContent = - opts.hideOtherSidebarContent || CONFIG.hideOtherSidebarContent; - CONFIG.namespace = opts.namespace || CONFIG.namespace; - CONFIG.pathNamespaces = opts.pathNamespaces || CONFIG.pathNamespaces; - } - - var isAuto = CONFIG.paths === 'auto'; - - hook.mounted(function (_) { - init$1(CONFIG, vm); - !isAuto && init(CONFIG, vm); - }); - hook.doneEach(function (_) { - update(CONFIG, vm); - isAuto && init(CONFIG, vm); - }); - }; - - $docsify.plugins = [].concat(install, $docsify.plugins); - -}()); diff --git a/docs/static/zoom-image.js b/docs/static/zoom-image.js deleted file mode 100644 index 3166f92e9..000000000 --- a/docs/static/zoom-image.js +++ /dev/null @@ -1,659 +0,0 @@ -(function () { - /*! medium-zoom 1.0.6 | MIT License | https://github.com/francoischalifour/medium-zoom */ - var _extends = Object.assign || function (target) { - var arguments$1 = arguments; - - for (var i = 1; i < arguments.length; i++) { - var source = arguments$1[i]; - - for (var key in source) { - if (Object.prototype.hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target; - }; - - var isSupported = function isSupported(node) { - return node.tagName === 'IMG'; - }; - - /* eslint-disable-next-line no-prototype-builtins */ - var isNodeList = function isNodeList(selector) { - return NodeList.prototype.isPrototypeOf(selector); - }; - - var isNode = function isNode(selector) { - return selector && selector.nodeType === 1; - }; - - var isSvg = function isSvg(image) { - var source = image.currentSrc || image.src; - return source.substr(-4).toLowerCase() === '.svg'; - }; - - var getImagesFromSelector = function getImagesFromSelector(selector) { - try { - if (Array.isArray(selector)) { - return selector.filter(isSupported); - } - - if (isNodeList(selector)) { - // Do not use spread operator or Array.from() for IE support - return [].slice.call(selector).filter(isSupported); - } - - if (isNode(selector)) { - return [selector].filter(isSupported); - } - - if (typeof selector === 'string') { - // Do not use spread operator or Array.from() for IE support - return [].slice.call(document.querySelectorAll(selector)).filter(isSupported); - } - - return []; - } catch (err) { - throw new TypeError('The provided selector is invalid.\n' + 'Expects a CSS selector, a Node element, a NodeList or an array.\n' + 'See: https://github.com/francoischalifour/medium-zoom'); - } - }; - - var createOverlay = function createOverlay(background) { - var overlay = document.createElement('div'); - overlay.classList.add('medium-zoom-overlay'); - overlay.style.background = background; - - return overlay; - }; - - var cloneTarget = function cloneTarget(template) { - var _template$getBounding = template.getBoundingClientRect(), - top = _template$getBounding.top, - left = _template$getBounding.left, - width = _template$getBounding.width, - height = _template$getBounding.height; - - var clone = template.cloneNode(); - var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; - - clone.removeAttribute('id'); - clone.style.position = 'absolute'; - clone.style.top = top + scrollTop + 'px'; - clone.style.left = left + scrollLeft + 'px'; - clone.style.width = width + 'px'; - clone.style.height = height + 'px'; - clone.style.transform = ''; - - return clone; - }; - - var createCustomEvent = function createCustomEvent(type, params) { - var eventParams = _extends({ - bubbles: false, - cancelable: false, - detail: undefined - }, params); - - if (typeof window.CustomEvent === 'function') { - return new CustomEvent(type, eventParams); - } - - var customEvent = document.createEvent('CustomEvent'); - customEvent.initCustomEvent(type, eventParams.bubbles, eventParams.cancelable, eventParams.detail); - - return customEvent; - }; - - var mediumZoom = function mediumZoom(selector) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - /** - * Ensure the compatibility with IE11 if no Promise polyfill are used. - */ - var Promise = window.Promise || function Promise(fn) { - function noop() {} - fn(noop, noop); - }; - - var _handleClick = function _handleClick(event) { - var target = event.target; - - - if (target === overlay) { - close(); - return; - } - - if (images.indexOf(target) === -1) { - return; - } - - toggle({ target: target }); - }; - - var _handleScroll = function _handleScroll() { - if (isAnimating || !active.original) { - return; - } - - var currentScroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - - if (Math.abs(scrollTop - currentScroll) > zoomOptions.scrollOffset) { - setTimeout(close, 150); - } - }; - - var _handleKeyUp = function _handleKeyUp(event) { - var key = event.key || event.keyCode; - - // Close if escape key is pressed - if (key === 'Escape' || key === 'Esc' || key === 27) { - close(); - } - }; - - var update = function update() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var newOptions = options; - - if (options.background) { - overlay.style.background = options.background; - } - - if (options.container && options.container instanceof Object) { - newOptions.container = _extends({}, zoomOptions.container, options.container); - } - - if (options.template) { - var template = isNode(options.template) ? options.template : document.querySelector(options.template); - - newOptions.template = template; - } - - zoomOptions = _extends({}, zoomOptions, newOptions); - - images.forEach(function (image) { - image.dispatchEvent(createCustomEvent('medium-zoom:update', { - detail: { zoom: zoom } - })); - }); - - return zoom; - }; - - var clone = function clone() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - return mediumZoom(_extends({}, zoomOptions, options)); - }; - - var attach = function attach() { - var arguments$1 = arguments; - - for (var _len = arguments.length, selectors = Array(_len), _key = 0; _key < _len; _key++) { - selectors[_key] = arguments$1[_key]; - } - - var newImages = selectors.reduce(function (imagesAccumulator, currentSelector) { - return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector)); - }, []); - - newImages.filter(function (newImage) { - return images.indexOf(newImage) === -1; - }).forEach(function (newImage) { - images.push(newImage); - newImage.classList.add('medium-zoom-image'); - }); - - eventListeners.forEach(function (_ref) { - var type = _ref.type, - listener = _ref.listener, - options = _ref.options; - - newImages.forEach(function (image) { - image.addEventListener(type, listener, options); - }); - }); - - return zoom; - }; - - var detach = function detach() { - var arguments$1 = arguments; - - for (var _len2 = arguments.length, selectors = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - selectors[_key2] = arguments$1[_key2]; - } - - if (active.zoomed) { - close(); - } - - var imagesToDetach = selectors.length > 0 ? selectors.reduce(function (imagesAccumulator, currentSelector) { - return [].concat(imagesAccumulator, getImagesFromSelector(currentSelector)); - }, []) : images; - - imagesToDetach.forEach(function (image) { - image.classList.remove('medium-zoom-image'); - image.dispatchEvent(createCustomEvent('medium-zoom:detach', { - detail: { zoom: zoom } - })); - }); - - images = images.filter(function (image) { - return imagesToDetach.indexOf(image) === -1; - }); - - return zoom; - }; - - var on = function on(type, listener) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - - images.forEach(function (image) { - image.addEventListener('medium-zoom:' + type, listener, options); - }); - - eventListeners.push({ type: 'medium-zoom:' + type, listener: listener, options: options }); - - return zoom; - }; - - var off = function off(type, listener) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - - images.forEach(function (image) { - image.removeEventListener('medium-zoom:' + type, listener, options); - }); - - eventListeners = eventListeners.filter(function (eventListener) { - return !(eventListener.type === 'medium-zoom:' + type && eventListener.listener.toString() === listener.toString()); - }); - - return zoom; - }; - - var open = function open() { - var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - target = _ref2.target; - - var _animate = function _animate() { - var container = { - width: document.documentElement.clientWidth, - height: document.documentElement.clientHeight, - left: 0, - top: 0, - right: 0, - bottom: 0 - }; - var viewportWidth = void 0; - var viewportHeight = void 0; - - if (zoomOptions.container) { - if (zoomOptions.container instanceof Object) { - // The container is given as an object with properties like width, height, left, top - container = _extends({}, container, zoomOptions.container); - - // We need to adjust custom options like container.right or container.bottom - viewportWidth = container.width - container.left - container.right - zoomOptions.margin * 2; - viewportHeight = container.height - container.top - container.bottom - zoomOptions.margin * 2; - } else { - // The container is given as an element - var zoomContainer = isNode(zoomOptions.container) ? zoomOptions.container : document.querySelector(zoomOptions.container); - - var _zoomContainer$getBou = zoomContainer.getBoundingClientRect(), - _width = _zoomContainer$getBou.width, - _height = _zoomContainer$getBou.height, - _left = _zoomContainer$getBou.left, - _top = _zoomContainer$getBou.top; - - container = _extends({}, container, { - width: _width, - height: _height, - left: _left, - top: _top - }); - } - } - - viewportWidth = viewportWidth || container.width - zoomOptions.margin * 2; - viewportHeight = viewportHeight || container.height - zoomOptions.margin * 2; - - var zoomTarget = active.zoomedHd || active.original; - var naturalWidth = isSvg(zoomTarget) ? viewportWidth : zoomTarget.naturalWidth || viewportWidth; - var naturalHeight = isSvg(zoomTarget) ? viewportHeight : zoomTarget.naturalHeight || viewportHeight; - - var _zoomTarget$getBoundi = zoomTarget.getBoundingClientRect(), - top = _zoomTarget$getBoundi.top, - left = _zoomTarget$getBoundi.left, - width = _zoomTarget$getBoundi.width, - height = _zoomTarget$getBoundi.height; - - var scaleX = Math.min(naturalWidth, viewportWidth) / width; - var scaleY = Math.min(naturalHeight, viewportHeight) / height; - var scale = Math.min(scaleX, scaleY); - var translateX = (-left + (viewportWidth - width) / 2 + zoomOptions.margin + container.left) / scale; - var translateY = (-top + (viewportHeight - height) / 2 + zoomOptions.margin + container.top) / scale; - var transform = 'scale(' + scale + ') translate3d(' + translateX + 'px, ' + translateY + 'px, 0)'; - - active.zoomed.style.transform = transform; - - if (active.zoomedHd) { - active.zoomedHd.style.transform = transform; - } - }; - - return new Promise(function (resolve) { - if (target && images.indexOf(target) === -1) { - resolve(zoom); - return; - } - - var _handleOpenEnd = function _handleOpenEnd() { - isAnimating = false; - active.zoomed.removeEventListener('transitionend', _handleOpenEnd); - active.original.dispatchEvent(createCustomEvent('medium-zoom:opened', { - detail: { zoom: zoom } - })); - - resolve(zoom); - }; - - if (active.zoomed) { - resolve(zoom); - return; - } - - if (target) { - // The zoom was triggered manually via a click - active.original = target; - } else if (images.length > 0) { - var _images = images; - active.original = _images[0]; - } else { - resolve(zoom); - return; - } - - active.original.dispatchEvent(createCustomEvent('medium-zoom:open', { - detail: { zoom: zoom } - })); - - scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; - isAnimating = true; - active.zoomed = cloneTarget(active.original); - - document.body.appendChild(overlay); - - if (zoomOptions.template) { - var template = isNode(zoomOptions.template) ? zoomOptions.template : document.querySelector(zoomOptions.template); - active.template = document.createElement('div'); - active.template.appendChild(template.content.cloneNode(true)); - - document.body.appendChild(active.template); - } - - document.body.appendChild(active.zoomed); - - window.requestAnimationFrame(function () { - document.body.classList.add('medium-zoom--opened'); - }); - - active.original.classList.add('medium-zoom-image--hidden'); - active.zoomed.classList.add('medium-zoom-image--opened'); - - active.zoomed.addEventListener('click', close); - active.zoomed.addEventListener('transitionend', _handleOpenEnd); - - if (active.original.getAttribute('data-zoom-src')) { - active.zoomedHd = active.zoomed.cloneNode(); - - // Reset the `scrset` property or the HD image won't load. - active.zoomedHd.removeAttribute('srcset'); - active.zoomedHd.removeAttribute('sizes'); - - active.zoomedHd.src = active.zoomed.getAttribute('data-zoom-src'); - - active.zoomedHd.onerror = function () { - clearInterval(getZoomTargetSize); - console.warn('Unable to reach the zoom image target ' + active.zoomedHd.src); - active.zoomedHd = null; - _animate(); - }; - - // We need to access the natural size of the full HD - // target as fast as possible to compute the animation. - var getZoomTargetSize = setInterval(function () { - if ( active.zoomedHd.complete) { - clearInterval(getZoomTargetSize); - active.zoomedHd.classList.add('medium-zoom-image--opened'); - active.zoomedHd.addEventListener('click', close); - document.body.appendChild(active.zoomedHd); - _animate(); - } - }, 10); - } else if (active.original.hasAttribute('srcset')) { - // If an image has a `srcset` attribuet, we don't know the dimensions of the - // zoomed (HD) image (like when `data-zoom-src` is specified). - // Therefore the approach is quite similar. - active.zoomedHd = active.zoomed.cloneNode(); - - // Resetting the sizes attribute tells the browser to load the - // image best fitting the current viewport size, respecting the `srcset`. - active.zoomedHd.removeAttribute('sizes'); - - // In Firefox, the `loading` attribute needs to be set to `eager` (default - // value) for the load event to be fired. - active.zoomedHd.removeAttribute('loading'); - - // Wait for the load event of the hd image. This will fire if the image - // is already cached. - var loadEventListener = active.zoomedHd.addEventListener('load', function () { - active.zoomedHd.removeEventListener('load', loadEventListener); - active.zoomedHd.classList.add('medium-zoom-image--opened'); - active.zoomedHd.addEventListener('click', close); - document.body.appendChild(active.zoomedHd); - _animate(); - }); - } else { - _animate(); - } - }); - }; - - var close = function close() { - return new Promise(function (resolve) { - if (isAnimating || !active.original) { - resolve(zoom); - return; - } - - var _handleCloseEnd = function _handleCloseEnd() { - active.original.classList.remove('medium-zoom-image--hidden'); - document.body.removeChild(active.zoomed); - if (active.zoomedHd) { - document.body.removeChild(active.zoomedHd); - } - document.body.removeChild(overlay); - active.zoomed.classList.remove('medium-zoom-image--opened'); - if (active.template) { - document.body.removeChild(active.template); - } - - isAnimating = false; - active.zoomed.removeEventListener('transitionend', _handleCloseEnd); - - active.original.dispatchEvent(createCustomEvent('medium-zoom:closed', { - detail: { zoom: zoom } - })); - - active.original = null; - active.zoomed = null; - active.zoomedHd = null; - active.template = null; - - resolve(zoom); - }; - - isAnimating = true; - document.body.classList.remove('medium-zoom--opened'); - active.zoomed.style.transform = ''; - - if (active.zoomedHd) { - active.zoomedHd.style.transform = ''; - } - - // Fade out the template so it's not too abrupt - if (active.template) { - active.template.style.transition = 'opacity 150ms'; - active.template.style.opacity = 0; - } - - active.original.dispatchEvent(createCustomEvent('medium-zoom:close', { - detail: { zoom: zoom } - })); - - active.zoomed.addEventListener('transitionend', _handleCloseEnd); - }); - }; - - var toggle = function toggle() { - var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - target = _ref3.target; - - if (active.original) { - return close(); - } - - return open({ target: target }); - }; - - var getOptions = function getOptions() { - return zoomOptions; - }; - - var getImages = function getImages() { - return images; - }; - - var getZoomedImage = function getZoomedImage() { - return active.original; - }; - - var images = []; - var eventListeners = []; - var isAnimating = false; - var scrollTop = 0; - var zoomOptions = options; - var active = { - original: null, - zoomed: null, - zoomedHd: null, - template: null - - // If the selector is omitted, it's replaced by the options - };if (Object.prototype.toString.call(selector) === '[object Object]') { - zoomOptions = selector; - } else if (selector || typeof selector === 'string' // to process empty string as a selector - ) { - attach(selector); - } - - // Apply the default option values - zoomOptions = _extends({ - margin: 0, - background: '#fff', - scrollOffset: 40, - container: null, - template: null - }, zoomOptions); - - var overlay = createOverlay(zoomOptions.background); - - document.addEventListener('click', _handleClick); - document.addEventListener('keyup', _handleKeyUp); - document.addEventListener('scroll', _handleScroll); - window.addEventListener('resize', close); - - var zoom = { - open: open, - close: close, - toggle: toggle, - update: update, - clone: clone, - attach: attach, - detach: detach, - on: on, - off: off, - getOptions: getOptions, - getImages: getImages, - getZoomedImage: getZoomedImage - }; - - return zoom; - }; - - function styleInject(css, ref) { - if ( ref === void 0 ) { ref = {}; } - var insertAt = ref.insertAt; - - if (!css || typeof document === 'undefined') { return; } - - var head = document.head || document.getElementsByTagName('head')[0]; - var style = document.createElement('style'); - style.type = 'text/css'; - - if (insertAt === 'top') { - if (head.firstChild) { - head.insertBefore(style, head.firstChild); - } else { - head.appendChild(style); - } - } else { - head.appendChild(style); - } - - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.appendChild(document.createTextNode(css)); - } - } - - var css = ".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}"; - styleInject(css); - - /* eslint-disable no-unused-vars */ - - var matchesSelector = - Element.prototype.matches || - Element.prototype.webkitMatchesSelector || - Element.prototype.msMatchesSelector; - - function install(hook) { - var zoom; - - hook.doneEach(function (_) { - var elms = Array.apply( - null, - document.querySelectorAll( - '.markdown-section img:not(.emoji):not([data-no-zoom])' - ) - ); - - elms = elms.filter(function (elm) { return matchesSelector.call(elm, 'a img') === false; }); - - if (zoom) { - zoom.detach(); - } - - zoom = mediumZoom(elms); - }); - } - - $docsify.plugins = [].concat(install, $docsify.plugins); - -}()); diff --git a/docs/zh-cn/api.md b/docs/zh-cn/API/base-app.md similarity index 80% rename from docs/zh-cn/api.md rename to docs/zh-cn/API/base-app.md index ed1789470..fe27686ff 100644 --- a/docs/zh-cn/api.md +++ b/docs/zh-cn/API/base-app.md @@ -1,6 +1,3 @@ - - -# ** 主应用API ** ## start **描述:**micro-app注册函数,全局执行一次 @@ -230,11 +227,14 @@ function removeDomScope(force?: boolean): void ```js import { removeDomScope } from '@micro-zoe/micro-app' -// 解除元素绑定 -removeDomScope() - -// 解除元素绑定,并且一定时间内阻止再次绑定(一个微任务Promise时间) -removeDomScope(true) +removeDomScope(true) // 解除元素绑定 +/** + * 中间区域的元素操作都指向主应用 + * 例如: + * document.body.appendChild(document.createElement('div')) + * div元素将插入到主应用body中 + */ +removeDomScope(false) // 恢复元素绑定 ``` @@ -384,7 +384,7 @@ interface RenderAppOptions { 'keep-alive'?: boolean, // 开启keep-alive模式,可选 destroy?: boolean, // 卸载时强制删除缓存资源,可选 fiber?: boolean, // 开启fiber模式,可选 - baseroute?: string, // 设置子应用的基础路由,可选 + baseroute?: string, // 设置子应用路由系统的基础路径,可选 ssr?: boolean, // 开启ssr模式,可选 // shadowDOM?: boolean, // 开启shadowDOM,可选 data?: Object, // 传递给子应用的数据,可选 @@ -612,196 +612,3 @@ import microApp from '@micro-zoe/micro-app' // setGlobalData只接受对象作为参数 microApp.setGlobalData({type: '全局数据'}) ``` - - - - -# ** 子应用API ** - -## pureCreateElement -**描述:**创建无绑定的纯净元素,该元素可以逃离元素隔离的边界,不受子应用沙箱的控制 - -**版本限制:** 0.8.2及以上版本 - -**使用方式:** -```js -const pureDiv = window.microApp.pureCreateElement('div') - -document.body.appendChild(pureDiv) -``` - - -## removeDomScope -**描述:**解除元素绑定,通常用于受子应用元素绑定影响,导致主应用元素错误绑定到子应用的情况 - -**版本限制:** 0.8.2及以上版本 - -**介绍:** -```js -/** - * @param force 解除元素绑定,并且一定时间内(一个微任务Promise时间)阻止再次绑定。 - */ -function removeDomScope(force?: boolean): void -``` - -**使用方式:** -```js -// 解除元素绑定 -window.microApp.removeDomScope() - -// 解除元素绑定,并且一定时间内阻止再次绑定(一个微任务Promise时间) -window.microApp.removeDomScope(true) -``` - -## rawWindow -**描述:**获取真实的window - -**使用方式:** -```js -window.rawWindow -``` - -## rawDocument -**描述:**获取真实的document - -**使用方式:** -```js -window.rawDocument -``` - - -## getData -**描述:**获取主应用下发的data数据 - -**使用方式:** -```js -const data = window.microApp.getData() // 返回主应用下发的data数据 -``` - -## addDataListener -**描述:**绑定数据监听函数 - -**介绍:** -```js -/** - * 绑定监听函数,监听函数只有在数据变化时才会触发 - * dataListener: 绑定函数 - * autoTrigger: 在初次绑定监听函数时如果有缓存数据,是否需要主动触发一次,默认为false - * !!!重要说明: 因为子应用是异步渲染的,而主应用发送数据是同步的, - * 如果在子应用渲染结束前主应用发送数据,则在绑定监听函数前数据已经发送,在初始化后不会触发绑定函数, - * 但这个数据会放入缓存中,此时可以设置autoTrigger为true主动触发一次监听函数来获取数据。 - */ -window.microApp.addDataListener(dataListener: Function, autoTrigger?: boolean) -``` - -**使用方式:** -```js -function dataListener (data) { - console.log('来自主应用的数据', data) -} - -window.microApp.addDataListener(dataListener) -``` - -## removeDataListener -**描述:**解绑数据监听函数 - -**使用方式:** - -```js -function dataListener (data) { - console.log('来自主应用的数据', data) -} - -window.microApp.removeDataListener(dataListener) -``` - -## clearDataListener -**描述:**清空当前子应用的所有数据监听函数(全局数据函数除外) - -**使用方式:** - -```js -window.microApp.clearDataListener() -``` - -## dispatch -**描述:**向主应用发送数据 - -**使用方式:** - -```js -// dispatch只接受对象作为参数 -window.microApp.dispatch({type: '子应用发送的数据'}) -``` - - -## getGlobalData -**描述:**获取全局数据 - -**使用方式:** -```js -const globalData = window.microApp.getGlobalData() // 返回全局数据 -``` - - -## addGlobalDataListener -**描述:**绑定数据监听函数 - -**介绍:** -```js -/** - * 绑定监听函数 - * dataListener: 绑定函数 - * autoTrigger: 在初次绑定监听函数时如果有缓存数据,是否需要主动触发一次,默认为false - */ -window.microApp.addGlobalDataListener(dataListener: Function, autoTrigger?: boolean) - -``` - -**使用方式:** -```js -function dataListener (data) { - console.log('全局数据', data) -} - -window.microApp.addGlobalDataListener(dataListener) -``` - -## removeGlobalDataListener -**描述:**解绑全局数据监听函数 - -**使用方式:** - -```js -function dataListener (data) { - console.log('全局数据', data) -} - -window.microApp.removeGlobalDataListener(dataListener) -``` - -## clearGlobalDataListener -**描述:**清空当前子应用绑定的所有全局数据监听函数 - -**使用方式:** - -```js -window.microApp.clearGlobalDataListener() -``` - -## setGlobalData -**描述:**发送全局数据 - -**使用方式:** - -```js -// setGlobalData只接受对象作为参数 -window.microApp.setGlobalData({type: '全局数据'}) -``` - - diff --git a/docs/zh-cn/API/child-app.md b/docs/zh-cn/API/child-app.md new file mode 100644 index 000000000..5ed9a0565 --- /dev/null +++ b/docs/zh-cn/API/child-app.md @@ -0,0 +1,184 @@ +## pureCreateElement +**描述:**创建无绑定的纯净元素,该元素可以逃离元素隔离的边界,不受子应用沙箱的控制 + +**版本限制:** 0.8.2及以上版本 + +**使用方式:** +```js +const pureDiv = window.microApp.pureCreateElement('div') + +document.body.appendChild(pureDiv) +``` + + +## removeDomScope +**描述:**解除元素绑定,通常用于受子应用元素绑定影响,导致主应用元素错误绑定到子应用的情况 + +**版本限制:** 0.8.2及以上版本 + +**介绍:** +```js +/** + * @param force 解除元素绑定,并且一定时间内(一个微任务Promise时间)阻止再次绑定。 + */ +function removeDomScope(force?: boolean): void +``` + +**使用方式:** +```js +window.microApp.removeDomScope(true) // 解除元素绑定 +/** + * 中间区域的元素操作都指向主应用 + * 例如: + * document.body.appendChild(document.createElement('div')) + * div元素将插入到主应用body中 + */ +window.microApp.removeDomScope(false) // 恢复元素绑定 +``` + +## rawWindow +**描述:**获取真实的window + +**使用方式:** +```js +window.rawWindow +``` + +## rawDocument +**描述:**获取真实的document + +**使用方式:** +```js +window.rawDocument +``` + + +## getData +**描述:**获取主应用下发的data数据 + +**使用方式:** +```js +const data = window.microApp.getData() // 返回主应用下发的data数据 +``` + +## addDataListener +**描述:**绑定数据监听函数 + +**介绍:** +```js +/** + * 绑定监听函数,监听函数只有在数据变化时才会触发 + * dataListener: 绑定函数 + * autoTrigger: 在初次绑定监听函数时如果有缓存数据,是否需要主动触发一次,默认为false + * !!!重要说明: 因为子应用是异步渲染的,而主应用发送数据是同步的, + * 如果在子应用渲染结束前主应用发送数据,则在绑定监听函数前数据已经发送,在初始化后不会触发绑定函数, + * 但这个数据会放入缓存中,此时可以设置autoTrigger为true主动触发一次监听函数来获取数据。 + */ +window.microApp.addDataListener(dataListener: Function, autoTrigger?: boolean) +``` + +**使用方式:** +```js +function dataListener (data) { + console.log('来自主应用的数据', data) +} + +window.microApp.addDataListener(dataListener) +``` + +## removeDataListener +**描述:**解绑数据监听函数 + +**使用方式:** + +```js +function dataListener (data) { + console.log('来自主应用的数据', data) +} + +window.microApp.removeDataListener(dataListener) +``` + +## clearDataListener +**描述:**清空当前子应用的所有数据监听函数(全局数据函数除外) + +**使用方式:** + +```js +window.microApp.clearDataListener() +``` + +## dispatch +**描述:**向主应用发送数据 + +**使用方式:** + +```js +// dispatch只接受对象作为参数 +window.microApp.dispatch({type: '子应用发送的数据'}) +``` + + +## getGlobalData +**描述:**获取全局数据 + +**使用方式:** +```js +const globalData = window.microApp.getGlobalData() // 返回全局数据 +``` + + +## addGlobalDataListener +**描述:**绑定数据监听函数 + +**介绍:** +```js +/** + * 绑定监听函数 + * dataListener: 绑定函数 + * autoTrigger: 在初次绑定监听函数时如果有缓存数据,是否需要主动触发一次,默认为false + */ +window.microApp.addGlobalDataListener(dataListener: Function, autoTrigger?: boolean) + +``` + +**使用方式:** +```js +function dataListener (data) { + console.log('全局数据', data) +} + +window.microApp.addGlobalDataListener(dataListener) +``` + +## removeGlobalDataListener +**描述:**解绑全局数据监听函数 + +**使用方式:** + +```js +function dataListener (data) { + console.log('全局数据', data) +} + +window.microApp.removeGlobalDataListener(dataListener) +``` + +## clearGlobalDataListener +**描述:**清空当前子应用绑定的所有全局数据监听函数 + +**使用方式:** + +```js +window.microApp.clearGlobalDataListener() +``` + +## setGlobalData +**描述:**发送全局数据 + +**使用方式:** + +```js +// setGlobalData只接受对象作为参数 +window.microApp.setGlobalData({type: '全局数据'}) +``` diff --git a/docs/zh-cn/changelog.md b/docs/zh-cn/changelog.md index 5009394a7..6368a801f 100644 --- a/docs/zh-cn/changelog.md +++ b/docs/zh-cn/changelog.md @@ -8,6 +8,47 @@ --- +### 1.0.0-rc.6 + +`2024-7-29` + +- **Bug Fix** + + - 🐞 修复 iframe沙箱下history.go传入的是非0数字时iframe被重置导致异常的问题,[PR 1112](https://github.com/micro-zoe/micro-app/pull/1112) by [keuby](https://github.com/keuby)。 + - 🐞 修复 iframe沙箱下子应用事件类型判断异常的问题,[issue 975](https://github.com/micro-zoe/micro-app/issues/975),[issue 1120](https://github.com/micro-zoe/micro-app/issues/1120),[PR 985](https://github.com/micro-zoe/micro-app/pull/985) by [keuby](https://github.com/keuby)。 + - 🐞 修复 UnoCSS等异步注册mount、unmount场景下导致umd模式加载失败的问题,[issue 881](https://github.com/micro-zoe/micro-app/issues/881)、[issue 1047](https://github.com/micro-zoe/micro-app/issues/1047)、[issue 1179](https://github.com/micro-zoe/micro-app/issues/1179)、[issue 1218](https://github.com/micro-zoe/micro-app/issues/1218)。 + - 🐞 修复 类型声明jsx.IntrinsicElements导致vue-ts部分元素lint异常的问题。 + - 🐞 修复 state路由模式下子应用为vue3时刷新浏览器路由状态丢失的问题。 + - 🐞 修复 iframe沙箱在默认模式下二次渲染时初始化沙箱过程中卸载子应用导致异常的问题。 + - 🐞 修复 当子应用的`window.unmount`非空且不为函数时卸载子应用报错的问题。 + - 🐞 修复 当子应用在开启预渲染后,加载资源过程中被卸载表现异常的问题。 + - 🐞 修复 fiber子应用在初始化过程中被卸载导致渲染异常的问题。 + - 🐞 修复 主应用和子应用都是vue-router@4.x时,跳转子应用后点击返回按钮浏览器地址错误的问题,[issue 1234](https://github.com/micro-zoe/micro-app/issues/1234)。 + - 🐞 修复 子应用beforeunload事件无法正常挂载的问题,[issue 1233](https://github.com/micro-zoe/micro-app/issues/1233)。 + - 🐞 修复 当官网文档页面内容含有tab时,跳转或刷新后标题锚点定为不准确的问题。 + - 🐞 修复 循环嵌套时,中间层子应用为iframe沙箱时通过data属性传递初始化数据失败的问题。 + - 🐞 修复 native路由模式下vue3按需加载页面在部分场景下点击浏览器前进后退按钮时浏览器地址错误。 + - 🐞 修复 svg中图片路径无法自动补全的问题,[issue 1222](https://github.com/micro-zoe/micro-app/issues/1222)。 + - 🐞 修复 Firefox浏览器下子应用`favicon.ico`将主应用图标替换的问题,[issue 1262](https://github.com/micro-zoe/micro-app/issues/1262)。 + - 🐞 修复 Firefox浏览器下子应用元素的`ownerDocument`指向异常导致React16子应用渲染失败的问题。 + - 🐞 修复 Firefox浏览器下子应用元素的原型链被重置导致子应用渲染异常的的问题,[1089](https://github.com/micro-zoe/micro-app/issues/1089)、[913](https://github.com/micro-zoe/micro-app/issues/913)。 + - 🐞 修复 iframe沙箱下`message`事件无法被触发的问题。 + - 🐞 修复 iframe沙箱下window和document通过`dispatchEvent`主动发送某些特殊事件时无法正常触发事件的问题。 + - 🐞 修复 iframe沙箱下`DOMParser`解析失败导致`AntV X6`, `docx-preview`等库运行异常的问题[1292](https://github.com/micro-zoe/micro-app/issues/1292)。 + - 🐞 修复 iframe沙箱下主应用元素被错误插入到子应用中的情况[1260](https://github.com/micro-zoe/micro-app/issues/1260)。 + - 🐞 修复 iframe沙箱下富文本编辑器表现异常的问题[1031](https://github.com/micro-zoe/micro-app/issues/1031)、[1231](https://github.com/micro-zoe/micro-app/issues/1231)、[1023](https://github.com/micro-zoe/micro-app/issues/1203)。 + - 🐞 修复 Fragment内部link、script等元素无法拦截和处理的问题。 + - 🐞 修复 iframe沙箱下通过`document.querySelector`、`document.querySelectorAll`获取script元素异常的问题。 + - 🐞 修复 样式隔离对CSS规则`@layer`的支持,[PR 1303](https://github.com/micro-zoe/micro-app/pull/1303) by [alexgofreight](https://github.com/alexgofreight)。 + - 🐞 修复 子应用存在多层CSS嵌套时样式隔离解析失败的问题,[PR 1300](https://github.com/micro-zoe/micro-app/pull/1300)、[PR 1298](https://github.com/micro-zoe/micro-app/pull/1298) by [alexgofreight](https://github.com/alexgofreight)。 + +- **Update** + - 🚀 优化 `removeDomScope`方法,支持解除元素绑定的开关操作。 + - 🚀 优化 沙箱架构设计。 + - 🚀 优化 子应用卸载行为逻辑。 + - 🚀 优化 路由相关文档。 + + ### 1.0.0-rc.5 `2024-4-29` @@ -584,7 +625,7 @@ - **Bug Fix** - - 🐞 修复了在火狐浏览器80及以上版本中,样式隔离执行速度过慢的问题。 + - 🐞 修复了在Firefox浏览器80及以上版本中,样式隔离执行速度过慢的问题。 ### 0.8.3 diff --git a/docs/zh-cn/configure.md b/docs/zh-cn/configure.md index 71227ac0f..f21ed7099 100644 --- a/docs/zh-cn/configure.md +++ b/docs/zh-cn/configure.md @@ -38,21 +38,10 @@ MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 - Default: `false` - 使用方式: `` -默认情况下,子应用的js会被提取并在后台运行,这会导致调试困难。 +默认情况下,子应用的js会被提取并在后台运行,script元素原位置会留下注释:`` -开启inline后,被提取的js会作为script标签插入应用中运行,在开发环境中更方便调试。 +开启inline模式后,script元素会被保留,方便查看和调试代码,但会稍微损耗性能,建议只在开发环境中使用。 -> [!NOTE] -> 开启inline后会稍微损耗性能,建议在开发环境中使用。 - -## destroy -- Desc: `卸载时强制删除缓存资源` -- Default: `false` -- 使用方式: `` - -默认情况下,子应用被卸载后不会删除缓存的静态资源和数据,以便在重新渲染时获得更好的性能。 - -开启destroy,子应用在卸载后会清空缓存资源和数据,当重新渲染时将和初次渲染的行为保持一致。 ## clear-data - Desc: `卸载时清空数据通讯中的缓存数据` @@ -65,6 +54,17 @@ MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 [destroy](/zh-cn/configure?id=destroy)也有同样的效果。 +## destroy +- Desc: `卸载时删除缓存资源` +- Default: `false` +- 使用方式: `` + +默认情况下,子应用被卸载后不会删除缓存的静态资源和沙箱数据,以便在重新渲染时获得更好的性能。 + +开启destroy,子应用在卸载后会清空缓存的静态资源和沙箱数据。 + +但destroy只适合一次性渲染的子应用,由于子应用每次初始化都可能会增加一些无法释放的内存,如果频繁渲染和卸载,设置destroy反而会增加内存消耗,请谨慎使用。 + ## disable-scopecss - Desc: `关闭样式隔离` @@ -130,16 +130,16 @@ keep-alive的优先级小于[destroy](/zh-cn/configure?id=destroy),当两者 - Default: `search` - 使用方式: `` -路由分为四种模式:`search`、`native`、`native-scope`、`pure`,每种模式对应不同的功能,以满足尽可能多的项目需求,详情参考[虚拟路由系统](/zh-cn/router)。 +路由模式分为:`search`、`native`、`native-scope`、`pure`、`state`,每种模式对应不同的功能,以满足尽可能多的项目需求,详情参考[虚拟路由系统](/zh-cn/router)。 ## baseroute -- Desc: `设置子应用的基础路由` +- Desc: `设置子应用的基础路径` - Type: `string` - Default: `''` - 使用方式: `` -在微前端环境下,子应用可以从window.__MICRO_APP_BASE_ROUTE__上获取baseroute的值,用于设置基础路由。 +在微前端环境下,子应用可以从window.__MICRO_APP_BASE_ROUTE__上获取baseroute的值,用于设置基础路径。 只有路由模式是native或native-scope我们才需要设置baseroute,详情参考[虚拟路由系统](/zh-cn/router)。 @@ -214,7 +214,7 @@ shadowDOM具有更强的样式隔离能力,开启后,``标签会 但shadowDOM在React框架及一些UI库中的兼容不是很好,经常会出现一些不可预料的问题,除非你很清楚它会带来的问题并有信心解决,否则不建议使用。 --> -## 全局配置 +## 全局配置 :id=global 全局配置会影响每一个子应用,请小心使用! **使用方式** @@ -256,18 +256,7 @@ microApp.start({ ``` ## 其它配置 -### global -当多个子应用使用相同的js或css资源,在link、script设置`global`属性会将文件提取为公共文件,共享给其它应用。 - -设置`global`属性后文件第一次加载会放入公共缓存,其它子应用加载相同的资源时直接从缓存中读取内容,从而提升渲染速度。 - -**使用方式** -```html - - -``` - -### globalAssets +### globalAssets :id=globalAssets globalAssets用于设置全局共享资源,它和预加载的思路相同,在浏览器空闲时加载资源并放入缓存,提高渲染效率。 当子应用加载相同地址的js或css资源时,会直接从缓存中提取数据,从而提升渲染速度。 @@ -285,7 +274,7 @@ microApp.start({ }) ``` -### exclude(过滤元素) +### exclude(过滤元素) :id=exclude 当子应用不需要加载某个js或css,可以通过在link、script、style设置exclude属性,当micro-app遇到带有exclude属性的元素会进行删除。 **使用方式** @@ -295,7 +284,7 @@ microApp.start({ ``` -### ignore(忽略元素) +### ignore(忽略元素) :id=ignore 当link、script、style元素具有ignore属性,micro-app不会处理它,元素将原封不动进行渲染。 使用场景例如:jsonp diff --git a/docs/zh-cn/dom-scope.md b/docs/zh-cn/dom-scope.md index 60ba46c5d..d80693d07 100644 --- a/docs/zh-cn/dom-scope.md +++ b/docs/zh-cn/dom-scope.md @@ -11,60 +11,37 @@ 这一点和ShadowDom不同,在微前端下主应用拥有统筹全局的作用,所以我们没有对主应用操作子应用元素的行为进行限制。 ### 解除元素绑定 -默认情况下,当子应用操作元素时会绑定元素作用域,而解绑过程是异步的,这可能会导致操作元素异常,此时有两种方式可以解决这个问题。 +默认情况下,当子应用操作元素时会绑定元素作用域,而解绑过程是异步的,这可能会导致操作元素异常。 -**方式一:执行removeDomScope** +**常见问题:**主应用元素错误插入到子应用``元素内部。 -[removeDomScope](/zh-cn/api?id=removedomscope)方法可以解除元素绑定,通常用于受子应用元素绑定影响,导致主应用元素错误绑定到子应用的情况。 +**解决方法:**使用`removeDomScope`方法解除元素绑定。 -**具体方式如下:** +具体方式如下: #### ** 主应用 ** ```js import { removeDomScope } from '@micro-zoe/micro-app' -// 解除元素绑定,并且一定时间内阻止再次绑定(一个微任务Promise时间) -removeDomScope(true) // 或者 removeDomScope() - -const div = window.document.createElement('div') -// 插入到主应用body中 -document.body.appendChild(div) -``` - -#### ** 子应用 ** -```js -// 解除元素绑定,并且一定时间内阻止再次绑定(一个微任务Promise时间) -window.microApp.removeDomScope(true) // 或者 window.microApp.removeDomScope() - -const div = window.rawDocument.createElement('div') -// 插入到主应用body中 -document.body.appendChild(div) -``` - - - -**方式二:使用setTimeout** - -#### ** 主应用 ** -```js -// 等待解绑结束后操作元素 -setTimeout(() => { - const div = window.document.createElement('div') - // 插入到主应用body中 - document.body.appendChild(div) -}, 0) +removeDomScope(true) // 解除元素绑定 +/** + * 中间区域的元素操作都指向主应用 + * 例如: + * document.body.appendChild(document.createElement('div')) + * div元素将插入到主应用body中 + */ +removeDomScope(false) // 恢复元素绑定 ``` #### ** 子应用 ** ```js -// 记录主应用document -const rawDocument = window.rawDocument - -// 等待解绑结束后操作元素 -setTimeout(() => { - const div = rawDocument.createElement('div') - // 插入到主应用body中 - rawDocument.body.appendChild(div) -}, 0) +window.microApp.removeDomScope(true) // 解除元素绑定 +/** + * 中间区域的元素操作都指向主应用 + * 例如: + * document.body.appendChild(document.createElement('div')) + * div元素将插入到主应用body中 + */ +window.microApp.removeDomScope(false) // 恢复元素绑定 ``` diff --git a/docs/zh-cn/env.md b/docs/zh-cn/env.md index c35297513..1a1ad7a1f 100644 --- a/docs/zh-cn/env.md +++ b/docs/zh-cn/env.md @@ -22,6 +22,8 @@ if (window.__MICRO_APP_ENVIRONMENT__) { 用于设置webpack动态[public-path](https://webpack.docschina.org/guides/public-path/#on-the-fly),将子应用的静态资源补全为 http 开头的绝对地址。 +**使用方式:** + **步骤1:** 在`子应用`src目录下创建名称为`public-path.js`的文件,并添加如下内容 ```js if (window.__MICRO_APP_ENVIRONMENT__) { @@ -36,13 +38,13 @@ import './public-path' ### `__MICRO_APP_BASE_ROUTE__` -**描述:子应用的基础路由** +**描述:子应用的基础路径** -详情见[路由-基础路由](/zh-cn/native-mode?id=基础路由)一章。 +详情见[路由-基础路径](/zh-cn/native-mode?id=基础路径)一章。 ### `__MICRO_APP_BASE_APPLICATION__` -**描述:判断应用是否是主应用** +**描述:判断当前应用是否是主应用** 在执行`microApp.start()`后此值才会生效 @@ -51,3 +53,27 @@ if (window.__MICRO_APP_BASE_APPLICATION__) { console.log('我是主应用') } ``` + + +### `rawWindow` + +**描述:获取真实window(即主应用window)** + +默认情况下子应用window指向代理对象,通过`rawWindow`可以获取真实window。 + +**使用方式:** +```js +window.rawWindow +``` + +### `rawDocument` + +**描述:获取真实document(即主应用document)** + +默认情况下子应用document指向代理对象,通过`rawDocument`可以获取真实document。 + +**使用方式:** +```js +window.rawDocument +``` + diff --git a/docs/zh-cn/framework/angular.md b/docs/zh-cn/framework/angular.md index 606a9a26e..fb8342204 100644 --- a/docs/zh-cn/framework/angular.md +++ b/docs/zh-cn/framework/angular.md @@ -1,6 +1,6 @@ 本篇以`angular 11`作为案例介绍angular的接入方式,其它版本angular接入方式会在后续补充,如果你在使用时出现问题,请在github上提issue告知我们。 -## 作为主应用 +## 作为主应用 :id=main #### 1、安装依赖 ```bash @@ -27,14 +27,15 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; }) ``` -#### 4、在页面中嵌入子应用 +#### 4、在页面中加载子应用 + +通过注册的自定义元素``加载子应用 ```html
    -

    子应用

    - +
    ``` @@ -44,9 +45,9 @@ import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; > 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html -## 作为子应用 +## 作为子应用 :id=child -#### 1、在主应用中引入`zone.js` +#### 1、在主应用中引入`zone.js` :id=zone 如果主应用非angular,那么主应用需要引入`zone.js`才能正确加载angular子应用。 步骤1、安装依赖 @@ -59,7 +60,7 @@ npm i zone.js --save import 'zone.js' ``` -#### 2、设置跨域支持 +#### 2、设置跨域支持 :id=Access-Control-Allow-Origin angular官方脚手架创建的项目在开发环境下默认支持跨域访问,不需要特殊处理。 其它项目在`webpack-dev-server`中添加headers。 @@ -70,8 +71,8 @@ headers: { } ``` -#### 3、监听卸载事件 -子应用被卸载时会接受到一个名为`unmount`的事件,在此可以进行卸载相关操作。 +#### 3、注册卸载函数 :id=unmount +子应用卸载时会自动执行`window.unmount`,在此可以进行卸载相关操作。 ```js // main.ts @@ -92,58 +93,14 @@ window.unmount = () => { 完成以上步骤微前端即可正常渲染。 -### 可选设置 +### 可选设置 :id=options 以下配置是针对子应用的,它们是可选的,建议根据实际情况选择设置。 -#### 1、开启umd模式,优化内存和性能 -MicroApp支持两种渲染微前端的模式,默认模式和umd模式。 - -- **默认模式:**子应用在初次渲染和后续渲染时会顺序执行所有js,以保证多次渲染的一致性。 -- **umd模式:**子应用暴露出`mount`、`unmount`方法,此时只在初次渲染时执行所有js,后续渲染只会执行这两个方法,在多次渲染时具有更好的性能和内存表现。 - -如果子应用渲染和卸载不频繁,那么使用默认模式即可,如果子应用渲染和卸载非常频繁建议使用umd模式。 +#### 1、开启umd模式,优化内存和性能 :id=umd +详情参考[umd模式](/zh-cn/umd)章节。 -```js -// main.ts -import { NgModuleRef } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { AppModule } from './app/app.module'; - -declare global { - interface Window { - microApp: any - mount: CallableFunction - unmount: CallableFunction - __MICRO_APP_ENVIRONMENT__: string - } -} -let app: void | NgModuleRef -// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 -window.mount = () => { - platformBrowserDynamic() - .bootstrapModule(AppModule) - .then((res: NgModuleRef) => { - app = res - }) - .catch(err => console.error(err)) -} - -// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 -window.unmount = () => { - // angular在部分场景下执行destroy时会删除根元素app-root,导致在此渲染时报错,此时可删除app.destroy()来避免这个问题 - app && app.destroy(); - app = undefined; -} - -// 如果不在微前端环境,则直接执行mount渲染 -if (!window.__MICRO_APP_ENVIRONMENT__) { - window.mount(); -} -``` - - -#### 2、设置 webpack.jsonpFunction +#### 2、设置 webpack.jsonpFunction :id=webpackJsonpFunction 如果微前端正常运行,则可以忽略这一步。 如果子应用资源加载混乱导致渲染失败,可以尝试设置`jsonpFunction`来解决,因为相同的`jsonpFunction`名称会导致资源污染。 @@ -179,10 +136,10 @@ module.exports = { -#### 3、设置 publicPath +#### 3、设置 publicPath :id=public-path 如果子应用出现静态资源地址404(js、css、图片),建议设置`publicPath`来尝试解决这个问题。 -`publicPath`是webpack提供的功能,所以vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) +`publicPath`是webpack提供的功能,vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) **步骤1:** 在子应用src目录下创建名称为`public-path.ts`的文件,并添加如下内容 ```js @@ -199,14 +156,18 @@ if (window.__MICRO_APP_ENVIRONMENT__) { import './public-path' ``` -#### 4、切换到iframe沙箱 +#### 4、切换到iframe沙箱 :id=iframe MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。 +```html + +``` + ## 常见问题 -#### 1、通过micro-app数据通信修改angular组件数据后视图不更新 +#### 1、通过micro-app数据通信修改angular组件数据后视图不更新 :id=question-1 **原因:**因为在angular区域外调用了内部的代码(主应用和子应用属于不同的angular区域),angular无法知道状态发生了变化。 @@ -214,5 +175,5 @@ MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 ![angular-question3](https://img14.360buyimg.com/imagetools/jfs/t1/207551/36/34684/49729/6523aee1F5efef0be/e50e6d782a223dc9.png ':size=800') -#### 2、主应用是react、nextjs应用,引入zone.js后导致micro-app元素生命周期异常 +#### 2、主应用是react、nextjs应用,引入zone.js后导致micro-app元素生命周期异常 :id=question-2 目前无法解决,请暂停使用生命周期函数。 diff --git a/docs/zh-cn/framework/introduce.md b/docs/zh-cn/framework/introduce.md index e9c468b00..149c436be 100644 --- a/docs/zh-cn/framework/introduce.md +++ b/docs/zh-cn/framework/introduce.md @@ -1,18 +1,16 @@ -上面的文档中,我们从功能的角度介绍如何接入微前端,这导致整体的逻辑不连贯。 +上面的文档中,我们从功能点的角度介绍如何接入微前端,整体逻辑不连贯。 -在手把手系列中,*我们会侧重于前端框架本身*,详细介绍它们作为主应用和子应用如何接入微前端。 +在手把手系列中,**我们会侧重于前端框架本身**,详细介绍它们作为主应用和子应用如何接入微前端。 -我们列举比较流行的前端框架,指出各框架的注意事项,规避各种可能出现的问题。 +我们列举了比较流行的前端框架,列出各框架的接入细节,规避各种可能出现的问题。 **目前有:** -- react -- vue -- vite -- angular -- nextjs -- nuxtjs +- [react](/zh-cn/framework/react) +- [vue](/zh-cn/framework/vue) +- [vite](/zh-cn/framework/vite) +- [angular](/zh-cn/framework/angular) +- [nextjs](/zh-cn/framework/nextjs) +- [nuxtjs](/zh-cn/framework/nuxtjs) > [!TIP] > 以上框架可以任意组合,换句话说任何一个框架都可以作为主应用嵌入其它类型的子应用,任何一个框架也可以作为子应用被其它框架嵌入,包括上面没有列举出的其它库,如 svelte、umi ... -> -> 我们只列举了部分框架,如果有其它框架需求,请在github上提issue告知我们。 diff --git a/docs/zh-cn/framework/nextjs.md b/docs/zh-cn/framework/nextjs.md index 25ee704e4..913feed6a 100644 --- a/docs/zh-cn/framework/nextjs.md +++ b/docs/zh-cn/framework/nextjs.md @@ -1,6 +1,6 @@ 本篇以`nextjs 11`作为案例介绍nextjs的接入方式,其它版本nextjs接入方式会在后续补充,如果你在使用时出现问题,请在github上提issue告知我们。 -## 作为主应用 +## 作为主应用 :id=main #### 1、安装依赖 ```bash @@ -27,7 +27,7 @@ function MyApp({ Component, pageProps }) { export default MyApp ``` -#### 3、在页面中嵌入子应用 +#### 3、在页面中加载子应用 因为micro-app只能运行在浏览器环境,所以在`useEffect`中通过变量控制子应用显示。 ```js @@ -43,7 +43,6 @@ const MyPage = () => { return (
    -

    子应用

    { // name:应用名称, url:应用地址 show && () @@ -61,9 +60,9 @@ export default MyPage > 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html -## 作为子应用 +## 作为子应用 :id=child -#### 1、在主应用中添加ssr配置 +#### 1、在主应用中添加ssr配置 :id=ssr 当子应用是ssr应用时,主应用需要在micro-app元素上添加ssr属性,此时micro-app会根据ssr模式加载子应用。 ```html @@ -71,7 +70,7 @@ export default MyPage ``` -#### 2、设置跨域支持 +#### 2、设置跨域支持 :id=Access-Control-Allow-Origin 通过自定义服务设置跨域访问,详情参考 [custom-server](https://nextjs.org/docs/advanced-features/custom-server) **步骤1、在根目录创建`server.js`** @@ -114,12 +113,12 @@ app.prepare().then(() => { } ``` -#### 3、设置`assetPrefix` 和 `publicRuntimeConfig` +#### 3、设置`assetPrefix` 和 `publicRuntimeConfig` :id=assetPrefix 在`next.config.js`中设置`assetPrefix`,为静态资源添加路径前缀,避免子应用的静态资源使用相对地址时加载失败的情况。 ```js // next.config.js -const basePath = '基础路由' // 默认为 '/' +const basePath = '基础路径' // 默认为 '/' // 静态资源路径前缀 const assetPrefix = process.env.NODE_ENV === 'production' ? `线上域名${basePath}` : `http://localhost:${process.env.PORT || 3000}${basePath}` @@ -154,7 +153,7 @@ export default Page ``` -#### 4、监听卸载 +#### 4、监听卸载 :id=unmount 子应用被卸载时会接受到一个名为`unmount`的事件,在此可以进行卸载相关操作。 ```js @@ -167,31 +166,34 @@ window.addEventListener('unmount', function () { > [!NOTE] > nextjs默认支持css module功能,如果你使用了此功能,建议关闭样式隔离以提升性能:`` -#### 5、切换到iframe沙箱 +#### 5、切换到iframe沙箱 :id=iframe MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。 +```html + +``` ## 常见问题 -#### 1、使用`next/image`组件加载图片失败 +#### 1、使用`next/image`组件加载图片失败 :id=question-1 **解决方式:** 在部分nextjs版本中(如:nextjs 11),使用`next/image`组件无法正确引入图片,此时推荐使用img元素代替。 -#### 2、无法预加载ssr子应用 +#### 2、无法预加载ssr子应用 :id=question-2 **原因:**因为ssr应用每个路由地址加载的html、js、css等静态资源都不同,所以无法对ssr子应用使用预加载。 -#### 3、控制台报错`Cannot read properties of null (reading 'tagName')` +#### 3、控制台报错`Cannot read properties of null (reading 'tagName')` :id=question-3 **原因:**当主应用和子应用都是nextjs应用时,`next/head`组件冲突。 **解决方式:**去掉子应用中`next/head`组件。 -#### 4、webpack.jsonpFunction冲突,导致加载子应用失败 +#### 4、webpack.jsonpFunction冲突,导致加载子应用失败 :id=question-4 **原因:**当主应用和子应用都是官方脚手架创建的项目,容易造成webpack.jsonpFunction冲突。 **解决方式:**修改子应用的webpack配置。 diff --git a/docs/zh-cn/framework/nuxtjs.md b/docs/zh-cn/framework/nuxtjs.md index dfa5e61a6..9d1ac14ce 100644 --- a/docs/zh-cn/framework/nuxtjs.md +++ b/docs/zh-cn/framework/nuxtjs.md @@ -1,6 +1,6 @@ 本篇以`nuxtjs 2`作为案例介绍nuxtjs的接入方式,其它版本nuxtjs接入方式会在后续补充,如果你在使用时出现问题,请在github上提issue告知我们。 -## 作为主应用 +## 作为主应用 :id=main #### 1、安装依赖 ```bash @@ -30,16 +30,13 @@ export default { ``` -#### 3、在页面中嵌入子应用 +#### 3、在页面中加载子应用 因为micro-app只能运行在浏览器环境,所以在`mounted`钩子中通过变量控制子应用显示。 ```html ``` -## 作为子应用 +## 作为子应用 :id=child -#### 1、在主应用中添加ssr配置 +#### 1、在主应用中添加ssr配置 :id=ssr 当子应用是ssr应用时,主应用需要在micro-app元素上添加ssr属性,此时micro-app会根据ssr模式加载子应用。 ```html @@ -67,7 +64,7 @@ export default { ``` -#### 2、设置跨域支持 +#### 2、设置跨域支持 :id=Access-Control-Allow-Origin 通过自定义服务设置跨域访问。 **步骤1、在根目录创建`server.js`** @@ -121,12 +118,12 @@ app.listen(port, host, () => { ``` -#### 3、通过env注入运行时变量`assetPrefix` +#### 3、通过env注入运行时变量`assetPrefix` :id=assetPrefix `assetPrefix`为静态资源路径前缀,开发者需要手动通过`assetPrefix`补全图片地址,避免子应用的图片在使用相对地址时加载失败的情况。 ```js // nuxt.config.js -const basePath = '基础路由' // 默认为 '/' +const basePath = '基础路径' // 默认为 '/' // 静态资源路径前缀 const assetPrefix = process.env.NODE_ENV === 'production' ? `线上域名${basePath}` : `http://localhost:${process.env.PORT || 3000}${basePath}` @@ -135,7 +132,7 @@ module.exports = { env: { assetPrefix, }, - // 设置基础路由 + // 设置基础路径 router: { base: basePath, }, @@ -165,7 +162,7 @@ export default Vue.extend({ ``` -#### 4、监听卸载 +#### 4、监听卸载 :id=unmount 子应用被卸载时会接受到一个名为`unmount`的事件,在此可以进行卸载相关操作。 ```js @@ -175,15 +172,18 @@ window.addEventListener('unmount', function () { }) ``` -#### 5、切换到iframe沙箱 +#### 5、切换到iframe沙箱 :id=iframe MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。 +```html + +``` ## 常见问题 -#### 1、控制台抛出警告`[Vue warn]: Unknown custom element: ` +#### 1、控制台抛出警告`[Vue warn]: Unknown custom element: ` :id=question-1 **解决方式:**在`nuxt.config.js`中添加配置,设置`ignoredElements`忽略micro-app元素。 ```js @@ -204,6 +204,6 @@ module.exports = { > > nuxtjs相关问题可以在[nuxtjs专属讨论贴](https://github.com/micro-zoe/micro-app/issues/169)下反馈。 -#### 2、无法预加载ssr子应用 +#### 2、无法预加载ssr子应用 :id=question-2 **原因:**因为ssr应用每个路由地址加载的html、js、css等静态资源都不同,所以无法对ssr子应用使用预加载。 diff --git a/docs/zh-cn/framework/react.md b/docs/zh-cn/framework/react.md index 1de6ec1e9..0da8b6b7f 100644 --- a/docs/zh-cn/framework/react.md +++ b/docs/zh-cn/framework/react.md @@ -1,6 +1,6 @@ 本篇以`React 16、17`作为案例介绍react的接入方式,其它版本react的接入方式以此类推。我们默认开发者掌握了各版本react的开发技巧,如示例中useEffect,在不支持hooks的版本中转换为componentDidMount。 -## 作为主应用 +## 作为主应用 :id=main #### 1、安装依赖 ```bash @@ -15,12 +15,14 @@ import microApp from '@micro-zoe/micro-app' microApp.start() ``` -#### 3、在页面中嵌入子应用 +#### 3、在页面中加载子应用 + +通过注册的自定义元素``加载子应用 + ```js export function MyPage () { return (
    -

    子应用👇

    // name:应用名称, url:应用地址
    @@ -33,9 +35,9 @@ export function MyPage () { > > 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html -## 作为子应用 +## 作为子应用 :id=child -#### 1、设置跨域支持 +#### 1、设置跨域支持 :id=Access-Control-Allow-Origin 使用`create-react-app`脚手架创建的项目,在 `config/webpackDevServer.config.js` 文件中添加headers。 @@ -47,7 +49,7 @@ headers: { } ``` -#### 2、注册卸载函数 +#### 2、注册卸载函数 :id=unmount 子应用卸载时会自动执行`window.unmount`,在此可以进行卸载相关操作。 ```js @@ -59,41 +61,13 @@ window.unmount = () => { 完成以上步骤微前端即可正常渲染。 -### 可选设置 +### 可选设置 :id=options 以下配置是针对子应用的,它们是可选的,建议根据实际情况选择设置。 -#### 1、开启umd模式,优化内存和性能 -MicroApp支持两种渲染微前端的模式,默认模式和umd模式。 - -- **默认模式:**子应用在初次渲染和后续渲染时会顺序执行所有js,以保证多次渲染的一致性。 -- **umd模式:**子应用暴露出`mount`、`unmount`方法,此时只在初次渲染时执行所有js,后续渲染只会执行这两个方法,在多次渲染时具有更好的性能和内存表现。 - -如果子应用渲染和卸载不频繁,那么使用默认模式即可,如果子应用渲染和卸载非常频繁建议使用umd模式。 - -```js -// index.js -import React from "react" -import ReactDOM from "react-dom" -import App from './App' - -// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 -window.mount = () => { - ReactDOM.render(, document.getElementById("root")) -} +#### 1、开启umd模式,优化内存和性能 :id=umd +详情参考[umd模式](/zh-cn/umd)章节。 -// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 -window.unmount = () => { - ReactDOM.unmountComponentAtNode(document.getElementById("root")) -} - -// 如果不在微前端环境,则直接执行mount渲染 -if (!window.__MICRO_APP_ENVIRONMENT__) { - window.mount() -} -``` - - -#### 2、设置 webpack.jsonpFunction +#### 2、设置 webpack.jsonpFunction :id=webpackJsonpFunction 如果微前端正常运行,可以忽略这一步。 如果子应用资源加载混乱导致渲染失败,可以尝试设置`jsonpFunction`来解决,因为相同的`jsonpFunction`名称会导致资源污染。 @@ -129,10 +103,10 @@ module.exports = { -#### 3、设置 publicPath +#### 3、设置 publicPath :id=public-path 如果子应用出现静态资源地址404(js、css、图片),建议设置`publicPath`来尝试解决这个问题。 -`publicPath`是webpack提供的功能,所以vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) +`publicPath`是webpack提供的功能,vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) **步骤1:** 在子应用src目录下创建名称为`public-path.js`的文件,并添加如下内容 ```js @@ -149,11 +123,14 @@ if (window.__MICRO_APP_ENVIRONMENT__) { import './public-path' ``` -#### 4、切换到iframe沙箱 +#### 4、切换到iframe沙箱 :id=iframe MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。 +```html + +``` ## 常见问题 无 diff --git a/docs/zh-cn/framework/vite.md b/docs/zh-cn/framework/vite.md index 5f8f4fb9d..fcf61fc7e 100644 --- a/docs/zh-cn/framework/vite.md +++ b/docs/zh-cn/framework/vite.md @@ -1,12 +1,12 @@ 本篇介绍了`vite`的接入方式,如果在使用时出现问题,请在github上联系我们。 -## 作为主应用 +## 作为主应用 :id=base vite作为主应用时没有特殊之处,具体方式参考各框架接入文档。 -## 作为子应用 +## 作为子应用 :id=child vite作为子应用只需`切换到iframe沙箱`,其它操作参考各框架接入文档。 -##### 切换到iframe沙箱 +##### 切换到iframe沙箱 :id=iframe ```html @@ -14,7 +14,7 @@ vite作为子应用只需`切换到iframe沙箱`,其它操作参考各框架 ## 常见问题 -#### 1、子应用中操作location异常 +### 1、子应用中操作location异常 :id=question-1 **原因:**vite构建script的type为module,导致无法拦截location操作。 @@ -26,11 +26,9 @@ window.microApp.location.host window.microApp.location.origin window.microApp.location.href = 'xxx' window.microApp.location.pathname = 'xxx' +window.microApp.location.reload() +... ``` -#### 2、iframe沙箱加载了主应用的资源 - -**解决方式:**在主应用head最前面插入下面js -```html - -``` +### 2、iframe沙箱加载了主应用的资源 :id=question-2 +参考[JS沙箱常见问题-5](/zh-cn/sandbox?id=iframe-source) diff --git a/docs/zh-cn/framework/vue.md b/docs/zh-cn/framework/vue.md index 7e750f0cb..9d03cd4ff 100644 --- a/docs/zh-cn/framework/vue.md +++ b/docs/zh-cn/framework/vue.md @@ -1,6 +1,6 @@ 本篇以`Vue 2、3`作为案例介绍vue的接入方式。 -## 作为主应用 +## 作为主应用 :id=main #### 1、安装依赖 ```bash @@ -15,14 +15,14 @@ import microApp from '@micro-zoe/micro-app' microApp.start() ``` -#### 3、嵌入子应用 +#### 3、加载子应用 + +通过注册的自定义元素``加载子应用 + ```html ``` @@ -32,9 +32,9 @@ microApp.start() > 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html -## 作为子应用 +## 作为子应用 :id=child -#### 1、设置跨域支持 +#### 1、设置跨域支持 :id=Access-Control-Allow-Origin @@ -55,7 +55,7 @@ vite默认开启跨域支持,不需要额外配置。 -#### 2、注册卸载函数 +#### 2、注册卸载函数 :id=unmount 子应用卸载时会自动执行`window.unmount`,在此可以进行卸载相关操作。 @@ -87,91 +87,14 @@ window.unmount = () => { 完成以上步骤微前端即可正常渲染。 -### 可选设置 +### 可选设置 :id=options 以下配置是针对子应用的,它们是可选的,建议根据实际情况选择设置。 -#### 1、开启umd模式,优化内存和性能 -MicroApp支持两种渲染微前端的模式,默认模式和umd模式。 - -- **默认模式:**子应用在初次渲染和后续渲染时会顺序执行所有js,以保证多次渲染的一致性。 -- **umd模式:**子应用暴露出`mount`、`unmount`方法,此时只在初次渲染时执行所有js,后续渲染只会执行这两个方法,在多次渲染时具有更好的性能和内存表现。 - -如果子应用渲染和卸载不频繁,那么使用默认模式即可,如果子应用渲染和卸载非常频繁建议使用umd模式。 +#### 1、开启umd模式,优化内存和性能 :id=umd +详情参考[umd模式](/zh-cn/umd)章节。 - - -#### ** Vue2 ** -```js -// main.js -import Vue from 'vue' -import router from './router' -import App from './App.vue' - -let app = null -// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 -window.mount = () => { - app = new Vue({ - router, - render: h => h(App), - }).$mount('#app') -} - -// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 -window.unmount = () => { - app.$destroy() - app.$el.innerHTML = '' - app = null -} -// 如果不在微前端环境,则直接执行mount渲染 -if (!window.__MICRO_APP_ENVIRONMENT__) { - window.mount() -} -``` - -#### ** Vue3 ** -```js -// main.js -import { createApp } from 'vue' -import * as VueRouter from 'vue-router' -import routes from './router' -import App from './App.vue' - -let app = null -let router = null -let history = null -// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 -window.mount = () => { - history = VueRouter.createWebHistory() - router = VueRouter.createRouter({ - history, - routes, - }) - - app = createApp(App) - app.use(router) - app.mount('#app') -} - -// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 -window.unmount = () => { - app.unmount() - history.destroy() - app = null - router = null - history = null -} - -// 如果不在微前端环境,则直接执行mount渲染 -if (!window.__MICRO_APP_ENVIRONMENT__) { - window.mount() -} -``` - - - - -#### 2、设置 webpack.jsonpFunction +#### 2、设置 webpack.jsonpFunction :id=webpackJsonpFunction 如果微前端正常运行,则可以忽略这一步。 如果子应用资源加载混乱导致渲染失败,可以尝试设置`jsonpFunction`来解决,因为相同的`jsonpFunction`名称会导致资源污染。 @@ -221,10 +144,10 @@ module.exports = { -#### 3、设置 publicPath +#### 3、设置 publicPath :id=public-path 如果子应用出现静态资源地址404(js、css、图片),建议设置`publicPath`来尝试解决这个问题。 -`publicPath`是webpack提供的功能,所以vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) +`publicPath`是webpack提供的功能,vite应用是不支持的,它可以补全静态资源的地址,详情参考webpack文档 [publicPath](https://webpack.docschina.org/guides/public-path/#on-the-fly) **步骤1:** 在子应用src目录下创建名称为`public-path.js`的文件,并添加如下内容 ```js @@ -241,15 +164,18 @@ if (window.__MICRO_APP_ENVIRONMENT__) { import './public-path' ``` -#### 4、切换到iframe沙箱 +#### 4、切换到iframe沙箱 :id=iframe MicroApp有两种沙箱方案:`with沙箱`和`iframe沙箱`。 默认开启with沙箱,如果with沙箱无法正常运行,可以尝试切换到iframe沙箱。 +```html + +``` ## 常见问题 -#### 1、主应用中抛出警告,micro-app未定义 +#### 1、主应用中抛出警告,micro-app未定义 :id=question-1 **报错信息:** - vue2: `[Vue warn]: Unknown custom element: ` @@ -311,32 +237,38 @@ export default defineConfig({ ``` -#### 2、虚拟路由系统为search模式时主应用循环刷新 +#### 2、Vue主应用加载子应用或跳转时子应用频繁卸载和渲染 :id=question-2 -**解决方式:**将router-view或者包含微前端的上层组件中`:key="route.fullPath"`改为`:key="route.path"`或者`:key="route.name"` +**原因:**如果将`route.fullPath`或`route.path`设置为key,那么当路由变化时Vue会重新渲染组件,导致``元素被频繁卸载和渲染。 -**例如:** +**解决方式:**将主应用中``或包含``元素的上层组件中`:key="route.fullPath"`或`:key="route.path"`改为`:key="route.name"` ```html + + + + + + + +``` + +**例如:** +```html +将: - + + - +修改为: - + + ``` - -```html - - - - - -``` diff --git a/docs/zh-cn/micro-app-devtools.md b/docs/zh-cn/micro-app-devtools.md index a421816b1..5568fa695 100644 --- a/docs/zh-cn/micro-app-devtools.md +++ b/docs/zh-cn/micro-app-devtools.md @@ -4,7 +4,8 @@ Github 地址为:[https://github.com/micro-zoe/micro-app-chrome-plugin](https: # 如何使用 -下载[插件地址](https://github.com/micro-zoe/micro-app-chrome-plugin/raw/master/micro-app-chrome-plugin.zip),(提示:无需解压),在chrome中输入[chrome://extensions](chrome://extensions)打开扩展程序,将已下载的插件拖入。 +在chrome中输入`chrome://extensions`打开扩展程序,打开[插件下载地址](https://github.com/micro-zoe/micro-app-chrome-plugin/releases),选择最新Release包的`micro-app-chrome-plugin.zip` +文件下载,无需解压,将已下载的插件拖入。 ![扩展程序](https://img12.360buyimg.com/imagetools/jfs/t1/119438/16/38287/53001/646b50e3F9012f2e8/3bba9844bbb1431b.png) @@ -13,29 +14,19 @@ Github 地址为:[https://github.com/micro-zoe/micro-app-chrome-plugin](https: ## 1、Environment环境 -可查看`Micro app`的`Environment`环境如下 +可查看`Micro app`的全局变量,目前显示的是最后一次加载的微应用信息,并支持点击具体条目跳转到官方文档说明。 -```js -'__MICRO_APP_ENVIRONMENT__': '判断应用是否在微前端环境中' -'__MICRO_APP_VERSION__': '微前端版本号' -'__MICRO_APP_NAME__': '应用名称' -'__MICRO_APP_PUBLIC_PATH__': '子应用的静态资源前缀' -'__MICRO_APP_BASE_ROUTE__': '子应用的基础路由' -``` - -![控制台](https://m.360buyimg.com/babel/jfs/t1/92170/34/45320/165007/650c20d5F5db8671a/7472d637694733c6.png) +![控制台](https://img14.360buyimg.com/imagetools/jfs/t1/249320/9/3342/57393/65a73e41Fe655b286/feb7e2aa224d0481.jpg) ## 2、Communicate通讯 -查看父子应用通讯 -数据通信面板 - -### 功能一、获取父应用数据 -点击按钮获取当前被嵌入页面基座应用的JSON格式数据 +用于查看页面`Micro app`微应用结构、基本信息,以及模拟发送接收数据。 +左侧展示的是页面微应用的层级结构,可选择对其进行操作。右侧上部显示当前应用的基本信息,包括名称、路由、iframe模式及版本号等信息。还可对其进行高亮标记,方便快速定位。 +所有应用均支持模拟获取数据及发送数据,并可自动储存历史记录。 -![数据](https://m.360buyimg.com/babel/jfs/t1/134966/38/37257/31060/650bfcb8Fd7206838/d80ac758e26cab7d.png) +![通讯](https://img14.360buyimg.com/imagetools/jfs/t1/242631/34/3623/54593/65a73e41Fabc284b6/61d467579d7a922e.jpg) -### 功能二、子应用开发环境模拟 +### 3、子应用开发环境模拟 点击按钮跳转至功能一中子应用开发环境模拟页面,此处模仿内嵌子应用,使用说明如下所示: 在子应用开发环境模拟页面中输入子页面`URL`等信息 @@ -57,26 +48,16 @@ Github 地址为:[https://github.com/micro-zoe/micro-app-chrome-plugin](https: #### 快捷打开方式二 点击鼠标右键,选择micro-app下,二级菜单点子应用开发环境模拟 -![快捷方式](https://m.360buyimg.com/babel/jfs/t1/172993/25/37523/30273/64a6384eF736c8180/59fa4375248f460f.png) -## 3、View子应用视图 -查看子应用相关视图信息 -### 查看子应用范围 -点击按钮即可获取当前被嵌入页面基座应用的视图 +![快捷方式](https://github.com/micro-zoe/micro-app-chrome-plugin/assets/14011130/91b40f7c-a826-4ffe-8c20-0b43a5c3bc6f) + -![嵌入页面](https://m.360buyimg.com/babel/jfs/t1/122818/13/33795/75508/64a6376dFda233623/601deb9d6e6c01ec.png) -#### 快捷打开方式 -点击鼠标右键,选择micro-app下,二级菜单点击查看子应用范围 -![快捷方式](https://m.360buyimg.com/babel/jfs/t1/138697/34/36942/29835/64a637f4F11b0ec84/87108f5df15e1b4b.png) +## 常见问题 +### 1、baseroute? +现象:插件系统的路由模块中,获取子应用链接功能与用户在嵌入微前端时是否使用到baseroute有很大的联系,如果用户配置了baseroute并且子应用路由确实使用了,则会获取正确的子应用链接,相反则可能会获取错误的子应用链接。 -## 4、Route路由 -查看子应用路由信息 +校正:若子应用与配置的baseroute无关联,建议删除配置顶baseroute。 -![快捷方式](https://m.360buyimg.com/babel/jfs/t1/104185/16/45873/134059/650bf92cFd2de845e/83d692c452ce2abb.png) -### 功能一、获取子应用路由 -点击查看子应用URL按钮即可获取当前页面下所有子应用的路由地址 -### 功能二、复制及打开子应用路由链接 -点击复制按钮复制子应用路由,点击打开按钮直接在浏览器打开子应用链接地址 ## 🤝 参与共建 @@ -85,5 +66,3 @@ Github 地址为:[https://github.com/micro-zoe/micro-app-chrome-plugin](https: ![image](https://img12.360buyimg.com/imagetools/jfs/t1/29962/13/20207/70265/646c9851Fe104e7c1/fed2ab97e2cf5f29.png) - - diff --git a/docs/zh-cn/native-mode.md b/docs/zh-cn/native-mode.md index 80c5c2a28..daef6f765 100644 --- a/docs/zh-cn/native-mode.md +++ b/docs/zh-cn/native-mode.md @@ -1,159 +1,306 @@ -native模式是指放开路由隔离,主应用和子应用同时基于浏览器路由进行渲染,共用同一套location和history,拥有更好的用户体验,但更容易导致主应用和子应用的路由冲突,具体原理参考[关于native模式的原理解析](/zh-cn/native-mode?id=关于native模式的原理解析)。 +不同于其它路由模式通过search参数或history.state进行路由隔离,native模式是指放开路由隔离,主应用和子应用同时基于浏览器地址进行渲染,也都会直接修改浏览器地址。 -native模式需要更加复杂的路由配置,主应用和子应用的路由都要进行一些改造。 +它拥有更好的用户体验,但也更容易导致主应用和子应用的路由冲突,所以需要更加复杂的路由配置,要对主应用和子应用路由进行一些改造。 -### 路由类型约束 -native模式下主、子应用需要遵循以下约束: -- 1、主应用是hash路由,子应用也必须是hash路由 -- 2、主应用是history路由,子应用可以是hash或history路由 +实际上主应用和子应用的路由即同时基于浏览器地址进行渲染,又相互独立,我们通过路由配置让两个独立的路由系统实现共存,具体原理参考[关于native模式的原理解析](/zh-cn/native-mode?id=关于native模式的原理解析)。 -### 基础路由 -**作用:** +### 基础路径 :id=base +基础路径即vue-router的[base](https://router.vuejs.org/zh/api/interfaces/RouterHistory.html#Properties-base)、react-router的[basename](https://reactrouter.com/en/main/router-components/browser-router#basename),通常与应用托管在服务器的文件夹地址一致,但在微前端下子应用基础路径的设置有所不同,需要根据主应用的地址动态设置。 -通常主应用和子应用各有一套路由系统,为了防止冲突,主应用需要分配一个路由给子应用,称之为基础路由,子应用可以在这个路由下渲染,但不能超出这个路由的范围,这就是基础路由的作用。 +由于主应用和子应用各有一套路由系统,为了防止冲突,主应用需要分配一个基础路径给子应用,子应用在这个路径下渲染,且不能超出这个路径的范围,实现主应用和子应用的并行渲染。 -**使用方式** +例如:如果子应用运行在主应用的 `/app/` 路径下,那么子应用的基础路径应设置为 `'/app/'`。 -主应用中通过设置 ``的`baseroute`属性下发,子应用通过`window.__MICRO_APP_BASE_ROUTE__`获取此值并设置基础路由。 +**注意:** + - 1、如果主应用是history路由,子应用是hash路由,主、子不需要做任何修改,以下设置可以忽略。 + - 2、如果主应用是hash路由,子应用也必须是hash路由,否则无法正常渲染。 + - 3、如果主、子同时是history路由或同时是hash路由,则按照下面的方式设置基础路径。 -**注意点:** -- 1、如果主应用是history路由,子应用是hash路由,不需要设置基础路由baseroute -- 2、如果子应用只有一个页面,没有使用`react-router`,`vue-router`之类,也不需要设置基础路由baseroute -- 3、vue-router在hash模式下无法通过base设置基础路由,需要创建一个空的路由页面,将其它路由作为它的children,具体设置如下: +#### 设置基础路径: :id=baseroute -```js -import RootApp from './root-app.vue' - -const routes = [ - { - path: window.__MICRO_APP_BASE_ROUTE__ || '/', - component: RootApp, - children: [ - // 其他的路由都写到这里 - ], - }, -] -``` - -`root-app.vue`内容如下: -```html - -``` +主应用通过`baseroute`下发基础路径的值,子应用通过`window.__MICRO_APP_BASE_ROUTE__`获取此值并设置基础路径。 - -**示例** - -**React** +#### 主应用 :id=main -#### ** 主应用 ** +#### ** react16 ** +**1、设置路由:**history路由和hash路由的配置方式一样,这里不做区分 + +限制:react-router版本为4.x或5.x ```js // router.js import { BrowserRouter, Switch, Route } from 'react-router-dom' -import ChildPage from './child-page' +import MyPage from './my-page' -export default function AppRoute () { +export function App () { return ( - // 非严格匹配,/child/* 都指向ChildPage组件 - // /child 就是分配给子应用的基础路由baseroute + // 设置动态路由,/child/one、child/two,以及所有/child开头的路由都指向MyPage组件 - + ) } +``` -// child-page.js -export function ChildPage () { +**2、设置baseroute:** +```js +// my-page.js +export function MyPage () { return (
    -

    子应用

    - + {/* 如果主应用也有基础路径,那么 baseroute = 主应用基础路径 + '/child' */} +
    ) } ``` -#### ** 子应用 ** +#### ** react18 ** + +**1、设置路由:**history路由和hash路由的配置方式一样,这里不做区分 + +限制:react-router版本为6.x ```js -import { BrowserRouter, Switch, Route } from 'react-router-dom' +// router.js +import { BrowserRouter, Routes, Route } from 'react-router-dom' +import MyPage from './my-page' -export default function AppRoute () { +export function App () { return ( - // 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取主应用下发的baseroute,如果没有设置baseroute属性,则此值默认为空字符串 - - ... + + + // 设置动态路由,/child/one、child/two,以及所有/child开头的路由都指向MyPage组件 + } + /> + ) } ``` - -**Vue** - - +**2、设置baseroute:** +```js +// my-page.js +export function MyPage () { + return ( +
    + {/* 如果主应用也有基础路径,那么 baseroute = 主应用基础路径 + '/child' */} + +
    + ) +} +``` -#### ** 主应用 ** +#### ** vue2 ** +**1、设置路由:**history路由和hash路由的配置方式一样,这里不做区分 ```js // router.js import Vue from 'vue' import VueRouter from 'vue-router' -import ChildPage from './child-page.vue' +import MyPage from './my-page.vue' Vue.use(VueRouter) const routes = [ { - // /child/* 都指向ChildPage组件 - path: '/child/*', // vue-router@4.x path的写法为:'/child/:page*' + // 设置动态路由,/child/one、child/two,以及所有/child开头的路由都指向MyPage组件 + path: '/child/*', + name: 'child', + component: MyPage, + }, + // 其它配置... +] + +export default routes +``` + +**2、设置baseroute:** +```html +// my-page.vue + +``` + +#### ** vue3 ** + +**1、设置路由:**history路由和hash路由的配置方式一样,这里不做区分 +```js +// router.js +import MyPage from './my-page.vue' + +const routes = [ + { + // 设置动态路由,/child/one、child/two,以及所有/child开头的路由都指向MyPage组件 + path: '/child/:page*', name: 'child', - component: ChildPage, + component: MyPage, }, + // 其它配置... ] export default routes +``` -// child-page.vue +**2、设置baseroute:** +```html +// my-page.vue ``` -#### ** 子应用 ** + + +#### 子应用 :id=child + + +#### ** react16 ** + +**设置基础路径:**history路由和hash路由的配置方式一样,这里不做区分 +```js +import { BrowserRouter, Switch, Route } from 'react-router-dom' + +export default function App () { + return ( + // 设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 + + // ... + + ) +} +``` + +#### ** react18 ** + +**设置基础路径:**history路由和hash路由的配置方式一样,这里不做区分 +```js +import { BrowserRouter, Routes, Route } from 'react-router-dom' + +export default function App () { + return ( + // 设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 + + // ... + + ) +} +``` + + +#### ** vue2 ** +**设置基础路径:** + + + +#### **history路由** ```js import Vue from 'vue' import VueRouter from 'vue-router' -import routes from './router' const router = new VueRouter({ - // 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取主应用下发的baseroute,如果没有设置baseroute属性,则此值默认为空字符串 + mode: 'history', + // 设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 base: window.__MICRO_APP_BASE_ROUTE__ || '/', - routes, + // 其它配置... }) +``` + +#### **hash路由** +vue2在hash模式下无法通过[base](https://v3.router.vuejs.org/zh/api/#base)设置基础路径,需要通过一个空的路由页面包裹实现,具体方式如下: -let app = new Vue({ - router, - render: h => h(App), -}).$mount('#app') +1、创建`root-app.vue`文件,内容如下: +```html + ``` + +2、将`root-app.vue`设置为基础页面,将其它路由作为它的children,children配置中的path要改为相对地址 +```js +import RootApp from './root-app.vue' + +const routes = [ + { + // 设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 + path: window.__MICRO_APP_BASE_ROUTE__ || '/', + component: RootApp, + children: [ + // 其它路由都写到这里,且path要改为相对地址 + ], + }, +] +``` + +3、跳转时补全路由地址 + +由于将`root-app.vue`设置为基础页面,跳转时要用window.__MICRO_APP_BASE_ROUTE__补全地址,例如: +```js +this.$router.push(window.__MICRO_APP_BASE_ROUTE__ + path) +``` +```html + +``` + -> [!TIP] -> vue-router@4.x设置base的方式请查看 https://next.router.vuejs.org/ -### 关于native模式的原理解析 -**原理:**子应用根据浏览器地址渲染对应的页面,而不是micro-app的url属性 +#### ** vue3 ** + +**设置基础路径:** + + +#### **history路由** + +```js +import { createRouter, createWebHistory } from 'vue-router' + +const router = createRouter({ + // 设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 + history: createWebHistory(window.__MICRO_APP_BASE_ROUTE__ || '/'), + // 其它配置... +}) +``` + +#### **hash路由** + +```js +import { createRouter, createWebHashHistory } from 'vue-router' + +const router = createRouter({ + /** + * 1、设置基础路径,window.__MICRO_APP_BASE_ROUTE__为主应用下发的baseroute,默认为空字符串 + * 2、vue3中hash模式的base需要以'#'开头,这里我们手动用'#'补全 + */ + history: createWebHashHistory(window.__MICRO_APP_BASE_ROUTE__ ? `/#${window.__MICRO_APP_BASE_ROUTE__}` : '/'), + // 其它配置... +}) +``` + + + + + + +### 关于native模式的原理解析 :id=principle +主应用和子应用的路由系统既相互独立又同时基于浏览器地址进行渲染。 + +相互独立:是指主应用和子应用是基于各自前端框架生成的路由系统,自身的路由变化不会直接影响对方,一方跳转到新的地址后,另外一方不会自动响应浏览器变化(除非刷新浏览器或者主动发送`PopStateEvent`事件)。 + +同时基于浏览器地址进行渲染:是指同一个浏览器地址,同时满足主应用和子应用的路由匹配,渲染自身页面。 + +**注意:**子应用基于浏览器地址进行渲染,而不是micro-app的url属性 ##### 例1: @@ -177,7 +324,7 @@ let app = new Vue({ ##### 例2: -场景:主应用是history路由,子应用也是history路由,我们要跳转主应用的`my-app`页面,`my-app`页面中嵌入子应用,我们要展现子应用的`page1`页面。 +场景:主应用是history路由,子应用也是history路由,我们要跳转主应用的`my-app`页面,`my-app`页面中嵌入了子应用,我们要展现子应用的`page1`页面。 那么浏览器地址应该为:`http://主应用域名/my-page/page1`,我们在主应用中跳转的参数为:`router.push('/my-page/page1')` @@ -185,27 +332,27 @@ let app = new Vue({ micro-app配置如下: ```html - + ``` ##### 例3: -场景:主应用是hash路由,子应用也是hash路由,我们要跳转主应用的`my-app`页面,`my-app`页面中嵌入子应用,我们要展现子应用的`page1`页面。 +场景:主应用是hash路由,子应用也是hash路由,我们要跳转主应用的`my-app`页面,`my-app`页面中嵌入了子应用,我们要展现子应用的`page1`页面。 那么浏览器地址应该为:`http://主应用域名/#/my-page/page1`,我们在主应用中跳转的参数为:`router.push('/my-page/page1')` 原理:主应用匹配到`#/my-page`路径并渲染`my-app`页面,因为`my-app`页面中嵌入了子应用,此时子应用开始加载并渲染,子应用在渲染时会匹配到`#/my-page/page1`并渲染`page1`页面。 ```html - + ``` ##### 例4: -场景:主应用是history路由,子应用是hash路由,我们要跳转主应用的`my-app`页面,页面中嵌入子应用,我们要展现子应用的`page1`页面。 +场景:主应用是history路由,子应用是hash路由,我们要跳转主应用的`my-app`页面,页面中嵌入了子应用,我们要展现子应用的`page1`页面。 那么浏览器地址应该为:`http://主应用域名/my-page/#/page1`,我们在主应用中跳转`my-app`页面的参数为:`router.push('/my-page/#/page1')` diff --git a/docs/zh-cn/nest.md b/docs/zh-cn/nest.md index dcf1802fd..05613464f 100644 --- a/docs/zh-cn/nest.md +++ b/docs/zh-cn/nest.md @@ -1,17 +1,32 @@ -`micro-app`支持多层嵌套,即子应用可以嵌入其它子应用,但为了防止标签名冲突,子应用中需要做一些修改。 +`micro-app`支持多层嵌套,即子应用可以嵌入其它子应用,但需要做一些修改。 -在`子应用`中设置`tagName`: +例如:A嵌套B,B嵌套C,B作为中间层应用需要做出如下修改: + +#### 步骤1: + +为了防止标签名冲突,在B应用中自定义`tagName`。 ```js +import microApp from '@micro-zoe/micro-app'; + microApp.start({ - tagName: 'micro-app-xxx', // 标签名称必须以 `micro-app-` 开头 + // 必须是以`micro-app-`开头的小写字母,例如:micro-app-b、micro-app-b-c + tagName: 'micro-app-xxx', }) ``` -在子应用中使用新定义的标签进行渲染,如: +在B中使用新定义的标签加载C: ```html - + ``` -> [!WARNING] -> 无论嵌套多少层,name都要保证全局唯一。 +#### 步骤2: + +将B应用切换为umd模式,详情参考[umd](/zh-cn/umd)。 + + +> [!NOTE] +> +> 1、无论嵌套多少层,name都要保证全局唯一。 +> +> 2、确保micro-app的版本一致,不同版本可能会导致冲突。 diff --git a/docs/zh-cn/questions.md b/docs/zh-cn/questions.md index 9ac9beb58..d8ff681eb 100644 --- a/docs/zh-cn/questions.md +++ b/docs/zh-cn/questions.md @@ -1,4 +1,4 @@ -## 1、我需要用到微前端吗? +## 1、我需要用到微前端吗? :id=1 在此之前建议你先阅读[Why Not Iframe](https://www.yuque.com/kuitos/gky7yw/gesexv)。 相比于iframe,微前端拥有更好的用户体验,同时它也要求开发者对于前端框架和路由原理具有一定的理解。 @@ -9,21 +9,12 @@ 如果你不知道自己是否需要用微前端,那么大概率是不需要。 -## 2、子应用一定要支持跨域吗? +## 2、子应用一定要支持跨域吗? :id=2 是的! -如果是开发环境,可以在webpack-dev-server中设置headers支持跨域。 -```js -devServer: { - headers: { - 'Access-Control-Allow-Origin': '*', - }, -}, -``` - -如果是线上环境,可以通过[配置nginx](https://segmentfault.com/a/1190000012550346)支持跨域。 +micro-app从主应用通过fetch加载子应用的静态资源,由于主应用与子应用的域名不一定相同,所以子应用必须支持跨域。 -## 3、兼容性如何 +## 3、兼容性如何 :id=3 micro-app依赖于CustomElements和Proxy两个较新的API。 对于不支持CustomElements的浏览器,可以通过引入polyfill进行兼容,详情可参考:[webcomponents/polyfills](https://github.com/webcomponents/polyfills/tree/master/packages/custom-elements)。 @@ -37,66 +28,25 @@ micro-app依赖于CustomElements和Proxy两个较新的API。 - 移动端:ios10+、android5+ -## 4、micro-app 报错 an app named xx already exists +## 4、micro-app 报错 an app named xx already exists :id=4 这是`name`名称冲突导致的,请确保每个子应用的`name`值是唯一的。 -## 5、主应用的样式影响到子应用 +## 5、主应用的样式影响到子应用 :id=5 虽然我们将子应用的样式进行隔离,但主应用的样式依然会影响到子应用,如果发生冲突,推荐通过约定前缀或CSS Modules方式解决。 如果你使用的是`ant-design`等组件库,一般会提供添加前缀进行样式隔离的功能。 -## 6、子应用在沙箱环境中如何获取到外部真实window? - 目前有3种方式在子应用中获取外部真实window - - 1、new Function("return window")() 或 Function("return window")() - - 2、(0, eval)('window') - - 3、window.rawWindow - -## 7、错误信息:xxx undefined - -**包括:** -- `xxx is not defined` -- `xxx is not a function` -- `Cannot read properties of undefined` - -**原因:** - -在微前端的沙箱环境中,顶层变量不会泄漏为全局变量。 +## 6、子应用如何获取到真实window、document :id=6 +子应用通过:`window.rawWindow`、`window.rawDocument` 可以获取真实的window、document -例如在正常情况下,通过 var name 或 function name () {} 定义的顶层变量会泄漏为全局变量,通过window.name或name就可以全局访问。 +## 7、子应用抛出错误信息:xxx 未定义 :id=7 +参考[JS沙箱常见问题-1](/zh-cn/sandbox?id=undefined) -但是在沙箱环境下这些顶层变量无法泄漏为全局变量,window.name或name为undefined,导致出现问题。 +## 8、jsonp请求如何处理? :id=8 +参考[ignore](/zh-cn/configure?id=ignore忽略元素) -**解决方式**: -*方式一:手动修改* - -将 var name 或 function name () {} 修改为 window.name = xx - -*方式二:通过插件系统修改子应用代码* - -比如常见的加载webpack打包的dll文件失败的问题,因为dll文件的内容和js地址相对固定,可以直接进行全局查找和修改。 -```js -microApp.start({ - plugins: { - modules: { - 应用名称: [{ - loader(code, url) { - if (url === 'xxx.js') { - code = code.replace('var xx_dll=', 'window.xx_dll=') - } - return code - } - }] - } - } -}) -``` - -## 8、jsonp请求如何处理? - 参考[ignore](/zh-cn/configure?id=ignore忽略元素) - - -## 9、子应用通过a标签下载文件失败 +## 9、子应用通过a标签下载文件失败 :id=9 **原因:**当跨域时(主应用和文件在不同域名下),无法通过a标签的download属性实现下载。 **解决方式:** @@ -129,7 +79,7 @@ microApp.start({ **方式2:**将文件放到主应用域名下,判断微前端环境下a标签href属性设置为主应用的文件地址 -## 10、iconfont 图标冲突了如何处理? +## 10、iconfont 图标冲突了如何处理? :id=10 | 产生原因 | 解决方案 | | ----------------------------------------------- | ------------------------------------------------------------ | @@ -166,43 +116,25 @@ microApp.start({ + ``` -## 11、Vue主应用接入微前端时循环刷新(页面闪烁) +## 11、子应用script元素被注释、消失 :id=11 +默认情况下,子应用的js会被提取并在后台运行,script元素原位置会留下注释:`` -**解决方式:**将主应用router-view或者包含微前端的上层组件中`:key="route.fullPath"`改为`:key="route.path"`或者`:key="route.name"` +如果想要保留script元素,可以开启inline模式,配置方式参考:[inline](/zh-cn/configure?id=inline) -**例如:** +## 12、Vue主应用接入微前端时循环刷新(页面闪烁) :id=12 +参考[Vue常见问题-2](/zh-cn/framework/vue?id=question-2) -```html - - - - - - - - - - - - - -``` +## 13、子应用使用`Module Federation`模块联邦时报错 :id=13 +参考[JS沙箱常见问题-2](/zh-cn/sandbox?id=module-federation) -```html - - +## 14、子应用`DllPlugin`拆分的文件加载失败 :id=14 +参考[JS沙箱常见问题-3](/zh-cn/sandbox?id=dllplugin) - - -``` - -## 12、iframe沙箱加载了主应用的资源 - -**解决方式:**如果主应用不会作为iframe嵌入,可以在主应用head最前面插入下面js -```html - -``` +## 15、iframe沙箱加载了主应用的资源 :id=15 +参考[JS沙箱常见问题-4](/zh-cn/sandbox?id=iframe-source) -## 13、一个页面加载过多个微前端 +## 16、内存泄漏 :id=16 +参考[JS沙箱常见问题-5](/zh-cn/sandbox?id=memory) -微前端在过多加载和深度嵌套时,要谨慎使用,尤其同个页面在不同版本微前端之间可能会有相互影响,使用者要酌情处理。 \ No newline at end of file +## 17、一个页面加载过多个微前端 :id=17 +微前端在过多加载和深度嵌套时,要谨慎使用,尤其同个页面在不同版本微前端之间可能会有相互影响,使用者要酌情处理。 diff --git a/docs/zh-cn/router.md b/docs/zh-cn/router.md index bbb17182f..b1fe7fbe7 100644 --- a/docs/zh-cn/router.md +++ b/docs/zh-cn/router.md @@ -2,8 +2,8 @@ MicroApp通过拦截浏览器路由事件以及自定义的location、history, 虚拟路由系统还提供了丰富的功能,帮助用户提升开发效率和使用体验。 -## 路由模式 -虚拟路由系统分为四种模式:`search`、`native`、`native-scope`、`pure` +## 路由模式 :id=router-mode +虚拟路由系统的模式有:`search`、`native`、`native-scope`、`pure`、`state`,每种模式对应不同的表现和功能,以满足尽可能多的项目需求,通过配置`router-mode`可以切换到不同的路由模式。 #### ** search模式 ** @@ -13,12 +13,14 @@ search是默认模式,通常不需要特意设置,search模式下子应用 **切换方式:** -设置单个子应用: +- 设置单个子应用: + ```html - ``` -全局设置: + +- 全局设置: + ```js import microApp from '@micro-zoe/micro-app' @@ -27,47 +29,21 @@ microApp.start({ }) ``` -**注意:search模式可能会导致Vue主应用循环刷新** - -**解决方式:**将router-view或者包含微前端的上层组件中`:key="route.fullPath"`改为`:key="route.path"`或者`:key="route.name"` - -**例如:** - -```html - - - - - - - - - - - - - -``` - -```html - - - - - -``` +**常见问题:**主应用为Vue时,嵌入子应用后页面循环刷新(页面闪烁),解决方式参考[Vue常见问题-2](/zh-cn/framework/vue?id=question-2) #### ** native模式 ** -native模式是指放开路由隔离,子应用和主应用共同基于浏览器路由进行渲染,它拥有更加直观和友好的路由体验,但更容易导致主应用和子应用的路由冲突,且需要更加复杂的路由配置,详情参考[native-mode](/zh-cn/native-mode) +native模式是指放开路由隔离,子应用和主应用共同基于浏览器路由进行渲染,它拥有更加直观和友好的路由体验,但配置方式更加复杂,详情参考[native-mode](/zh-cn/native-mode) **切换方式:** -设置单个子应用: +- 设置单个子应用: + ```html - ``` -全局设置: + +- 全局设置: + ```js import microApp from '@micro-zoe/micro-app' @@ -75,18 +51,21 @@ microApp.start({ 'router-mode': 'native', // 所有子应用都设置为native模式 }) ``` +**常见问题:**主应用为Vue时,路由跳转后子应用频繁卸载和渲染,解决方式参考[Vue常见问题-2](/zh-cn/framework/vue?id=question-2) #### ** native-scope模式 ** native-scope模式的功能和用法和native模式一样,唯一不同点在于native-scope模式下子应用的域名指向自身而非主应用。 **切换方式:** -设置单个子应用: +- 设置单个子应用: + ```html - ``` -全局设置: + +- 全局设置: + ```js import microApp from '@micro-zoe/micro-app' @@ -95,17 +74,21 @@ microApp.start({ }) ``` +**常见问题:**主应用为Vue时,路由跳转后子应用频繁卸载和渲染,解决方式参考[Vue常见问题-2](/zh-cn/framework/vue?id=question-2) + #### ** pure模式 ** -pure模式是指子应用独立于浏览器进行渲染,即不修改浏览器地址,也不增加路由堆栈,pure模式下的子应用更像是一个组件。 +pure模式是指子应用独立于浏览器路由系统进行渲染,即不修改浏览器地址,也不增加路由堆栈,pure模式下的子应用更像是一个组件。 **切换方式:** -设置单个子应用: +- 设置单个子应用: + ```html - ``` -全局设置: + +- 全局设置: + ```js import microApp from '@micro-zoe/micro-app' @@ -115,18 +98,20 @@ microApp.start({ ``` #### ** state模式 ** -state模式是指基于浏览器history.state进行渲染的路由模式,在不修改浏览器地址的情况下模拟各种路由行为,相比其它路由模式更加简洁优雅。 +state模式是指基于浏览器history.state进行渲染的路由模式,在不修改浏览器地址的情况下模拟路由行为,相比其它路由模式更加简洁优雅。 -state模式的表现和iframe类似,但却没有iframe存在的问题。 +state模式的表现和iframe路由系统类似,但却没有iframe路由存在的问题。 **切换方式:** -设置单个子应用: +- 设置单个子应用: + ```html - ``` -全局设置: + +- 全局设置: + ```js import microApp from '@micro-zoe/micro-app' @@ -138,8 +123,8 @@ microApp.start({ -## 配置项 -#### 1、关闭虚拟路由系统 +## 配置项 :id=configuration +#### 1、关闭虚拟路由系统 :id=disable-memory-router 实际上虚拟路由系统是无法关闭的,这里的配置只是为了向下兼容旧版本,它的表现和native路由模式一致。 **使用方式:** @@ -159,7 +144,7 @@ microApp.start({ }) ``` -#### 2、保留路由状态 +#### 2、保留路由状态 :id=keep-router-state 默认情况下,子应用卸载后重新渲染,将和首次加载一样渲染子应用的首页。 设置`keep-router-state`可以保留子应用路由状态,在卸载后重新渲染时将恢复卸载前的页面(页面中的状态不保留)。 @@ -187,7 +172,7 @@ microApp.start({ -## 导航 +## 导航 :id=navigation 通过虚拟路由系统,我们可以方便的进行跨应用的跳转,如: 1. 主应用控制子应用跳转 2. 子应用控制主应用跳转 @@ -346,7 +331,7 @@ baseRouter.主应用路由的方法(...) * @param {string} path 必填,子应用除域名外的全量地址(也可以带上域名) * @param {boolean} replace 可选,是否使用replace模式,不新增堆栈记录,默认为false */ -router.push({ name: '子应用名称', path: '页面地址', replace: 是否使用replace模式 }) +window.microApp.router.push({ name: '子应用名称', path: '页面地址', replace: 是否使用replace模式 }) ``` **示例:** @@ -376,7 +361,7 @@ window.microApp.router.push({name: 'my-app', path: '/page1', replace: true }) * @param {string} path 必填,子应用除域名外的全量地址(也可以带上域名) * @param {boolean} replace 可选,是否使用replace模式,默认为true */ -router.replace({ name: '子应用名称', path: '页面地址', replace: 是否使用replace模式 }) +window.microApp.router.replace({ name: '子应用名称', path: '页面地址', replace: 是否使用replace模式 }) ``` **示例:** @@ -404,7 +389,7 @@ window.microApp.router.replace({name: 'my-app', path: '/page1', replace: false } /** * @param {number} n 前进或后退多少步 */ -router.go(n) +window.microApp.router.go(n) ``` **示例:** @@ -418,10 +403,7 @@ window.microApp.router.go(3) ### router.back -**介绍:**它的功能和window.history.back()一致,表示在历史堆栈中后退一步。 -```js -router.back() -``` +**介绍:**它的功能和window.history.back一致,表示在历史堆栈中后退一步。 **示例:** ```js @@ -431,10 +413,7 @@ window.microApp.router.back() ### router.forward -**介绍:**它的功能和window.history.forward()一致,表示在历史堆栈中前进一步。 -```js -router.forward() -``` +**介绍:**它的功能和window.history.forward一致,表示在历史堆栈中前进一步。 **示例:** ```js @@ -445,14 +424,14 @@ window.microApp.router.forward() -## 设置默认页面 +## 设置默认页面 :id=default-page 子应用默认渲染首页,但可以通过设置`defaultPage`渲染指定的默认页面。 **注意事项:** - 1、defaultPage只在初始化渲染时有效,控制子应用跳转请参考[导航](/zh-cn/router?id=导航) -- 2、defaultPage必须是子应用页面的绝对地址,为了防止设置错误,建议单独打开子应用,跳转目标页面,复制粘贴浏览器地址,包括hash和search,将此值设置为`defaultPage`,也可以去掉域名,简化代码 -- 3、由于`native`、`native-scope`模式是基于浏览器进行渲染,通过浏览器url控制子应用渲染的页面,`defaultPage`在这两种模式下无效 +- 2、defaultPage必须是子应用页面的绝对地址,为了防止出错,建议单独打开子应用,跳转目标页面,复制粘贴浏览器地址,包括hash和search,将此值设置为`defaultPage`,也可以去掉域名,简化代码 +- 3、由于`native`、`native-scope`模式是基于浏览器进行渲染,`defaultPage`在这两种模式下无效,通过浏览器url控制子应用默认页面即可。 #### 使用方式 @@ -526,7 +505,7 @@ const defaultPage = router.getDefaultPage('my-app') -## 导航守卫 +## 导航守卫 :id=router-guards 导航守卫用于监听子应用的路由变化,类似于vue-router的全局守卫,不同点是MicroApp的导航守卫无法取消跳转。 #### 全局前置守卫 @@ -614,7 +593,7 @@ const cancelCallback = microApp.router.afterEach((to, from, appName) => { cancelCallback() ``` -## 获取路由信息 +## 获取路由信息 :id=information **介绍:**获取子应用的路由信息,返回值与子应用的location相同 ```js /** @@ -644,7 +623,7 @@ const routeInfo = window.microApp.router.current.get('my-app') -## 编解码 +## 编解码 :id=code **介绍:**子应用同步到浏览器的路由信息是经过特殊编码的(encodeURIComponent + 特殊字符转译),如果用户想要编码或解码子应用的路由信息,可以使用编解码的API。 ![alt](https://img12.360buyimg.com/imagetools/jfs/t1/204018/30/36539/9736/6523add2F41753832/31f5ad7e48ea6570.png ':size=700') @@ -689,7 +668,7 @@ const encodeResult = window.microApp.router.decode('%2Fpage1%2F') ``` -## 同步路由信息 +## 同步路由信息 :id=attach-router 在一些特殊情况下,主应用的跳转会导致浏览器地址上子应用信息丢失,此时可以主动调用方法,将子应用的路由信息同步到浏览器地址上。 **介绍:**主动将子应用的路由信息同步到浏览器地址上 diff --git a/docs/zh-cn/sandbox.md b/docs/zh-cn/sandbox.md index d7b307431..79809d800 100644 --- a/docs/zh-cn/sandbox.md +++ b/docs/zh-cn/sandbox.md @@ -1,41 +1,77 @@ -### 沙箱介绍 -我们使用`Proxy`拦截了用户全局操作的行为,防止对window的访问和修改,避免全局变量污染。`micro-app`中的每个子应用都运行在沙箱环境,以获取相对纯净的运行空间。 +JS沙箱通过自定义的window、document拦截子应用的JS操作,实现一个相对独立的运行空间,避免全局变量污染,让每个子应用都拥有一个相对纯净的运行环境。 -沙箱是默认开启的,正常情况下不建议关闭,以避免出现不可预知的问题。 +`micro-app`有两种沙箱模式:with沙箱和iframe沙箱,它们覆盖不同的使用场景且可以随意切换,默认情况下使用with沙箱,如果无法正常运行可以切换到iframe沙箱。 -如何关闭沙箱请查看:[disableSandbox](/zh-cn/configure?id=disablesandbox) +## 知识点 -### 注意事项 +#### 1、子应用如何获取到真实window、document :id=rawWindow -#### 1、子应用在沙箱环境中如何获取到真实window -目前有3种方式在子应用中获取外部真实window -- 1、new Function("return window")() 或 Function("return window")() -- 2、(0, eval)('window') -- 3、window.rawWindow +子应用通过:`window.rawWindow`、`window.rawDocument` 可以获取真实的window、document(即最外层主应用的window和document)。 + + +## 常见问题 + +### 1、子应用抛出错误信息:xxx 未定义 :id=undefined **包括:** - `xxx is not defined` - `xxx is not a function` - `Cannot read properties of undefined` +**常见场景:** + - 1、webpack DllPlugin 拆分的独立文件 + - 2、通过script引入的第三方js文件 + **原因:** 在沙箱环境中,顶层变量不会泄漏为全局变量。 -例如在正常情况下,通过 var name 或 function name () {} 定义的顶层变量会泄漏为全局变量,通过window.name或name就可以全局访问。 - -但是在沙箱环境下这些顶层变量无法泄漏为全局变量,window.name或name的值为undefined,导致出现问题。 +例如:在正常情况下,通过 var name 或 function name () {} 定义的顶层变量会泄漏为全局变量,通过window.name或name就可以全局访问,但是在沙箱环境下这些顶层变量无法泄漏为全局变量,window.name或name的值为undefined,导致出现问题。 **解决方式**: -*方式一:手动修改* +##### 方式一:修改子应用webpack dll配置 + +子应用webpack dll配置文件中[output.library.type](https://webpack.docschina.org/configuration/output/#outputlibrarytype)设置为`window`,这种方式适合DllPlugin拆分的独立文件。 +```js +// webpack.dll.config.js +module.exports = { + // ... + output: { + library: { + type: 'window', + }, + }, +} +``` + +##### 方式二:手动修改 将 var name 或 function name () {} 修改为 window.name = xx -*方式二:通过插件系统修改子应用代码* +##### 方式三:通过插件系统修改子应用代码 + +通过插件系统,将 var name 或 function name () {} 修改为 window.name = xx,不同项目的代码形式并不统一,根据实际情况调整。 -比如常见的加载webpack打包的dll文件失败的问题,因为dll文件的内容和js地址相对固定,可以直接进行全局查找和修改。 ```js microApp.start({ plugins: { @@ -43,7 +79,8 @@ microApp.start({ 应用名称: [{ loader(code, url) { if (url === 'xxx.js') { - code = code.replace('var xx_dll=', 'window.xx_dll=') + // 根据实际情况调整 + code = code.replace('var xxx=', 'window.xxx=') } return code } @@ -53,22 +90,83 @@ microApp.start({ }) ``` -#### 3、基座如何对子应用 document 的一些属性进行自定义代理扩展 +### 2、子应用使用`Module Federation`模块联邦时报错 :id=module-federation +**原因:**与上述[常见问题1](/zh-cn/sandbox?id=undefined)相同,在沙箱环境中,顶层变量不会泄漏为全局变量导致的。 -**场景:** +**解决方式:**将`ModuleFederationPlugin`插件中`library.type`设置为`window`。 -微前端模式下,通常由基座负责设置站点标题,不希望受到子应用的干扰。 -但是因为 microApp 对 documet 的代理处理过程,并没有处理 document.title,所以子应用中可能通过 `document.title = 'xxx'` 意外改变了基座的站点标题。 +```js +new ModuleFederationPlugin({ + // ... + name: "app1", + library: { + type: "window", + name: "app1", + }, +}) +``` -**解决方式**: +### 3、子应用`DllPlugin`拆分的文件加载失败 :id=DllPlugin -*通过 customProxyDocumentProps 对 document 的属性进行自定义代理扩展* +**原因:**与上述[常见问题1](/zh-cn/sandbox?id=undefined)相同,在沙箱环境中,顶层变量不会泄漏为全局变量导致的。 -通过给title设置一个空函数,来忽略 document.title 执行 +**解决方式:**修改子应用webpack dll配置 + +子应用webpack dll配置文件中[output.library.type](https://webpack.docschina.org/configuration/output/#outputlibrarytype)设置为`window`。 +```js +// webpack.dll.config.js +module.exports = { + // ... + output: { + library: { + type: 'window', + }, + }, +} +``` + +### 4、iframe沙箱加载了主应用的资源 :id=iframe-source + +![iframe-source](https://img12.360buyimg.com/imagetools/jfs/t1/233529/17/19491/20911/667027a9F8cfada1e/7cf9213644e14b24.png ':size=700') + +**原因:**由于iframe的src必须指向主应用域名,导致沙箱在初始化时有几率加载主应用的静态资源。 + +**解决方式:** + +**方案一:**在主应用创建一个空的empty.html文件,将iframe的src指向它 + +- 步骤1:在静态资源文件夹中创建一个空的empty.html文件 +``` +静态资源文件夹:即vue、react项目的public文件夹,angular项目的assets文件夹,不同项目可能会不同,根据实际情况调整。 +``` + +- 步骤2:设置iframeSrc,指向empty.html文件 ```js microApp.start({ - customProxyDocumentProps: new Map([ - ['title', (value) => {}] - ]), + iframeSrc: 'http://主应用域名/基础路径(如果有)/empty.html', }) ``` +如果是多层嵌套,中间层的iframeSrc也要指向最外层主应用的empty.html + + +**方案二:**使用window.stop()阻止脚本执行 + +- 在主应用head最前面插入下面js: +```html + +``` +window.stop虽然可以阻止脚本执行,但对于已经发送的js请求无法撤回,所以network中会看到canceled请求,但不影响正常功能,如果无法接受推荐使用方案一。 + + +### 5、内存优化 :id=memory +为了优化性能,沙箱在子应用初始化时会缓存静态资源和数据,在子应用卸载后不会自动清除,以提升二次渲染速度,这是正常现象。 + +初始化时占用的内存是一次性的,不会一直增长。 + +如果在切换子应用时内存一直增长,造成内存泄漏风险,需要进行以下操作: + +- 1、将子应用切换到umd模式,切换方式参考[umd模式](/zh-cn/umd) +- 2、不要设置[destroy](/zh-cn/configure?id=destroy)属性 +- 3、保证name和url一一对应 + +做到以上几点基本上不会有内存泄漏问题,如果问题依然存在,可以试着切换到[iframe](/zh-cn/configure?id=iframe)沙箱。 diff --git a/docs/zh-cn/start.md b/docs/zh-cn/start.md index 56968da7c..5ac7e2761 100755 --- a/docs/zh-cn/start.md +++ b/docs/zh-cn/start.md @@ -1,13 +1,13 @@ 我们分别列出主应用和子应用需要进行的修改,具体介绍`micro-app`的使用方式。 -### 主应用 +### 主应用 :id=main -1、安装依赖 +**1、安装依赖** ```bash npm i @micro-zoe/micro-app --save ``` -2、初始化`micro-app` +**2、初始化`micro-app`** ```js // index.js import microApp from '@micro-zoe/micro-app' @@ -15,14 +15,16 @@ import microApp from '@micro-zoe/micro-app' microApp.start() ``` -3、嵌入子应用 +**3、加载子应用** + +micro-app通过自定义元素``加载子应用,使用方式像iframe一样简洁 + #### ** React ** ```js export function MyPage () { return (
    -

    子应用👇

    // name:应用名称, url:应用地址
    @@ -33,32 +35,63 @@ export function MyPage () { #### ** Vue ** ```html ``` -### 子应用 +> [!NOTE] +> 1、name:必传参数,必须以字母开头,且不可以带特殊符号(中划线、下划线除外) +> +> 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html + -1、在webpack-dev-server的headers中设置跨域支持。 +### 子应用 :id=child + +micro-app从主应用通过fetch加载子应用的静态资源,由于主应用与子应用的域名不一定相同,所以子应用需要支持跨域。 + +子应用设置跨域方式如下: + + +#### ** webpack ** ```js devServer: { headers: { 'Access-Control-Allow-Origin': '*', } -}, +} +``` + +#### ** vite ** +```js +export default defineConfig({ + server: { + headers: { + 'Access-Control-Allow-Origin': '*', + } + } +}) ``` -完成以上步骤即完成微前端的接入。 +#### ** nginx ** +```js +# location根据实际情况调整 +location / { + add_header 'Access-Control-Allow-Origin' '*'; + # 其它配置... +} +``` + +#### ** nodejs ** +以express为例,手动配置中间件 +```js +app.all('*', (req, res, next) => { + res.header('Access-Control-Allow-Origin', '*'); + // 其它配置 +}) +``` + -> [!NOTE] -> 1、name:必传参数,必须以字母开头,且不可以带特殊符号(中划线、下划线除外) -> -> 2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html -> -> 3、子应用必须支持跨域,跨域配置参考[这里](/zh-cn/questions?id=_2、子应用静态资源一定要支持跨域吗?) +完成以上步骤即完成微前端的接入,更详细的接入步骤请参考[手把手](/zh-cn/framework/introduce)。 diff --git a/docs/zh-cn/umd.md b/docs/zh-cn/umd.md new file mode 100644 index 000000000..e2a22b9d8 --- /dev/null +++ b/docs/zh-cn/umd.md @@ -0,0 +1,141 @@ +MicroApp支持两种渲染微前端的模式,默认模式和umd模式。 + +- **默认模式:**子应用在初次渲染和后续渲染时会顺序执行所有js,以保证多次渲染的一致性。 +- **umd模式:**子应用暴露出`mount`、`unmount`方法,此时只在初次渲染时执行所有js,后续渲染只会执行这两个方法,在多次渲染时具有更好的性能和内存表现。 + +通常情况下,我们推荐使用umd模式,以获得更好的性能和内存表现,默认模式更适合渲染和卸载不频繁的子应用。 + +**开启umd方式:** + + +#### ** Vue2 ** +```js +// main.js +import Vue from 'vue' +import router from './router' +import App from './App.vue' + +let app = null +// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 +window.mount = () => { + app = new Vue({ + router, + render: h => h(App), + }).$mount('#app') +} + +// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 +window.unmount = () => { + app.$destroy() + app.$el.innerHTML = '' + app = null +} + +// 如果不在微前端环境,则直接执行mount渲染 +if (!window.__MICRO_APP_ENVIRONMENT__) { + window.mount() +} +``` + +#### ** Vue3 ** +```js +// main.js +import { createApp } from 'vue' +import { createRouter, createWebHistory } from 'vue-router' +import routes from './router' +import App from './App.vue' + +let app = null +let router = null +let history = null +// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 +window.mount = () => { + history = createWebHistory() + router = createRouter({ + history, + routes, + }) + + app = createApp(App) + app.use(router) + app.mount('#app') +} + +// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 +window.unmount = () => { + app.unmount() + history.destroy() + app = null + router = null + history = null +} + +// 如果不在微前端环境,则直接执行mount渲染 +if (!window.__MICRO_APP_ENVIRONMENT__) { + window.mount() +} +``` + +#### ** React ** +```js +// index.js +import React from "react" +import ReactDOM from "react-dom" +import App from './App' + +// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 +window.mount = () => { + ReactDOM.render(, document.getElementById("root")) +} + +// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 +window.unmount = () => { + ReactDOM.unmountComponentAtNode(document.getElementById("root")) +} + +// 如果不在微前端环境,则直接执行mount渲染 +if (!window.__MICRO_APP_ENVIRONMENT__) { + window.mount() +} +``` + +#### ** Angular ** +```js +// main.ts +import { NgModuleRef } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; + +declare global { + interface Window { + microApp: any + mount: CallableFunction + unmount: CallableFunction + __MICRO_APP_ENVIRONMENT__: string + } +} + +let app: void | NgModuleRef +// 👇 将渲染操作放入 mount 函数,子应用初始化时会自动执行 +window.mount = () => { + platformBrowserDynamic() + .bootstrapModule(AppModule) + .then((res: NgModuleRef) => { + app = res + }) + .catch(err => console.error(err)) +} + +// 👇 将卸载操作放入 unmount 函数,就是上面步骤2中的卸载函数 +window.unmount = () => { + // angular在部分场景下执行destroy时会删除根元素app-root,导致在此渲染时报错,此时可删除app.destroy()来避免这个问题 + app && app.destroy(); + app = undefined; +} + +// 如果不在微前端环境,则直接执行mount渲染 +if (!window.__MICRO_APP_ENVIRONMENT__) { + window.mount(); +} +``` + diff --git a/package.json b/package.json index 75b353d8f..65ff663bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@micro-zoe/micro-app", - "version": "1.0.0-rc.5", + "version": "1.0.0-rc.6", "description": "A lightweight, efficient and powerful micro front-end framework", "private": false, "main": "lib/index.min.js", @@ -96,6 +96,7 @@ "@rollup/plugin-babel": "~5.2.2", "@rollup/plugin-node-resolve": "~11.0.1", "@rollup/plugin-replace": "~2.4.1", + "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "~8.1.0", "@types/jest": "~26.0.24", "@types/node": "~14.14.19", diff --git a/rollup.config.js b/rollup.config.js index fd51e1f5d..c5f6b2682 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -3,7 +3,7 @@ import fse from 'fs-extra' import typescript from '@rollup/plugin-typescript' import resolve from '@rollup/plugin-node-resolve' import babel from '@rollup/plugin-babel' -import { terser } from 'rollup-plugin-terser' +import terser from '@rollup/plugin-terser' import replace from '@rollup/plugin-replace' const version = require('./package.json').version const cwd = process.cwd() @@ -88,6 +88,7 @@ const cjsConfig = Object.assign({}, baseConfigForNormal, { plugins: baseConfigForNormal.plugins.concat([ terser({ ecma: 5, + safari10: true, }), ]), }) diff --git a/src/constants.ts b/src/constants.ts index 08beaa6d8..f1e9453ca 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -51,7 +51,6 @@ export enum MicroAppConfig { DISABLE_MEMORY_ROUTER = 'disable-memory-router', DISABLE_PATCH_REQUEST = 'disable-patch-request', KEEP_ROUTER_STATE = 'keep-router-state', - HIDDEN_ROUTER = 'hidden-router', KEEP_ALIVE = 'keep-alive', CLEAR_DATA ='clear-data', SSR = 'ssr', @@ -106,12 +105,12 @@ const BASE_SCOPE_WINDOW_EVENT = [ 'popstate', 'hashchange', 'load', - 'beforeunload', 'unload', 'unmount', 'appstate-change', 'statechange', 'mounted', + // 'beforeunload', // remove at 2024.5.30 by cangdu ] // bind event of with sandbox @@ -120,6 +119,7 @@ export const SCOPE_WINDOW_EVENT_OF_WITH = BASE_SCOPE_WINDOW_EVENT // bind event of iframe sandbox export const SCOPE_WINDOW_EVENT_OF_IFRAME = BASE_SCOPE_WINDOW_EVENT.concat([ 'unhandledrejection', + 'message' ]) // on event bound to child app window @@ -128,9 +128,9 @@ const BASE_SCOPE_WINDOW_ON_EVENT = [ 'onpopstate', 'onhashchange', 'onload', - 'onbeforeunload', 'onunload', 'onerror' + // 'onbeforeunload', // remove at 2024.5.30 by cangdu ] // bind on event of with sandbox diff --git a/src/create_app.ts b/src/create_app.ts index c2504729f..3f3570d2e 100644 --- a/src/create_app.ts +++ b/src/create_app.ts @@ -25,7 +25,6 @@ import { isPromise, logError, getRootContainer, - isObject, execMicroAppGlobalHook, pureCreateElement, isDivElement, @@ -63,7 +62,6 @@ export default class CreateApp implements AppInterface { private umdHookMount: Func | null = null private umdHookUnmount: Func | null = null private preRenderEvents?: CallableFunction[] | null - private lifeCycleState: string | null = null public umdMode = false public source: sourceType // TODO: 类型优化,加上iframe沙箱 @@ -144,8 +142,8 @@ export default class CreateApp implements AppInterface { }: OnLoadParam): void { if (++this.loadSourceLevel === 2) { this.source.html = html - - if (!this.isPrefetch && !this.isUnmounted()) { + if (this.isUnmounted()) return + if (!this.isPrefetch) { getRootContainer(this.container!).mount(this) } else if (this.isPrerender) { /** @@ -284,9 +282,8 @@ export default class CreateApp implements AppInterface { this.routerMode = routerMode const dispatchBeforeMount = () => { - this.setLifeCycleState(lifeCycles.BEFOREMOUNT) dispatchLifecyclesEvent( - this.container!, + this.container, this.name, lifeCycles.BEFOREMOUNT, ) @@ -305,7 +302,7 @@ export default class CreateApp implements AppInterface { appState: appStates.MOUNTING }) - // TODO: 将所有cloneContainer中的'as Element'去掉,兼容shadowRoot的场景 + // TODO: 兼容shadowRoot的场景 this.cloneContainer(this.container, this.source.html, !this.umdMode) this.sandBox?.start({ @@ -316,51 +313,57 @@ export default class CreateApp implements AppInterface { }) if (!this.umdMode) { - // update element info of html - this.sandBox?.actionBeforeExecScripts(this.container) - // if all js are executed, param isFinished will be true - execScripts(this, (isFinished: boolean) => { - if (!this.umdMode) { - const { mount, unmount } = this.getUmdLibraryHooks() - /** - * umdHookUnmount can works in default mode - * register through window.unmount - */ - // TODO: 不对,这里要改,因为unmount不一定是函数 - this.umdHookUnmount = unmount as Func + // patch element info of html + this.sandBox?.actionsBeforeExecScripts(this.container, (mount, unmount) => { + if (!this.umdMode && !this.isUnmounted()) { + this.umdHookMount = isFunction(mount) ? mount : null + // umdHookUnmount can works in default mode, register by window.unmount + this.umdHookUnmount = isFunction(unmount) ? unmount : null // if mount & unmount is function, the sub app is umd mode - if (isFunction(mount) && isFunction(unmount)) { - this.umdHookMount = mount as Func - // sandbox must exist - this.sandBox!.markUmdMode(this.umdMode = true) + if (isFunction(this.umdHookMount) && isFunction(this.umdHookUnmount)) { + this.sandBox?.markUmdMode(this.umdMode = true) try { - this.handleMounted(this.umdHookMount(microApp.getData(this.name, true))) + // if appState is mounted, it means that isFinished is true and this.handleMounted has already been executed, just exec this.umdHookMount + if (this.getAppState() === appStates.MOUNTED) { + this.umdHookMount(microApp.getData(this.name, true)) + } else { + this.handleMounted(this.umdHookMount(microApp.getData(this.name, true))) + } } catch (e) { - /** - * TODO: - * 1. 是否应该直接抛出错误 - * 2. 是否应该触发error生命周期 - */ - logError('An error occurred in window.mount \n', this.name, e) + logError('An error occurred when mount \n', this.name, e) } - } else if (isFinished === true) { - this.handleMounted() } } }) + + // if all js are executed, param isFinished will be true + execScripts(this, (isFinished: boolean) => { + if (!this.umdMode && isFinished === true) { + this.handleMounted() + } + }) } else { this.sandBox?.rebuildEffectSnapshot() try { this.handleMounted(this.umdHookMount!(microApp.getData(this.name, true))) } catch (e) { - logError('An error occurred in window.mount \n', this.name, e) + logError('An error occurred when mount \n', this.name, e) } } } } + /** + * Initialization of sandbox is async, especially iframe sandbox are macro tasks + * when child apps switch quickly, we need to pay attention to the following points: + * NOTE: + * 1. unmount app before exec nextAction (especially: iframe sandbox + default mode + remount) + * this.container is null, this.sandBox will not start + * 2. remount app of note 1 + * 3. unmount app during exec js + */ // TODO: 可优化? - this.sandBox ? this.sandBox.sandboxReady.then(nextAction) : nextAction() + this.sandBox ? this.sandBox.sandboxReady.then(() => !this.isUnmounted() && nextAction()) : nextAction() } /** @@ -369,15 +372,16 @@ export default class CreateApp implements AppInterface { */ private handleMounted (umdHookMountResult?: unknown): void { const dispatchAction = () => { + const nextAction = () => this.actionsAfterMounted() if (isPromise(umdHookMountResult)) { umdHookMountResult - .then(() => this.dispatchMountedEvent()) + .then(nextAction) .catch((e) => { logError('An error occurred in window.mount \n', this.name, e) - this.dispatchMountedEvent() + nextAction() }) } else { - this.dispatchMountedEvent() + nextAction() } } @@ -392,7 +396,7 @@ export default class CreateApp implements AppInterface { /** * dispatch mounted event when app run finished */ - private dispatchMountedEvent (): void { + private actionsAfterMounted (): void { if (!this.isUnmounted()) { this.setAppState(appStates.MOUNTED) // call window.onmount of child app @@ -411,11 +415,9 @@ export default class CreateApp implements AppInterface { // dispatch mounted event to micro app dispatchCustomEventToMicroApp(this, 'mounted') - this.setLifeCycleState(lifeCycles.MOUNTED) - // dispatch event mounted to parent dispatchLifecyclesEvent( - this.container!, + this.container, this.name, lifeCycles.MOUNTED, ) @@ -441,6 +443,8 @@ export default class CreateApp implements AppInterface { * unmount app * NOTE: * 1. do not add any params on account of unmountApp + * 2. this.container maybe null: Initialization of sandbox is async, child app may unmount before exec nextAction of mount + * 3. unmount app when loading files (this.container is not null) * @param destroy completely destroy, delete cache resources * @param clearData clear data of dateCenter * @param keepRouteState keep route state when unmount, default is false @@ -456,14 +460,34 @@ export default class CreateApp implements AppInterface { this.setAppState(appStates.UNMOUNT) - let umdHookUnmountResult: unknown = null try { - // call umd unmount hook before the sandbox is cleared - umdHookUnmountResult = this.umdHookUnmount?.(microApp.getData(this.name, true)) + this.handleUnmounted( + destroy, + clearData, + keepRouteState, + unmountcb, + this.umdHookUnmount?.(microApp.getData(this.name, true)), + ) } catch (e) { - logError('An error occurred in window.unmount \n', this.name, e) + logError('An error occurred when unmount \n', this.name, e) } + } + /** + * handle for promise umdHookUnmount + * @param destroy completely destroy, delete cache resources + * @param clearData clear data of dateCenter + * @param keepRouteState keep route state when unmount, default is false + * @param unmountcb callback of unmount + * @param umdHookUnmountResult result of umdHookUnmount + */ + private handleUnmounted ( + destroy: boolean, + clearData: boolean, + keepRouteState: boolean, + unmountcb?: CallableFunction, + umdHookUnmountResult?: unknown, + ): void { // dispatch state event to micro app dispatchCustomEventToMicroApp(this, 'statechange', { appState: appStates.UNMOUNT @@ -479,33 +503,7 @@ export default class CreateApp implements AppInterface { microGlobalEvent.ONUNMOUNT, ) - this.handleUnmounted({ - destroy, - clearData, - keepRouteState, - unmountcb, - umdHookUnmountResult, - }) - } - - /** - * handle for promise umdHookUnmount - * @param destroy completely destroy, delete cache resources - * @param clearData clear data of dateCenter - * @param keepRouteState keep route state when unmount, default is false - * @param unmountcb callback of unmount - * @param umdHookUnmountResult result of umdHookUnmount - */ - private handleUnmounted ({ - destroy, - clearData, - keepRouteState, - unmountcb, - umdHookUnmountResult, - }: UnmountParam & { - umdHookUnmountResult: unknown, - }): void { - const nextAction = () => this.actionsForUnmount({ + const nextAction = () => this.actionsAfterUnmounted({ destroy, clearData, keepRouteState, @@ -515,7 +513,12 @@ export default class CreateApp implements AppInterface { if (isPromise(umdHookUnmountResult)) { // async window.unmount will cause appName bind error in nest app removeDomScope() - umdHookUnmountResult.then(nextAction).catch(nextAction) + umdHookUnmountResult + .then(nextAction) + .catch((e) => { + logError('An error occurred in window.unmount \n', this.name, e) + nextAction() + }) } else { nextAction() } @@ -528,7 +531,7 @@ export default class CreateApp implements AppInterface { * @param keepRouteState keep route state when unmount, default is false * @param unmountcb callback of unmount */ - private actionsForUnmount ({ + private actionsAfterUnmounted ({ destroy, clearData, keepRouteState, @@ -551,11 +554,9 @@ export default class CreateApp implements AppInterface { clearData: clearData || destroy, }) - this.setLifeCycleState(lifeCycles.UNMOUNT) - // dispatch unmount event to base app dispatchLifecyclesEvent( - this.container!, + this.container, this.name, lifeCycles.UNMOUNT, ) @@ -566,13 +567,25 @@ export default class CreateApp implements AppInterface { } private clearOptions (destroy: boolean): void { - this.container!.innerHTML = '' - this.container = null this.isPrerender = false this.preRenderEvents = null this.setKeepAliveState(null) + if (this.container) { + this.container.innerHTML = '' + this.container = null + } else if (!this.umdMode) { + /** + * this.container is null means sandBox.start has not exec, so sandBox.stop won't exec either + * we should remove iframeElement in default mode manually + */ + this.sandBox?.deleteIframeElement?.() + } // in iframe sandbox & default mode, delete the sandbox & iframeElement - // TODO: with沙箱与iframe沙箱保持一致:with沙箱默认模式下删除 或者 iframe沙箱umd模式下保留 + /** + * TODO: + * 1. with沙箱与iframe沙箱保持一致:with沙箱默认模式下删除 或者 iframe沙箱umd模式下保留 + * 2. 接1.0,this.sandBox置空,还需要注意后续app.sandBox相关操作,比如 scripts.ts --> app.iframe ? app.sandBox!.microBody : app.querySelector('micro-app-body'),如果是fiber或者预加载,会存在卸载后js还在处理的情况 + */ if (this.iframe && !this.umdMode) this.sandBox = null if (destroy) this.actionsForCompletelyDestroy() removeDomScope() @@ -600,10 +613,9 @@ export default class CreateApp implements AppInterface { appState: 'afterhidden', }) - this.setLifeCycleState(lifeCycles.AFTERHIDDEN) // dispatch afterHidden event to base app dispatchLifecyclesEvent( - this.container!, + this.container, this.name, lifeCycles.AFTERHIDDEN, ) @@ -666,7 +678,7 @@ export default class CreateApp implements AppInterface { /** * TODO: * 问题:当路由模式为custom时,keep-alive应用在重新展示,是否需要根据子应用location信息更新浏览器地址? - * 暂时不这么做吧,因为无法确定二次展示时新旧地址是否相同,是否带有特殊信息 + * 暂时不这么做,因为无法确定二次展示时新旧地址是否相同,是否带有特殊信息 */ if (isRouterModeSearch(this.name)) { // called before lifeCyclesEvent @@ -678,8 +690,6 @@ export default class CreateApp implements AppInterface { appState: 'aftershow', }) - this.setLifeCycleState(lifeCycles.AFTERSHOW) - // dispatch afterShow event to base app dispatchLifecyclesEvent( this.container, @@ -693,15 +703,13 @@ export default class CreateApp implements AppInterface { * @param e Error */ public onerror (e: Error): void { - this.setLifeCycleState(lifeCycles.ERROR) - // dispatch state event to micro app dispatchCustomEventToMicroApp(this, 'statechange', { appState: appStates.LOAD_FAILED }) dispatchLifecyclesEvent( - this.container!, + this.container, this.name, lifeCycles.ERROR, e, @@ -723,8 +731,8 @@ export default class CreateApp implements AppInterface { /** * clone origin elements to target - * @param origin Cloned element * @param target Accept cloned elements + * @param origin Cloned element * @param deep deep clone or transfer dom */ private cloneContainer ( @@ -767,16 +775,6 @@ export default class CreateApp implements AppInterface { return this.state } - // set app lifeCycleState - private setLifeCycleState (state: string): void { - this.lifeCycleState = state - } - - // get app lifeCycleState - public getLifeCycleState (): string { - return this.lifeCycleState || '' - } - // set keep-alive state private setKeepAliveState (state: string | null): void { this.keepAliveState = state @@ -797,28 +795,6 @@ export default class CreateApp implements AppInterface { return keepAliveStates.KEEP_ALIVE_HIDDEN === this.keepAliveState } - // get umd library, if it not exist, return empty object - private getUmdLibraryHooks (): Record { - // after execScripts, the app maybe unmounted - if (!this.isUnmounted() && this.sandBox) { - const libraryName = getRootContainer(this.container!).getAttribute('library') || `micro-app-${this.name}` - - const proxyWindow = this.sandBox.proxyWindow as Record - - // compatible with pre versions - if (isObject(proxyWindow[libraryName])) { - return proxyWindow[libraryName] - } - - return { - mount: proxyWindow.mount, - unmount: proxyWindow.unmount, - } - } - - return {} - } - private getMicroAppGlobalHook (eventName: string): Func | null { const listener = (this.sandBox?.proxyWindow as Record)?.[eventName] return isFunction(listener) ? listener : null diff --git a/src/index.ts b/src/index.ts index 1575c5219..7f0ed1c2c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ export { unmountAllApps, reload, renderApp, - getAppStatus } from './micro_app' export { default as preFetch, diff --git a/src/interact/index.ts b/src/interact/index.ts index 834a9bec5..4b2fb1b2d 100644 --- a/src/interact/index.ts +++ b/src/interact/index.ts @@ -20,7 +20,7 @@ const eventCenter = new EventCenter() */ function createEventName (appName: string, fromBaseApp: boolean): string { if (!isString(appName) || !appName) return '' - return fromBaseApp ? `__from_base_app_${appName}__` : `__from_micro_app_${appName}__` + return fromBaseApp ? `__${appName}_from_base_app__` : `__${appName}_from_micro_app__` } // Global data diff --git a/src/interact/lifecycles_event.ts b/src/interact/lifecycles_event.ts index 53451488d..fefe1ce6e 100644 --- a/src/interact/lifecycles_event.ts +++ b/src/interact/lifecycles_event.ts @@ -1,7 +1,7 @@ import type { lifeCyclesType, AppInterface } from '@micro-app/types' import microApp from '../micro_app' import { - logError, + logWarn, isFunction, removeDomScope, getRootContainer, @@ -35,13 +35,13 @@ type LifecycleEventName = keyof lifeCyclesType * @param error param from error hook */ export default function dispatchLifecyclesEvent ( - element: HTMLElement | ShadowRoot, + element: HTMLElement | ShadowRoot | null, appName: string, lifecycleName: LifecycleEventName, error?: Error, ): void { if (!element) { - return logError(`element does not exist in lifecycle ${lifecycleName}`, appName) + return logWarn(`element does not exist in lifecycle ${lifecycleName}`, appName) } element = getRootContainer(element) diff --git a/src/libs/global_env.ts b/src/libs/global_env.ts index f9a2a66a1..3409e32ab 100644 --- a/src/libs/global_env.ts +++ b/src/libs/global_env.ts @@ -1,5 +1,4 @@ import type { - AppInterface, RequestIdleCallbackInfo, RequestIdleCallbackOptions, } from '@micro-app/types' @@ -12,6 +11,9 @@ import { import { rejectMicroAppStyle, } from '../source/patch' +import { + updateElementInfo, +} from '../sandbox/adapter' declare global { interface Node { @@ -26,12 +28,6 @@ declare global { __MICRO_APP_HAS_SCOPED__?: boolean } - interface HTMLElement { - reload(destroy?: boolean): Promise - mount(app: AppInterface): void - unmount (destroy?: boolean, unmountcb?: CallableFunction): void - } - interface Window { requestIdleCallback ( callback: (info: RequestIdleCallbackInfo) => void, @@ -43,13 +39,8 @@ declare global { __MICRO_APP_BASE_APPLICATION__?: boolean __REACT_ERROR_OVERLAY_GLOBAL_HOOK__: boolean rawLocation: Location - rawWindow: Window - rawDocument: Document - Document: any - Element: any, - Node: any, - EventTarget: any, - HTMLElement: HTMLElement, + rawWindow: any + rawDocument: any } } @@ -70,16 +61,19 @@ export function initGlobalEnv (): void { const rawRootElement = rawWindow.Element const rawRootNode = rawWindow.Node const rawRootEventTarget = rawWindow.EventTarget + const rawDocumentFragment = rawWindow.DocumentFragment // save patch raw methods, pay attention to this binding + const rawAppendChild = rawRootNode.prototype.appendChild + const rawInsertBefore = rawRootNode.prototype.insertBefore + const rawReplaceChild = rawRootNode.prototype.replaceChild + const rawRemoveChild = rawRootNode.prototype.removeChild const rawSetAttribute = rawRootElement.prototype.setAttribute - const rawAppendChild = rawRootElement.prototype.appendChild - const rawInsertBefore = rawRootElement.prototype.insertBefore - const rawReplaceChild = rawRootElement.prototype.replaceChild - const rawRemoveChild = rawRootElement.prototype.removeChild const rawAppend = rawRootElement.prototype.append const rawPrepend = rawRootElement.prototype.prepend - const rawCloneNode = rawRootElement.prototype.cloneNode + const rawFragmentAppend = rawDocumentFragment.prototype.append + const rawFragmentPrepend = rawDocumentFragment.prototype.prepend + const rawCloneNode = rawRootNode.prototype.cloneNode const rawElementQuerySelector = rawRootElement.prototype.querySelector const rawElementQuerySelectorAll = rawRootElement.prototype.querySelectorAll const rawInsertAdjacentElement = rawRootElement.prototype.insertAdjacentElement @@ -99,12 +93,10 @@ export function initGlobalEnv (): void { const rawGetElementsByTagName = rawRootDocument.prototype.getElementsByTagName const rawGetElementsByName = rawRootDocument.prototype.getElementsByName - const ImageProxy = new Proxy(Image, { + // TODO: 将ImageProxy移出去 + const ImageProxy = new Proxy(rawWindow.Image, { construct (Target, args): HTMLImageElement { - const elementImage = new Target(...args) - const currentAppName = getCurrentAppName() - if (currentAppName) elementImage.__MICRO_APP_NAME__ = currentAppName - return elementImage + return updateElementInfo(new Target(...args), getCurrentAppName()) }, }) @@ -134,6 +126,7 @@ export function initGlobalEnv (): void { rawRootDocument, rawRootElement, rawRootNode, + rawDocumentFragment, // source/patch rawSetAttribute, @@ -143,6 +136,8 @@ export function initGlobalEnv (): void { rawRemoveChild, rawAppend, rawPrepend, + rawFragmentAppend, + rawFragmentPrepend, rawCloneNode, rawElementQuerySelector, rawElementQuerySelectorAll, diff --git a/src/libs/utils.ts b/src/libs/utils.ts index b8df237b5..63479ef18 100644 --- a/src/libs/utils.ts +++ b/src/libs/utils.ts @@ -7,6 +7,7 @@ import type { AttrsType, fiberTasks, MicroAppElementTagNameMap, + MicroAppElementInterface, } from '@micro-app/types' export const version = '__MICRO_APP_VERSION__' @@ -88,7 +89,7 @@ export function isPromise (target: unknown): target is Promise { // is bind function export function isBoundFunction (target: unknown): boolean { - return isFunction(target) && target.name.indexOf('bound ') === 0 && !target.hasOwnProperty('prototype') + return isFunction(target) && target.name?.indexOf('bound ') === 0 && !target.hasOwnProperty('prototype') } // is constructor function @@ -152,10 +153,18 @@ export function isBaseElement (target: unknown): target is HTMLBaseElement { return toTypeString(target) === '[object HTMLBaseElement]' } +export function isDocumentFragment (target: unknown): target is DocumentFragment { + return toTypeString(target) === '[object DocumentFragment]' +} + export function isMicroAppBody (target: unknown): target is HTMLElement { return isElement(target) && target.tagName.toUpperCase() === 'MICRO-APP-BODY' } +export function isMicroAppHead (target: unknown): target is HTMLElement { + return isElement(target) && target.tagName.toUpperCase() === 'MICRO-APP-HEAD' +} + // is ProxyDocument export function isProxyDocument (target: unknown): target is Document { return toTypeString(target) === '[object ProxyDocument]' @@ -235,6 +244,15 @@ export function defer (fn: Func, ...args: unknown[]): void { Promise.resolve().then(fn.bind(null, ...args)) } +/** + * async execution with macro task + * @param fn callback + * @param args params + */ +export function macro (fn: Func, delay = 0, ...args: unknown[]): void { + setTimeout(fn.bind(null, ...args), delay) +} + /** * create URL as MicroLocation */ @@ -300,8 +318,7 @@ export function formatAppName (name: string | null): string { export function getEffectivePath (url: string): string { const { origin, pathname } = createURL(url) if (/\.(\w+)$/.test(pathname)) { - const fullPath = `${origin}${pathname}` - const pathArr = fullPath.split('/') + const pathArr = `${origin}${pathname}`.split('/') pathArr.pop() return pathArr.join('/') + '/' } @@ -417,37 +434,72 @@ export function promiseRequestIdle (callback: CallableFunction): Promise { /** * Record the currently running app.name */ -let currentMicroAppName: string | null = null +let currentAppName: string | null = null export function setCurrentAppName (appName: string | null): void { - currentMicroAppName = appName + currentAppName = appName } // get the currently running app.name export function getCurrentAppName (): string | null { - return currentMicroAppName + return currentAppName } -// Clear appName -let preventSetAppName = false -export function removeDomScope (force?: boolean): void { - setCurrentAppName(null) - if (force && !preventSetAppName) { - preventSetAppName = true +export function throttleDeferForSetAppName (appName: string): void { + if (currentAppName !== appName && !getPreventSetState()) { + setCurrentAppName(appName) defer(() => { - preventSetAppName = false + setCurrentAppName(null) }) } } -export function throttleDeferForSetAppName (appName: string) { - if (currentMicroAppName !== appName && !preventSetAppName) { - setCurrentAppName(appName) +// only for iframe document.body(head).querySelector(querySelectorAll) +let iframeCurrentAppName: string | null = null +export function setIframeCurrentAppName (appName: string | null) { + iframeCurrentAppName = appName +} + +export function getIframeCurrentAppName (): string | null { + return iframeCurrentAppName +} + +export function throttleDeferForIframeAppName (appName: string): void { + if (iframeCurrentAppName !== appName && !getPreventSetState()) { + setIframeCurrentAppName(appName) defer(() => { - setCurrentAppName(null) + setIframeCurrentAppName(null) }) } } +// prevent set app name +let preventSetState = false +export function getPreventSetState (): boolean { + return preventSetState +} + +/** + * prevent set appName + * usage: + * removeDomScope(true) + * -----> element scope point to base app <----- + * removeDomScope(false) + */ +export function removeDomScope (force?: boolean): void { + if (force !== false) { + setCurrentAppName(null) + setIframeCurrentAppName(null) + if (force && !preventSetState) { + preventSetState = true + defer(() => { + preventSetState = false + }) + } + } else { + preventSetState = false + } +} + // is safari browser export function isSafari (): boolean { return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) @@ -480,12 +532,13 @@ export function isUniqueElement (key: string): boolean { ) } +export type RootContainer = HTMLElement & MicroAppElementInterface /** * get micro-app element * @param target app container */ -export function getRootContainer (target: HTMLElement | ShadowRoot): HTMLElement { - return (isShadowRoot(target) ? (target as ShadowRoot).host : target) as HTMLElement +export function getRootContainer (target: HTMLElement | ShadowRoot): RootContainer { + return (isShadowRoot(target) ? (target as ShadowRoot).host : target) as RootContainer } /** @@ -670,17 +723,23 @@ export function clearDOM ($dom: HTMLElement | ShadowRoot | Document): void { } } -type BaseHTMLElementType = HTMLElement & { - new (): HTMLElement; - prototype: HTMLElement; -} - -/** - * get HTMLElement from base app - * @returns HTMLElement - */ -export function getBaseHTMLElement (): BaseHTMLElementType { - return (window.rawWindow?.HTMLElement || window.HTMLElement) as BaseHTMLElementType +export function instanceOf unknown>( + instance: unknown, + constructor: T, +): instance is T extends new (...args: unknown[]) => infer R ? R : boolean { + if (instance === null || instance === undefined) { + return false + } else if (!isFunction(constructor)) { + throw new TypeError("Right-hand side of 'instanceof' is not callable") + } + let proto = Object.getPrototypeOf(instance) + while (proto) { + if (proto === constructor.prototype) { + return true + } + proto = Object.getPrototypeOf(proto) + } + return false } /** @@ -694,3 +753,11 @@ const formatEventList = ['mounted', 'unmount'] export function formatEventType (type: string, appName: string): string { return formatEventList.includes(type) ? `${type}-${appName}` : type } + +/** + * Is the object empty + * target maybe number, string, array ... + */ +export function isEmptyObject (target: unknown): boolean { + return isPlainObject(target) ? !Object.keys(target).length : true +} diff --git a/src/micro_app.ts b/src/micro_app.ts index 774b593aa..33e28174e 100644 --- a/src/micro_app.ts +++ b/src/micro_app.ts @@ -24,7 +24,7 @@ import { isFunction, } from './libs/utils' import { EventCenterForBaseApp } from './interact' -import globalEnv, { initGlobalEnv } from './libs/global_env' +import { initGlobalEnv } from './libs/global_env' import { appInstanceMap } from './create_app' import { lifeCycles } from './constants' import { router } from './sandbox/router' @@ -167,7 +167,7 @@ export function unmountApp (appName: string, options?: unmountAppOptions): Promi } } } else { - logWarn(`app ${appName} does not exist`) + logWarn(`app ${appName} does not exist when unmountApp`) resolve(false) } }) @@ -197,7 +197,7 @@ export function reload (appName: string, destroy?: boolean): Promise { resolve(false) } } else { - logWarn(`app ${appName} does not exist`) + logWarn(`app ${appName} does not exist when reload app`) resolve(false) } }) @@ -269,20 +269,6 @@ export function renderApp (options: RenderAppOptions): Promise { }) } -/** - * get app state - * @param appName app.name - * @returns app.state - */ -export function getAppStatus (appName: string): string | void { - const app = appInstanceMap.get(formatAppName(appName)) - if (app) { - return app.getLifeCycleState() - } else { - logWarn(`app ${appName} does not exist`) - } -} - export class MicroApp extends EventCenterForBaseApp implements MicroAppBaseType { tagName = 'micro-app' hasInit = false @@ -295,7 +281,6 @@ export class MicroApp extends EventCenterForBaseApp implements MicroAppBaseType getAllApps = getAllApps reload = reload renderApp = renderApp - getAppStatus = getAppStatus start (options?: OptionsType): void { if (!isBrowser || !window.customElements) { return logError('micro-app is not supported in this environment') @@ -322,7 +307,7 @@ export class MicroApp extends EventCenterForBaseApp implements MicroAppBaseType initGlobalEnv() - if (globalEnv.rawWindow.customElements.get(this.tagName)) { + if (window.customElements.get(this.tagName)) { return logWarn(`element ${this.tagName} is already defined`) } diff --git a/src/micro_app_element.ts b/src/micro_app_element.ts index d9c92a3ae..0edcaeff1 100644 --- a/src/micro_app_element.ts +++ b/src/micro_app_element.ts @@ -1,7 +1,7 @@ /* eslint-disable no-new */ import type { AttrType, - MicroAppElementType, + MicroAppElementInterface, AppInterface, OptionsType, NormalKey, @@ -22,7 +22,6 @@ import { createURL, isPlainObject, getEffectivePath, - getBaseHTMLElement, } from './libs/utils' import { ObservedAttrName, @@ -43,7 +42,7 @@ import { * @param tagName element name */ export function defineElement (tagName: string): void { - class MicroAppElement extends getBaseHTMLElement() implements MicroAppElementType { + class MicroAppElement extends HTMLElement implements MicroAppElementInterface { static get observedAttributes (): string[] { return ['name', 'url'] } @@ -69,6 +68,13 @@ export function defineElement (tagName: string): void { // keep-alive: open keep-alive mode public connectedCallback (): void { + /** + * In FireFox, iframe Node.prototype will point to native Node.prototype after insert to document + * If .prototype is not MicroAppElement.prototype, we should reset it + */ + if (Object.getPrototypeOf(this) !== MicroAppElement.prototype) { + Object.setPrototypeOf(this, MicroAppElement.prototype) + } const cacheCount = ++this.connectedCount this.connectStateMap.set(cacheCount, true) /** @@ -586,6 +592,18 @@ export function defineElement (tagName: string): void { } } + /** + * get delay time of router event + * @returns delay time + */ + public getRouterEventDelay (): number { + let delay = parseInt(this.getAttribute('router-event-delay') as string) + if (isNaN(delay)) { + delay = parseInt((isFunction(microApp.options['router-event-delay']) ? microApp.options['router-event-delay'](this.appName) : microApp.options['router-event-delay']) as unknown as string) + } + return !isNaN(delay) ? delay : 0 + } + /** * Data from the base application */ @@ -624,5 +642,5 @@ export function defineElement (tagName: string): void { } } - globalEnv.rawWindow.customElements.define(tagName, MicroAppElement) + window.customElements.define(tagName, MicroAppElement) } diff --git a/src/prefetch.ts b/src/prefetch.ts index 8ccb6eb3d..f1f9b5c8b 100644 --- a/src/prefetch.ts +++ b/src/prefetch.ts @@ -69,7 +69,7 @@ export default function preFetch (apps: prefetchParamList, delay?: number): void /** * TODO: remove setTimeout - * Is there a better way? + * 如果要保留setTimeout,则需要考虑清空定时器的情况 */ setTimeout(() => { // releasePrefetchEffect() diff --git a/src/sandbox/adapter.ts b/src/sandbox/adapter.ts index d7b054207..804e770cc 100644 --- a/src/sandbox/adapter.ts +++ b/src/sandbox/adapter.ts @@ -7,13 +7,20 @@ import { defer, isNode, rawDefineProperties, + isMicroAppBody, + getPreventSetState, + throttleDeferForIframeAppName, } from '../libs/utils' import { appInstanceMap, + isIframeSandbox, } from '../create_app' +import microApp from '../micro_app' export class BaseSandbox implements BaseSandboxType { - constructor () { + constructor (appName: string, url: string) { + this.appName = appName + this.url = url this.injectReactHMRProperty() } @@ -38,6 +45,8 @@ export class BaseSandbox implements BaseSandboxType { 'onhashchange', ] + public appName: string + public url: string // Properties that can only get and set in microAppWindow, will not escape to rawWindow public scopeProperties: PropertyKey[] = Array.from(this.staticScopeProperties) // Properties that can be escape to rawWindow @@ -48,6 +57,8 @@ export class BaseSandbox implements BaseSandboxType { public escapeKeys = new Set() // Promise used to mark whether the sandbox is initialized public sandboxReady!: Promise + // reset mount, unmount when stop in default mode + public clearHijackUmdHooks!: () => void // adapter for react private injectReactHMRProperty (): void { @@ -100,16 +111,17 @@ export function fixReactHMRConflict (app: AppInterface): void { * @param container target dom * @param appName app name */ -export function patchElementTree (container: Element | ShadowRoot, appName: string): void { - const children = Array.from(container.children) +export function patchElementTree ( + container: Node, + appName: string, +): void { + const children = Array.from(container.childNodes) children.length && children.forEach((child) => { patchElementTree(child, appName) }) - for (const child of children) { - updateElementInfo(child, appName) - } + updateElementInfo(container, appName) } /** @@ -118,33 +130,108 @@ export function patchElementTree (container: Element | ShadowRoot, appName: stri * @param appName app name * @returns target node */ -export function updateElementInfo (node: T, appName: string): T { - const proxyWindow = appInstanceMap.get(appName)?.sandBox?.proxyWindow +export function updateElementInfo (node: T, appName: string | null): T { if ( + appName && isNode(node) && - !node.__MICRO_APP_NAME__ && + node.__MICRO_APP_NAME__ !== appName && !node.__PURE_ELEMENT__ && - proxyWindow + !getPreventSetState() ) { /** * TODO: * 1. 测试baseURI和ownerDocument在with沙箱中是否正确 * 经过验证with沙箱不能重写ownerDocument,否则react点击事件会触发两次 - * 2. with沙箱所有node设置__MICRO_APP_NAME__都使用updateElementInfo */ rawDefineProperties(node, { - baseURI: { - configurable: true, - // if disable-memory-router or router-mode='disable', href point to base app - get: () => proxyWindow.location.href, - }, __MICRO_APP_NAME__: { configurable: true, + enumerable: true, writable: true, value: appName, }, }) + + /** + * In FireFox, iframe Node.prototype will point to native Node.prototype after insert to document + * + * Performance: + * iframe element.__proto__ === browser HTMLElement.prototype // Chrome: false, FireFox: true + * iframe element.__proto__ === iframe HTMLElement.prototype // Chrome: true, FireFox: false + * + * NOTE: + * 1. Node.prototype.baseURI + * 2. Node.prototype.ownerDocument + * 3. Node.prototype.parentNode + * 4. Node.prototype.getRootNode + * 5. Node.prototype.cloneNode + * 6. Element.prototype.innerHTML + * 7. Image + */ + if (isIframeSandbox(appName)) { + const proxyWindow = appInstanceMap.get(appName)?.sandBox?.proxyWindow + if (proxyWindow) { + rawDefineProperties(node, { + baseURI: { + configurable: true, + enumerable: true, + get: () => proxyWindow.location.href, + }, + ownerDocument: { + configurable: true, + enumerable: true, + get: () => node !== proxyWindow.document ? proxyWindow.document : null, + }, + parentNode: getIframeParentNodeDesc( + appName, + globalEnv.rawParentNodeDesc, + ), + getRootNode: { + configurable: true, + enumerable: true, + writable: true, + value: function getRootNode (): Node { + return proxyWindow.document + } + }, + }) + } + } } return node } + +/** + * get Descriptor of Node.prototype.parentNode for iframe + * @param appName app name + * @param parentNode parentNode Descriptor of iframe or browser + */ +export function getIframeParentNodeDesc ( + appName: string, + parentNodeDesc: PropertyDescriptor, +): PropertyDescriptor { + return { + configurable: true, + enumerable: true, + get (this: Node) { + throttleDeferForIframeAppName(appName) + const result: ParentNode = parentNodeDesc.get?.call(this) + /** + * If parentNode is , return rawDocument.body + * Scenes: + * 1. element-ui@2/lib/utils/vue-popper.js + * if (this.popperElm.parentNode === document.body) ... + * e.g.: + * 1. element-ui@2.x el-dropdown + * WARNING: + * Will it cause other problems ? + * e.g. target.parentNode.remove(target) + */ + if (isMicroAppBody(result) && appInstanceMap.get(appName)?.container) { + return microApp.options.getRootElementParentNode?.(this, appName) || globalEnv.rawDocument.body + } + return result + } + } +} diff --git a/src/sandbox/bind_function.ts b/src/sandbox/bind_function.ts index 8015c188c..2cc4101b4 100644 --- a/src/sandbox/bind_function.ts +++ b/src/sandbox/bind_function.ts @@ -19,7 +19,15 @@ function isConstructorFunction (value: FunctionConstructor & {__MICRO_APP_IS_CON // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export default function bindFunctionToRawTarget (value: any, rawTarget: T, key = 'WINDOW'): B { - if (isFunction(value) && !isConstructorFunction(value) && !isBoundedFunction(value)) { + /** + * In safari, nest app like: A -> B -> C + * if B is iframe sandbox, and C is with sandbox, same property of document in C is abnormal + * e.g: + * document.all: + * - typeof document.all ==> 'function' + * - document.all.bind ==> undefined + */ + if (isFunction(value) && !isConstructorFunction(value) && !isBoundedFunction(value) && value.bind) { const cacheKey = `__MICRO_APP_BOUND_${key}_FUNCTION__` if (value[cacheKey]) return value[cacheKey] diff --git a/src/sandbox/iframe/document.ts b/src/sandbox/iframe/document.ts index 07735dd9e..2e8682879 100644 --- a/src/sandbox/iframe/document.ts +++ b/src/sandbox/iframe/document.ts @@ -11,7 +11,7 @@ import { logWarn, isUniqueElement, isInvalidQuerySelectorKey, - throttleDeferForSetAppName, + throttleDeferForIframeAppName, } from '../../libs/utils' import globalEnv from '../../libs/global_env' import bindFunctionToRawTarget from '../bind_function' @@ -114,42 +114,51 @@ function patchDocumentPrototype (appName: string, microAppWindow: microAppWindow return updateElementInfo(element, appName) } - function getDefaultRawTarget (target: Document): Document { - return microDocument !== target ? target : rawDocument + function getBindTarget (target: Document): Document { + /** + * handler for: + * 1. document.getElementsByTagName('head')[0].querySelector('script') + * 2. document.querySelector('body').querySelectorAll('script') + * ... + */ + throttleDeferForIframeAppName(appName) + // DOMParser.document !== microDocument + return microDocument === target ? rawDocument : target } // query element👇 function querySelector (this: Document, selectors: string): any { + const _this = getBindTarget(this) if ( !selectors || isUniqueElement(selectors) || - microDocument !== this + rawDocument !== _this ) { - const _this = getDefaultRawTarget(this) return rawMicroQuerySelector.call(_this, selectors) } - return appInstanceMap.get(appName)?.querySelector(selectors) ?? null + return appInstanceMap.get(appName)?.querySelector(selectors) ?? rawMicroQuerySelector.call(microDocument, selectors) ?? null } function querySelectorAll (this: Document, selectors: string): any { + const _this = getBindTarget(this) if ( !selectors || isUniqueElement(selectors) || - microDocument !== this + rawDocument !== _this ) { - const _this = getDefaultRawTarget(this) return rawMicroQuerySelectorAll.call(_this, selectors) } - return appInstanceMap.get(appName)?.querySelectorAll(selectors) ?? [] + const result = appInstanceMap.get(appName)?.querySelectorAll(selectors) ?? [] + return result.length ? result : rawMicroQuerySelectorAll.call(microDocument, selectors) } microRootDocument.prototype.querySelector = querySelector microRootDocument.prototype.querySelectorAll = querySelectorAll microRootDocument.prototype.getElementById = function getElementById (key: string): HTMLElement | null { - const _this = getDefaultRawTarget(this) + const _this = getBindTarget(this) if (isInvalidQuerySelectorKey(key)) { return rawMicroGetElementById.call(_this, key) } @@ -162,7 +171,7 @@ function patchDocumentPrototype (appName: string, microAppWindow: microAppWindow } microRootDocument.prototype.getElementsByClassName = function getElementsByClassName (key: string): HTMLCollectionOf { - const _this = getDefaultRawTarget(this) + const _this = getBindTarget(this) if (isInvalidQuerySelectorKey(key)) { return rawMicroGetElementsByClassName.call(_this, key) } @@ -175,7 +184,7 @@ function patchDocumentPrototype (appName: string, microAppWindow: microAppWindow } microRootDocument.prototype.getElementsByTagName = function getElementsByTagName (key: string): HTMLCollectionOf { - const _this = getDefaultRawTarget(this) + const _this = getBindTarget(this) if ( isUniqueElement(key) || isInvalidQuerySelectorKey(key) @@ -193,7 +202,7 @@ function patchDocumentPrototype (appName: string, microAppWindow: microAppWindow } microRootDocument.prototype.getElementsByName = function getElementsByName (key: string): NodeListOf { - const _this = getDefaultRawTarget(this) + const _this = getBindTarget(this) if (isInvalidQuerySelectorKey(key)) { return rawMicroGetElementsByName.call(_this, key) } @@ -275,7 +284,7 @@ function patchDocumentProperty ( enumerable: true, configurable: true, get: () => { - throttleDeferForSetAppName(appName) + throttleDeferForIframeAppName(appName) return rawDocument[tagName] }, set: (value: unknown) => { rawDocument[tagName] = value }, @@ -284,7 +293,7 @@ function patchDocumentProperty ( } function patchDocumentEffect (appName: string, microAppWindow: microAppWindowType): CommonEffectHook { - const { rawDocument, rawAddEventListener, rawRemoveEventListener } = globalEnv + const { rawDocument, rawAddEventListener, rawRemoveEventListener, rawDispatchEvent } = globalEnv const eventListenerMap = new Map>() const sstEventListenerMap = new Map>() let onClickHandler: unknown = null @@ -325,6 +334,10 @@ function patchDocumentEffect (appName: string, microAppWindow: microAppWindowTyp rawRemoveEventListener.call(getEventTarget(type, this), type, handler, options) } + microRootDocument.prototype.dispatchEvent = function (event: Event): boolean { + return rawDispatchEvent.call(getEventTarget(event?.type, this), event) + } + // 重新定义microRootDocument.prototype 上的on开头方法 function createSetterHandler (eventName: string): (value: unknown) => void { if (eventName === 'onclick') { diff --git a/src/sandbox/iframe/element.ts b/src/sandbox/iframe/element.ts index 31e26879a..0be7c8e90 100644 --- a/src/sandbox/iframe/element.ts +++ b/src/sandbox/iframe/element.ts @@ -3,7 +3,6 @@ import type { } from '@micro-app/types' import type IframeSandbox from './index' import globalEnv from '../../libs/global_env' -import microApp from '../../micro_app' import { rawDefineProperty, CompletionPath, @@ -11,15 +10,12 @@ import { isBaseElement, isElement, isNode, - isMicroAppBody, - throttleDeferForSetAppName, + isDocumentFragment, } from '../../libs/utils' import { updateElementInfo, + getIframeParentNodeDesc, } from '../adapter' -import { - appInstanceMap, -} from '../../create_app' /** * patch Element & Node of child app @@ -38,16 +34,22 @@ export function patchElement ( patchIframeAttribute(url, microAppWindow) } +/** + * patch iframe Node/Element + * + */ function patchIframeNode ( appName: string, microAppWindow: microAppWindowType, sandbox: IframeSandbox, ): void { const rawRootElement = globalEnv.rawRootElement // native root Element + const rawRootNode = globalEnv.rawRootNode const rawDocument = globalEnv.rawDocument const microDocument = microAppWindow.document const microRootNode = microAppWindow.Node const microRootElement = microAppWindow.Element + const microDocumentFragment = microAppWindow.DocumentFragment // const rawMicroGetRootNode = microRootNode.prototype.getRootNode const rawMicroAppendChild = microRootNode.prototype.appendChild const rawMicroInsertBefore = microRootNode.prototype.insertBefore @@ -55,11 +57,13 @@ function patchIframeNode ( const rawMicroRemoveChild = microRootNode.prototype.removeChild const rawMicroAppend = microRootElement.prototype.append const rawMicroPrepend = microRootElement.prototype.prepend + const rawMicroFragmentAppend = microDocumentFragment.prototype.append + const rawMicroFragmentPrepend = microDocumentFragment.prototype.prepend const rawMicroInsertAdjacentElement = microRootElement.prototype.insertAdjacentElement const rawMicroCloneNode = microRootNode.prototype.cloneNode - const rawInnerHTMLDesc = Object.getOwnPropertyDescriptor(microRootElement.prototype, 'innerHTML') as PropertyDescriptor - const rawParentNodeDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'parentNode') as PropertyDescriptor - const rawOwnerDocumentDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'ownerDocument') as PropertyDescriptor + const rawInnerHTMLDesc = Object.getOwnPropertyDescriptor(microRootElement.prototype, 'innerHTML')! + const rawParentNodeDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'parentNode')! + const rawOwnerDocumentDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'ownerDocument')! const isPureNode = (target: unknown): boolean | void => { return (isScriptElement(target) || isBaseElement(target)) && target.__PURE_ELEMENT__ @@ -75,21 +79,12 @@ function patchIframeNode ( return parent } - microRootNode.prototype.getRootNode = function getRootNode (): Node { - return microDocument - // TODO: 什么情况下返回原生document? - // const rootNode = rawMicroGetRootNode.call(this, options) - // if (rootNode === appInstanceMap.get(appName)?.container) return microDocument - // return rootNode - } - microRootNode.prototype.appendChild = function appendChild (node: T): T { - // TODO: 有必要执行这么多次updateElementInfo? updateElementInfo(node, appName) if (isPureNode(node)) { return rawMicroAppendChild.call(this, node) } - return rawRootElement.prototype.appendChild.call(getRawTarget(this), node) + return rawRootNode.prototype.appendChild.call(getRawTarget(this), node) } microRootNode.prototype.insertBefore = function insertBefore (node: T, child: Node | null): T { @@ -97,7 +92,7 @@ function patchIframeNode ( if (isPureNode(node)) { return rawMicroInsertBefore.call(this, node, child) } - return rawRootElement.prototype.insertBefore.call(getRawTarget(this), node, child) + return rawRootNode.prototype.insertBefore.call(getRawTarget(this), node, child) } microRootNode.prototype.replaceChild = function replaceChild (node: Node, child: T): T { @@ -105,17 +100,17 @@ function patchIframeNode ( if (isPureNode(node)) { return rawMicroReplaceChild.call(this, node, child) } - return rawRootElement.prototype.replaceChild.call(getRawTarget(this), node, child) + return rawRootNode.prototype.replaceChild.call(getRawTarget(this), node, child) } microRootNode.prototype.removeChild = function removeChild (oldChild: T): T { if (isPureNode(oldChild) || this.contains(oldChild)) { return rawMicroRemoveChild.call(this, oldChild) } - return rawRootElement.prototype.removeChild.call(getRawTarget(this), oldChild) + return rawRootNode.prototype.removeChild.call(getRawTarget(this), oldChild) } - microRootElement.prototype.append = function append (...nodes: (Node | string)[]): void { + microDocumentFragment.prototype.append = microRootElement.prototype.append = function append (...nodes: (Node | string)[]): void { let i = 0; let hasPureNode = false while (i < nodes.length) { nodes[i] = isNode(nodes[i]) ? nodes[i] : microDocument.createTextNode(nodes[i]) @@ -123,12 +118,12 @@ function patchIframeNode ( i++ } if (hasPureNode) { - return rawMicroAppend.call(this, ...nodes) + return (isDocumentFragment(this) ? rawMicroFragmentAppend : rawMicroAppend).call(this, ...nodes) } return rawRootElement.prototype.append.call(getRawTarget(this), ...nodes) } - microRootElement.prototype.prepend = function prepend (...nodes: (Node | string)[]): void { + microDocumentFragment.prototype.prepend = microRootElement.prototype.prepend = function prepend (...nodes: (Node | string)[]): void { let i = 0; let hasPureNode = false while (i < nodes.length) { nodes[i] = isNode(nodes[i]) ? nodes[i] : microDocument.createTextNode(nodes[i]) @@ -136,7 +131,7 @@ function patchIframeNode ( i++ } if (hasPureNode) { - return rawMicroPrepend.call(this, ...nodes) + return (isDocumentFragment(this) ? rawMicroFragmentPrepend : rawMicroPrepend).call(this, ...nodes) } return rawRootElement.prototype.prepend.call(getRawTarget(this), ...nodes) } @@ -154,30 +149,59 @@ function patchIframeNode ( return rawRootElement.prototype.insertAdjacentElement.call(getRawTarget(this), where, element) } - // patch cloneNode - microRootNode.prototype.cloneNode = function cloneNode (deep?: boolean): Node { - const clonedNode = rawMicroCloneNode.call(this, deep) - return updateElementInfo(clonedNode, appName) - } + /** + * Specific prototype properties: + * 1. baseURI + * 2. ownerDocument + * 3. parentNode + * 4. innerHTML + */ + rawDefineProperty(microRootNode.prototype, 'baseURI', { + configurable: true, + enumerable: true, + get () { + return sandbox.proxyWindow.location.href + }, + }) rawDefineProperty(microRootNode.prototype, 'ownerDocument', { configurable: true, enumerable: true, get () { return this.__PURE_ELEMENT__ || this === microDocument - ? rawOwnerDocumentDesc.get!.call(this) + ? rawOwnerDocumentDesc.get?.call(this) : microDocument }, }) + // patch parentNode + rawDefineProperty(microRootNode.prototype, 'parentNode', getIframeParentNodeDesc( + appName, + rawParentNodeDesc, + )) + + microRootNode.prototype.getRootNode = function getRootNode (): Node { + return microDocument + // TODO: any case return document? + // const rootNode = rawMicroGetRootNode.call(this, options) + // if (rootNode === appInstanceMap.get(appName)?.container) return microDocument + // return rootNode + } + + // patch cloneNode + microRootNode.prototype.cloneNode = function cloneNode (deep?: boolean): Node { + const clonedNode = rawMicroCloneNode.call(this, deep) + return updateElementInfo(clonedNode, appName) + } + rawDefineProperty(microRootElement.prototype, 'innerHTML', { configurable: true, enumerable: true, get () { - return rawInnerHTMLDesc.get!.call(this) + return rawInnerHTMLDesc.get?.call(this) }, set (code: string) { - rawInnerHTMLDesc.set!.call(this, code) + rawInnerHTMLDesc.set?.call(this, code) Array.from(this.children).forEach((child) => { if (isElement(child)) { updateElementInfo(child, appName) @@ -186,34 +210,6 @@ function patchIframeNode ( } }) - // patch parentNode - rawDefineProperty(microRootNode.prototype, 'parentNode', { - configurable: true, - enumerable: true, - get () { - /** - * set current appName for hijack parentNode of html - * NOTE: - * 1. Is there a problem with setting the current appName in iframe mode - */ - throttleDeferForSetAppName(appName) - const result: ParentNode = rawParentNodeDesc.get!.call(this) - /** - * If parentNode is , return rawDocument.body - * Scenes: - * 1. element-ui@2/lib/utils/vue-popper.js - * if (this.popperElm.parentNode === document.body) ... - * WARNING: - * Will it cause other problems ? - * e.g. target.parentNode.remove(target) - */ - if (isMicroAppBody(result) && appInstanceMap.get(appName)?.container) { - return microApp.options.getRootElementParentNode?.(this, appName) || globalEnv.rawDocument.body - } - return result - } - }) - // Adapt to new image(...) scene const ImageProxy = new Proxy(microAppWindow.Image, { construct (Target, args): HTMLImageElement { @@ -236,19 +232,27 @@ function patchIframeAttribute (url: string, microAppWindow: microAppWindowType): microRootElement.prototype.setAttribute = function setAttribute (key: string, value: any): void { if ( - ((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) || - (key === 'href' && /^link$/i.test(this.tagName)) + /^micro-app(-\S+)?/i.test(this.tagName) && + key === 'data' && + this.setAttribute !== microRootElement.prototype.setAttribute ) { - value = CompletionPath(value, url) + this.setAttribute(key, value) + } else { + if ( + ((key === 'src' || key === 'srcset') && /^(img|script|video|audio|source|embed)$/i.test(this.tagName)) || + (key === 'href' && /^(link|image)$/i.test(this.tagName)) + ) { + value = CompletionPath(value, url) + } + rawMicroSetAttribute.call(this, key, value) } - - rawMicroSetAttribute.call(this, key, value) } const protoAttrList: Array<[HTMLElement, string]> = [ [microAppWindow.HTMLImageElement.prototype, 'src'], [microAppWindow.HTMLScriptElement.prototype, 'src'], [microAppWindow.HTMLLinkElement.prototype, 'href'], + [microAppWindow.SVGImageElement.prototype, 'href'], ] /** diff --git a/src/sandbox/iframe/index.ts b/src/sandbox/iframe/index.ts index 13e51f5de..e4f987a40 100644 --- a/src/sandbox/iframe/index.ts +++ b/src/sandbox/iframe/index.ts @@ -1,4 +1,5 @@ import type { + Func, microAppWindowType, MicroLocation, SandBoxStartParams, @@ -19,6 +20,8 @@ import { isArray, defer, createURL, + rawDefineProperties, + isFunction, } from '../../libs/utils' import { EventCenterForMicroApp, @@ -80,6 +83,8 @@ export default class IframeSandbox { // TODO: 放到 super中定义,super(appName, url),with沙箱也需要简化 public appName: string public url: string + // reset mount, unmount when stop in default mode + public clearHijackUmdHooks!: () => void constructor (appName: string, url: string) { this.appName = appName @@ -127,9 +132,10 @@ export default class IframeSandbox { this.iframe = pureCreateElement('iframe') const iframeAttrs: Record = { + id: appName, src: microApp.options.iframeSrc || browserPath, style: 'display: none', - id: appName, + 'powered-by': 'micro-app', } Object.keys(iframeAttrs).forEach((key) => this.iframe!.setAttribute(key, iframeAttrs[key])) @@ -169,15 +175,6 @@ export default class IframeSandbox { * 1. iframe router and browser router are separated, we should update iframe router manually * 2. withSandbox location is browser location when disable memory-router, so no need to do anything */ - /** - * TODO: - * 1. iframe关闭虚拟路由系统后,default-page无法使用,推荐用户直接使用浏览器地址控制首页渲染 - * 补充:keep-router-state 也无法配置,因为keep-router-state一定为true。 - * 2. 导航拦截、current.route 可以正常使用 - * 3. 可以正常控制子应用跳转,方式还是自上而下(也可以是子应用内部跳转,这种方式更好一点,减小对基座的影响,不会导致vue的循环刷新) - * 4. 关闭虚拟路由以后会对应 route-mode='custom' 模式,包括with沙箱也会这么做 - * 5. 关闭虚拟路由是指尽可能模拟没有虚拟路由的情况,子应用直接获取浏览器location和history,控制浏览器跳转 - */ this.initRouteState(defaultPage) // unique listener of popstate event for child app @@ -214,7 +211,9 @@ export default class IframeSandbox { destroy, clearData, }: SandBoxStopParams): void { + // sandbox.stop may exec before sandbox.start, e.g: iframe sandbox + default mode + remount if (!this.active) return + this.recordAndReleaseEffect({ clearData }, !umdMode || destroy) /* --- memory router part --- start */ @@ -232,6 +231,8 @@ export default class IframeSandbox { Reflect.deleteProperty(globalEnv.rawWindow, key) }) this.escapeKeys.clear() + + this.clearHijackUmdHooks() } if (--globalEnv.activeSandbox === 0) { @@ -240,7 +241,7 @@ export default class IframeSandbox { } if (--IframeSandbox.activeCount === 0) { - // TODO: Is there anything to put here? + // TODO: Is there anything to do? } this.active = false @@ -492,10 +493,55 @@ export default class IframeSandbox { * action before exec scripts when mount * Actions: * 1. patch static elements from html + * 2. hijack umd hooks -- mount, unmount, micro-app-appName * @param container micro app container */ - public actionBeforeExecScripts (container: Element | ShadowRoot): void { + public actionsBeforeExecScripts (container: Element | ShadowRoot, handleUmdHooks: Func): void { this.patchStaticElement(container) + this.clearHijackUmdHooks = this.hijackUmdHooks(this.appName, this.microAppWindow, handleUmdHooks) + } + + // hijack mount, unmount, micro-app-appName hook to microAppWindow + private hijackUmdHooks ( + appName: string, + microAppWindow: microAppWindowType, + handleUmdHooks: Func, + ): () => void { + let mount: Func | null, unmount: Func | null, microAppLibrary: Record | null + rawDefineProperties(microAppWindow, { + mount: { + configurable: true, + get: () => mount, + set: (value) => { + if (this.active && isFunction(value) && !mount) { + handleUmdHooks(mount = value, unmount) + } + } + }, + unmount: { + configurable: true, + get: () => unmount, + set: (value) => { + if (this.active && isFunction(value) && !unmount) { + handleUmdHooks(mount, unmount = value) + } + } + }, + [`micro-app-${appName}`]: { + configurable: true, + get: () => microAppLibrary, + set: (value) => { + if (this.active && isPlainObject(value) && !microAppLibrary) { + microAppLibrary = value + handleUmdHooks(microAppLibrary.mount, microAppLibrary.unmount) + } + } + } + }) + + return () => { + mount = unmount = microAppLibrary = null + } } public setStaticAppState (state: string): void { diff --git a/src/sandbox/iframe/special_key.ts b/src/sandbox/iframe/special_key.ts index 464b3e612..b3158508b 100644 --- a/src/sandbox/iframe/special_key.ts +++ b/src/sandbox/iframe/special_key.ts @@ -1,11 +1,11 @@ export const escape2RawWindowKeys = [ 'getComputedStyle', + // FIX ISSUE: https://github.com/micro-zoe/micro-app/issues/1292 + 'DOMParser', 'visualViewport', 'matchMedia', - // 'DOMParser', 'ResizeObserver', 'IntersectionObserver', - // 'dispatchEvent', ] export const escape2RawWindowRegExpKeys = [ @@ -13,13 +13,11 @@ export const escape2RawWindowRegExpKeys = [ /mutationObserver$/i, /height$|width$/i, /offset$/i, - // /event$/i, /selection$/i, /^range/i, /^screen/i, /^scroll/i, /X$|Y$/, - // /^(?:HTML\w*)?Element$/, ] export const uniqueDocumentElement = [ @@ -29,33 +27,50 @@ export const uniqueDocumentElement = [ 'title', ] -// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (属性) +export const hijackMicroLocationKeys = [ + 'host', + 'hostname', + 'port', + 'protocol', + 'origin', +] + +// hijack InstanceOf of iframe class +export const hijackInstanceOfWindowRegExpKeys = [ + /^((HTML|SVG)\w*|MathML)?Element$/, + /^(Node|Text|Attr|Comment|EventTarget|CharacterData|NamedNodeMap|ShadowRoot)$/, + /^Document(Type|Fragment)?$/, + /^(?!PopState).*Event$/, + /^DataTransfer/ +] + +// proxy to shadowRoot or rawDocument (property) export const proxy2RawDocOrShadowKeys = [ 'childElementCount', 'children', 'firstElementChild', 'firstChild', 'lastElementChild', - 'activeElement', // Element not has, document or shadowRoot has - 'fullscreenElement', // Element not has, document or shadowRoot has - 'pictureInPictureElement', // Element not has, document or shadowRoot has - 'pointerLockElement', // Element not has, document or shadowRoot has - 'styleSheets', // Element not has, document or shadowRoot has + 'activeElement', // not for Element, just for document/shadowRoot + 'fullscreenElement', // not for Element, just for document/shadowRoot + 'pictureInPictureElement', // not for Element, just for document/shadowRoot + 'pointerLockElement', // not for Element, just for document/shadowRoot + 'styleSheets', // not for Element, just for document/shadowRoot ] -// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (方法) +// proxy to shadowRoot or rawDocument (method) export const proxy2RawDocOrShadowMethods = [ 'append', 'contains', 'replaceChildren', - 'createRange', // Element not has, document or shadowRoot has - 'getSelection', // Element not has, document or shadowRoot has - 'elementFromPoint', // Element not has, document or shadowRoot has - 'elementsFromPoint', // Element not has, document or shadowRoot has - 'getAnimations', // Element not has, document or shadowRoot has + 'createRange', // not for Element, just for document/shadowRoot + 'getSelection', // not for Element, just for document/shadowRoot + 'elementFromPoint', // not for Element, just for document/shadowRoot + 'elementsFromPoint', // not for Element, just for document/shadowRoot + 'getAnimations', // not for Element, just for document/shadowRoot ] -// 直接代理到原生document上 (属性) +// proxy to rawDocument (property) export const proxy2RawDocumentKeys = [ 'characterSet', 'compatMode', @@ -76,7 +91,7 @@ export const proxy2RawDocumentKeys = [ 'fonts', ] -// 直接代理到原生document上 (方法) +// proxy to rawDocument (method) export const proxy2RawDocumentMethods = [ 'execCommand', 'createRange', @@ -85,5 +100,4 @@ export const proxy2RawDocumentMethods = [ 'getElementsByTagNameNS', 'hasFocus', 'prepend', - // 'dispatchEvent', ] diff --git a/src/sandbox/iframe/window.ts b/src/sandbox/iframe/window.ts index ecca66199..dbb96a7c5 100644 --- a/src/sandbox/iframe/window.ts +++ b/src/sandbox/iframe/window.ts @@ -11,6 +11,8 @@ import { isFunction, logWarn, includes, + instanceOf, + isConstructor, } from '../../libs/utils' import { GLOBAL_KEY_TO_WINDOW, @@ -20,6 +22,7 @@ import { import { escape2RawWindowKeys, escape2RawWindowRegExpKeys, + // hijackInstanceOfWindowRegExpKeys, } from './special_key' /** @@ -78,6 +81,42 @@ function patchWindowProperty ( return false }) + /** + * In FireFox, iframe Element.prototype will point to native Element.prototype after insert to document + * Rewrite all constructor's Symbol.hasInstance of iframeWindow + * NOTE: + * 1. native event instanceof iframe window.Event + * 2. native node instanceof iframe window.Node + * 3. native element instanceof iframe window.Element + * 4. native url instanceof iframe window.URL + * ... + */ + if (isConstructor(microAppWindow[key]) && key in rawWindow) { + rawDefineProperty(microAppWindow[key], Symbol.hasInstance, { + configurable: true, + enumerable: false, + value (target: unknown): boolean { + return target instanceof rawWindow[key] || instanceOf(target, microAppWindow[key]) + }, + }) + } + + // hijackInstanceOfWindowRegExpKeys.some((reg: RegExp) => { + // if (reg.test(key) && key in rawWindow) { + // rawDefineProperty(microAppWindow[key], Symbol.hasInstance, { + // configurable: true, + // enumerable: false, + // value: (target: unknown) => { + // return target instanceof rawWindow[key] + // ? true + // : instanceOf(target, microAppWindow[key]) + // }, + // }) + // return true + // } + // return false + // }) + return /^on/.test(key) && !SCOPE_WINDOW_ON_EVENT_OF_IFRAME.includes(key) }) .forEach((eventName: string) => { @@ -178,11 +217,15 @@ function createProxyWindow ( } function patchWindowEffect (microAppWindow: microAppWindowType): CommonEffectHook { - const { rawWindow, rawAddEventListener, rawRemoveEventListener } = globalEnv + const { rawWindow, rawAddEventListener, rawRemoveEventListener, rawDispatchEvent } = globalEnv const eventListenerMap = new Map>() const sstEventListenerMap = new Map>() function getEventTarget (type: string): Window { + /** + * TODO: SCOPE_WINDOW_EVENT_OF_IFRAME的事件非常少,有可能导致问题 + * 1、一些未知的需要绑定到iframe的事件被错误的绑定到原生window上 + */ return SCOPE_WINDOW_EVENT_OF_IFRAME.includes(type) ? microAppWindow : rawWindow } @@ -214,6 +257,10 @@ function patchWindowEffect (microAppWindow: microAppWindowType): CommonEffectHoo rawRemoveEventListener.call(getEventTarget(type), type, listener, options) } + microAppWindow.dispatchEvent = function (event: Event): boolean { + return rawDispatchEvent.call(getEventTarget(event?.type), event) + } + const reset = (): void => { sstEventListenerMap.clear() } diff --git a/src/sandbox/router/core.ts b/src/sandbox/router/core.ts index c8217fc4b..8c8eced2f 100644 --- a/src/sandbox/router/core.ts +++ b/src/sandbox/router/core.ts @@ -1,6 +1,7 @@ import type { MicroLocation, MicroState, + MicroRouterInfoState, LocationQuery, HandleMicroPathResult, } from '@micro-app/types' @@ -13,6 +14,7 @@ import { isUndefined, isPlainObject, createURL, + isEmptyObject, } from '../../libs/utils' import { appInstanceMap, @@ -30,19 +32,19 @@ import microApp from '../../micro_app' // set micro app state to origin state export function setMicroState ( appName: string, - microState: MicroState, - targetLocation: MicroLocation, + microState?: MicroState, + targetLocation?: MicroLocation, ): MicroState { // TODO: 验证native模式下修改state nextjs路由是否正常 const rawState = globalEnv.rawWindow.history.state - const additionalState: Record = { + const additionalState: Record<'__MICRO_APP_STATE__', Record> = { __MICRO_APP_STATE__: assign({}, rawState?.__MICRO_APP_STATE__, { [appName]: { - fullPath: targetLocation.pathname + targetLocation.search + targetLocation.hash, - state: microState, + fullPath: targetLocation ? targetLocation.pathname + targetLocation.search + targetLocation.hash : null, + state: microState ?? null, mode: getRouterMode(appName), } - }) + }), } // create new state object @@ -60,14 +62,19 @@ export function removeMicroState (appName: string, rawState: MicroState): MicroS } } - return assign({}, rawState) + return !isEmptyObject(rawState) ? assign({}, rawState) : null } // get micro app state form origin state export function getMicroState (appName: string): MicroState { const rawState = globalEnv.rawWindow.history.state - // rawState?.__MICRO_APP_STATE__?.[appName]?.state || (isRouterModeCustom(appName) ? rawState : null) - return rawState?.__MICRO_APP_STATE__?.[appName]?.state || (isRouterModeCustom(appName) ? rawState : null) + return rawState?.__MICRO_APP_STATE__?.[appName]?.state || null +} + +// get micro app router info state form origin state +export function getMicroRouterInfoState (appName: string): MicroRouterInfoState | null { + const rawState = globalEnv.rawWindow.history.state + return rawState?.__MICRO_APP_STATE__?.[appName] || null } const ENC_AD_RE = /&/g // %M1 @@ -119,7 +126,7 @@ export function getMicroPathFromURL (appName: string): string | null { * NOTE: * 1. state mode: all base on __MICRO_APP_STATE__ * 2. pure mode: navigate by location.xxx may contain one-time information in __MICRO_APP_STATE__ - * 3. native/scope mode: vue-router@4 will exec replaceState base on state before pushState, like: + * 3. native mode: vue-router@4 will exec replaceState with history.state before pushState, like: * history.replaceState( * assign({}, history.state, {...}), * title, @@ -127,8 +134,13 @@ export function getMicroPathFromURL (appName: string): string | null { * ) * when base app jump to another page from child page, it will replace child path with base app path * e.g: base-home --> child-home --> child-about(will replace with child-home before jump to base-home) --> base-home, when go back, it will back to child-home not child-about - * So we take the fullPath as the standard + * So we take the fullPath as standard */ + // 问题:1、同一个页面多个子应用,一个修改后... --- native模式不支持多个子应用同时渲染,多个子应用推荐使用其它模式 + // if (isRouterModeCustom(appName)) { + // return rawLocation.pathname + rawLocation.search + rawLocation.hash + // } + // return rawState?.__MICRO_APP_STATE__?.[appName]?.fullPath || null return rawState?.__MICRO_APP_STATE__?.[appName]?.fullPath || (isRouterModeCustom(appName) ? rawLocation.pathname + rawLocation.search + rawLocation.hash : null) } diff --git a/src/sandbox/router/event.ts b/src/sandbox/router/event.ts index 0778420ad..d1db73806 100644 --- a/src/sandbox/router/event.ts +++ b/src/sandbox/router/event.ts @@ -14,7 +14,9 @@ import { import { getMicroPathFromURL, getMicroState, + getMicroRouterInfoState, isEffectiveApp, + isRouterModeCustom, } from './core' import { updateMicroLocation, @@ -22,6 +24,8 @@ import { import { removeDomScope, isFunction, + macro, + getRootContainer, } from '../../libs/utils' import globalEnv from '../../libs/global_env' @@ -48,20 +52,32 @@ export function addHistoryListener (appName: string): CallableFunction { !e.onlyForBrowser ) { /** - * TODO: vue-router@4 navigate async when receive popstateEvent, but child may respond to popstateEvent immediately(vue2, react), so when go back throw browser child will not unmount sync, and will respond to popstateEvent before base app, this will cause some problems - * __MICRO_APP_BASE_ROUTE__不可控,用户设置的值是随机的且不一定使用,用它作为判断依据太过危险 - */ - // const microAppWindow = appInstanceMap.get(appName)!.sandBox!.microAppWindow - // const rawLocation = globalEnv.rawWindow.location - // if ( - // !isRouterModeCustom(appName) || - // !microAppWindow.__MICRO_APP_BASE_ROUTE__ || - // // 主history、子hash,主、子都是hash如何处理 - // microAppWindow.__MICRO_APP_BASE_ROUTE__.includes('#') || - // `${rawLocation.pathname}/`.startsWith(('/' + microAppWindow.__MICRO_APP_BASE_ROUTE__).replace(/^\/+/, '/')) - // ) { - updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName)) - // } + * base app may respond to popstateEvent async(lazy load page & browser back/forward), but child app will respond to popstateEvent immediately(vue2, react), this will cause some problems + * 2 solutions: + * 1. child app respond to popstateEvent async -- router-event-delay + * 2. child app will not respond to popstateEvent in some scenarios (history.state===null || history.state?__MICRO_APP_STATE__[appName]) + * NOTE 1: + * 1. browser back/forward + * 2. location.hash/search/pathname = xxx + * 3. , + * 4. history.back/go/forward + * 5. history.pushState/replaceState + * + * NOTE2: + * 1、react16 hash mode navigate by location.hash = xxx, history.state is always null, but react16 respond to popstateEvent sync + * 2、multiple child apps may has problems + */ + if ( + !isRouterModeCustom(appName) || + !globalEnv.rawWindow.history.state || + getMicroRouterInfoState(appName) + ) { + const container = appInstanceMap.get(appName)?.container + macro( + () => updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName)), + (container && getRootContainer(container))?.getRouterEventDelay() ?? 0 + ) + } } } @@ -84,27 +100,29 @@ export function updateMicroLocationWithEvent ( appName: string, targetFullPath: string | null, ): void { - const app = appInstanceMap.get(appName)! - const proxyWindow = app.sandBox!.proxyWindow - const microAppWindow = app.sandBox!.microAppWindow - let isHashChange = false - // for hashChangeEvent - const oldHref = proxyWindow.location.href - // Do not attach micro state to url when targetFullPath is empty - if (targetFullPath) { - const oldHash = proxyWindow.location.hash - updateMicroLocation(appName, targetFullPath, microAppWindow.location as MicroLocation) - isHashChange = proxyWindow.location.hash !== oldHash - } + const app = appInstanceMap.get(appName) + if (app?.sandBox) { + const proxyWindow = app.sandBox.proxyWindow + const microAppWindow = app.sandBox.microAppWindow + let isHashChange = false + // for hashChangeEvent + const oldHref = proxyWindow.location.href + // Do not attach micro state to url when targetFullPath is empty + if (targetFullPath) { + const oldHash = proxyWindow.location.hash + updateMicroLocation(appName, targetFullPath, microAppWindow.location as MicroLocation) + isHashChange = proxyWindow.location.hash !== oldHash + } - // dispatch formatted popStateEvent to child - dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) + // dispatch formatted popStateEvent to child + dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) - // dispatch formatted hashChangeEvent to child when hash change - if (isHashChange) dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref) + // dispatch formatted hashChangeEvent to child when hash change + if (isHashChange) dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref) - // clear element scope before trigger event of next app - removeDomScope() + // clear element scope before trigger event of next app + removeDomScope() + } } /** diff --git a/src/sandbox/router/history.ts b/src/sandbox/router/history.ts index e5c8f1a30..c1cec0af8 100644 --- a/src/sandbox/router/history.ts +++ b/src/sandbox/router/history.ts @@ -7,6 +7,7 @@ import type { HandleMicroPathResult, } from '@micro-app/types' import globalEnv from '../../libs/global_env' +import bindFunctionToRawTarget from '../bind_function' import { isString, createURL, @@ -14,22 +15,34 @@ import { isURL, assign, removeDomScope, + isUndefined, + isNull, } from '../../libs/utils' import { setMicroPathToURL, setMicroState, getMicroState, + getMicroRouterInfoState, getMicroPathFromURL, isEffectiveApp, isRouterModePure, isRouterModeSearch, isRouterModeState, + isRouterModeCustom, } from './core' -import { dispatchNativeEvent } from './event' -import { updateMicroLocation } from './location' -import bindFunctionToRawTarget from '../bind_function' -import { getActiveApps } from '../../micro_app' -import { appInstanceMap, isIframeSandbox } from '../../create_app' +import { + dispatchNativeEvent, +} from './event' +import { + updateMicroLocation, +} from './location' +import { + getActiveApps, +} from '../../micro_app' +import { + appInstanceMap, + isIframeSandbox, +} from '../../create_app' /** * create proxyHistory for microApp @@ -42,26 +55,23 @@ export function createMicroHistory (appName: string, microLocation: MicroLocatio function getMicroHistoryMethod (methodName: string): CallableFunction { return function (...rests: any[]): void { // TODO: 测试iframe的URL兼容isURL的情况 - if (isString(rests[2]) || isURL(rests[2])) { - const targetLocation = createURL(rests[2], microLocation.href) - const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash - if (!isRouterModePure(appName)) { - navigateWithNativeEvent( - appName, - methodName, - setMicroPathToURL(appName, targetLocation), - true, - setMicroState(appName, rests[0], targetLocation), - rests[1], - ) - } - if (targetFullPath !== microLocation.fullPath) { - updateMicroLocation(appName, targetFullPath, microLocation) - } - appInstanceMap.get(appName)?.sandBox.updateIframeBase?.() - } else { - nativeHistoryNavigate(appName, methodName, rests[2], rests[0], rests[1]) + rests[2] = isUndefined(rests[2]) || isNull(rests[2]) || ('' + rests[2] === '') ? microLocation.href : '' + rests[2] + const targetLocation = createURL(rests[2], microLocation.href) + const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash + if (!isRouterModePure(appName)) { + navigateWithNativeEvent( + appName, + methodName, + setMicroPathToURL(appName, targetLocation), + true, + setMicroState(appName, rests[0], targetLocation), + rests[1], + ) + } + if (targetFullPath !== microLocation.fullPath) { + updateMicroLocation(appName, targetFullPath, microLocation) } + appInstanceMap.get(appName)?.sandBox.updateIframeBase?.() } } @@ -72,6 +82,9 @@ export function createMicroHistory (appName: string, microLocation: MicroLocatio return { pushState, replaceState, + go (delta?: number) { + return rawHistory.go(delta) + } } as MicroHistory } @@ -206,15 +219,38 @@ function reWriteHistoryMethod (method: History['pushState' | 'replaceState']): C excludeHiddenApp: true, excludePreRender: true, }).forEach(appName => { + // TODO: 大部分情况下,history.pushState 都是先执行,micro-app后卸载,所以会产生一种情况:跳转到新地址后,search模式会在url上添加参数,卸载后再将参数删除,所以会导致浏览器地址闪烁,是否需要去掉这个功能 if ((isRouterModeSearch(appName) || isRouterModeState(appName)) && !getMicroPathFromURL(appName)) { const app = appInstanceMap.get(appName)! attachRouteToBrowserURL( appName, - setMicroPathToURL(appName, app.sandBox.proxyWindow.location as MicroLocation), - setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location as MicroLocation), + setMicroPathToURL(appName, app.sandBox.proxyWindow.location), + setMicroState(appName, getMicroState(appName), app.sandBox.proxyWindow.location), + ) + } + + if (isRouterModeCustom(appName) && !getMicroRouterInfoState(appName)) { + nativeHistoryNavigate( + appName, + 'replaceState', + rawWindow.location.href, + setMicroState(appName) ) } + + // if (isRouterModeCustom(appName) || isRouterModeSearch(appName)) { + /** + * history.pushState/replaceState后主动触发子应用响应 + * 问题:子应用的卸载可能是异步的,而跳转的地址不一定在基础路径中,太快响应pushState可能会导致url地址被子应用改变或者子应用404,Promise太快卸载时出问题、setTimeout太慢keep-alive二次渲染后出问题 + * 1、history.pushState/replaceState执行后,子应用以异步的形式被主应用卸载,Promise响应时子应用还在,导致子应用跳转404后者浏览器url被子应用修改,产生异常 + * 2、keep-alive应用二次渲染时,由于setTimeout响应过慢,子应用在渲染后才接受到popstate事件,响应新的url,从而导致状态丢失 + * 3、同一个页面多个子应用,修改地址响应 + * 4、vue3跳转前会执行一次replace,有没有影响? + */ + + // } }) + // fix bug for nest app removeDomScope() } diff --git a/src/sandbox/router/location.ts b/src/sandbox/router/location.ts index 7c27905f0..b79b50d98 100644 --- a/src/sandbox/router/location.ts +++ b/src/sandbox/router/location.ts @@ -344,14 +344,14 @@ export function autoTriggerNavigationGuard (appName: string, microLocation: Micr */ export function updateMicroLocation ( appName: string, - path: string, + targetFullPath: string, microLocation: MicroLocation, type?: string, ): void { // record old values of microLocation to `from` const from = createGuardLocation(appName, microLocation) // if is iframeSandbox, microLocation muse be rawLocation of iframe, not proxyLocation - const newLocation = createURL(path, microLocation.href) + const newLocation = createURL(targetFullPath, microLocation.href) if (isIframeSandbox(appName)) { const microAppWindow = appInstanceMap.get(appName)!.sandBox.microAppWindow microAppWindow.rawReplaceState?.call(microAppWindow.history, getMicroState(appName), '', newLocation.href) @@ -362,9 +362,26 @@ export function updateMicroLocation ( } microLocation.self.href = targetHref } + + /** + * native模式从state中取值,而浏览器地址的修改无法控制,很可能出现浏览器地址和__MICRO_APP_STATE__不一致的情况 + * 尤其是在初始化和前进后退时,由于vue-router4会主动修改url地址,倒是上述情况经常出现 + * 为了结局这个问题,在子应用初始化和响应popstate事件后,判断__MICRO_APP_STATE__和浏览器地址是否一致,如果不一致,则将浏览器地址更新为__MICRO_APP_STATE__的地址 + * 说明: + * 1、如果__MICRO_APP_STATE__和url不一样,那么更新url的操作是对的,否则会产生url和渲染页面不一致的问题,开发者会更加困惑 + * 2、当native模式有多个子应用同时存在,其中一个修改url地址,另外一个并不会改变__MICRO_APP_STATE__,刷新就产生问题,不一致,第二是根据谁更新url? + */ + const rawLocation = globalEnv.rawWindow.location + if ( + isRouterModeCustom(appName) && + (targetFullPath !== rawLocation.pathname + rawLocation.search + rawLocation.hash) && + type !== 'prevent' + ) { + nativeHistoryNavigate(appName, 'replaceState', targetFullPath, globalEnv.rawWindow.history.state) + } + // update latest values of microLocation to `to` const to = createGuardLocation(appName, microLocation) - // The hook called only when fullPath changed if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) { executeNavigationGuard(appName, to, from) diff --git a/src/sandbox/scoped_css.ts b/src/sandbox/scoped_css.ts index dff910b08..183a58ca6 100644 --- a/src/sandbox/scoped_css.ts +++ b/src/sandbox/scoped_css.ts @@ -92,9 +92,24 @@ class CSSParser { const m = this.commonMatch(/^[^{]+/, skip) if (!m) return false + /** + * NOTE: + * 1. :is(h1, h2, h3):has(+ h2, + h3, + h4) {} + * should be ==> micro-app[name=xxx] :is(h1, h2, h3):has(+ h2, + h3, + h4) {} + * 2. :dir(ltr) {} + * should be ==> micro-app[name=xxx] :dir(ltr) {} + * 3. body :not(div, .fancy) {} + * should be ==> micro-app[name=xxx] micro-app-body :not(div, .fancy) {} + * 4. .a, .b, li:nth-child(3) + * should be ==> micro-app[name=xxx] .a, micro-app[name=xxx] .b, micro-app[name=xxx] li:nth-child(3) + * 5. :is(.a, .b, .c) a {} + * should be ==> micro-app[name=xxx] :is(.a, .b, .c) a {} + * 6. :where(.a, .b, .c) a {} + * should be ==> micro-app[name=xxx] :where(.a, .b, .c) a {} + */ return m[0].replace(/(^|,[\n\s]*)([^,]+)/g, (_, separator, selector) => { selector = trim(selector) - if (!( + if (selector && !( this.scopecssDisableNextLine || ( this.scopecssDisable && ( @@ -126,7 +141,7 @@ class CSSParser { return true } - private matchAllDeclarations (nesting = 1): void { + private matchAllDeclarations (nesting = 0): void { let cssValue = (this.commonMatch(/^(?:url\(["']?(?:[^)"'}]+)["']?\)|[^{}/])*/, true) as RegExpExecArray)[0] if (cssValue) { @@ -156,14 +171,6 @@ class CSSParser { if (!this.cssText) return - if (this.cssText.charAt(0) === '}') { - if (!nesting) return - if (nesting > 1) { - this.commonMatch(/}+/) - } - return this.matchAllDeclarations(nesting - 1) - } - // extract comments in declarations if (this.cssText.charAt(0) === '/') { if (this.cssText.charAt(1) === '*') { @@ -171,11 +178,13 @@ class CSSParser { } else { this.commonMatch(/\/+/) } - } - - if (this.cssText.charAt(0) === '{') { - this.commonMatch(/{+\s*/) + } else if (this.cssText.charAt(0) === '{') { + this.matchOpenBrace() nesting++ + } else if (this.cssText.charAt(0) === '}') { + if (nesting < 1) return + this.matchCloseBrace() + nesting-- } return this.matchAllDeclarations(nesting) @@ -196,7 +205,8 @@ class CSSParser { this.documentRule() || this.pageRule() || this.hostRule() || - this.fontFaceRule() + this.fontFaceRule() || + this.layerRule() } // :global is CSS Modules rule, it will be converted to normal syntax @@ -275,6 +285,23 @@ class CSSParser { return this.commonHandlerForAtRuleWithSelfRule('font-face') } + // https://developer.mozilla.org/en-US/docs/Web/CSS/@layer + private layerRule (): boolean | void { + if (!this.commonMatch(/^@layer\s*([^{;]+)/)) return false + + if (!this.matchOpenBrace()) return !!this.commonMatch(/^[;]+/) + + this.matchComments() + + this.matchRules() + + if (!this.matchCloseBrace()) return parseError('@layer missing \'}\'', this.linkPath) + + this.matchLeadingSpaces() + + return true + } + // https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule private mediaRule = this.createMatcherForRuleWithChildRule(/^@media *([^{]+)/, '@media') // https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule @@ -399,7 +426,7 @@ class CSSParser { } private matchCloseBrace () { - return this.commonMatch(/^}/) + return this.commonMatch(/^}\s*/) } // match and slice the leading spaces diff --git a/src/sandbox/with/document.ts b/src/sandbox/with/document.ts index 998ab287b..211c106bb 100644 --- a/src/sandbox/with/document.ts +++ b/src/sandbox/with/document.ts @@ -16,6 +16,9 @@ import { import { appInstanceMap, } from '../../create_app' +import { + updateElementInfo, +} from '../adapter' /** * create proxyDocument and MicroDocument, rewrite document of child app @@ -79,8 +82,7 @@ function createProxyDocument ( options?: ElementCreationOptions, ): HTMLElement { const element = rawCreateElement.call(rawDocument, tagName, options) - element.__MICRO_APP_NAME__ = appName - return element + return updateElementInfo(element, appName) } function createElementNS ( @@ -89,8 +91,7 @@ function createProxyDocument ( options?: string | ElementCreationOptions, ): HTMLElement { const element = rawCreateElementNS.call(rawDocument, namespaceURI, name, options) - element.__MICRO_APP_NAME__ = appName - return element + return updateElementInfo(element, appName) } /** diff --git a/src/sandbox/with/index.ts b/src/sandbox/with/index.ts index 546157f63..f19dda790 100644 --- a/src/sandbox/with/index.ts +++ b/src/sandbox/with/index.ts @@ -1,4 +1,5 @@ import type { + Func, microAppWindowType, WithSandBoxInterface, plugins, @@ -33,6 +34,7 @@ import { rawHasOwnProperty, pureCreateElement, assign, + isFunction, } from '../../libs/utils' import { patchDocument, @@ -100,7 +102,7 @@ export default class WithSandBox extends BaseSandbox implements WithSandBoxInter public microAppWindow = new CustomWindow() as MicroAppWindowType // Proxy target constructor (appName: string, url: string) { - super() + super(appName, url) this.patchWith((resolve: CallableFunction) => { // get scopeProperties and escapeProperties from plugins this.getSpecialProperties(appName) @@ -205,6 +207,7 @@ export default class WithSandBox extends BaseSandbox implements WithSandBoxInter * 1. injectedKeys and escapeKeys must be placed at the back * 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart * 3. umd mode will not delete global keys + * 4. mount & unmount hook should delete in default mode when stop */ if (!umdMode || destroy) { clearMicroEventSource(this.microAppWindow.__MICRO_APP_NAME__) @@ -218,6 +221,8 @@ export default class WithSandBox extends BaseSandbox implements WithSandBoxInter Reflect.deleteProperty(globalEnv.rawWindow, key) }) this.escapeKeys.clear() + + this.clearHijackUmdHooks() } if (--globalEnv.activeSandbox === 0) { @@ -260,6 +265,7 @@ export default class WithSandBox extends BaseSandbox implements WithSandBoxInter microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), { removeDomScope, pureCreateElement, + location: microAppWindow.location, router, }) } @@ -593,10 +599,55 @@ export default class WithSandBox extends BaseSandbox implements WithSandBoxInter * action before exec scripts when mount * Actions: * 1. patch static elements from html + * 2. hijack umd hooks -- mount, unmount, micro-app-appName * @param container micro app container */ - public actionBeforeExecScripts (container: Element | ShadowRoot): void { + public actionsBeforeExecScripts (container: Element | ShadowRoot, handleUmdHooks: Func): void { this.patchStaticElement(container) + this.clearHijackUmdHooks = this.hijackUmdHooks(this.appName, this.microAppWindow, handleUmdHooks) + } + + // hijack mount, unmount, micro-app-appName hook to microAppWindow + private hijackUmdHooks ( + appName: string, + microAppWindow: microAppWindowType, + handleUmdHooks: Func, + ): () => void { + let mount: Func | null, unmount: Func | null, microAppLibrary: Record | null + rawDefineProperties(microAppWindow, { + mount: { + configurable: true, + get: () => mount, + set: (value) => { + if (this.active && isFunction(value) && !mount) { + handleUmdHooks(mount = value, unmount) + } + } + }, + unmount: { + configurable: true, + get: () => unmount, + set: (value) => { + if (this.active && isFunction(value) && !unmount) { + handleUmdHooks(mount, unmount = value) + } + } + }, + [`micro-app-${appName}`]: { + configurable: true, + get: () => microAppLibrary, + set: (value) => { + if (this.active && isPlainObject(value) && !microAppLibrary) { + microAppLibrary = value + handleUmdHooks(microAppLibrary.mount, microAppLibrary.unmount) + } + } + } + }) + + return () => { + mount = unmount = microAppLibrary = null + } } public setStaticAppState (state: string): void { diff --git a/src/source/index.ts b/src/source/index.ts index 6e0177b19..88fd6a2d8 100644 --- a/src/source/index.ts +++ b/src/source/index.ts @@ -95,7 +95,7 @@ export function extractSourceDom (htmlStr: string, app: AppInterface): void { flatChildren(wrapElement, app, microAppHead, fiberStyleTasks) /** - * Style and link are parallel, because it takes a lot of time for link to request resources. During this period, style processing can be performed to improve efficiency. + * Style and link are parallel, as it takes a lot of time for link to request resources. During this period, style processing can be performed to improve efficiency. */ const fiberStyleResult = serialExecFiberTasks(fiberStyleTasks) diff --git a/src/source/links.ts b/src/source/links.ts index 77581c10d..057a00dbc 100644 --- a/src/source/links.ts +++ b/src/source/links.ts @@ -96,7 +96,7 @@ export function extractLinkFromHtml ( } else { return { address: href, linkInfo } } - } else if (rel && ['prefetch', 'preload', 'prerender', 'modulepreload'].includes(rel)) { + } else if (rel && ['prefetch', 'preload', 'prerender', 'modulepreload', 'icon'].includes(rel)) { // preload prefetch prerender .... if (isDynamic) { replaceComment = document.createComment(`link element with rel=${rel}${href ? ' & href=' + href : ''} removed by micro-app`) diff --git a/src/source/patch.ts b/src/source/patch.ts index 1efa58fa9..04ab0f872 100644 --- a/src/source/patch.ts +++ b/src/source/patch.ts @@ -24,6 +24,10 @@ import { isScriptElement, isIFrameElement, isMicroAppBody, + isMicroAppHead, + isNull, + getIframeCurrentAppName, + isDocumentFragment, } from '../libs/utils' import scopedCSS from '../sandbox/scoped_css' import { @@ -39,6 +43,7 @@ import { } from './scripts' import { fixReactHMRConflict, + updateElementInfo, } from '../sandbox/adapter' import microApp from '../micro_app' import globalEnv from '../libs/global_env' @@ -139,17 +144,17 @@ function handleNewNode (child: Node, app: AppInterface): Node { * @param app app * @param method raw method * @param parent parent node - * @param targetChild target node - * @param passiveChild second param of insertBefore and replaceChild + * @param targetNode target node + * @param passiveNode second param of insertBefore and replaceChild */ function invokePrototypeMethod ( app: AppInterface, rawMethod: Func, parent: Node, - targetChild: Node, - passiveChild?: Node | null, + targetNode: Node, + passiveNode?: Node | null, ): any { - const hijackParent = getHijackParent(parent, targetChild, app) + const hijackParent = getHijackParent(parent, targetNode, app) if (hijackParent) { /** * If parentNode is , return rawDocument.body @@ -168,9 +173,9 @@ function invokePrototypeMethod ( isMicroAppBody(hijackParent) && rawMethod !== globalEnv.rawRemoveChild ) { - const descriptor = Object.getOwnPropertyDescriptor(targetChild, 'parentNode') - if ((!descriptor || descriptor.configurable) && !targetChild.__MICRO_APP_HAS_DPN__) { - rawDefineProperties(targetChild, { + const descriptor = Object.getOwnPropertyDescriptor(targetNode, 'parentNode') + if ((!descriptor || descriptor.configurable) && !targetNode.__MICRO_APP_HAS_DPN__) { + rawDefineProperties(targetNode, { parentNode: { configurable: true, get () { @@ -192,63 +197,63 @@ function invokePrototypeMethod ( if ( __DEV__ && - isIFrameElement(targetChild) && + isIFrameElement(targetNode) && rawMethod === globalEnv.rawAppendChild ) { fixReactHMRConflict(app) } /** - * 1. If passiveChild exists, it must be insertBefore or replaceChild - * 2. When removeChild, targetChild may not be in microAppHead or head + * 1. If passiveNode exists, it must be insertBefore or replaceChild + * 2. When removeChild, targetNode may not be in microAppHead or head * NOTE: - * 1. If passiveChild not in hijackParent, insertBefore replaceChild will be degraded to appendChild - * E.g: document.head.replaceChild(targetChild, document.scripts[0]) - * 2. If passiveChild not in hijackParent but in parent and method is insertBefore, try insert it into the position corresponding to hijackParent - * E.g: document.head.insertBefore(targetChild, document.head.childNodes[0]) + * 1. If passiveNode not in hijackParent, insertBefore replaceChild will be degraded to appendChild + * E.g: document.head.replaceChild(targetNode, document.scripts[0]) + * 2. If passiveNode not in hijackParent but in parent and method is insertBefore, try insert it into the position corresponding to hijackParent + * E.g: document.head.insertBefore(targetNode, document.head.childNodes[0]) * ISSUE: https://github.com/micro-zoe/micro-app/issues/1071 */ - if (passiveChild && !hijackParent.contains(passiveChild)) { - if (rawMethod === globalEnv.rawInsertBefore && parent.contains(passiveChild)) { - const indexOfParent = Array.from(parent.childNodes).indexOf(passiveChild as ChildNode) + if (passiveNode && !hijackParent.contains(passiveNode)) { + if (rawMethod === globalEnv.rawInsertBefore && parent.contains(passiveNode)) { + const indexOfParent = Array.from(parent.childNodes).indexOf(passiveNode as ChildNode) if (hijackParent.childNodes[indexOfParent]) { - return invokeRawMethod(rawMethod, hijackParent, targetChild, hijackParent.childNodes[indexOfParent]) + return invokeRawMethod(rawMethod, hijackParent, targetNode, hijackParent.childNodes[indexOfParent], app) } } - return globalEnv.rawAppendChild.call(hijackParent, targetChild) - } else if (rawMethod === globalEnv.rawRemoveChild && !hijackParent.contains(targetChild)) { - if (parent.contains(targetChild)) { - return rawMethod.call(parent, targetChild) + return globalEnv.rawAppendChild.call(hijackParent, targetNode) + } else if (rawMethod === globalEnv.rawRemoveChild && !hijackParent.contains(targetNode)) { + if (parent.contains(targetNode)) { + return rawMethod.call(parent, targetNode) } - return targetChild + return targetNode } - return invokeRawMethod(rawMethod, hijackParent, targetChild, passiveChild) + return invokeRawMethod(rawMethod, hijackParent, targetNode, passiveNode, app) } - return invokeRawMethod(rawMethod, parent, targetChild, passiveChild) + return invokeRawMethod(rawMethod, parent, targetNode, passiveNode, app) } // head/body map to micro-app-head/micro-app-body function getHijackParent ( parent: Node, - targetChild: Node, + targetNode: Node, app: AppInterface, ): HTMLElement | null | undefined { if (app) { if (parent === document.head) { - if (app.iframe && isScriptElement(targetChild)) { + if (app.iframe && isScriptElement(targetNode)) { return app.sandBox.microHead } return app.querySelector('micro-app-head') } if (parent === document.body || parent === document.body.parentNode) { - if (app.iframe && isScriptElement(targetChild)) { + if (app.iframe && isScriptElement(targetNode)) { return app.sandBox.microBody } return app.querySelector('micro-app-body') } - if (app.iframe && isScriptElement(targetChild)) { + if (app.iframe && isScriptElement(targetNode)) { return app.sandBox.microBody } } @@ -258,18 +263,36 @@ function getHijackParent ( function invokeRawMethod ( rawMethod: Func, parent: Node, - targetChild: Node, - passiveChild?: Node | null + targetNode: Node, + passiveNode?: Node | null, + app?: AppInterface, ) { if (isPendMethod(rawMethod)) { - return rawMethod.call(parent, targetChild) + /** + * In iframe sandbox, script will pend to iframe.body, so we should reset rawMethod, because: + * Element.prototype.append === DocumentFragment.prototype.append ==> false + * Element.prototype.prepend === DocumentFragment.prototype.prepend ==> false + */ + if (app?.iframe && isScriptElement(targetNode)) { + if (rawMethod === globalEnv.rawFragmentAppend) { + rawMethod = globalEnv.rawAppend + } else if (rawMethod === globalEnv.rawFragmentPrepend) { + rawMethod = globalEnv.rawPrepend + } + } + return rawMethod.call(parent, targetNode) } - return rawMethod.call(parent, targetChild, passiveChild) + return rawMethod.call(parent, targetNode, passiveNode) } function isPendMethod (method: CallableFunction) { - return method === globalEnv.rawAppend || method === globalEnv.rawPrepend + return ( + method === globalEnv.rawAppend || + method === globalEnv.rawPrepend || + method === globalEnv.rawFragmentAppend || + method === globalEnv.rawFragmentPrepend + ) } /** @@ -286,7 +309,7 @@ function completePathDynamic (app: AppInterface, newChild: Node): void { if (newChild.hasAttribute('srcset')) { globalEnv.rawSetAttribute.call(newChild, 'srcset', CompletionPath(newChild.getAttribute('srcset')!, app.url)) } - } else if (/^link$/i.test(newChild.tagName) && newChild.hasAttribute('href')) { + } else if (/^(link|image)$/i.test(newChild.tagName) && newChild.hasAttribute('href')) { globalEnv.rawSetAttribute.call(newChild, 'href', CompletionPath(newChild.getAttribute('href')!, app.url)) } } @@ -296,13 +319,13 @@ function completePathDynamic (app: AppInterface, newChild: Node): void { * method of handle new node * @param parent parent node * @param newChild new node - * @param passiveChild passive node + * @param passiveNode passive node * @param rawMethod method */ function commonElementHandler ( parent: Node, newChild: Node, - passiveChild: Node | null, + passiveNode: Node | null, rawMethod: Func, ) { const currentAppName = getCurrentAppName() @@ -314,30 +337,24 @@ function commonElementHandler ( currentAppName ) ) { - newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName! - const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__) - if (isStyleElement(newChild)) { - const isShadowNode = parent.getRootNode() - const isShadowEnvironment = isShadowNode instanceof ShadowRoot - isShadowEnvironment && newChild.setAttribute('ignore', 'true') - } + updateElementInfo(newChild, newChild.__MICRO_APP_NAME__ || currentAppName) + const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__!) if (app?.container) { + if (isStyleElement(newChild)) { + parent.getRootNode() instanceof ShadowRoot && newChild.setAttribute('ignore', 'true') + } completePathDynamic(app, newChild) return invokePrototypeMethod( app, rawMethod, parent, handleNewNode(newChild, app), - passiveChild && getMappingNode(passiveChild), + passiveNode && getMappingNode(passiveNode), ) } } - if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) { - return rawMethod.call(parent, newChild) - } - - return rawMethod.call(parent, newChild, passiveChild) + return invokeRawMethod(rawMethod, parent, newChild, passiveNode) } /** @@ -348,42 +365,23 @@ export function patchElementAndDocument (): void { const rawRootElement = globalEnv.rawRootElement const rawRootNode = globalEnv.rawRootNode + const rawDocumentFragment = globalEnv.rawDocumentFragment // prototype methods of add element👇 - rawRootElement.prototype.appendChild = function appendChild (newChild: T): T { + rawRootNode.prototype.appendChild = function appendChild (newChild: T): T { return commonElementHandler(this, newChild, null, globalEnv.rawAppendChild) } - rawRootElement.prototype.insertBefore = function insertBefore (newChild: T, refChild: Node | null): T { + rawRootNode.prototype.insertBefore = function insertBefore (newChild: T, refChild: Node | null): T { return commonElementHandler(this, newChild, refChild, globalEnv.rawInsertBefore) } - rawRootElement.prototype.replaceChild = function replaceChild (newChild: Node, oldChild: T): T { + rawRootNode.prototype.replaceChild = function replaceChild (newChild: Node, oldChild: T): T { return commonElementHandler(this, newChild, oldChild, globalEnv.rawReplaceChild) } - rawRootElement.prototype.append = function append (...nodes: (Node | string)[]): void { - let i = 0 - while (i < nodes.length) { - let node = nodes[i] - node = isNode(node) ? node : globalEnv.rawCreateTextNode.call(globalEnv.rawDocument, node) - commonElementHandler(this, markElement(node as Node), null, globalEnv.rawAppend) - i++ - } - } - - rawRootElement.prototype.prepend = function prepend (...nodes: (Node | string)[]): void { - let i = nodes.length - while (i > 0) { - let node = nodes[i - 1] - node = isNode(node) ? node : globalEnv.rawCreateTextNode.call(globalEnv.rawDocument, node) - commonElementHandler(this, markElement(node as Node), null, globalEnv.rawPrepend) - i-- - } - } - // prototype methods of delete element👇 - rawRootElement.prototype.removeChild = function removeChild (oldChild: T): T { + rawRootNode.prototype.removeChild = function removeChild (oldChild: T): T { if (oldChild?.__MICRO_APP_NAME__) { const app = appInstanceMap.get(oldChild.__MICRO_APP_NAME__) if (app?.container) { @@ -404,6 +402,36 @@ export function patchElementAndDocument (): void { return globalEnv.rawRemoveChild.call(this, oldChild) as T } + rawDocumentFragment.prototype.append = rawRootElement.prototype.append = function append (...nodes: (Node | string)[]): void { + let i = 0 + while (i < nodes.length) { + let node = nodes[i] + node = isNode(node) ? node : globalEnv.rawCreateTextNode.call(globalEnv.rawDocument, node) + commonElementHandler( + this, + markElement(node as Node), + null, + isDocumentFragment(this) ? globalEnv.rawFragmentAppend : globalEnv.rawAppend, + ) + i++ + } + } + + rawDocumentFragment.prototype.prepend = rawRootElement.prototype.prepend = function prepend (...nodes: (Node | string)[]): void { + let i = nodes.length + while (i > 0) { + let node = nodes[i - 1] + node = isNode(node) ? node : globalEnv.rawCreateTextNode.call(globalEnv.rawDocument, node) + commonElementHandler( + this, + markElement(node as Node), + null, + isDocumentFragment(this) ? globalEnv.rawFragmentPrepend : globalEnv.rawPrepend, + ) + i-- + } + } + /** * The insertAdjacentElement method of the Element interface inserts a given element node at a given position relative to the element it is invoked upon. * NOTE: @@ -422,58 +450,105 @@ export function patchElementAndDocument (): void { return globalEnv.rawInsertAdjacentElement.call(this, where, element) } - // patch cloneNode - rawRootElement.prototype.cloneNode = function cloneNode (deep?: boolean): Node { - const clonedNode = globalEnv.rawCloneNode.call(this, deep) - this.__MICRO_APP_NAME__ && (clonedNode.__MICRO_APP_NAME__ = this.__MICRO_APP_NAME__) - return clonedNode - } - /** * document.body(head).querySelector(querySelectorAll) hijack to microAppBody(microAppHead).querySelector(querySelectorAll) * NOTE: * 1. May cause some problems! * 2. Add config options? */ - function getQueryTarget (target: Node): Node | null { - const currentAppName = getCurrentAppName() - if ((target === document.body || target === document.head) && currentAppName) { + function getElementQueryTarget (targetNode: Node): Node | null { + const currentAppName = getIframeCurrentAppName() || getCurrentAppName() + if ((targetNode === document.body || targetNode === document.head) && currentAppName) { const app = appInstanceMap.get(currentAppName) if (app?.container) { - if (target === document.body) { - return app.querySelector('micro-app-body') - } else if (target === document.head) { - return app.querySelector('micro-app-head') + if (targetNode === document.body) { + return app.querySelector('micro-app-body') + } else if (targetNode === document.head) { + return app.querySelector('micro-app-head') } } } - return target + return targetNode + } + + /** + * In iframe sandbox, script will render to iframe instead of micro-app-body + * So when query elements, we need to search both micro-app and iframe + * @param isEmpty get empty result + * @param targetNode targetNode element + * @param result origin result + * @param selectors selectors + * @param methodName querySelector or querySelectorAll + */ + function getElementQueryResult ( + isEmpty: boolean, + targetNode: Node, + result: T, + selectors: string, + methodName: string, + ): T { + if (isEmpty) { + const currentAppName = getIframeCurrentAppName() || getCurrentAppName() + if (currentAppName && isIframeSandbox(currentAppName)) { + const app = appInstanceMap.get(currentAppName)! + if (isMicroAppHead(targetNode)) { + return app.sandBox.microHead[methodName](selectors) + } + if (isMicroAppBody(targetNode)) { + return app.sandBox.microBody[methodName](selectors) + } + } + } + return result } rawRootElement.prototype.querySelector = function querySelector (selectors: string): Node | null { - return globalEnv.rawElementQuerySelector.call(getQueryTarget(this) ?? this, selectors) + const _this = getElementQueryTarget(this) ?? this + const result = globalEnv.rawElementQuerySelector.call(_this, selectors) + return getElementQueryResult( + isNull(result) && _this !== this, + _this, + result, + selectors, + 'querySelector', + ) } rawRootElement.prototype.querySelectorAll = function querySelectorAll (selectors: string): NodeListOf { - return globalEnv.rawElementQuerySelectorAll.call(getQueryTarget(this) ?? this, selectors) + const _this = getElementQueryTarget(this) ?? this + const result = globalEnv.rawElementQuerySelectorAll.call(_this, selectors) + return getElementQueryResult>( + !result.length && _this !== this, + _this, + result, + selectors, + 'querySelectorAll', + ) } // rewrite setAttribute, complete resource address rawRootElement.prototype.setAttribute = function setAttribute (key: string, value: any): void { - const appName = this.__MICRO_APP_NAME__ || getCurrentAppName() if ( - appName && - appInstanceMap.has(appName) && - ( - ((key === 'src' || key === 'srcset') && /^(img|script|video|audio|source|embed)$/i.test(this.tagName)) || - (key === 'href' && /^link$/i.test(this.tagName)) - ) + /^micro-app(-\S+)?/i.test(this.tagName) && + key === 'data' && + this.setAttribute !== rawRootElement.prototype.setAttribute ) { - const app = appInstanceMap.get(appName) - value = CompletionPath(value, app!.url) + this.setAttribute(key, value) + } else { + const appName = this.__MICRO_APP_NAME__ || getCurrentAppName() + if ( + appName && + appInstanceMap.has(appName) && + ( + ((key === 'src' || key === 'srcset') && /^(img|script|video|audio|source|embed)$/i.test(this.tagName)) || + (key === 'href' && /^(link|image)$/i.test(this.tagName)) + ) + ) { + const app = appInstanceMap.get(appName) + value = CompletionPath(value, app!.url) + } + globalEnv.rawSetAttribute.call(this, key, value) } - - globalEnv.rawSetAttribute.call(this, key, value) } /** @@ -503,7 +578,7 @@ export function patchElementAndDocument (): void { // return get?.call(this) // }, // set: function (value) { - // const currentAppName = getCurrentAppName() + // const currentAppName = this.__MICRO_APP_NAME__ || getCurrentAppName() // if (currentAppName && appInstanceMap.has(currentAppName)) { // const app = appInstanceMap.get(currentAppName) // value = CompletionPath(value, app!.url) @@ -513,41 +588,24 @@ export function patchElementAndDocument (): void { // }) // }) - rawDefineProperty(rawRootElement.prototype, 'innerHTML', { - configurable: true, - enumerable: true, - get () { - return globalEnv.rawInnerHTMLDesc.get.call(this) - }, - set (code: string) { - globalEnv.rawInnerHTMLDesc.set.call(this, code) - const currentAppName = getCurrentAppName() - Array.from(this.children).forEach((child) => { - if (isElement(child) && currentAppName) { - // TODO: 使用updateElementInfo进行更新 - child.__MICRO_APP_NAME__ = currentAppName - } - }) - } - }) - rawDefineProperty(rawRootNode.prototype, 'parentNode', { configurable: true, enumerable: true, get () { /** - * hijack parentNode of html + * hijack parentNode of html for with sandbox * Scenes: * 1. element-ui@2/lib/utils/popper.js * // root is child app window, so root.document is proxyDocument or microDocument * if (element.parentNode === root.document) ... */ - const currentAppName = getCurrentAppName() + const currentAppName = getIframeCurrentAppName() || getCurrentAppName() if (currentAppName && this === globalEnv.rawDocument.firstElementChild) { const microDocument = appInstanceMap.get(currentAppName)?.sandBox?.proxyWindow?.document if (microDocument) return microDocument } - const result = globalEnv.rawParentNodeDesc.get.call(this) as Node + // NOTE: run after hijack html.parentNode + const result = globalEnv.rawParentNodeDesc.get.call(this) /** * If parentNode is , return rawDocument.body * Scenes: @@ -565,6 +623,29 @@ export function patchElementAndDocument (): void { return result }, }) + + rawDefineProperty(rawRootElement.prototype, 'innerHTML', { + configurable: true, + enumerable: true, + get () { + return globalEnv.rawInnerHTMLDesc.get.call(this) + }, + set (code: string) { + globalEnv.rawInnerHTMLDesc.set.call(this, code) + const currentAppName = this.__MICRO_APP_NAME__ || getCurrentAppName() + Array.from(this.children).forEach((child) => { + if (isElement(child) && currentAppName) { + updateElementInfo(child, currentAppName) + } + }) + } + }) + + // patch cloneNode + rawRootNode.prototype.cloneNode = function cloneNode (deep?: boolean): Node { + const clonedNode = globalEnv.rawCloneNode.call(this, deep) + return updateElementInfo(clonedNode, this.__MICRO_APP_NAME__) + } } /** @@ -572,9 +653,7 @@ export function patchElementAndDocument (): void { * @param element new element */ function markElement (element: T): T { - const currentAppName = getCurrentAppName() - if (currentAppName) element.__MICRO_APP_NAME__ = currentAppName - return element + return updateElementInfo(element, getCurrentAppName()) } // methods of document @@ -655,7 +734,7 @@ function patchDocument () { rawRootDocument.prototype.querySelector = querySelector rawRootDocument.prototype.querySelectorAll = querySelectorAll - rawRootDocument.prototype.getElementById = function getElementById (key: string): HTMLElement | null { + rawRootDocument.prototype.getElementById = function getElementById (this: Document, key: string): HTMLElement | null { const _this = getBindTarget(this) if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) { return globalEnv.rawGetElementById.call(_this, key) @@ -668,7 +747,7 @@ function patchDocument () { } } - rawRootDocument.prototype.getElementsByClassName = function getElementsByClassName (key: string): HTMLCollectionOf { + rawRootDocument.prototype.getElementsByClassName = function getElementsByClassName (this: Document, key: string): HTMLCollectionOf { const _this = getBindTarget(this) if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) { return globalEnv.rawGetElementsByClassName.call(_this, key) @@ -681,7 +760,7 @@ function patchDocument () { } } - rawRootDocument.prototype.getElementsByTagName = function getElementsByTagName (key: string): HTMLCollectionOf { + rawRootDocument.prototype.getElementsByTagName = function getElementsByTagName (this: Document, key: string): HTMLCollectionOf { const _this = getBindTarget(this) const currentAppName = getCurrentAppName() if ( @@ -700,7 +779,7 @@ function patchDocument () { } } - rawRootDocument.prototype.getElementsByName = function getElementsByName (key: string): NodeListOf { + rawRootDocument.prototype.getElementsByName = function getElementsByName (this: Document, key: string): NodeListOf { const _this = getBindTarget(this) if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) { return globalEnv.rawGetElementsByName.call(_this, key) @@ -734,18 +813,18 @@ export function releasePatchElementAndDocument (): void { const rawRootElement = globalEnv.rawRootElement const rawRootNode = globalEnv.rawRootNode - rawRootElement.prototype.appendChild = globalEnv.rawAppendChild - rawRootElement.prototype.insertBefore = globalEnv.rawInsertBefore - rawRootElement.prototype.replaceChild = globalEnv.rawReplaceChild - rawRootElement.prototype.removeChild = globalEnv.rawRemoveChild + rawRootNode.prototype.appendChild = globalEnv.rawAppendChild + rawRootNode.prototype.insertBefore = globalEnv.rawInsertBefore + rawRootNode.prototype.replaceChild = globalEnv.rawReplaceChild + rawRootNode.prototype.removeChild = globalEnv.rawRemoveChild + rawRootNode.prototype.cloneNode = globalEnv.rawCloneNode rawRootElement.prototype.append = globalEnv.rawAppend rawRootElement.prototype.prepend = globalEnv.rawPrepend - rawRootElement.prototype.cloneNode = globalEnv.rawCloneNode rawRootElement.prototype.querySelector = globalEnv.rawElementQuerySelector rawRootElement.prototype.querySelectorAll = globalEnv.rawElementQuerySelectorAll rawRootElement.prototype.setAttribute = globalEnv.rawSetAttribute - rawDefineProperty(rawRootElement.prototype, 'innerHTML', globalEnv.rawInnerHTMLDesc) rawDefineProperty(rawRootNode.prototype, 'parentNode', globalEnv.rawParentNodeDesc) + rawDefineProperty(rawRootElement.prototype, 'innerHTML', globalEnv.rawInnerHTMLDesc) } // Set the style of micro-app-head and micro-app-body diff --git a/src/source/scripts.ts b/src/source/scripts.ts index 9138b7a01..655068ed1 100644 --- a/src/source/scripts.ts +++ b/src/source/scripts.ts @@ -524,7 +524,7 @@ export function runScript ( */ if (!replaceElement) { // TEST IGNORE - const parent = app.iframe ? app.sandBox!.microBody : app.querySelector('micro-app-body') + const parent = app.iframe ? app.sandBox?.microBody : app.querySelector('micro-app-body') parent?.appendChild(scriptElement) } } else { @@ -550,7 +550,7 @@ export function runDynamicRemoteScript ( scriptInfo: ScriptSourceInfo, originScript: HTMLScriptElement, ): HTMLScriptElement | Comment { - const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment('dynamic script extract by micro-app') + const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment(`dynamic script with src='${address}' extract by micro-app`) const dispatchScriptOnLoadEvent = () => dispatchOnLoadEvent(originScript) @@ -594,7 +594,7 @@ export function runDynamicInlineScript ( app: AppInterface, scriptInfo: ScriptSourceInfo, ): HTMLScriptElement | Comment { - const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment('dynamic script extract by micro-app') + const replaceElement = isInlineMode(app, scriptInfo) ? pureCreateElement('script') : document.createComment('dynamic inline script extract by micro-app') runScript(address, app, scriptInfo, void 0, replaceElement as HTMLScriptElement) diff --git a/typings/global.d.ts b/typings/global.d.ts index b28b71a1c..c52da5d74 100644 --- a/typings/global.d.ts +++ b/typings/global.d.ts @@ -82,6 +82,8 @@ declare module '@micro-app/types' { staticEscapeProperties: PropertyKey[] // Variables that scoped in child app staticScopeProperties: PropertyKey[] + // clear mount, unmount when stop in default mode + clearHijackUmdHooks: () => void } interface WithSandBoxInterface extends BaseSandboxType { @@ -104,7 +106,7 @@ declare module '@micro-app/types' { setPreRenderState (state: boolean): void markUmdMode(state: boolean): void patchStaticElement (container: Element | ShadowRoot): void - actionBeforeExecScripts (container: Element | ShadowRoot): void + actionsBeforeExecScripts (container: Element | ShadowRoot, handleUmdHooks: Func): void deleteIframeElement? (): void setStaticAppState (state: string): void } @@ -169,7 +171,7 @@ declare module '@micro-app/types' { } // app instance - interface AppInterface extends Pick { + interface AppInterface extends Pick { source: sourceType // source list // TODO: 去掉any sandBox: WithSandBoxInterface | null | any // sandbox @@ -234,9 +236,6 @@ declare module '@micro-app/types' { // show app when connectedCallback with keep-alive showKeepAliveApp (container: HTMLElement | ShadowRoot): void - - // get app lifecycle state - getLifeCycleState (): string } interface prefetchParam { @@ -342,10 +341,10 @@ declare module '@micro-app/types' { 'disable-memory-router'?: boolean 'disable-patch-request'?: boolean 'keep-router-state'?: boolean - 'hidden-router'?: boolean 'keep-alive'?: boolean 'clear-data'?: boolean 'router-mode'?: string + 'router-event-delay'?: number | ((appName: string) => number), iframe?: boolean ssr?: boolean fiber?: boolean @@ -376,18 +375,25 @@ declare module '@micro-app/types' { start(options?: OptionsType): void } - interface MicroAppElementType { + interface MicroAppElementInterface { appName: AttrType // app name appUrl: AttrType // app url - // Hooks for element append to documents connectedCallback (): void - // Hooks for element delete from documents disconnectedCallback (): void - // Hooks for element attributes change attributeChangedCallback (a: 'name' | 'url', o: string, n: string): void + // public mount action for micro_app_element & create_app + mount (app: AppInterface): void + // unmount app + unmount (destroy?: boolean, unmountcb?: CallableFunction): void + // Re render app from the command line + reload (destroy?: boolean): Promise + // get delay time of router event + getRouterEventDelay (): number + // rewrite micro-app.setAttribute, process attr data + setAttribute (key: string, value: any): void } // special CallableFunction for interact @@ -404,6 +410,11 @@ declare module '@micro-app/types' { type MicroHistory = ProxyHandler type MicroState = any + interface MicroRouterInfoState { + fullPath: string | null, + state: MicroState, + mode: string, + } type HistoryProxyValue = Pick< History, @@ -554,12 +565,6 @@ declare module '@micro-app/types' { } } -declare namespace JSX { - interface IntrinsicElements { - 'micro-app': any - } -} - declare module '@micro-zoe/micro-app/polyfill/jsx-custom-event' declare const __DEV__: boolean diff --git a/yarn.lock b/yarn.lock index cf3b991f4..6377fbd49 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1317,6 +1317,15 @@ "@rollup/pluginutils" "^3.1.0" magic-string "^0.25.7" +"@rollup/plugin-terser@^0.4.4": + version "0.4.4" + resolved "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz#15dffdb3f73f121aa4fbb37e7ca6be9aeea91962" + integrity sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A== + dependencies: + serialize-javascript "^6.0.1" + smob "^1.0.0" + terser "^5.17.4" + "@rollup/plugin-typescript@~8.1.0": version "8.1.1" resolved "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.1.1.tgz#cadd6c381a92cc7e8148cc8b1eeba146020635d0" @@ -6795,6 +6804,13 @@ serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -6919,6 +6935,11 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +smob@^1.0.0: + version "1.5.0" + resolved "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" + integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -7295,6 +7316,16 @@ terser@^5.0.0: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.17.4: + version "5.31.0" + resolved "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz#06eef86f17007dbad4593f11a574c7f5eb02c6a1" + integrity sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"