From 2a0fdeae313bf1f56f7e64a8a1372fc526155e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Fri, 10 Mar 2023 17:18:32 +0800 Subject: [PATCH] add frontend/vben from vben-admin-thin --- .gitignore | 3 + frontend/vben/.editorconfig | 19 + frontend/vben/.env | 8 + frontend/vben/.env.development | 22 + frontend/vben/.env.production | 35 + frontend/vben/.eslintignore | 15 + frontend/vben/.eslintrc.js | 76 + frontend/vben/.gitignore | 33 + frontend/vben/.gitpod.yml | 6 + frontend/vben/.prettierignore | 9 + frontend/vben/.stylelintignore | 3 + frontend/vben/LICENSE | 22 + frontend/vben/README.md | 101 + frontend/vben/build/config/themeConfig.ts | 79 + frontend/vben/build/constant.ts | 6 + .../vben/build/generate/generateModifyVars.ts | 37 + frontend/vben/build/generate/icon/index.ts | 72 + frontend/vben/build/getConfigFileName.ts | 9 + frontend/vben/build/script/buildConf.ts | 47 + frontend/vben/build/script/postBuild.ts | 23 + frontend/vben/build/utils.ts | 92 + frontend/vben/build/vite/plugin/compress.ts | 35 + frontend/vben/build/vite/plugin/html.ts | 40 + frontend/vben/build/vite/plugin/imagemin.ts | 34 + frontend/vben/build/vite/plugin/index.ts | 82 + frontend/vben/build/vite/plugin/mock.ts | 19 + frontend/vben/build/vite/plugin/pwa.ts | 33 + .../vben/build/vite/plugin/styleImport.ts | 81 + frontend/vben/build/vite/plugin/svgSprite.ts | 17 + frontend/vben/build/vite/plugin/theme.ts | 89 + frontend/vben/build/vite/plugin/visualizer.ts | 17 + frontend/vben/build/vite/proxy.ts | 34 + frontend/vben/commitlint.config.js | 107 + frontend/vben/index.html | 159 + frontend/vben/mock/_createProductionServer.ts | 18 + frontend/vben/mock/_util.ts | 62 + frontend/vben/mock/demo/account.ts | 71 + frontend/vben/mock/demo/api-cascader.ts | 325 + frontend/vben/mock/demo/select-demo.ts | 28 + frontend/vben/mock/demo/system.ts | 202 + frontend/vben/mock/demo/table-demo.ts | 52 + frontend/vben/mock/demo/tree-demo.ts | 38 + frontend/vben/mock/sys/menu.ts | 260 + frontend/vben/mock/sys/user.ts | 122 + frontend/vben/package.json | 191 + frontend/vben/postcss.config.js | 5 + frontend/vben/prettier.config.js | 10 + frontend/vben/public/favicon.ico | Bin 0 -> 894 bytes frontend/vben/public/resource/img/logo.png | Bin 0 -> 4042 bytes .../vben/public/resource/img/pwa-192x192.png | Bin 0 -> 12205 bytes .../vben/public/resource/img/pwa-512x512.png | Bin 0 -> 52656 bytes .../vben/public/resource/tinymce/langs/en.js | 419 + .../public/resource/tinymce/langs/zh_CN.js | 389 + .../ui/oxide-dark/content.inline.min.css | 7 + .../skins/ui/oxide-dark/content.min.css | 7 + .../ui/oxide-dark/content.mobile.min.css | 7 + .../tinymce/skins/ui/oxide-dark/skin.min.css | 7 + .../skins/ui/oxide-dark/skin.mobile.min.css | 7 + .../ui/oxide-dark/skin.shadowdom.min.css | 7 + .../skins/ui/oxide/content.inline.min.css | 7 + .../tinymce/skins/ui/oxide/content.min.css | 7 + .../skins/ui/oxide/content.mobile.min.css | 7 + .../skins/ui/oxide/fonts/tinymce-mobile.woff | Bin 0 -> 4624 bytes .../tinymce/skins/ui/oxide/skin.min.css | 7 + .../skins/ui/oxide/skin.mobile.min.css | 7 + .../skins/ui/oxide/skin.shadowdom.min.css | 7 + frontend/vben/src/App.vue | 21 + frontend/vben/src/api/demo/account.ts | 16 + frontend/vben/src/api/demo/cascader.ts | 9 + frontend/vben/src/api/demo/error.ts | 12 + .../vben/src/api/demo/model/accountModel.ts | 7 + frontend/vben/src/api/demo/model/areaModel.ts | 12 + .../vben/src/api/demo/model/optionsModel.ts | 15 + .../vben/src/api/demo/model/systemModel.ts | 74 + .../vben/src/api/demo/model/tableModel.ts | 20 + frontend/vben/src/api/demo/select.ts | 11 + frontend/vben/src/api/demo/system.ts | 44 + frontend/vben/src/api/demo/table.ts | 20 + frontend/vben/src/api/demo/tree.ts | 11 + frontend/vben/src/api/model/baseModel.ts | 9 + frontend/vben/src/api/sys/menu.ts | 14 + frontend/vben/src/api/sys/model/menuModel.ts | 16 + .../vben/src/api/sys/model/uploadModel.ts | 5 + frontend/vben/src/api/sys/model/userModel.ts | 38 + frontend/vben/src/api/sys/user.ts | 55 + .../vben/src/assets/icons/download-count.svg | 1 + .../src/assets/icons/dynamic-avatar-1.svg | 1 + .../src/assets/icons/dynamic-avatar-2.svg | 1 + .../src/assets/icons/dynamic-avatar-3.svg | 1 + .../src/assets/icons/dynamic-avatar-4.svg | 1 + .../src/assets/icons/dynamic-avatar-5.svg | 1 + .../src/assets/icons/dynamic-avatar-6.svg | 1 + frontend/vben/src/assets/icons/moon.svg | 16 + frontend/vben/src/assets/icons/sun.svg | 42 + frontend/vben/src/assets/icons/test.svg | 21 + .../vben/src/assets/icons/total-sales.svg | 1 + .../vben/src/assets/icons/transaction.svg | 1 + .../vben/src/assets/icons/visit-count.svg | 1 + frontend/vben/src/assets/images/demo.png | Bin 0 -> 33342 bytes frontend/vben/src/assets/images/header.jpg | Bin 0 -> 16880 bytes frontend/vben/src/assets/images/logo.png | Bin 0 -> 28304 bytes frontend/vben/src/assets/svg/illustration.svg | 1 + .../vben/src/assets/svg/login-bg-dark.svg | 19 + frontend/vben/src/assets/svg/login-bg.svg | 17 + frontend/vben/src/assets/svg/login-box-bg.svg | 1 + frontend/vben/src/assets/svg/net-error.svg | 1 + frontend/vben/src/assets/svg/no-data.svg | 1 + .../vben/src/assets/svg/preview/p-rotate.svg | 1 + .../vben/src/assets/svg/preview/resume.svg | 1 + .../vben/src/assets/svg/preview/scale.svg | 1 + .../vben/src/assets/svg/preview/unrotate.svg | 1 + .../vben/src/assets/svg/preview/unscale.svg | 1 + .../vben/src/components/Application/index.ts | 15 + .../Application/src/AppDarkModeToggle.vue | 76 + .../Application/src/AppLocalePicker.vue | 76 + .../components/Application/src/AppLogo.vue | 93 + .../Application/src/AppProvider.vue | 82 + .../Application/src/search/AppSearch.vue | 33 + .../src/search/AppSearchFooter.vue | 56 + .../src/search/AppSearchKeyItem.vue | 11 + .../Application/src/search/AppSearchModal.vue | 267 + .../Application/src/search/useMenuSearch.ts | 166 + .../Application/src/useAppContext.ts | 17 + frontend/vben/src/components/Basic/index.ts | 8 + .../src/components/Basic/src/BasicArrow.vue | 84 + .../src/components/Basic/src/BasicHelp.vue | 114 + .../src/components/Basic/src/BasicTitle.vue | 76 + frontend/vben/src/components/Button/index.ts | 9 + .../src/components/Button/src/BasicButton.vue | 40 + .../Button/src/PopConfirmButton.vue | 54 + .../vben/src/components/Button/src/props.ts | 19 + .../vben/src/components/Container/index.ts | 10 + .../Container/src/LazyContainer.vue | 145 + .../Container/src/ScrollContainer.vue | 93 + .../src/collapse/CollapseContainer.vue | 110 + .../Container/src/collapse/CollapseHeader.vue | 38 + .../src/components/Container/src/typing.ts | 17 + .../vben/src/components/CountDown/index.ts | 6 + .../components/CountDown/src/CountButton.vue | 62 + .../CountDown/src/CountdownInput.vue | 54 + .../components/CountDown/src/useCountdown.ts | 51 + .../vben/src/components/Description/index.ts | 6 + .../Description/src/Description.vue | 184 + .../src/components/Description/src/typing.ts | 50 + .../Description/src/useDescription.ts | 28 + frontend/vben/src/components/Drawer/index.ts | 6 + .../src/components/Drawer/src/BasicDrawer.vue | 256 + .../Drawer/src/components/DrawerFooter.vue | 82 + .../Drawer/src/components/DrawerHeader.vue | 74 + .../vben/src/components/Drawer/src/props.ts | 44 + .../vben/src/components/Drawer/src/typing.ts | 193 + .../src/components/Drawer/src/useDrawer.ts | 161 + .../vben/src/components/Dropdown/index.ts | 5 + .../src/components/Dropdown/src/Dropdown.vue | 96 + .../src/components/Dropdown/src/typing.ts | 9 + .../src/components/Icon/data/icons.data.ts | 786 ++ frontend/vben/src/components/Icon/index.ts | 7 + .../vben/src/components/Icon/src/Icon.vue | 121 + .../src/components/Icon/src/IconPicker.vue | 188 + .../vben/src/components/Icon/src/SvgIcon.vue | 65 + frontend/vben/src/components/Loading/index.ts | 5 + .../src/components/Loading/src/Loading.vue | 79 + .../components/Loading/src/createLoading.ts | 65 + .../vben/src/components/Loading/src/typing.ts | 10 + .../src/components/Loading/src/useLoading.ts | 49 + frontend/vben/src/components/Menu/index.ts | 3 + .../src/components/Menu/src/BasicMenu.vue | 164 + .../Menu/src/components/BasicMenuItem.vue | 20 + .../Menu/src/components/BasicSubMenuItem.vue | 55 + .../Menu/src/components/MenuItemContent.vue | 34 + .../vben/src/components/Menu/src/index.less | 74 + .../vben/src/components/Menu/src/props.ts | 60 + .../vben/src/components/Menu/src/types.ts | 25 + .../src/components/Menu/src/useOpenKeys.ts | 83 + frontend/vben/src/components/Modal/index.ts | 8 + .../src/components/Modal/src/BasicModal.vue | 242 + .../components/Modal/src/components/Modal.tsx | 31 + .../Modal/src/components/ModalClose.vue | 106 + .../Modal/src/components/ModalFooter.vue | 40 + .../Modal/src/components/ModalHeader.vue | 22 + .../Modal/src/components/ModalWrapper.vue | 169 + .../components/Modal/src/hooks/useModal.ts | 163 + .../Modal/src/hooks/useModalContext.ts | 16 + .../Modal/src/hooks/useModalDrag.ts | 107 + .../Modal/src/hooks/useModalFullScreen.ts | 43 + .../vben/src/components/Modal/src/index.less | 127 + .../vben/src/components/Modal/src/props.ts | 83 + .../vben/src/components/Modal/src/typing.ts | 209 + frontend/vben/src/components/Page/index.ts | 9 + .../src/components/Page/src/PageFooter.vue | 50 + .../src/components/Page/src/PageWrapper.vue | 191 + .../vben/src/components/Scrollbar/index.ts | 8 + .../components/Scrollbar/src/Scrollbar.vue | 206 + .../vben/src/components/Scrollbar/src/bar.ts | 110 + .../src/components/Scrollbar/src/types.d.ts | 18 + .../vben/src/components/Scrollbar/src/util.ts | 50 + .../vben/src/components/SimpleMenu/index.ts | 2 + .../components/SimpleMenu/src/SimpleMenu.vue | 160 + .../SimpleMenu/src/SimpleMenuTag.vue | 68 + .../SimpleMenu/src/SimpleSubMenu.vue | 116 + .../SimpleMenu/src/components/Menu.vue | 158 + .../src/components/MenuCollapseTransition.vue | 78 + .../SimpleMenu/src/components/MenuItem.vue | 107 + .../SimpleMenu/src/components/SubMenuItem.vue | 333 + .../SimpleMenu/src/components/menu.less | 309 + .../SimpleMenu/src/components/types.ts | 25 + .../SimpleMenu/src/components/useMenu.ts | 84 + .../src/components/useSimpleMenuContext.ts | 18 + .../src/components/SimpleMenu/src/index.less | 77 + .../src/components/SimpleMenu/src/types.ts | 5 + .../components/SimpleMenu/src/useOpenKeys.ts | 50 + .../src/components/StrengthMeter/index.ts | 4 + .../StrengthMeter/src/StrengthMeter.vue | 142 + .../vben/src/components/Transition/index.ts | 27 + .../Transition/src/CollapseTransition.vue | 78 + .../Transition/src/CreateTransition.tsx | 73 + .../Transition/src/ExpandTransition.ts | 89 + .../vben/src/components/registerGlobComp.ts | 7 + frontend/vben/src/design/ant/btn.less | 285 + frontend/vben/src/design/ant/index.less | 67 + frontend/vben/src/design/ant/input.less | 31 + frontend/vben/src/design/ant/pagination.less | 96 + frontend/vben/src/design/ant/table.less | 76 + frontend/vben/src/design/color.less | 138 + frontend/vben/src/design/config.less | 2 + frontend/vben/src/design/index.less | 44 + frontend/vben/src/design/public.less | 51 + frontend/vben/src/design/theme.less | 52 + frontend/vben/src/design/transition/base.less | 18 + frontend/vben/src/design/transition/fade.less | 93 + .../vben/src/design/transition/index.less | 10 + .../vben/src/design/transition/scale.less | 21 + .../vben/src/design/transition/scroll.less | 67 + .../vben/src/design/transition/slide.less | 39 + frontend/vben/src/design/transition/zoom.less | 27 + frontend/vben/src/design/var/breakpoint.less | 33 + frontend/vben/src/design/var/easing.less | 18 + frontend/vben/src/design/var/index.less | 39 + frontend/vben/src/directives/clickOutside.ts | 86 + frontend/vben/src/directives/index.ts | 11 + frontend/vben/src/directives/loading.ts | 39 + frontend/vben/src/directives/permission.ts | 32 + frontend/vben/src/directives/repeatClick.ts | 31 + .../vben/src/directives/ripple/index.less | 21 + frontend/vben/src/directives/ripple/index.ts | 191 + frontend/vben/src/enums/appEnum.ts | 52 + frontend/vben/src/enums/breakpointEnum.ts | 28 + frontend/vben/src/enums/cacheEnum.ts | 28 + frontend/vben/src/enums/exceptionEnum.ts | 27 + frontend/vben/src/enums/httpEnum.ts | 31 + frontend/vben/src/enums/menuEnum.ts | 50 + frontend/vben/src/enums/pageEnum.ts | 10 + frontend/vben/src/enums/roleEnum.ts | 7 + frontend/vben/src/enums/sizeEnum.ts | 19 + .../vben/src/hooks/component/useFormItem.ts | 60 + .../src/hooks/component/usePageContext.ts | 18 + .../src/hooks/core/onMountedOrActivated.ts | 18 + frontend/vben/src/hooks/core/useAttrs.ts | 40 + frontend/vben/src/hooks/core/useContext.ts | 44 + frontend/vben/src/hooks/core/useRefs.ts | 16 + frontend/vben/src/hooks/core/useTimeout.ts | 45 + .../vben/src/hooks/event/useBreakpoint.ts | 89 + .../vben/src/hooks/event/useEventListener.ts | 58 + .../hooks/event/useIntersectionObserver.ts | 48 + frontend/vben/src/hooks/event/useScroll.ts | 65 + frontend/vben/src/hooks/event/useScrollTo.ts | 59 + .../vben/src/hooks/event/useWindowSizeFn.ts | 35 + frontend/vben/src/hooks/setting/index.ts | 30 + .../src/hooks/setting/useHeaderSetting.ts | 102 + .../vben/src/hooks/setting/useMenuSetting.ts | 164 + .../hooks/setting/useMultipleTabSetting.ts | 28 + .../vben/src/hooks/setting/useRootSetting.ts | 92 + .../src/hooks/setting/useTransitionSetting.ts | 31 + frontend/vben/src/hooks/web/useAppInject.ts | 10 + .../vben/src/hooks/web/useContentHeight.ts | 191 + .../vben/src/hooks/web/useCopyToClipboard.ts | 68 + frontend/vben/src/hooks/web/useDesign.ts | 22 + frontend/vben/src/hooks/web/useECharts.ts | 121 + frontend/vben/src/hooks/web/useFullContent.ts | 28 + frontend/vben/src/hooks/web/useI18n.ts | 55 + frontend/vben/src/hooks/web/useMessage.tsx | 123 + frontend/vben/src/hooks/web/usePage.ts | 53 + frontend/vben/src/hooks/web/usePagination.ts | 34 + frontend/vben/src/hooks/web/usePermission.ts | 111 + frontend/vben/src/hooks/web/useScript.ts | 46 + frontend/vben/src/hooks/web/useSortable.ts | 21 + frontend/vben/src/hooks/web/useTabs.ts | 103 + frontend/vben/src/hooks/web/useTitle.ts | 35 + frontend/vben/src/hooks/web/useWatermark.ts | 100 + .../src/layouts/default/content/index.vue | 51 + .../default/content/useContentContext.ts | 17 + .../default/content/useContentViewHeight.ts | 42 + .../src/layouts/default/feature/index.vue | 81 + .../vben/src/layouts/default/footer/index.vue | 95 + .../layouts/default/header/MultipleHeader.vue | 126 + .../default/header/components/Breadcrumb.vue | 204 + .../default/header/components/FullScreen.vue | 37 + .../default/header/components/index.ts | 12 + .../header/components/notify/NoticeList.vue | 189 + .../default/header/components/notify/data.ts | 193 + .../header/components/notify/index.vue | 91 + .../components/user-dropdown/DropMenuItem.vue | 32 + .../header/components/user-dropdown/index.vue | 161 + .../src/layouts/default/header/index.less | 196 + .../vben/src/layouts/default/header/index.vue | 197 + frontend/vben/src/layouts/default/index.vue | 87 + .../vben/src/layouts/default/menu/index.vue | 197 + .../src/layouts/default/menu/useLayoutMenu.ts | 109 + .../layouts/default/setting/SettingDrawer.tsx | 415 + .../setting/components/InputNumberItem.vue | 56 + .../default/setting/components/SelectItem.vue | 75 + .../setting/components/SettingFooter.vue | 99 + .../default/setting/components/SwitchItem.vue | 66 + .../setting/components/ThemeColorPicker.vue | 88 + .../default/setting/components/TypePicker.vue | 178 + .../default/setting/components/index.ts | 8 + .../vben/src/layouts/default/setting/enum.ts | 155 + .../src/layouts/default/setting/handler.ts | 171 + .../src/layouts/default/setting/index.vue | 26 + .../src/layouts/default/sider/DragBar.vue | 66 + .../src/layouts/default/sider/LayoutSider.vue | 185 + .../src/layouts/default/sider/MixSider.vue | 590 + .../vben/src/layouts/default/sider/index.vue | 57 + .../layouts/default/sider/useLayoutSider.ts | 143 + .../default/tabs/components/FoldButton.vue | 42 + .../default/tabs/components/TabContent.vue | 76 + .../default/tabs/components/TabRedo.vue | 33 + .../vben/src/layouts/default/tabs/index.less | 207 + .../vben/src/layouts/default/tabs/index.vue | 142 + .../vben/src/layouts/default/tabs/types.ts | 25 + .../layouts/default/tabs/useMultipleTabs.ts | 80 + .../layouts/default/tabs/useTabDropdown.ts | 140 + .../layouts/default/trigger/HeaderTrigger.vue | 25 + .../layouts/default/trigger/SiderTrigger.vue | 21 + .../src/layouts/default/trigger/index.vue | 22 + frontend/vben/src/layouts/page/index.vue | 67 + frontend/vben/src/layouts/page/transition.ts | 33 + frontend/vben/src/locales/helper.ts | 37 + frontend/vben/src/locales/lang/en.ts | 12 + frontend/vben/src/locales/lang/en/common.ts | 20 + .../vben/src/locales/lang/en/component.ts | 129 + frontend/vben/src/locales/lang/en/layout.ts | 106 + .../vben/src/locales/lang/en/routes/basic.ts | 4 + .../src/locales/lang/en/routes/dashboard.ts | 6 + .../vben/src/locales/lang/en/routes/demo.ts | 189 + frontend/vben/src/locales/lang/en/sys.ts | 96 + .../lang/zh-CN/antdLocale/DatePicker.ts | 19 + .../vben/src/locales/lang/zh-CN/common.ts | 20 + .../vben/src/locales/lang/zh-CN/component.ts | 134 + .../vben/src/locales/lang/zh-CN/layout.ts | 106 + .../src/locales/lang/zh-CN/routes/basic.ts | 4 + .../locales/lang/zh-CN/routes/dashboard.ts | 6 + .../src/locales/lang/zh-CN/routes/demo.ts | 181 + frontend/vben/src/locales/lang/zh-CN/sys.ts | 94 + frontend/vben/src/locales/lang/zh_CN.ts | 10 + frontend/vben/src/locales/setupI18n.ts | 44 + frontend/vben/src/locales/useLocale.ts | 69 + frontend/vben/src/logics/initAppConfig.ts | 84 + frontend/vben/src/logics/mitt/routeChange.ts | 31 + frontend/vben/src/logics/theme/dark.ts | 24 + frontend/vben/src/logics/theme/index.ts | 17 + .../vben/src/logics/theme/updateBackground.ts | 75 + .../vben/src/logics/theme/updateColorWeak.ts | 9 + .../vben/src/logics/theme/updateGrayMode.ts | 9 + frontend/vben/src/logics/theme/util.ts | 11 + frontend/vben/src/main.ts | 64 + frontend/vben/src/router/constant.ts | 24 + frontend/vben/src/router/guard/index.ts | 147 + .../vben/src/router/guard/paramMenuGuard.ts | 47 + .../vben/src/router/guard/permissionGuard.ts | 118 + frontend/vben/src/router/guard/stateGuard.ts | 24 + frontend/vben/src/router/helper/menuHelper.ts | 106 + .../vben/src/router/helper/routeHelper.ts | 172 + frontend/vben/src/router/index.ts | 42 + frontend/vben/src/router/menus/index.ts | 126 + frontend/vben/src/router/routes/basic.ts | 48 + frontend/vben/src/router/routes/index.ts | 42 + .../vben/src/router/routes/modules/about.ts | 31 + .../src/router/routes/modules/dashboard.ts | 37 + .../vben/src/router/routes/modules/setup.ts | 31 + frontend/vben/src/router/types.ts | 58 + .../vben/src/settings/componentSetting.ts | 51 + frontend/vben/src/settings/designSetting.ts | 48 + .../vben/src/settings/encryptionSetting.ts | 13 + frontend/vben/src/settings/localeSetting.ts | 29 + frontend/vben/src/settings/projectSetting.ts | 177 + frontend/vben/src/settings/siteSetting.ts | 8 + frontend/vben/src/store/index.ts | 10 + frontend/vben/src/store/modules/app.ts | 108 + frontend/vben/src/store/modules/locale.ts | 55 + .../vben/src/store/modules/multipleTab.ts | 359 + frontend/vben/src/store/modules/permission.ts | 259 + frontend/vben/src/store/modules/user.ts | 177 + frontend/vben/src/utils/auth/index.ts | 26 + frontend/vben/src/utils/bem.ts | 52 + frontend/vben/src/utils/cache/index.ts | 32 + frontend/vben/src/utils/cache/memory.ts | 107 + frontend/vben/src/utils/cache/persistent.ts | 125 + frontend/vben/src/utils/cache/storageCache.ts | 109 + frontend/vben/src/utils/cipher.ts | 55 + frontend/vben/src/utils/color.ts | 151 + frontend/vben/src/utils/dateUtil.ts | 23 + frontend/vben/src/utils/domUtils.ts | 180 + frontend/vben/src/utils/env.ts | 83 + frontend/vben/src/utils/event/index.ts | 42 + .../utils/factory/createAsyncComponent.tsx | 63 + frontend/vben/src/utils/file/base64Conver.ts | 41 + frontend/vben/src/utils/file/download.ts | 96 + frontend/vben/src/utils/helper/treeHelper.ts | 216 + frontend/vben/src/utils/helper/tsxHelper.tsx | 35 + frontend/vben/src/utils/http/axios/Axios.ts | 237 + .../vben/src/utils/http/axios/axiosCancel.ts | 60 + .../vben/src/utils/http/axios/axiosRetry.ts | 28 + .../src/utils/http/axios/axiosTransform.ts | 52 + .../vben/src/utils/http/axios/checkStatus.ts | 80 + frontend/vben/src/utils/http/axios/helper.ts | 48 + frontend/vben/src/utils/http/axios/index.ts | 267 + frontend/vben/src/utils/index.ts | 92 + frontend/vben/src/utils/is.ts | 99 + frontend/vben/src/utils/lib/echarts.ts | 57 + frontend/vben/src/utils/log.ts | 9 + frontend/vben/src/utils/mitt.ts | 101 + frontend/vben/src/utils/propTypes.ts | 34 + frontend/vben/src/utils/props.ts | 185 + frontend/vben/src/utils/types.ts | 42 + frontend/vben/src/utils/uuid.ts | 28 + .../analysis/components/GrowCard.vue | 14 + .../analysis/components/SalesProductPie.vue | 64 + .../analysis/components/SiteAnalysis.vue | 38 + .../analysis/components/VisitAnalysis.vue | 89 + .../analysis/components/VisitAnalysisBar.vue | 47 + .../analysis/components/VisitRadar.vue | 94 + .../analysis/components/VisitSource.vue | 81 + .../dashboard/analysis/components/props.ts | 16 + .../vben/src/views/dashboard/analysis/data.ts | 8 + .../src/views/dashboard/analysis/index.vue | 25 + .../workbench/components/DynamicInfo.vue | 31 + .../workbench/components/ProjectCard.vue | 32 + .../workbench/components/QuickNav.vue | 17 + .../workbench/components/SaleRadar.vue | 94 + .../workbench/components/WorkbenchHeader.vue | 33 + .../dashboard/workbench/components/data.ts | 156 + .../src/views/dashboard/workbench/index.vue | 36 + frontend/vben/src/views/setup/index.vue | 43 + frontend/vben/src/views/sys/about/index.vue | 98 + .../src/views/sys/exception/Exception.vue | 148 + .../vben/src/views/sys/exception/index.ts | 1 + .../views/sys/login/ForgetPasswordForm.vue | 64 + frontend/vben/src/views/sys/login/Login.vue | 215 + .../vben/src/views/sys/login/LoginForm.vue | 137 + .../src/views/sys/login/LoginFormTitle.vue | 24 + .../vben/src/views/sys/login/MobileForm.vue | 63 + .../vben/src/views/sys/login/RegisterForm.vue | 104 + .../views/sys/login/SessionTimeoutLogin.vue | 53 + frontend/vben/src/views/sys/login/useLogin.ts | 118 + .../vben/src/views/sys/redirect/index.vue | 30 + frontend/vben/stylelint.config.js | 100 + frontend/vben/tsconfig.json | 44 + frontend/vben/types/axios.d.ts | 53 + frontend/vben/types/config.d.ts | 158 + frontend/vben/types/global.d.ts | 101 + frontend/vben/types/index.d.ts | 27 + frontend/vben/types/module.d.ts | 16 + frontend/vben/types/store.d.ts | 40 + frontend/vben/types/utils.d.ts | 5 + frontend/vben/types/vue-router.d.ts | 45 + frontend/vben/vite.config.ts | 115 + frontend/vben/windi.config.ts | 74 + frontend/vben/yarn.lock | 9754 +++++++++++++++++ 469 files changed, 42028 insertions(+) create mode 100644 frontend/vben/.editorconfig create mode 100644 frontend/vben/.env create mode 100644 frontend/vben/.env.development create mode 100644 frontend/vben/.env.production create mode 100644 frontend/vben/.eslintignore create mode 100644 frontend/vben/.eslintrc.js create mode 100644 frontend/vben/.gitignore create mode 100644 frontend/vben/.gitpod.yml create mode 100644 frontend/vben/.prettierignore create mode 100644 frontend/vben/.stylelintignore create mode 100644 frontend/vben/LICENSE create mode 100644 frontend/vben/README.md create mode 100644 frontend/vben/build/config/themeConfig.ts create mode 100644 frontend/vben/build/constant.ts create mode 100644 frontend/vben/build/generate/generateModifyVars.ts create mode 100644 frontend/vben/build/generate/icon/index.ts create mode 100644 frontend/vben/build/getConfigFileName.ts create mode 100644 frontend/vben/build/script/buildConf.ts create mode 100644 frontend/vben/build/script/postBuild.ts create mode 100644 frontend/vben/build/utils.ts create mode 100644 frontend/vben/build/vite/plugin/compress.ts create mode 100644 frontend/vben/build/vite/plugin/html.ts create mode 100644 frontend/vben/build/vite/plugin/imagemin.ts create mode 100644 frontend/vben/build/vite/plugin/index.ts create mode 100644 frontend/vben/build/vite/plugin/mock.ts create mode 100644 frontend/vben/build/vite/plugin/pwa.ts create mode 100644 frontend/vben/build/vite/plugin/styleImport.ts create mode 100644 frontend/vben/build/vite/plugin/svgSprite.ts create mode 100644 frontend/vben/build/vite/plugin/theme.ts create mode 100644 frontend/vben/build/vite/plugin/visualizer.ts create mode 100644 frontend/vben/build/vite/proxy.ts create mode 100644 frontend/vben/commitlint.config.js create mode 100644 frontend/vben/index.html create mode 100644 frontend/vben/mock/_createProductionServer.ts create mode 100644 frontend/vben/mock/_util.ts create mode 100644 frontend/vben/mock/demo/account.ts create mode 100644 frontend/vben/mock/demo/api-cascader.ts create mode 100644 frontend/vben/mock/demo/select-demo.ts create mode 100644 frontend/vben/mock/demo/system.ts create mode 100644 frontend/vben/mock/demo/table-demo.ts create mode 100644 frontend/vben/mock/demo/tree-demo.ts create mode 100644 frontend/vben/mock/sys/menu.ts create mode 100644 frontend/vben/mock/sys/user.ts create mode 100644 frontend/vben/package.json create mode 100755 frontend/vben/postcss.config.js create mode 100644 frontend/vben/prettier.config.js create mode 100644 frontend/vben/public/favicon.ico create mode 100644 frontend/vben/public/resource/img/logo.png create mode 100644 frontend/vben/public/resource/img/pwa-192x192.png create mode 100644 frontend/vben/public/resource/img/pwa-512x512.png create mode 100644 frontend/vben/public/resource/tinymce/langs/en.js create mode 100755 frontend/vben/public/resource/tinymce/langs/zh_CN.js create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.inline.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/content.inline.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/content.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css create mode 100644 frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css create mode 100644 frontend/vben/src/App.vue create mode 100644 frontend/vben/src/api/demo/account.ts create mode 100644 frontend/vben/src/api/demo/cascader.ts create mode 100644 frontend/vben/src/api/demo/error.ts create mode 100644 frontend/vben/src/api/demo/model/accountModel.ts create mode 100644 frontend/vben/src/api/demo/model/areaModel.ts create mode 100644 frontend/vben/src/api/demo/model/optionsModel.ts create mode 100644 frontend/vben/src/api/demo/model/systemModel.ts create mode 100644 frontend/vben/src/api/demo/model/tableModel.ts create mode 100644 frontend/vben/src/api/demo/select.ts create mode 100644 frontend/vben/src/api/demo/system.ts create mode 100644 frontend/vben/src/api/demo/table.ts create mode 100644 frontend/vben/src/api/demo/tree.ts create mode 100644 frontend/vben/src/api/model/baseModel.ts create mode 100644 frontend/vben/src/api/sys/menu.ts create mode 100644 frontend/vben/src/api/sys/model/menuModel.ts create mode 100644 frontend/vben/src/api/sys/model/uploadModel.ts create mode 100644 frontend/vben/src/api/sys/model/userModel.ts create mode 100644 frontend/vben/src/api/sys/user.ts create mode 100644 frontend/vben/src/assets/icons/download-count.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-1.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-2.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-3.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-4.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-5.svg create mode 100644 frontend/vben/src/assets/icons/dynamic-avatar-6.svg create mode 100644 frontend/vben/src/assets/icons/moon.svg create mode 100644 frontend/vben/src/assets/icons/sun.svg create mode 100644 frontend/vben/src/assets/icons/test.svg create mode 100644 frontend/vben/src/assets/icons/total-sales.svg create mode 100644 frontend/vben/src/assets/icons/transaction.svg create mode 100644 frontend/vben/src/assets/icons/visit-count.svg create mode 100644 frontend/vben/src/assets/images/demo.png create mode 100644 frontend/vben/src/assets/images/header.jpg create mode 100644 frontend/vben/src/assets/images/logo.png create mode 100644 frontend/vben/src/assets/svg/illustration.svg create mode 100644 frontend/vben/src/assets/svg/login-bg-dark.svg create mode 100644 frontend/vben/src/assets/svg/login-bg.svg create mode 100644 frontend/vben/src/assets/svg/login-box-bg.svg create mode 100644 frontend/vben/src/assets/svg/net-error.svg create mode 100644 frontend/vben/src/assets/svg/no-data.svg create mode 100644 frontend/vben/src/assets/svg/preview/p-rotate.svg create mode 100644 frontend/vben/src/assets/svg/preview/resume.svg create mode 100644 frontend/vben/src/assets/svg/preview/scale.svg create mode 100644 frontend/vben/src/assets/svg/preview/unrotate.svg create mode 100644 frontend/vben/src/assets/svg/preview/unscale.svg create mode 100644 frontend/vben/src/components/Application/index.ts create mode 100644 frontend/vben/src/components/Application/src/AppDarkModeToggle.vue create mode 100644 frontend/vben/src/components/Application/src/AppLocalePicker.vue create mode 100644 frontend/vben/src/components/Application/src/AppLogo.vue create mode 100644 frontend/vben/src/components/Application/src/AppProvider.vue create mode 100644 frontend/vben/src/components/Application/src/search/AppSearch.vue create mode 100644 frontend/vben/src/components/Application/src/search/AppSearchFooter.vue create mode 100644 frontend/vben/src/components/Application/src/search/AppSearchKeyItem.vue create mode 100644 frontend/vben/src/components/Application/src/search/AppSearchModal.vue create mode 100644 frontend/vben/src/components/Application/src/search/useMenuSearch.ts create mode 100644 frontend/vben/src/components/Application/src/useAppContext.ts create mode 100644 frontend/vben/src/components/Basic/index.ts create mode 100644 frontend/vben/src/components/Basic/src/BasicArrow.vue create mode 100644 frontend/vben/src/components/Basic/src/BasicHelp.vue create mode 100644 frontend/vben/src/components/Basic/src/BasicTitle.vue create mode 100644 frontend/vben/src/components/Button/index.ts create mode 100644 frontend/vben/src/components/Button/src/BasicButton.vue create mode 100644 frontend/vben/src/components/Button/src/PopConfirmButton.vue create mode 100644 frontend/vben/src/components/Button/src/props.ts create mode 100644 frontend/vben/src/components/Container/index.ts create mode 100644 frontend/vben/src/components/Container/src/LazyContainer.vue create mode 100644 frontend/vben/src/components/Container/src/ScrollContainer.vue create mode 100644 frontend/vben/src/components/Container/src/collapse/CollapseContainer.vue create mode 100644 frontend/vben/src/components/Container/src/collapse/CollapseHeader.vue create mode 100644 frontend/vben/src/components/Container/src/typing.ts create mode 100644 frontend/vben/src/components/CountDown/index.ts create mode 100644 frontend/vben/src/components/CountDown/src/CountButton.vue create mode 100644 frontend/vben/src/components/CountDown/src/CountdownInput.vue create mode 100644 frontend/vben/src/components/CountDown/src/useCountdown.ts create mode 100644 frontend/vben/src/components/Description/index.ts create mode 100644 frontend/vben/src/components/Description/src/Description.vue create mode 100644 frontend/vben/src/components/Description/src/typing.ts create mode 100644 frontend/vben/src/components/Description/src/useDescription.ts create mode 100644 frontend/vben/src/components/Drawer/index.ts create mode 100644 frontend/vben/src/components/Drawer/src/BasicDrawer.vue create mode 100644 frontend/vben/src/components/Drawer/src/components/DrawerFooter.vue create mode 100644 frontend/vben/src/components/Drawer/src/components/DrawerHeader.vue create mode 100644 frontend/vben/src/components/Drawer/src/props.ts create mode 100644 frontend/vben/src/components/Drawer/src/typing.ts create mode 100644 frontend/vben/src/components/Drawer/src/useDrawer.ts create mode 100644 frontend/vben/src/components/Dropdown/index.ts create mode 100644 frontend/vben/src/components/Dropdown/src/Dropdown.vue create mode 100644 frontend/vben/src/components/Dropdown/src/typing.ts create mode 100644 frontend/vben/src/components/Icon/data/icons.data.ts create mode 100644 frontend/vben/src/components/Icon/index.ts create mode 100644 frontend/vben/src/components/Icon/src/Icon.vue create mode 100644 frontend/vben/src/components/Icon/src/IconPicker.vue create mode 100644 frontend/vben/src/components/Icon/src/SvgIcon.vue create mode 100644 frontend/vben/src/components/Loading/index.ts create mode 100644 frontend/vben/src/components/Loading/src/Loading.vue create mode 100644 frontend/vben/src/components/Loading/src/createLoading.ts create mode 100644 frontend/vben/src/components/Loading/src/typing.ts create mode 100644 frontend/vben/src/components/Loading/src/useLoading.ts create mode 100644 frontend/vben/src/components/Menu/index.ts create mode 100644 frontend/vben/src/components/Menu/src/BasicMenu.vue create mode 100644 frontend/vben/src/components/Menu/src/components/BasicMenuItem.vue create mode 100644 frontend/vben/src/components/Menu/src/components/BasicSubMenuItem.vue create mode 100644 frontend/vben/src/components/Menu/src/components/MenuItemContent.vue create mode 100644 frontend/vben/src/components/Menu/src/index.less create mode 100644 frontend/vben/src/components/Menu/src/props.ts create mode 100644 frontend/vben/src/components/Menu/src/types.ts create mode 100644 frontend/vben/src/components/Menu/src/useOpenKeys.ts create mode 100644 frontend/vben/src/components/Modal/index.ts create mode 100644 frontend/vben/src/components/Modal/src/BasicModal.vue create mode 100644 frontend/vben/src/components/Modal/src/components/Modal.tsx create mode 100644 frontend/vben/src/components/Modal/src/components/ModalClose.vue create mode 100644 frontend/vben/src/components/Modal/src/components/ModalFooter.vue create mode 100644 frontend/vben/src/components/Modal/src/components/ModalHeader.vue create mode 100644 frontend/vben/src/components/Modal/src/components/ModalWrapper.vue create mode 100644 frontend/vben/src/components/Modal/src/hooks/useModal.ts create mode 100644 frontend/vben/src/components/Modal/src/hooks/useModalContext.ts create mode 100644 frontend/vben/src/components/Modal/src/hooks/useModalDrag.ts create mode 100644 frontend/vben/src/components/Modal/src/hooks/useModalFullScreen.ts create mode 100644 frontend/vben/src/components/Modal/src/index.less create mode 100644 frontend/vben/src/components/Modal/src/props.ts create mode 100644 frontend/vben/src/components/Modal/src/typing.ts create mode 100644 frontend/vben/src/components/Page/index.ts create mode 100644 frontend/vben/src/components/Page/src/PageFooter.vue create mode 100644 frontend/vben/src/components/Page/src/PageWrapper.vue create mode 100644 frontend/vben/src/components/Scrollbar/index.ts create mode 100644 frontend/vben/src/components/Scrollbar/src/Scrollbar.vue create mode 100644 frontend/vben/src/components/Scrollbar/src/bar.ts create mode 100644 frontend/vben/src/components/Scrollbar/src/types.d.ts create mode 100644 frontend/vben/src/components/Scrollbar/src/util.ts create mode 100644 frontend/vben/src/components/SimpleMenu/index.ts create mode 100644 frontend/vben/src/components/SimpleMenu/src/SimpleMenu.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/SimpleMenuTag.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/SimpleSubMenu.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/Menu.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/MenuItem.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/SubMenuItem.vue create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/menu.less create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/types.ts create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/useMenu.ts create mode 100644 frontend/vben/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts create mode 100644 frontend/vben/src/components/SimpleMenu/src/index.less create mode 100644 frontend/vben/src/components/SimpleMenu/src/types.ts create mode 100644 frontend/vben/src/components/SimpleMenu/src/useOpenKeys.ts create mode 100644 frontend/vben/src/components/StrengthMeter/index.ts create mode 100644 frontend/vben/src/components/StrengthMeter/src/StrengthMeter.vue create mode 100644 frontend/vben/src/components/Transition/index.ts create mode 100644 frontend/vben/src/components/Transition/src/CollapseTransition.vue create mode 100644 frontend/vben/src/components/Transition/src/CreateTransition.tsx create mode 100644 frontend/vben/src/components/Transition/src/ExpandTransition.ts create mode 100644 frontend/vben/src/components/registerGlobComp.ts create mode 100644 frontend/vben/src/design/ant/btn.less create mode 100644 frontend/vben/src/design/ant/index.less create mode 100644 frontend/vben/src/design/ant/input.less create mode 100644 frontend/vben/src/design/ant/pagination.less create mode 100644 frontend/vben/src/design/ant/table.less create mode 100644 frontend/vben/src/design/color.less create mode 100644 frontend/vben/src/design/config.less create mode 100644 frontend/vben/src/design/index.less create mode 100644 frontend/vben/src/design/public.less create mode 100644 frontend/vben/src/design/theme.less create mode 100644 frontend/vben/src/design/transition/base.less create mode 100644 frontend/vben/src/design/transition/fade.less create mode 100644 frontend/vben/src/design/transition/index.less create mode 100644 frontend/vben/src/design/transition/scale.less create mode 100644 frontend/vben/src/design/transition/scroll.less create mode 100644 frontend/vben/src/design/transition/slide.less create mode 100644 frontend/vben/src/design/transition/zoom.less create mode 100644 frontend/vben/src/design/var/breakpoint.less create mode 100644 frontend/vben/src/design/var/easing.less create mode 100644 frontend/vben/src/design/var/index.less create mode 100644 frontend/vben/src/directives/clickOutside.ts create mode 100644 frontend/vben/src/directives/index.ts create mode 100644 frontend/vben/src/directives/loading.ts create mode 100644 frontend/vben/src/directives/permission.ts create mode 100644 frontend/vben/src/directives/repeatClick.ts create mode 100644 frontend/vben/src/directives/ripple/index.less create mode 100644 frontend/vben/src/directives/ripple/index.ts create mode 100644 frontend/vben/src/enums/appEnum.ts create mode 100644 frontend/vben/src/enums/breakpointEnum.ts create mode 100644 frontend/vben/src/enums/cacheEnum.ts create mode 100644 frontend/vben/src/enums/exceptionEnum.ts create mode 100644 frontend/vben/src/enums/httpEnum.ts create mode 100644 frontend/vben/src/enums/menuEnum.ts create mode 100644 frontend/vben/src/enums/pageEnum.ts create mode 100644 frontend/vben/src/enums/roleEnum.ts create mode 100644 frontend/vben/src/enums/sizeEnum.ts create mode 100644 frontend/vben/src/hooks/component/useFormItem.ts create mode 100644 frontend/vben/src/hooks/component/usePageContext.ts create mode 100644 frontend/vben/src/hooks/core/onMountedOrActivated.ts create mode 100644 frontend/vben/src/hooks/core/useAttrs.ts create mode 100644 frontend/vben/src/hooks/core/useContext.ts create mode 100644 frontend/vben/src/hooks/core/useRefs.ts create mode 100644 frontend/vben/src/hooks/core/useTimeout.ts create mode 100644 frontend/vben/src/hooks/event/useBreakpoint.ts create mode 100644 frontend/vben/src/hooks/event/useEventListener.ts create mode 100644 frontend/vben/src/hooks/event/useIntersectionObserver.ts create mode 100644 frontend/vben/src/hooks/event/useScroll.ts create mode 100644 frontend/vben/src/hooks/event/useScrollTo.ts create mode 100644 frontend/vben/src/hooks/event/useWindowSizeFn.ts create mode 100644 frontend/vben/src/hooks/setting/index.ts create mode 100644 frontend/vben/src/hooks/setting/useHeaderSetting.ts create mode 100644 frontend/vben/src/hooks/setting/useMenuSetting.ts create mode 100644 frontend/vben/src/hooks/setting/useMultipleTabSetting.ts create mode 100644 frontend/vben/src/hooks/setting/useRootSetting.ts create mode 100644 frontend/vben/src/hooks/setting/useTransitionSetting.ts create mode 100644 frontend/vben/src/hooks/web/useAppInject.ts create mode 100644 frontend/vben/src/hooks/web/useContentHeight.ts create mode 100644 frontend/vben/src/hooks/web/useCopyToClipboard.ts create mode 100644 frontend/vben/src/hooks/web/useDesign.ts create mode 100644 frontend/vben/src/hooks/web/useECharts.ts create mode 100644 frontend/vben/src/hooks/web/useFullContent.ts create mode 100644 frontend/vben/src/hooks/web/useI18n.ts create mode 100644 frontend/vben/src/hooks/web/useMessage.tsx create mode 100644 frontend/vben/src/hooks/web/usePage.ts create mode 100644 frontend/vben/src/hooks/web/usePagination.ts create mode 100644 frontend/vben/src/hooks/web/usePermission.ts create mode 100644 frontend/vben/src/hooks/web/useScript.ts create mode 100644 frontend/vben/src/hooks/web/useSortable.ts create mode 100644 frontend/vben/src/hooks/web/useTabs.ts create mode 100644 frontend/vben/src/hooks/web/useTitle.ts create mode 100644 frontend/vben/src/hooks/web/useWatermark.ts create mode 100644 frontend/vben/src/layouts/default/content/index.vue create mode 100644 frontend/vben/src/layouts/default/content/useContentContext.ts create mode 100644 frontend/vben/src/layouts/default/content/useContentViewHeight.ts create mode 100644 frontend/vben/src/layouts/default/feature/index.vue create mode 100644 frontend/vben/src/layouts/default/footer/index.vue create mode 100644 frontend/vben/src/layouts/default/header/MultipleHeader.vue create mode 100644 frontend/vben/src/layouts/default/header/components/Breadcrumb.vue create mode 100644 frontend/vben/src/layouts/default/header/components/FullScreen.vue create mode 100644 frontend/vben/src/layouts/default/header/components/index.ts create mode 100644 frontend/vben/src/layouts/default/header/components/notify/NoticeList.vue create mode 100644 frontend/vben/src/layouts/default/header/components/notify/data.ts create mode 100644 frontend/vben/src/layouts/default/header/components/notify/index.vue create mode 100644 frontend/vben/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue create mode 100644 frontend/vben/src/layouts/default/header/components/user-dropdown/index.vue create mode 100644 frontend/vben/src/layouts/default/header/index.less create mode 100644 frontend/vben/src/layouts/default/header/index.vue create mode 100644 frontend/vben/src/layouts/default/index.vue create mode 100644 frontend/vben/src/layouts/default/menu/index.vue create mode 100644 frontend/vben/src/layouts/default/menu/useLayoutMenu.ts create mode 100644 frontend/vben/src/layouts/default/setting/SettingDrawer.tsx create mode 100644 frontend/vben/src/layouts/default/setting/components/InputNumberItem.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/SelectItem.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/SettingFooter.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/SwitchItem.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/ThemeColorPicker.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/TypePicker.vue create mode 100644 frontend/vben/src/layouts/default/setting/components/index.ts create mode 100644 frontend/vben/src/layouts/default/setting/enum.ts create mode 100644 frontend/vben/src/layouts/default/setting/handler.ts create mode 100644 frontend/vben/src/layouts/default/setting/index.vue create mode 100644 frontend/vben/src/layouts/default/sider/DragBar.vue create mode 100644 frontend/vben/src/layouts/default/sider/LayoutSider.vue create mode 100644 frontend/vben/src/layouts/default/sider/MixSider.vue create mode 100644 frontend/vben/src/layouts/default/sider/index.vue create mode 100644 frontend/vben/src/layouts/default/sider/useLayoutSider.ts create mode 100644 frontend/vben/src/layouts/default/tabs/components/FoldButton.vue create mode 100644 frontend/vben/src/layouts/default/tabs/components/TabContent.vue create mode 100644 frontend/vben/src/layouts/default/tabs/components/TabRedo.vue create mode 100644 frontend/vben/src/layouts/default/tabs/index.less create mode 100644 frontend/vben/src/layouts/default/tabs/index.vue create mode 100644 frontend/vben/src/layouts/default/tabs/types.ts create mode 100644 frontend/vben/src/layouts/default/tabs/useMultipleTabs.ts create mode 100644 frontend/vben/src/layouts/default/tabs/useTabDropdown.ts create mode 100644 frontend/vben/src/layouts/default/trigger/HeaderTrigger.vue create mode 100644 frontend/vben/src/layouts/default/trigger/SiderTrigger.vue create mode 100644 frontend/vben/src/layouts/default/trigger/index.vue create mode 100644 frontend/vben/src/layouts/page/index.vue create mode 100644 frontend/vben/src/layouts/page/transition.ts create mode 100644 frontend/vben/src/locales/helper.ts create mode 100644 frontend/vben/src/locales/lang/en.ts create mode 100644 frontend/vben/src/locales/lang/en/common.ts create mode 100644 frontend/vben/src/locales/lang/en/component.ts create mode 100644 frontend/vben/src/locales/lang/en/layout.ts create mode 100644 frontend/vben/src/locales/lang/en/routes/basic.ts create mode 100644 frontend/vben/src/locales/lang/en/routes/dashboard.ts create mode 100644 frontend/vben/src/locales/lang/en/routes/demo.ts create mode 100644 frontend/vben/src/locales/lang/en/sys.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/antdLocale/DatePicker.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/common.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/component.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/layout.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/routes/basic.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/routes/dashboard.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/routes/demo.ts create mode 100644 frontend/vben/src/locales/lang/zh-CN/sys.ts create mode 100644 frontend/vben/src/locales/lang/zh_CN.ts create mode 100644 frontend/vben/src/locales/setupI18n.ts create mode 100644 frontend/vben/src/locales/useLocale.ts create mode 100644 frontend/vben/src/logics/initAppConfig.ts create mode 100644 frontend/vben/src/logics/mitt/routeChange.ts create mode 100644 frontend/vben/src/logics/theme/dark.ts create mode 100644 frontend/vben/src/logics/theme/index.ts create mode 100644 frontend/vben/src/logics/theme/updateBackground.ts create mode 100644 frontend/vben/src/logics/theme/updateColorWeak.ts create mode 100644 frontend/vben/src/logics/theme/updateGrayMode.ts create mode 100644 frontend/vben/src/logics/theme/util.ts create mode 100644 frontend/vben/src/main.ts create mode 100644 frontend/vben/src/router/constant.ts create mode 100644 frontend/vben/src/router/guard/index.ts create mode 100644 frontend/vben/src/router/guard/paramMenuGuard.ts create mode 100644 frontend/vben/src/router/guard/permissionGuard.ts create mode 100644 frontend/vben/src/router/guard/stateGuard.ts create mode 100644 frontend/vben/src/router/helper/menuHelper.ts create mode 100644 frontend/vben/src/router/helper/routeHelper.ts create mode 100644 frontend/vben/src/router/index.ts create mode 100644 frontend/vben/src/router/menus/index.ts create mode 100644 frontend/vben/src/router/routes/basic.ts create mode 100644 frontend/vben/src/router/routes/index.ts create mode 100644 frontend/vben/src/router/routes/modules/about.ts create mode 100644 frontend/vben/src/router/routes/modules/dashboard.ts create mode 100644 frontend/vben/src/router/routes/modules/setup.ts create mode 100644 frontend/vben/src/router/types.ts create mode 100644 frontend/vben/src/settings/componentSetting.ts create mode 100644 frontend/vben/src/settings/designSetting.ts create mode 100644 frontend/vben/src/settings/encryptionSetting.ts create mode 100644 frontend/vben/src/settings/localeSetting.ts create mode 100644 frontend/vben/src/settings/projectSetting.ts create mode 100644 frontend/vben/src/settings/siteSetting.ts create mode 100644 frontend/vben/src/store/index.ts create mode 100644 frontend/vben/src/store/modules/app.ts create mode 100644 frontend/vben/src/store/modules/locale.ts create mode 100644 frontend/vben/src/store/modules/multipleTab.ts create mode 100644 frontend/vben/src/store/modules/permission.ts create mode 100644 frontend/vben/src/store/modules/user.ts create mode 100644 frontend/vben/src/utils/auth/index.ts create mode 100644 frontend/vben/src/utils/bem.ts create mode 100644 frontend/vben/src/utils/cache/index.ts create mode 100644 frontend/vben/src/utils/cache/memory.ts create mode 100644 frontend/vben/src/utils/cache/persistent.ts create mode 100644 frontend/vben/src/utils/cache/storageCache.ts create mode 100644 frontend/vben/src/utils/cipher.ts create mode 100644 frontend/vben/src/utils/color.ts create mode 100644 frontend/vben/src/utils/dateUtil.ts create mode 100644 frontend/vben/src/utils/domUtils.ts create mode 100644 frontend/vben/src/utils/env.ts create mode 100644 frontend/vben/src/utils/event/index.ts create mode 100644 frontend/vben/src/utils/factory/createAsyncComponent.tsx create mode 100644 frontend/vben/src/utils/file/base64Conver.ts create mode 100644 frontend/vben/src/utils/file/download.ts create mode 100644 frontend/vben/src/utils/helper/treeHelper.ts create mode 100644 frontend/vben/src/utils/helper/tsxHelper.tsx create mode 100644 frontend/vben/src/utils/http/axios/Axios.ts create mode 100644 frontend/vben/src/utils/http/axios/axiosCancel.ts create mode 100644 frontend/vben/src/utils/http/axios/axiosRetry.ts create mode 100644 frontend/vben/src/utils/http/axios/axiosTransform.ts create mode 100644 frontend/vben/src/utils/http/axios/checkStatus.ts create mode 100644 frontend/vben/src/utils/http/axios/helper.ts create mode 100644 frontend/vben/src/utils/http/axios/index.ts create mode 100644 frontend/vben/src/utils/index.ts create mode 100644 frontend/vben/src/utils/is.ts create mode 100644 frontend/vben/src/utils/lib/echarts.ts create mode 100644 frontend/vben/src/utils/log.ts create mode 100644 frontend/vben/src/utils/mitt.ts create mode 100644 frontend/vben/src/utils/propTypes.ts create mode 100644 frontend/vben/src/utils/props.ts create mode 100644 frontend/vben/src/utils/types.ts create mode 100644 frontend/vben/src/utils/uuid.ts create mode 100644 frontend/vben/src/views/dashboard/analysis/components/GrowCard.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/SalesProductPie.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/SiteAnalysis.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/VisitAnalysis.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/VisitAnalysisBar.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/VisitRadar.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/VisitSource.vue create mode 100644 frontend/vben/src/views/dashboard/analysis/components/props.ts create mode 100644 frontend/vben/src/views/dashboard/analysis/data.ts create mode 100644 frontend/vben/src/views/dashboard/analysis/index.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/DynamicInfo.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/ProjectCard.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/QuickNav.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/SaleRadar.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/WorkbenchHeader.vue create mode 100644 frontend/vben/src/views/dashboard/workbench/components/data.ts create mode 100644 frontend/vben/src/views/dashboard/workbench/index.vue create mode 100644 frontend/vben/src/views/setup/index.vue create mode 100644 frontend/vben/src/views/sys/about/index.vue create mode 100644 frontend/vben/src/views/sys/exception/Exception.vue create mode 100644 frontend/vben/src/views/sys/exception/index.ts create mode 100644 frontend/vben/src/views/sys/login/ForgetPasswordForm.vue create mode 100644 frontend/vben/src/views/sys/login/Login.vue create mode 100644 frontend/vben/src/views/sys/login/LoginForm.vue create mode 100644 frontend/vben/src/views/sys/login/LoginFormTitle.vue create mode 100644 frontend/vben/src/views/sys/login/MobileForm.vue create mode 100644 frontend/vben/src/views/sys/login/RegisterForm.vue create mode 100644 frontend/vben/src/views/sys/login/SessionTimeoutLogin.vue create mode 100644 frontend/vben/src/views/sys/login/useLogin.ts create mode 100644 frontend/vben/src/views/sys/redirect/index.vue create mode 100644 frontend/vben/stylelint.config.js create mode 100644 frontend/vben/tsconfig.json create mode 100644 frontend/vben/types/axios.d.ts create mode 100644 frontend/vben/types/config.d.ts create mode 100644 frontend/vben/types/global.d.ts create mode 100644 frontend/vben/types/index.d.ts create mode 100644 frontend/vben/types/module.d.ts create mode 100644 frontend/vben/types/store.d.ts create mode 100644 frontend/vben/types/utils.d.ts create mode 100644 frontend/vben/types/vue-router.d.ts create mode 100644 frontend/vben/vite.config.ts create mode 100644 frontend/vben/windi.config.ts create mode 100644 frontend/vben/yarn.lock diff --git a/.gitignore b/.gitignore index 66fd13c..1b3a47d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +# MacOS storage file +.DS_Store diff --git a/frontend/vben/.editorconfig b/frontend/vben/.editorconfig new file mode 100644 index 0000000..dccf841 --- /dev/null +++ b/frontend/vben/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=true +indent_style=space +indent_size=2 +max_line_length = 100 + +[*.{yml,yaml,json}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/frontend/vben/.env b/frontend/vben/.env new file mode 100644 index 0000000..d696d5f --- /dev/null +++ b/frontend/vben/.env @@ -0,0 +1,8 @@ +# port +VITE_PORT = 3100 + +# spa-title +VITE_GLOB_APP_TITLE = 试卷网络管理系统 + +# spa shortname +VITE_GLOB_APP_SHORT_NAME = paper_manager diff --git a/frontend/vben/.env.development b/frontend/vben/.env.development new file mode 100644 index 0000000..9236123 --- /dev/null +++ b/frontend/vben/.env.development @@ -0,0 +1,22 @@ +# Whether to open mock +VITE_USE_MOCK = true + +# public path +VITE_PUBLIC_PATH = / + +# Cross-domain proxy, you can configure multiple +# Please note that no line breaks +VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]] +# VITE_PROXY=[["/api","https://vvbin.cn/test"]] + +# Delete console +VITE_DROP_CONSOLE = false + +# Basic interface address SPA +VITE_GLOB_API_URL=/basic-api + +# File upload address, optional +VITE_GLOB_UPLOAD_URL=/upload + +# Interface prefix +VITE_GLOB_API_URL_PREFIX= diff --git a/frontend/vben/.env.production b/frontend/vben/.env.production new file mode 100644 index 0000000..9785c06 --- /dev/null +++ b/frontend/vben/.env.production @@ -0,0 +1,35 @@ +# Whether to open mock +VITE_USE_MOCK = false + +# public path +VITE_PUBLIC_PATH = / + +# Delete console +VITE_DROP_CONSOLE = true + +# Whether to enable gzip or brotli compression +# Optional: gzip | brotli | none +# If you need multiple forms, you can use `,` to separate +VITE_BUILD_COMPRESS = 'none' + +# Whether to delete origin files when using compress, default false +VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false + +# Basic interface address SPA +VITE_GLOB_API_URL=/basic-api + +# File upload address, optional +# It can be forwarded by nginx or write the actual address directly +VITE_GLOB_UPLOAD_URL=/upload + +# Interface prefix +VITE_GLOB_API_URL_PREFIX= + +# Whether to enable image compression +VITE_USE_IMAGEMIN= true + +# use pwa +VITE_USE_PWA = false + +# Is it compatible with older browsers +VITE_LEGACY = false diff --git a/frontend/vben/.eslintignore b/frontend/vben/.eslintignore new file mode 100644 index 0000000..348631b --- /dev/null +++ b/frontend/vben/.eslintignore @@ -0,0 +1,15 @@ + +*.sh +node_modules +*.md +*.woff +*.ttf +.vscode +.idea +dist +/public +/docs +.husky +.local +/bin +Dockerfile diff --git a/frontend/vben/.eslintrc.js b/frontend/vben/.eslintrc.js new file mode 100644 index 0000000..9aa3e10 --- /dev/null +++ b/frontend/vben/.eslintrc.js @@ -0,0 +1,76 @@ +module.exports = { + root: true, + env: { + browser: true, + node: true, + es6: true, + }, + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + ecmaVersion: 2020, + sourceType: 'module', + jsxPragma: 'React', + ecmaFeatures: { + jsx: true, + }, + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: { + 'vue/script-setup-uses-vars': 'error', + '@typescript-eslint/ban-ts-ignore': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-empty-function': 'off', + 'vue/custom-event-name-casing': 'off', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + 'no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + 'space-before-function-paren': 'off', + + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/require-explicit-emits': 'off', + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always', + }, + svg: 'always', + math: 'always', + }, + ], + 'vue/multi-word-component-names': 'off', + }, +}; diff --git a/frontend/vben/.gitignore b/frontend/vben/.gitignore new file mode 100644 index 0000000..e6922c4 --- /dev/null +++ b/frontend/vben/.gitignore @@ -0,0 +1,33 @@ +node_modules +.DS_Store +dist +.npmrc +.cache + +tests/server/static +tests/server/static/upload + +.local +# local env files +.env.local +.env.*.local +.eslintcache + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +# .vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +package-lock.json +pnpm-lock.yaml + diff --git a/frontend/vben/.gitpod.yml b/frontend/vben/.gitpod.yml new file mode 100644 index 0000000..866381f --- /dev/null +++ b/frontend/vben/.gitpod.yml @@ -0,0 +1,6 @@ +ports: + - port: 3344 + onOpen: open-preview +tasks: + - init: pnpm install + command: pnpm run dev diff --git a/frontend/vben/.prettierignore b/frontend/vben/.prettierignore new file mode 100644 index 0000000..f7e39e6 --- /dev/null +++ b/frontend/vben/.prettierignore @@ -0,0 +1,9 @@ +/dist/* +.local +.output.js +/node_modules/** + +**/*.svg +**/*.sh + +/public/* diff --git a/frontend/vben/.stylelintignore b/frontend/vben/.stylelintignore new file mode 100644 index 0000000..0517076 --- /dev/null +++ b/frontend/vben/.stylelintignore @@ -0,0 +1,3 @@ +/dist/* +/public/* +public/* diff --git a/frontend/vben/LICENSE b/frontend/vben/LICENSE new file mode 100644 index 0000000..9e4c0d4 --- /dev/null +++ b/frontend/vben/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2020-2023, Vben +Copyright (c) 2023-2023, fumiama(源文雨) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/frontend/vben/README.md b/frontend/vben/README.md new file mode 100644 index 0000000..7e34298 --- /dev/null +++ b/frontend/vben/README.md @@ -0,0 +1,101 @@ +
VbenAdmin Logo

+ +[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE) + +

Vue vben admin

+
+ +## 简介 + +精简 Vue Vben Admin。 + +## 特性 + +- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发 +- **TypeScript**: 应用程序级 JavaScript 的语言 +- **主题**:可配置的主题 +- **国际化**:内置完善的国际化方案 +- **Mock 数据** 内置 Mock 数据方案 +- **权限** 内置完善的动态路由权限生成方案 +- **组件** 二次封装了多个常用的组件 + +## 预览 + +- [vue-vben-admin](https://vvbin.cn/next/) - 完整版中文站点 +- [vue-vben-admin-gh-pages](https://anncwb.github.io/vue-vben-admin/) - 完整版 github 站点 +- [vben-admin-thin-next](https://vvbin.cn/thin/next/) - 简化版中文站点 +- [vben-admin-thin-gh-pages](https://anncwb.github.io/vben-admin-thin-next/) - 简化版 github 站点 + +## 准备 + +- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) -项目开发环境 +- [Vite](https://vitejs.dev/) - 熟悉 vite 特性 +- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法 +- [TypeScript](https://www.typescriptlang.org/) - 熟悉`TypeScript`基本语法 +- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法 +- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用 +- [Ant-Design-Vue](https://2x.antdv.com/docs/vue/introduce-cn/) - ui 基本使用 +- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法 + +## 安装使用 + +- 获取项目代码 + +```bash +git clone https://github.com/anncwb/vue-vben-admin.git +``` + +- 安装依赖 + +```bash +cd vue-vben-admin +git checkout thin +pnpm install + +``` + +- 运行 + +```bash +pnpm serve +``` + +- 打包 + +```bash +pnpm build +``` + +## Git 贡献提交规范 + +- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)) + + - `feat` 增加新功能 + - `fix` 修复问题/BUG + - `style` 代码风格相关无影响运行结果的 + - `perf` 优化/性能提升 + - `refactor` 重构 + - `revert` 撤销修改 + - `test` 测试相关 + - `docs` 文档/注释 + - `chore` 依赖更新/脚手架配置修改等 + - `workflow` 工作流改进 + - `ci` 持续集成 + - `types` 类型定义文件更改 + - `wip` 开发中 + +## 相关仓库 + +如果这些插件对你有帮助,可以给一个 star 支持下 + +- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - 用于本地及开发环境数据 mock +- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - 用于 html 模版转换及压缩 +- [vite-plugin-style-import](https://github.com/anncwb/vite-plugin-style-import) - 用于组件库样式按需引入 +- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - 用于在线切换主题色等颜色相关配置 +- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - 用于打包压缩图片资源 +- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - 用于打包输出.gz|.brotil 文件 +- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - 用于快速生成 svg 雪碧图 + +## License + +[MIT © Vben-2020](./LICENSE) diff --git a/frontend/vben/build/config/themeConfig.ts b/frontend/vben/build/config/themeConfig.ts new file mode 100644 index 0000000..c816b6d --- /dev/null +++ b/frontend/vben/build/config/themeConfig.ts @@ -0,0 +1,79 @@ +import { generate } from '@ant-design/colors'; + +export const primaryColor = '#0960bd'; + +export const darkMode = 'light'; + +type Fn = (...arg: any) => any; + +type GenerateTheme = 'default' | 'dark'; + +export interface GenerateColorsParams { + mixLighten: Fn; + mixDarken: Fn; + tinycolor: any; + color?: string; +} + +export function generateAntColors(color: string, theme: GenerateTheme = 'default') { + return generate(color, { + theme, + }); +} + +export function getThemeColors(color?: string) { + const tc = color || primaryColor; + const lightColors = generateAntColors(tc); + const primary = lightColors[5]; + const modeColors = generateAntColors(primary, 'dark'); + + return [...lightColors, ...modeColors]; +} + +export function generateColors({ + color = primaryColor, + mixLighten, + mixDarken, + tinycolor, +}: GenerateColorsParams) { + const arr = new Array(19).fill(0); + const lightens = arr.map((_t, i) => { + return mixLighten(color, i / 5); + }); + + const darkens = arr.map((_t, i) => { + return mixDarken(color, i / 5); + }); + + const alphaColors = arr.map((_t, i) => { + return tinycolor(color) + .setAlpha(i / 20) + .toRgbString(); + }); + + const shortAlphaColors = alphaColors.map((item) => item.replace(/\s/g, '').replace(/0\./g, '.')); + + const tinycolorLightens = arr + .map((_t, i) => { + return tinycolor(color) + .lighten(i * 5) + .toHexString(); + }) + .filter((item) => item !== '#ffffff'); + + const tinycolorDarkens = arr + .map((_t, i) => { + return tinycolor(color) + .darken(i * 5) + .toHexString(); + }) + .filter((item) => item !== '#000000'); + return [ + ...lightens, + ...darkens, + ...alphaColors, + ...shortAlphaColors, + ...tinycolorDarkens, + ...tinycolorLightens, + ].filter((item) => !item.includes('-')); +} diff --git a/frontend/vben/build/constant.ts b/frontend/vben/build/constant.ts new file mode 100644 index 0000000..2c6119c --- /dev/null +++ b/frontend/vben/build/constant.ts @@ -0,0 +1,6 @@ +/** + * The name of the configuration file entered in the production environment + */ +export const GLOB_CONFIG_FILE_NAME = '_app.config.js'; + +export const OUTPUT_DIR = 'dist'; diff --git a/frontend/vben/build/generate/generateModifyVars.ts b/frontend/vben/build/generate/generateModifyVars.ts new file mode 100644 index 0000000..44670e2 --- /dev/null +++ b/frontend/vben/build/generate/generateModifyVars.ts @@ -0,0 +1,37 @@ +import { generateAntColors, primaryColor } from '../config/themeConfig'; +import { getThemeVariables } from 'ant-design-vue/dist/theme'; +import { resolve } from 'path'; + +/** + * less global variable + */ +export function generateModifyVars(dark = false) { + const palettes = generateAntColors(primaryColor); + const primary = palettes[5]; + + const primaryColorObj: Record = {}; + + for (let index = 0; index < 10; index++) { + primaryColorObj[`primary-${index + 1}`] = palettes[index]; + } + + const modifyVars = getThemeVariables({ dark }); + return { + ...modifyVars, + // Used for global import to avoid the need to import each style file separately + // reference: Avoid repeated references + hack: `${modifyVars.hack} @import (reference) "${resolve('src/design/config.less')}";`, + 'primary-color': primary, + ...primaryColorObj, + 'info-color': primary, + 'processing-color': primary, + 'success-color': '#55D187', // Success color + 'error-color': '#ED6F6F', // False color + 'warning-color': '#EFBD47', // Warning color + //'border-color-base': '#EEEEEE', + 'font-size-base': '14px', // Main font size + 'border-radius-base': '2px', // Component/float fillet + 'link-color': primary, // Link color + 'app-content-background': '#fafafa', // Link color + }; +} diff --git a/frontend/vben/build/generate/icon/index.ts b/frontend/vben/build/generate/icon/index.ts new file mode 100644 index 0000000..b01fec4 --- /dev/null +++ b/frontend/vben/build/generate/icon/index.ts @@ -0,0 +1,72 @@ +import path from 'path'; +import fs from 'fs-extra'; +import inquirer from 'inquirer'; +import colors from 'picocolors'; +import pkg from '../../../package.json'; + +async function generateIcon() { + const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json'); + + const raw = await fs.readJSON(path.join(dir, 'collections.json')); + + const collections = Object.entries(raw).map(([id, v]) => ({ + ...(v as any), + id, + })); + + const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name })); + + inquirer + .prompt([ + { + type: 'list', + name: 'useType', + choices: [ + { key: 'local', value: 'local', name: 'Local' }, + { key: 'onLine', value: 'onLine', name: 'OnLine' }, + ], + message: 'How to use icons?', + }, + { + type: 'list', + name: 'iconSet', + choices: choices, + message: 'Select the icon set that needs to be generated?', + }, + { + type: 'input', + name: 'output', + message: 'Select the icon set that needs to be generated?', + default: 'src/components/Icon/data', + }, + ]) + .then(async (answers) => { + const { iconSet, output, useType } = answers; + const outputDir = path.resolve(process.cwd(), output); + fs.ensureDir(outputDir); + const genCollections = collections.filter((item) => [iconSet].includes(item.id)); + const prefixSet: string[] = []; + for (const info of genCollections) { + const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`)); + if (data) { + const { prefix } = data; + const isLocal = useType === 'local'; + const icons = Object.keys(data.icons).map( + (item) => `${isLocal ? prefix + ':' : ''}${item}`, + ); + + await fs.writeFileSync( + path.join(output, `icons.data.ts`), + `export default ${isLocal ? JSON.stringify(icons) : JSON.stringify({ prefix, icons })}`, + ); + prefixSet.push(prefix); + } + } + fs.emptyDir(path.join(process.cwd(), 'node_modules/.vite')); + console.log( + `✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`, + ); + }); +} + +generateIcon(); diff --git a/frontend/vben/build/getConfigFileName.ts b/frontend/vben/build/getConfigFileName.ts new file mode 100644 index 0000000..d61cd41 --- /dev/null +++ b/frontend/vben/build/getConfigFileName.ts @@ -0,0 +1,9 @@ +/** + * Get the configuration file variable name + * @param env + */ +export const getConfigFileName = (env: Record) => { + return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__` + .toUpperCase() + .replace(/\s/g, ''); +}; diff --git a/frontend/vben/build/script/buildConf.ts b/frontend/vben/build/script/buildConf.ts new file mode 100644 index 0000000..0c8089c --- /dev/null +++ b/frontend/vben/build/script/buildConf.ts @@ -0,0 +1,47 @@ +/** + * Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging + */ +import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'; +import fs, { writeFileSync } from 'fs-extra'; +import colors from 'picocolors'; + +import { getEnvConfig, getRootPath } from '../utils'; +import { getConfigFileName } from '../getConfigFileName'; + +import pkg from '../../package.json'; + +interface CreateConfigParams { + configName: string; + config: any; + configFileName?: string; +} + +function createConfig(params: CreateConfigParams) { + const { configName, config, configFileName } = params; + try { + const windowConf = `window.${configName}`; + // Ensure that the variable will not be modified + let configStr = `${windowConf}=${JSON.stringify(config)};`; + configStr += ` + Object.freeze(${windowConf}); + Object.defineProperty(window, "${configName}", { + configurable: false, + writable: false, + }); + `.replace(/\s/g, ''); + + fs.mkdirp(getRootPath(OUTPUT_DIR)); + writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr); + + console.log(colors.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`); + console.log(colors.gray(OUTPUT_DIR + '/' + colors.green(configFileName)) + '\n'); + } catch (error) { + console.log(colors.red('configuration file configuration file failed to package:\n' + error)); + } +} + +export function runBuildConfig() { + const config = getEnvConfig(); + const configFileName = getConfigFileName(config); + createConfig({ config, configName: configFileName, configFileName: GLOB_CONFIG_FILE_NAME }); +} diff --git a/frontend/vben/build/script/postBuild.ts b/frontend/vben/build/script/postBuild.ts new file mode 100644 index 0000000..42635d8 --- /dev/null +++ b/frontend/vben/build/script/postBuild.ts @@ -0,0 +1,23 @@ +// #!/usr/bin/env node + +import { runBuildConfig } from './buildConf'; +import colors from 'picocolors'; + +import pkg from '../../package.json'; + +export const runBuild = async () => { + try { + const argvList = process.argv.splice(2); + + // Generate configuration file + if (!argvList.includes('disabled-config')) { + runBuildConfig(); + } + + console.log(`✨ ${colors.cyan(`[${pkg.name}]`)}` + ' - build successfully!'); + } catch (error) { + console.log(colors.red('vite build error:\n' + error)); + process.exit(1); + } +}; +runBuild(); diff --git a/frontend/vben/build/utils.ts b/frontend/vben/build/utils.ts new file mode 100644 index 0000000..c201514 --- /dev/null +++ b/frontend/vben/build/utils.ts @@ -0,0 +1,92 @@ +import fs from 'fs'; +import path from 'path'; +import dotenv from 'dotenv'; + +export function isDevFn(mode: string): boolean { + return mode === 'development'; +} + +export function isProdFn(mode: string): boolean { + return mode === 'production'; +} + +/** + * Whether to generate package preview + */ +export function isReportMode(): boolean { + return process.env.REPORT === 'true'; +} + +// Read all environment variable configuration files to process.env +export function wrapperEnv(envConf: Recordable): ViteEnv { + const ret: any = {}; + + for (const envName of Object.keys(envConf)) { + let realName = envConf[envName].replace(/\\n/g, '\n'); + realName = realName === 'true' ? true : realName === 'false' ? false : realName; + + if (envName === 'VITE_PORT') { + realName = Number(realName); + } + if (envName === 'VITE_PROXY' && realName) { + try { + realName = JSON.parse(realName.replace(/'/g, '"')); + } catch (error) { + realName = ''; + } + } + ret[envName] = realName; + if (typeof realName === 'string') { + process.env[envName] = realName; + } else if (typeof realName === 'object') { + process.env[envName] = JSON.stringify(realName); + } + } + return ret; +} + +/** + * 获取当前环境下生效的配置文件名 + */ +function getConfFiles() { + const script = process.env.npm_lifecycle_script; + const reg = new RegExp('--mode ([a-z_\\d]+)'); + const result = reg.exec(script as string) as any; + if (result) { + const mode = result[1] as string; + return ['.env', `.env.${mode}`]; + } + return ['.env', '.env.production']; +} + +/** + * Get the environment variables starting with the specified prefix + * @param match prefix + * @param confFiles ext + */ +export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) { + let envConfig = {}; + confFiles.forEach((item) => { + try { + const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item))); + envConfig = { ...envConfig, ...env }; + } catch (e) { + console.error(`Error in parsing ${item}`, e); + } + }); + const reg = new RegExp(`^(${match})`); + Object.keys(envConfig).forEach((key) => { + if (!reg.test(key)) { + Reflect.deleteProperty(envConfig, key); + } + }); + return envConfig; +} + +/** + * Get user root directory + * @param dir file path + */ +export function getRootPath(...dir: string[]) { + return path.resolve(process.cwd(), ...dir); +} diff --git a/frontend/vben/build/vite/plugin/compress.ts b/frontend/vben/build/vite/plugin/compress.ts new file mode 100644 index 0000000..ff4f631 --- /dev/null +++ b/frontend/vben/build/vite/plugin/compress.ts @@ -0,0 +1,35 @@ +/** + * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated + * https://github.com/anncwb/vite-plugin-compression + */ +import type { PluginOption } from 'vite'; +import compressPlugin from 'vite-plugin-compression'; + +export function configCompressPlugin( + compress: 'gzip' | 'brotli' | 'none', + deleteOriginFile = false, +): PluginOption | PluginOption[] { + const compressList = compress.split(','); + + const plugins: PluginOption[] = []; + + if (compressList.includes('gzip')) { + plugins.push( + compressPlugin({ + ext: '.gz', + deleteOriginFile, + }), + ); + } + + if (compressList.includes('brotli')) { + plugins.push( + compressPlugin({ + ext: '.br', + algorithm: 'brotliCompress', + deleteOriginFile, + }), + ); + } + return plugins; +} diff --git a/frontend/vben/build/vite/plugin/html.ts b/frontend/vben/build/vite/plugin/html.ts new file mode 100644 index 0000000..6af034a --- /dev/null +++ b/frontend/vben/build/vite/plugin/html.ts @@ -0,0 +1,40 @@ +/** + * Plugin to minimize and use ejs template syntax in index.html. + * https://github.com/anncwb/vite-plugin-html + */ +import type { PluginOption } from 'vite'; +import { createHtmlPlugin } from 'vite-plugin-html'; +import pkg from '../../../package.json'; +import { GLOB_CONFIG_FILE_NAME } from '../../constant'; + +export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) { + const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env; + + const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`; + + const getAppConfigSrc = () => { + return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`; + }; + + const htmlPlugin: PluginOption[] = createHtmlPlugin({ + minify: isBuild, + inject: { + // Inject data into ejs template + data: { + title: VITE_GLOB_APP_TITLE, + }, + // Embed the generated app.config.js file + tags: isBuild + ? [ + { + tag: 'script', + attrs: { + src: getAppConfigSrc(), + }, + }, + ] + : [], + }, + }); + return htmlPlugin; +} diff --git a/frontend/vben/build/vite/plugin/imagemin.ts b/frontend/vben/build/vite/plugin/imagemin.ts new file mode 100644 index 0000000..a023573 --- /dev/null +++ b/frontend/vben/build/vite/plugin/imagemin.ts @@ -0,0 +1,34 @@ +// Image resource files used to compress the output of the production environment +// https://github.com/anncwb/vite-plugin-imagemin +import viteImagemin from 'vite-plugin-imagemin'; + +export function configImageminPlugin() { + const plugin = viteImagemin({ + gifsicle: { + optimizationLevel: 7, + interlaced: false, + }, + optipng: { + optimizationLevel: 7, + }, + mozjpeg: { + quality: 20, + }, + pngquant: { + quality: [0.8, 0.9], + speed: 4, + }, + svgo: { + plugins: [ + { + name: 'removeViewBox', + }, + { + name: 'removeEmptyAttrs', + active: false, + }, + ], + }, + }); + return plugin; +} diff --git a/frontend/vben/build/vite/plugin/index.ts b/frontend/vben/build/vite/plugin/index.ts new file mode 100644 index 0000000..66956a3 --- /dev/null +++ b/frontend/vben/build/vite/plugin/index.ts @@ -0,0 +1,82 @@ +import { PluginOption } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import legacy from '@vitejs/plugin-legacy' +import purgeIcons from 'vite-plugin-purge-icons' +import windiCSS from 'vite-plugin-windicss' +import VitePluginCertificate from 'vite-plugin-mkcert' +//import vueSetupExtend from 'vite-plugin-vue-setup-extend'; +import { configHtmlPlugin } from './html' +import { configPwaConfig } from './pwa' +import { configMockPlugin } from './mock' +import { configCompressPlugin } from './compress' +import { configStyleImportPlugin } from './styleImport' +import { configVisualizerConfig } from './visualizer' +import { configThemePlugin } from './theme' +import { configImageminPlugin } from './imagemin' +import { configSvgIconsPlugin } from './svgSprite' + +export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) { + const { + VITE_USE_IMAGEMIN, + VITE_USE_MOCK, + VITE_LEGACY, + VITE_BUILD_COMPRESS, + VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE, + } = viteEnv + + const vitePlugins: (PluginOption | PluginOption[])[] = [ + // have to + vue(), + // have to + vueJsx(), + // support name + //vueSetupExtend(), + VitePluginCertificate({ + source: 'coding', + }), + ] + + // vite-plugin-windicss + vitePlugins.push(windiCSS()) + + // @vitejs/plugin-legacy + VITE_LEGACY && isBuild && vitePlugins.push(legacy()) + + // vite-plugin-html + vitePlugins.push(configHtmlPlugin(viteEnv, isBuild)) + + // vite-plugin-svg-icons + vitePlugins.push(configSvgIconsPlugin(isBuild)) + + // vite-plugin-mock + VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild)) + + // vite-plugin-purge-icons + vitePlugins.push(purgeIcons()) + + // vite-plugin-style-import + vitePlugins.push(configStyleImportPlugin(isBuild)) + + // rollup-plugin-visualizer + vitePlugins.push(configVisualizerConfig()) + + // vite-plugin-theme + vitePlugins.push(configThemePlugin(isBuild)) + + // The following plugins only work in the production environment + if (isBuild) { + // vite-plugin-imagemin + VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin()) + + // rollup-plugin-gzip + vitePlugins.push( + configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE), + ) + + // vite-plugin-pwa + vitePlugins.push(configPwaConfig(viteEnv)) + } + + return vitePlugins +} diff --git a/frontend/vben/build/vite/plugin/mock.ts b/frontend/vben/build/vite/plugin/mock.ts new file mode 100644 index 0000000..d241e26 --- /dev/null +++ b/frontend/vben/build/vite/plugin/mock.ts @@ -0,0 +1,19 @@ +/** + * Mock plugin for development and production. + * https://github.com/anncwb/vite-plugin-mock + */ +import { viteMockServe } from 'vite-plugin-mock'; + +export function configMockPlugin(isBuild: boolean) { + return viteMockServe({ + ignore: /^\_/, + mockPath: 'mock', + localEnabled: !isBuild, + prodEnabled: isBuild, + injectCode: ` + import { setupProdMockServer } from '../mock/_createProductionServer'; + + setupProdMockServer(); + `, + }); +} diff --git a/frontend/vben/build/vite/plugin/pwa.ts b/frontend/vben/build/vite/plugin/pwa.ts new file mode 100644 index 0000000..90ef5bc --- /dev/null +++ b/frontend/vben/build/vite/plugin/pwa.ts @@ -0,0 +1,33 @@ +/** + * Zero-config PWA for Vite + * https://github.com/antfu/vite-plugin-pwa + */ +import { VitePWA } from 'vite-plugin-pwa'; + +export function configPwaConfig(env: ViteEnv) { + const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env; + + if (VITE_USE_PWA) { + // vite-plugin-pwa + const pwaPlugin = VitePWA({ + manifest: { + name: VITE_GLOB_APP_TITLE, + short_name: VITE_GLOB_APP_SHORT_NAME, + icons: [ + { + src: './resource/img/pwa-192x192.png', + sizes: '192x192', + type: 'image/png', + }, + { + src: './resource/img/pwa-512x512.png', + sizes: '512x512', + type: 'image/png', + }, + ], + }, + }); + return pwaPlugin; + } + return []; +} diff --git a/frontend/vben/build/vite/plugin/styleImport.ts b/frontend/vben/build/vite/plugin/styleImport.ts new file mode 100644 index 0000000..60d5684 --- /dev/null +++ b/frontend/vben/build/vite/plugin/styleImport.ts @@ -0,0 +1,81 @@ +/** + * Introduces component library styles on demand. + * https://github.com/anncwb/vite-plugin-style-import + */ +import { createStyleImportPlugin } from 'vite-plugin-style-import' + +export function configStyleImportPlugin(_isBuild: boolean) { + if (!_isBuild) { + return [] + } + const styleImportPlugin = createStyleImportPlugin({ + libs: [ + { + libraryName: 'ant-design-vue', + esModule: true, + resolveStyle: (name) => { + // 这里是无需额外引入样式文件的“子组件”列表 + const ignoreList = [ + 'anchor-link', + 'sub-menu', + 'menu-item', + 'menu-divider', + 'menu-item-group', + 'breadcrumb-item', + 'breadcrumb-separator', + 'form-item', + 'step', + 'select-option', + 'select-opt-group', + 'card-grid', + 'card-meta', + 'collapse-panel', + 'descriptions-item', + 'list-item', + 'list-item-meta', + 'table-column', + 'table-column-group', + 'tab-pane', + 'tab-content', + 'timeline-item', + 'tree-node', + 'skeleton-input', + 'skeleton-avatar', + 'skeleton-title', + 'skeleton-paragraph', + 'skeleton-image', + 'skeleton-button', + ] + // 这里是需要额外引入样式的子组件列表 + // 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失 + const replaceList = { + 'typography-text': 'typography', + 'typography-title': 'typography', + 'typography-paragraph': 'typography', + 'typography-link': 'typography', + 'dropdown-button': 'dropdown', + 'input-password': 'input', + 'input-search': 'input', + 'input-group': 'input', + 'radio-group': 'radio', + 'checkbox-group': 'checkbox', + 'layout-sider': 'layout', + 'layout-content': 'layout', + 'layout-footer': 'layout', + 'layout-header': 'layout', + 'month-picker': 'date-picker', + 'range-picker': 'date-picker', + 'image-preview-group': 'image', + } + + return ignoreList.includes(name) + ? '' + : replaceList.hasOwnProperty(name) + ? `ant-design-vue/es/${replaceList[name]}/style/index` + : `ant-design-vue/es/${name}/style/index` + }, + }, + ], + }) + return styleImportPlugin +} diff --git a/frontend/vben/build/vite/plugin/svgSprite.ts b/frontend/vben/build/vite/plugin/svgSprite.ts new file mode 100644 index 0000000..61f637f --- /dev/null +++ b/frontend/vben/build/vite/plugin/svgSprite.ts @@ -0,0 +1,17 @@ +/** + * Vite Plugin for fast creating SVG sprites. + * https://github.com/anncwb/vite-plugin-svg-icons + */ + +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; +import path from 'path'; + +export function configSvgIconsPlugin(isBuild: boolean) { + const svgIconsPlugin = createSvgIconsPlugin({ + iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')], + svgoOptions: isBuild, + // default + symbolId: 'icon-[dir]-[name]', + }); + return svgIconsPlugin; +} diff --git a/frontend/vben/build/vite/plugin/theme.ts b/frontend/vben/build/vite/plugin/theme.ts new file mode 100644 index 0000000..118983f --- /dev/null +++ b/frontend/vben/build/vite/plugin/theme.ts @@ -0,0 +1,89 @@ +/** + * Vite plugin for website theme color switching + * https://github.com/anncwb/vite-plugin-theme + */ +import type { PluginOption } from 'vite'; +import path from 'path'; +import { + viteThemePlugin, + antdDarkThemePlugin, + mixLighten, + mixDarken, + tinycolor, +} from 'vite-plugin-theme'; +import { getThemeColors, generateColors } from '../../config/themeConfig'; +import { generateModifyVars } from '../../generate/generateModifyVars'; + +export function configThemePlugin(isBuild: boolean): PluginOption[] { + const colors = generateColors({ + mixDarken, + mixLighten, + tinycolor, + }); + const plugin = [ + viteThemePlugin({ + resolveSelector: (s) => { + s = s.trim(); + switch (s) { + case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon': + return '.ant-steps-item-icon > .ant-steps-icon'; + case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)': + case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover': + case '.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active': + return s; + case '.ant-steps-item-icon > .ant-steps-icon': + return s; + case '.ant-select-item-option-selected:not(.ant-select-item-option-disabled)': + return s; + default: + if (s.indexOf('.ant-btn') >= -1) { + // 按钮被重新定制过,需要过滤掉class防止覆盖 + return s; + } + } + return s.startsWith('[data-theme') ? s : `[data-theme] ${s}`; + }, + colorVariables: [...getThemeColors(), ...colors], + }), + antdDarkThemePlugin({ + preloadFiles: [ + path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.less'), + //path.resolve(process.cwd(), 'node_modules/ant-design-vue/dist/antd.dark.less'), + path.resolve(process.cwd(), 'src/design/index.less'), + ], + filter: (id) => (isBuild ? !id.endsWith('antd.less') : true), + // extractCss: false, + darkModifyVars: { + ...generateModifyVars(true), + 'text-color': '#c9d1d9', + 'primary-1': 'rgb(255 255 255 / 8%)', + 'text-color-base': '#c9d1d9', + 'component-background': '#151515', + 'heading-color': 'rgb(255 255 255 / 65%)', + // black: '#0e1117', + // #8b949e + 'text-color-secondary': '#8b949e', + 'border-color-base': '#303030', + // 'border-color-split': '#30363d', + 'item-active-bg': '#111b26', + 'app-content-background': '#1e1e1e', + 'tree-node-selected-bg': '#11263c', + + 'alert-success-border-color': '#274916', + 'alert-success-bg-color': '#162312', + 'alert-success-icon-color': '#49aa19', + 'alert-info-border-color': '#153450', + 'alert-info-bg-color': '#111b26', + 'alert-info-icon-color': '#177ddc', + 'alert-warning-border-color': '#594214', + 'alert-warning-bg-color': '#2b2111', + 'alert-warning-icon-color': '#d89614', + 'alert-error-border-color': '#58181c', + 'alert-error-bg-color': '#2a1215', + 'alert-error-icon-color': '#a61d24', + }, + }), + ]; + + return plugin as unknown as PluginOption[]; +} diff --git a/frontend/vben/build/vite/plugin/visualizer.ts b/frontend/vben/build/vite/plugin/visualizer.ts new file mode 100644 index 0000000..75d4451 --- /dev/null +++ b/frontend/vben/build/vite/plugin/visualizer.ts @@ -0,0 +1,17 @@ +/** + * Package file volume analysis + */ +import visualizer from 'rollup-plugin-visualizer'; +import { isReportMode } from '../../utils'; + +export function configVisualizerConfig() { + if (isReportMode()) { + return visualizer({ + filename: './node_modules/.cache/visualizer/stats.html', + open: true, + gzipSize: true, + brotliSize: true, + }) as Plugin; + } + return []; +} diff --git a/frontend/vben/build/vite/proxy.ts b/frontend/vben/build/vite/proxy.ts new file mode 100644 index 0000000..8525397 --- /dev/null +++ b/frontend/vben/build/vite/proxy.ts @@ -0,0 +1,34 @@ +/** + * Used to parse the .env.development proxy configuration + */ +import type { ProxyOptions } from 'vite'; + +type ProxyItem = [string, string]; + +type ProxyList = ProxyItem[]; + +type ProxyTargetList = Record; + +const httpsRE = /^https:\/\//; + +/** + * Generate proxy + * @param list + */ +export function createProxy(list: ProxyList = []) { + const ret: ProxyTargetList = {}; + for (const [prefix, target] of list) { + const isHttps = httpsRE.test(target); + + // https://github.com/http-party/node-http-proxy#options + ret[prefix] = { + target: target, + changeOrigin: true, + ws: true, + rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''), + // https is require secure=false + ...(isHttps ? { secure: false } : {}), + }; + } + return ret; +} diff --git a/frontend/vben/commitlint.config.js b/frontend/vben/commitlint.config.js new file mode 100644 index 0000000..dbe4b09 --- /dev/null +++ b/frontend/vben/commitlint.config.js @@ -0,0 +1,107 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +const scopes = fs + .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name.replace(/s$/, '')) + +// precomputed scope +const scopeComplete = execSync('git status --porcelain || true') + .toString() + .trim() + .split('\n') + .find((r) => ~r.indexOf('M src')) + ?.replace(/(\/)/g, '%%') + ?.match(/src%%((\w|-)*)/)?.[1] + ?.replace(/s$/, '') + +/** @type {import('cz-git').UserConfig} */ +module.exports = { + ignores: [(commit) => commit.includes('init')], + extends: ['@commitlint/config-conventional'], + rules: { + 'body-leading-blank': [2, 'always'], + 'footer-leading-blank': [1, 'always'], + 'header-max-length': [2, 'always', 108], + 'subject-empty': [2, 'never'], + 'type-empty': [2, 'never'], + 'subject-case': [0], + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'perf', + 'style', + 'docs', + 'test', + 'refactor', + 'build', + 'ci', + 'chore', + 'revert', + 'wip', + 'workflow', + 'types', + 'release', + ], + ], + }, + prompt: { + /** @use `yarn commit :f` */ + alias: { + f: 'docs: fix typos', + r: 'docs: update README', + s: 'style: update code format', + b: 'build: bump dependencies', + c: 'chore: update config', + }, + customScopesAlign: !scopeComplete ? 'top' : 'bottom', + defaultScope: scopeComplete, + scopes: [...scopes, 'mock'], + allowEmptyIssuePrefixs: false, + allowCustomIssuePrefixs: false, + + // English + typesAppend: [ + { value: 'wip', name: 'wip: work in process' }, + { value: 'workflow', name: 'workflow: workflow improvements' }, + { value: 'types', name: 'types: type definition file changes' }, + ], + + // 中英文对照版 + // messages: { + // type: '选择你要提交的类型 :', + // scope: '选择一个提交范围 (可选):', + // customScope: '请输入自定义的提交范围 :', + // subject: '填写简短精炼的变更描述 :\n', + // body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n', + // breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n', + // footerPrefixsSelect: '选择关联issue前缀 (可选):', + // customFooterPrefixs: '输入自定义issue前缀 :', + // footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', + // confirmCommit: '是否提交或修改commit ?', + // }, + // types: [ + // { value: 'feat', name: 'feat: 新增功能' }, + // { value: 'fix', name: 'fix: 修复缺陷' }, + // { value: 'docs', name: 'docs: 文档变更' }, + // { value: 'style', name: 'style: 代码格式' }, + // { value: 'refactor', name: 'refactor: 代码重构' }, + // { value: 'perf', name: 'perf: 性能优化' }, + // { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' }, + // { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' }, + // { value: 'ci', name: 'ci: 修改 CI 配置、脚本' }, + // { value: 'revert', name: 'revert: 回滚 commit' }, + // { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' }, + // { value: 'wip', name: 'wip: 正在开发中' }, + // { value: 'workflow', name: 'workflow: 工作流程改进' }, + // { value: 'types', name: 'types: 类型定义文件修改' }, + // ], + // emptyScopesAlias: 'empty: 不填写', + // customScopesAlias: 'custom: 自定义', + }, +} diff --git a/frontend/vben/index.html b/frontend/vben/index.html new file mode 100644 index 0000000..3f1aa76 --- /dev/null +++ b/frontend/vben/index.html @@ -0,0 +1,159 @@ + + + + + + + + <%= title %> + + + + +
+ +
+
+ +
+ +
+
<%= title %>
+
+
+
+ + + diff --git a/frontend/vben/mock/_createProductionServer.ts b/frontend/vben/mock/_createProductionServer.ts new file mode 100644 index 0000000..a44310b --- /dev/null +++ b/frontend/vben/mock/_createProductionServer.ts @@ -0,0 +1,18 @@ +import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'; + +const modules = import.meta.globEager('./**/*.ts'); + +const mockModules: any[] = []; +Object.keys(modules).forEach((key) => { + if (key.includes('/_')) { + return; + } + mockModules.push(...modules[key].default); +}); + +/** + * Used in a production environment. Need to manually import all modules + */ +export function setupProdMockServer() { + createProdMockServer(mockModules); +} diff --git a/frontend/vben/mock/_util.ts b/frontend/vben/mock/_util.ts new file mode 100644 index 0000000..de4d558 --- /dev/null +++ b/frontend/vben/mock/_util.ts @@ -0,0 +1,62 @@ +// Interface data format used to return a unified format +import { ResultEnum } from '/@/enums/httpEnum'; + +export function resultSuccess(result: T, { message = 'ok' } = {}) { + return { + code: ResultEnum.SUCCESS, + result, + message, + type: 'success', + }; +} + +export function resultPageSuccess( + page: number, + pageSize: number, + list: T[], + { message = 'ok' } = {}, +) { + const pageData = pagination(page, pageSize, list); + + return { + ...resultSuccess({ + items: pageData, + total: list.length, + }), + message, + }; +} + +export function resultError( + message = 'Request failed', + { code = ResultEnum.ERROR, result = null } = {}, +) { + return { + code, + result, + message, + type: 'error', + }; +} + +export function pagination(pageNo: number, pageSize: number, array: T[]): T[] { + const offset = (pageNo - 1) * Number(pageSize); + return offset + Number(pageSize) >= array.length + ? array.slice(offset, array.length) + : array.slice(offset, offset + Number(pageSize)); +} + +export interface requestParams { + method: string; + body: any; + headers?: { authorization?: string }; + query: any; +} + +/** + * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改 + * + */ +export function getRequestToken({ headers }: requestParams): string | undefined { + return headers?.authorization; +} diff --git a/frontend/vben/mock/demo/account.ts b/frontend/vben/mock/demo/account.ts new file mode 100644 index 0000000..a392493 --- /dev/null +++ b/frontend/vben/mock/demo/account.ts @@ -0,0 +1,71 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultSuccess, resultError } from '../_util'; +import { ResultEnum } from '../../src/enums/httpEnum'; + +const userInfo = { + name: 'Vben', + userid: '00000001', + email: 'test@gmail.com', + signature: '海纳百川,有容乃大', + introduction: '微笑着,努力着,欣赏着', + title: '交互专家', + group: '某某某事业群-某某平台部-某某技术部-UED', + tags: [ + { + key: '0', + label: '很有想法的', + }, + { + key: '1', + label: '专注设计', + }, + { + key: '2', + label: '辣~', + }, + { + key: '3', + label: '大长腿', + }, + { + key: '4', + label: '川妹子', + }, + { + key: '5', + label: '海纳百川', + }, + ], + notifyCount: 12, + unreadCount: 11, + country: 'China', + address: 'Xiamen City 77', + phone: '0592-268888888', +}; + +export default [ + { + url: '/basic-api/account/getAccountInfo', + timeout: 1000, + method: 'get', + response: () => { + return resultSuccess(userInfo); + }, + }, + { + url: '/basic-api/user/sessionTimeout', + method: 'post', + statusCode: 401, + response: () => { + return resultError(); + }, + }, + { + url: '/basic-api/user/tokenExpired', + method: 'post', + statusCode: 200, + response: () => { + return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number }); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/demo/api-cascader.ts b/frontend/vben/mock/demo/api-cascader.ts new file mode 100644 index 0000000..6334ef5 --- /dev/null +++ b/frontend/vben/mock/demo/api-cascader.ts @@ -0,0 +1,325 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultSuccess } from '../_util'; + +const areaList: any[] = [ + { + id: '530825900854620160', + code: '430000', + parentCode: '100000', + levelType: 1, + name: '湖南省', + province: '湖南省', + city: null, + district: null, + town: null, + village: null, + parentPath: '430000', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900883980288', + code: '430100', + parentCode: '430000', + levelType: 2, + name: '长沙市', + province: '湖南省', + city: '长沙市', + district: null, + town: null, + village: null, + parentPath: '430000,430100', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900951089152', + code: '430102', + parentCode: '430100', + levelType: 3, + name: '芙蓉区', + province: '湖南省', + city: '长沙市', + district: '芙蓉区', + town: null, + village: null, + parentPath: '430000,430100,430102', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825901014003712', + code: '430104', + parentCode: '430100', + levelType: 3, + name: '岳麓区', + province: '湖南省', + city: '长沙市', + district: '岳麓区', + town: null, + village: null, + parentPath: '430000,430100,430104', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530825900988837888', + code: '430103', + parentCode: '430100', + levelType: 3, + name: '天心区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: null, + village: null, + parentPath: '430000,430100,430103', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 16:33:42', + customized: false, + usable: true, + }, + { + id: '530826672489115648', + code: '430103002', + parentCode: '430103', + levelType: 4, + name: '坡子街街道', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: null, + parentPath: '430000,430100,430103,430103002', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-12-14 15:26:43', + customized: false, + usable: true, + }, + { + id: '530840241171607552', + code: '430103002001', + parentCode: '430103002', + levelType: 5, + name: '八角亭社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '八角亭社区', + parentPath: '430000,430100,430103,430103002,430103002001', + createTime: '2020-11-30 15:47:31', + updateTime: '2021-01-20 14:07:23', + customized: false, + usable: true, + }, + { + id: '530840241200967680', + code: '430103002002', + parentCode: '430103002', + levelType: 5, + name: '西牌楼社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '西牌楼社区', + parentPath: '430000,430100,430103,430103002,430103002002', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241230327808', + code: '430103002003', + parentCode: '430103002', + levelType: 5, + name: '太平街社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '太平街社区', + parentPath: '430000,430100,430103,430103002,430103002003', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241259687936', + code: '430103002005', + parentCode: '430103002', + levelType: 5, + name: '坡子街社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '坡子街社区', + parentPath: '430000,430100,430103,430103002,430103002005', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241284853760', + code: '430103002006', + parentCode: '430103002', + levelType: 5, + name: '青山祠社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '青山祠社区', + parentPath: '430000,430100,430103,430103002,430103002006', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241310019584', + code: '430103002007', + parentCode: '430103002', + levelType: 5, + name: '沙河社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '沙河社区', + parentPath: '430000,430100,430103,430103002,430103002007', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241381322752', + code: '430103002008', + parentCode: '430103002', + levelType: 5, + name: '碧湘社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '碧湘社区', + parentPath: '430000,430100,430103,430103002,430103002008', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241410682880', + code: '430103002009', + parentCode: '430103002', + levelType: 5, + name: '创远社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '创远社区', + parentPath: '430000,430100,430103,430103002,430103002009', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241431654400', + code: '430103002010', + parentCode: '430103002', + levelType: 5, + name: '楚湘社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '楚湘社区', + parentPath: '430000,430100,430103,430103002,430103002010', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241465208832', + code: '430103002011', + parentCode: '430103002', + levelType: 5, + name: '西湖社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '西湖社区', + parentPath: '430000,430100,430103,430103002,430103002011', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241502957568', + code: '430103002012', + parentCode: '430103002', + levelType: 5, + name: '登仁桥社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '登仁桥社区', + parentPath: '430000,430100,430103,430103002,430103002012', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, + { + id: '530840241553289216', + code: '430103002013', + parentCode: '430103002', + levelType: 5, + name: '文庙坪社区', + province: '湖南省', + city: '长沙市', + district: '天心区', + town: '坡子街街道', + village: '文庙坪社区', + parentPath: '430000,430100,430103,430103002,430103002013', + createTime: '2020-11-30 15:47:31', + updateTime: '2020-11-30 17:30:41', + customized: false, + usable: true, + }, +]; +export default [ + { + url: '/basic-api/cascader/getAreaRecord', + timeout: 1000, + method: 'post', + response: ({ body }) => { + const { parentCode } = body || {}; + if (!parentCode) { + return resultSuccess(areaList.filter((it) => it.code === '430000')); + } + return resultSuccess(areaList.filter((it) => it.parentCode === parentCode)); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/demo/select-demo.ts b/frontend/vben/mock/demo/select-demo.ts new file mode 100644 index 0000000..631c6bb --- /dev/null +++ b/frontend/vben/mock/demo/select-demo.ts @@ -0,0 +1,28 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultSuccess } from '../_util'; + +const demoList = (keyword, count = 20) => { + const result = { + list: [] as any[], + }; + for (let index = 0; index < count; index++) { + result.list.push({ + name: `${keyword ?? ''}选项${index}`, + id: `${index}`, + }); + } + return result; +}; + +export default [ + { + url: '/basic-api/select/getDemoOptions', + timeout: 1000, + method: 'get', + response: ({ query }) => { + const { keyword, count } = query; + console.log(keyword); + return resultSuccess(demoList(keyword, count)); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/demo/system.ts b/frontend/vben/mock/demo/system.ts new file mode 100644 index 0000000..c417727 --- /dev/null +++ b/frontend/vben/mock/demo/system.ts @@ -0,0 +1,202 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultError, resultPageSuccess, resultSuccess } from '../_util'; + +const accountList = (() => { + const result: any[] = []; + for (let index = 0; index < 20; index++) { + result.push({ + id: `${index}`, + account: '@first', + email: '@email', + nickname: '@cname()', + role: '@first', + createTime: '@datetime', + remark: '@cword(10,20)', + 'status|1': ['0', '1'], + }); + } + return result; +})(); + +const roleList = (() => { + const result: any[] = []; + for (let index = 0; index < 4; index++) { + result.push({ + id: index + 1, + orderNo: `${index + 1}`, + roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index], + roleValue: '@first', + createTime: '@datetime', + remark: '@cword(10,20)', + menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index], + 'status|1': ['0', '1'], + }); + } + return result; +})(); + +const deptList = (() => { + const result: any[] = []; + for (let index = 0; index < 3; index++) { + result.push({ + id: `${index}`, + deptName: ['华东分部', '华南分部', '西北分部'][index], + orderNo: index + 1, + createTime: '@datetime', + remark: '@cword(10,20)', + 'status|1': ['0', '0', '1'], + children: (() => { + const children: any[] = []; + for (let j = 0; j < 4; j++) { + children.push({ + id: `${index}-${j}`, + deptName: ['研发部', '市场部', '商务部', '财务部'][j], + orderNo: j + 1, + createTime: '@datetime', + remark: '@cword(10,20)', + 'status|1': ['0', '1'], + parentDept: `${index}`, + children: undefined, + }); + } + return children; + })(), + }); + } + return result; +})(); + +const menuList = (() => { + const result: any[] = []; + for (let index = 0; index < 3; index++) { + result.push({ + id: `${index}`, + icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index], + component: 'LAYOUT', + type: '0', + menuName: ['Dashboard', '权限管理', '功能'][index], + permission: '', + orderNo: index + 1, + createTime: '@datetime', + 'status|1': ['0', '0', '1'], + children: (() => { + const children: any[] = []; + for (let j = 0; j < 4; j++) { + children.push({ + id: `${index}-${j}`, + type: '1', + menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j], + icon: 'ion:document', + permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index], + component: [ + '/dashboard/welcome/index', + '/dashboard/analysis/index', + '/dashboard/workbench/index', + '/dashboard/test/index', + ][j], + orderNo: j + 1, + createTime: '@datetime', + 'status|1': ['0', '1'], + parentMenu: `${index}`, + children: (() => { + const children: any[] = []; + for (let k = 0; k < 4; k++) { + children.push({ + id: `${index}-${j}-${k}`, + type: '2', + menuName: '按钮' + (j + 1) + '-' + (k + 1), + icon: '', + permission: + ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] + + ':btn' + + (k + 1), + component: [ + '/dashboard/welcome/index', + '/dashboard/analysis/index', + '/dashboard/workbench/index', + '/dashboard/test/index', + ][j], + orderNo: j + 1, + createTime: '@datetime', + 'status|1': ['0', '1'], + parentMenu: `${index}-${j}`, + children: undefined, + }); + } + return children; + })(), + }); + } + return children; + })(), + }); + } + return result; +})(); + +export default [ + { + url: '/basic-api/system/getAccountList', + timeout: 100, + method: 'get', + response: ({ query }) => { + const { page = 1, pageSize = 20 } = query; + return resultPageSuccess(page, pageSize, accountList); + }, + }, + { + url: '/basic-api/system/getRoleListByPage', + timeout: 100, + method: 'get', + response: ({ query }) => { + const { page = 1, pageSize = 20 } = query; + return resultPageSuccess(page, pageSize, roleList); + }, + }, + { + url: '/basic-api/system/setRoleStatus', + timeout: 500, + method: 'post', + response: ({ query }) => { + const { id, status } = query; + return resultSuccess({ id, status }); + }, + }, + { + url: '/basic-api/system/getAllRoleList', + timeout: 100, + method: 'get', + response: () => { + return resultSuccess(roleList); + }, + }, + { + url: '/basic-api/system/getDeptList', + timeout: 100, + method: 'get', + response: () => { + return resultSuccess(deptList); + }, + }, + { + url: '/basic-api/system/getMenuList', + timeout: 100, + method: 'get', + response: () => { + return resultSuccess(menuList); + }, + }, + { + url: '/basic-api/system/accountExist', + timeout: 500, + method: 'post', + response: ({ body }) => { + const { account } = body || {}; + if (account && account.indexOf('admin') !== -1) { + return resultError('该字段不能包含admin'); + } else { + return resultSuccess(`${account} can use`); + } + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/demo/table-demo.ts b/frontend/vben/mock/demo/table-demo.ts new file mode 100644 index 0000000..f3a0f16 --- /dev/null +++ b/frontend/vben/mock/demo/table-demo.ts @@ -0,0 +1,52 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { Random } from 'mockjs'; +import { resultPageSuccess } from '../_util'; + +function getRandomPics(count = 10): string[] { + const arr: string[] = []; + for (let i = 0; i < count; i++) { + arr.push(Random.image('800x600', Random.color(), Random.color(), Random.title())); + } + return arr; +} + +const demoList = (() => { + const result: any[] = []; + for (let index = 0; index < 200; index++) { + result.push({ + id: `${index}`, + beginTime: '@datetime', + endTime: '@datetime', + address: '@city()', + name: '@cname()', + name1: '@cname()', + name2: '@cname()', + name3: '@cname()', + name4: '@cname()', + name5: '@cname()', + name6: '@cname()', + name7: '@cname()', + name8: '@cname()', + avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()), + imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1), + imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1), + date: `@date('yyyy-MM-dd')`, + time: `@time('HH:mm')`, + 'no|100000-10000000': 100000, + 'status|1': ['normal', 'enable', 'disable'], + }); + } + return result; +})(); + +export default [ + { + url: '/basic-api/table/getDemoList', + timeout: 100, + method: 'get', + response: ({ query }) => { + const { page = 1, pageSize = 20 } = query; + return resultPageSuccess(page, pageSize, demoList); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/demo/tree-demo.ts b/frontend/vben/mock/demo/tree-demo.ts new file mode 100644 index 0000000..6fdcb85 --- /dev/null +++ b/frontend/vben/mock/demo/tree-demo.ts @@ -0,0 +1,38 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultSuccess } from '../_util'; + +const demoTreeList = (keyword) => { + const result = { + list: [] as Recordable[], + }; + for (let index = 0; index < 5; index++) { + const children: Recordable[] = []; + for (let j = 0; j < 3; j++) { + children.push({ + title: `${keyword ?? ''}选项${index}-${j}`, + value: `${index}-${j}`, + key: `${index}-${j}`, + }); + } + result.list.push({ + title: `${keyword ?? ''}选项${index}`, + value: `${index}`, + key: `${index}`, + children, + }); + } + return result; +}; + +export default [ + { + url: '/basic-api/tree/getDemoOptions', + timeout: 1000, + method: 'get', + response: ({ query }) => { + const { keyword } = query; + console.log(keyword); + return resultSuccess(demoTreeList(keyword)); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/mock/sys/menu.ts b/frontend/vben/mock/sys/menu.ts new file mode 100644 index 0000000..1df2a22 --- /dev/null +++ b/frontend/vben/mock/sys/menu.ts @@ -0,0 +1,260 @@ +import { resultSuccess, resultError, getRequestToken, requestParams } from '../_util' +import { MockMethod } from 'vite-plugin-mock' +import { createFakeUserList } from './user' + +// single +const dashboardRoute = { + path: '/dashboard', + name: 'Dashboard', + component: 'LAYOUT', + redirect: '/dashboard/analysis', + meta: { + title: 'routes.dashboard.dashboard', + hideChildrenInMenu: true, + icon: 'bx:bx-home', + }, + children: [ + { + path: 'analysis', + name: 'Analysis', + component: '/dashboard/analysis/index', + meta: { + hideMenu: true, + hideBreadcrumb: true, + title: 'routes.dashboard.analysis', + currentActiveMenu: '/dashboard', + icon: 'bx:bx-home', + }, + }, + { + path: 'workbench', + name: 'Workbench', + component: '/dashboard/workbench/index', + meta: { + hideMenu: true, + hideBreadcrumb: true, + title: 'routes.dashboard.workbench', + currentActiveMenu: '/dashboard', + icon: 'bx:bx-home', + }, + }, + ], +} + +const backRoute = { + path: 'back', + name: 'PermissionBackDemo', + meta: { + title: 'routes.demo.permission.back', + }, + + children: [ + { + path: 'page', + name: 'BackAuthPage', + component: '/demo/permission/back/index', + meta: { + title: 'routes.demo.permission.backPage', + }, + }, + { + path: 'btn', + name: 'BackAuthBtn', + component: '/demo/permission/back/Btn', + meta: { + title: 'routes.demo.permission.backBtn', + }, + }, + ], +} + +const authRoute = { + path: '/permission', + name: 'Permission', + component: 'LAYOUT', + redirect: '/permission/front/page', + meta: { + icon: 'carbon:user-role', + title: 'routes.demo.permission.permission', + }, + children: [backRoute], +} + +const levelRoute = { + path: '/level', + name: 'Level', + component: 'LAYOUT', + redirect: '/level/menu1/menu1-1', + meta: { + icon: 'carbon:user-role', + title: 'routes.demo.level.level', + }, + + children: [ + { + path: 'menu1', + name: 'Menu1Demo', + meta: { + title: 'Menu1', + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11Demo', + meta: { + title: 'Menu1-1', + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111Demo', + component: '/demo/level/Menu111', + meta: { + title: 'Menu111', + }, + }, + ], + }, + { + path: 'menu1-2', + name: 'Menu12Demo', + component: '/demo/level/Menu12', + meta: { + title: 'Menu1-2', + }, + }, + ], + }, + { + path: 'menu2', + name: 'Menu2Demo', + component: '/demo/level/Menu2', + meta: { + title: 'Menu2', + }, + }, + ], +} + +const sysRoute = { + path: '/system', + name: 'System', + component: 'LAYOUT', + redirect: '/system/account', + meta: { + icon: 'ion:settings-outline', + title: 'routes.demo.system.moduleName', + }, + children: [ + { + path: 'account', + name: 'AccountManagement', + meta: { + title: 'routes.demo.system.account', + ignoreKeepAlive: true, + }, + component: '/demo/system/account/index', + }, + { + path: 'account_detail/:id', + name: 'AccountDetail', + meta: { + hideMenu: true, + title: 'routes.demo.system.account_detail', + ignoreKeepAlive: true, + showMenu: false, + currentActiveMenu: '/system/account', + }, + component: '/demo/system/account/AccountDetail', + }, + { + path: 'role', + name: 'RoleManagement', + meta: { + title: 'routes.demo.system.role', + ignoreKeepAlive: true, + }, + component: '/demo/system/role/index', + }, + { + path: 'dept', + name: 'DeptManagement', + meta: { + title: 'routes.demo.system.dept', + ignoreKeepAlive: true, + }, + component: '/demo/system/dept/index', + }, + { + path: 'changePassword', + name: 'ChangePassword', + meta: { + title: 'routes.demo.system.password', + ignoreKeepAlive: true, + }, + component: '/demo/system/password/index', + }, + ], +} + +const linkRoute = { + path: '/link', + name: 'Link', + component: 'LAYOUT', + meta: { + icon: 'ion:tv-outline', + title: 'routes.demo.iframe.frame', + }, + children: [ + { + path: 'doc', + name: 'Doc', + meta: { + title: 'routes.demo.iframe.doc', + frameSrc: 'https://vvbin.cn/doc-next/', + }, + }, + { + path: 'https://vvbin.cn/doc-next/', + name: 'DocExternal', + component: 'LAYOUT', + meta: { + title: 'routes.demo.iframe.docExternal', + }, + }, + ], +} + +export default [ + { + url: '/basic-api/getMenuList', + timeout: 1000, + method: 'get', + response: (request: requestParams) => { + const token = getRequestToken(request) + if (!token) { + return resultError('Invalid token!') + } + const checkUser = createFakeUserList().find((item) => item.token === token) + if (!checkUser) { + return resultError('Invalid user token!') + } + const id = checkUser.userId + let menu: Object[] + switch (id) { + case '1': + dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[0].path + menu = [dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute] + break + case '2': + dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[1].path + menu = [dashboardRoute, authRoute, levelRoute, linkRoute] + break + default: + menu = [] + } + + return resultSuccess(menu) + }, + }, +] as MockMethod[] diff --git a/frontend/vben/mock/sys/user.ts b/frontend/vben/mock/sys/user.ts new file mode 100644 index 0000000..5b569d4 --- /dev/null +++ b/frontend/vben/mock/sys/user.ts @@ -0,0 +1,122 @@ +import { MockMethod } from 'vite-plugin-mock'; +import { resultError, resultSuccess, getRequestToken, requestParams } from '../_util'; + +export function createFakeUserList() { + return [ + { + userId: '1', + username: 'vben', + realName: 'Vben Admin', + avatar: 'https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640', + desc: 'manager', + password: '123456', + token: 'fakeToken1', + homePath: '/dashboard/analysis', + roles: [ + { + roleName: 'Super Admin', + value: 'super', + }, + ], + }, + { + userId: '2', + username: 'test', + password: '123456', + realName: 'test user', + avatar: 'https://q1.qlogo.cn/g?b=qq&nk=339449197&s=640', + desc: 'tester', + token: 'fakeToken2', + homePath: '/dashboard/workbench', + roles: [ + { + roleName: 'Tester', + value: 'test', + }, + ], + }, + ]; +} + +const fakeCodeList: any = { + '1': ['1000', '3000', '5000'], + + '2': ['2000', '4000', '6000'], +}; +export default [ + // mock user login + { + url: '/basic-api/login', + timeout: 200, + method: 'post', + response: ({ body }) => { + const { username, password } = body; + const checkUser = createFakeUserList().find( + (item) => item.username === username && password === item.password, + ); + if (!checkUser) { + return resultError('Incorrect account or password!'); + } + const { userId, username: _username, token, realName, desc, roles } = checkUser; + return resultSuccess({ + roles, + userId, + username: _username, + token, + realName, + desc, + }); + }, + }, + { + url: '/basic-api/getUserInfo', + method: 'get', + response: (request: requestParams) => { + const token = getRequestToken(request); + if (!token) return resultError('Invalid token'); + const checkUser = createFakeUserList().find((item) => item.token === token); + if (!checkUser) { + return resultError('The corresponding user information was not obtained!'); + } + return resultSuccess(checkUser); + }, + }, + { + url: '/basic-api/getPermCode', + timeout: 200, + method: 'get', + response: (request: requestParams) => { + const token = getRequestToken(request); + if (!token) return resultError('Invalid token'); + const checkUser = createFakeUserList().find((item) => item.token === token); + if (!checkUser) { + return resultError('Invalid token!'); + } + const codeList = fakeCodeList[checkUser.userId]; + + return resultSuccess(codeList); + }, + }, + { + url: '/basic-api/logout', + timeout: 200, + method: 'get', + response: (request: requestParams) => { + const token = getRequestToken(request); + if (!token) return resultError('Invalid token'); + const checkUser = createFakeUserList().find((item) => item.token === token); + if (!checkUser) { + return resultError('Invalid token!'); + } + return resultSuccess(undefined, { message: 'Token has been destroyed' }); + }, + }, + { + url: '/basic-api/testRetry', + statusCode: 405, + method: 'get', + response: () => { + return resultError('Error!'); + }, + }, +] as MockMethod[]; diff --git a/frontend/vben/package.json b/frontend/vben/package.json new file mode 100644 index 0000000..8fcf5fb --- /dev/null +++ b/frontend/vben/package.json @@ -0,0 +1,191 @@ +{ + "name": "vben-admin", + "version": "2.8.0", + "author": { + "name": "vben", + "email": "anncwb@126.com", + "url": "https://github.com/anncwb" + }, + "scripts": { + "commit": "czg", + "bootstrap": "pnpm install", + "serve": "npm run dev", + "dev": "vite", + "build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts", + "build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts", + "build:no-cache": "pnpm clean:cache && npm run build", + "report": "cross-env REPORT=true npm run build", + "type:check": "vue-tsc --noEmit --skipLibCheck", + "preview": "npm run build && vite preview", + "preview:dist": "vite preview", + "log": "conventional-changelog -p angular -i CHANGELOG.md -s", + "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite", + "clean:lib": "rimraf node_modules", + "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", + "lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", + "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", + "lint:lint-staged": "lint-staged", + "test:unit": "jest", + "test:gzip": "npx http-server dist --cors --gzip -c-1", + "test:br": "npx http-server dist --cors --brotli -c-1", + "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", + "prepare": "husky install", + "gen:icon": "esno ./build/generate/icon/index.ts" + }, + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-vue": "^6.1.0", + "@iconify/iconify": "^2.2.1", + "@logicflow/core": "^1.1.13", + "@logicflow/extension": "^1.1.13", + "@vue/runtime-core": "^3.2.33", + "@vue/shared": "^3.2.33", + "@vueuse/core": "^8.3.0", + "@vueuse/shared": "^8.3.0", + "@zxcvbn-ts/core": "^2.0.1", + "ant-design-vue": "^3.2.0", + "axios": "^0.26.1", + "codemirror": "^5.65.3", + "cropperjs": "^1.5.12", + "crypto-js": "^4.1.1", + "dayjs": "^1.11.1", + "echarts": "^5.3.2", + "intro.js": "^5.1.0", + "lodash-es": "^4.17.21", + "mockjs": "^1.1.0", + "nprogress": "^0.2.0", + "path-to-regexp": "^6.2.0", + "pinia": "2.0.12", + "qs": "^6.10.3", + "resize-observer-polyfill": "^1.5.1", + "showdown": "^2.1.0", + "sortablejs": "^1.15.0", + "tinymce": "^5.10.3", + "vditor": "^3.8.13", + "vue": "^3.2.33", + "vue-i18n": "^9.1.9", + "vue-json-pretty": "^2.0.6", + "vue-router": "^4.0.14", + "vue-types": "^4.1.1", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@commitlint/cli": "^16.2.3", + "@commitlint/config-conventional": "^16.2.1", + "@iconify/json": "^2.1.30", + "@purge-icons/generated": "^0.8.1", + "@types/codemirror": "^5.60.5", + "@types/crypto-js": "^4.1.1", + "@types/fs-extra": "^9.0.13", + "@types/inquirer": "^8.2.1", + "@types/intro.js": "^3.0.2", + "@types/lodash-es": "^4.17.6", + "@types/mockjs": "^1.0.6", + "@types/node": "^17.0.25", + "@types/nprogress": "^0.2.0", + "@types/qs": "^6.9.7", + "@types/showdown": "^1.9.4", + "@types/sortablejs": "^1.10.7", + "@typescript-eslint/eslint-plugin": "^5.20.0", + "@typescript-eslint/parser": "^5.20.0", + "@vitejs/plugin-legacy": "^1.8.1", + "@vitejs/plugin-vue": "^2.3.1", + "@vitejs/plugin-vue-jsx": "^1.3.10", + "@vue/compiler-sfc": "^3.2.33", + "@vue/test-utils": "^2.0.0-rc.21", + "autoprefixer": "^10.4.4", + "conventional-changelog-cli": "^2.2.2", + "cross-env": "^7.0.3", + "cz-git": "^1.3.11", + "czg": "^1.3.11", + "dotenv": "^16.0.0", + "eslint": "^8.13.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-vue": "^8.6.0", + "esno": "^0.14.1", + "fs-extra": "^10.1.0", + "husky": "^7.0.4", + "inquirer": "^8.2.2", + "less": "^4.1.2", + "lint-staged": "12.3.7", + "npm-run-all": "^4.1.5", + "picocolors": "^1.0.0", + "postcss": "^8.4.12", + "postcss-html": "^1.4.1", + "postcss-less": "^6.0.0", + "prettier": "^2.6.2", + "rimraf": "^3.0.2", + "rollup": "^2.70.2", + "rollup-plugin-visualizer": "^5.6.0", + "stylelint": "^14.7.1", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-recommended": "^7.0.0", + "stylelint-config-recommended-vue": "^1.4.0", + "stylelint-config-standard": "^25.0.0", + "stylelint-order": "^5.0.0", + "ts-node": "^10.7.0", + "typescript": "^4.6.3", + "vite": "^2.9.5", + "vite-plugin-compression": "^0.5.1", + "vite-plugin-html": "^3.2.0", + "vite-plugin-imagemin": "^0.6.1", + "vite-plugin-mkcert": "^1.6.0", + "vite-plugin-mock": "^2.9.6", + "vite-plugin-purge-icons": "^0.8.1", + "vite-plugin-pwa": "^0.11.13", + "vite-plugin-style-import": "^2.0.0", + "vite-plugin-svg-icons": "^2.0.1", + "vite-plugin-theme": "^0.8.6", + "vite-plugin-vue-setup-extend": "^0.4.0", + "vite-plugin-windicss": "^1.8.4", + "vue-eslint-parser": "^8.3.0", + "vue-tsc": "^0.33.9" + }, + "resolutions": { + "bin-wrapper": "npm:bin-wrapper-china", + "rollup": "^2.56.3", + "gifsicle": "5.2.0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/anncwb/vue-vben-admin.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/anncwb/vue-vben-admin/issues" + }, + "homepage": "https://github.com/anncwb/vue-vben-admin", + "engines": { + "node": "^12 || >=14" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "eslint --fix", + "prettier --write" + ], + "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [ + "prettier --write--parser json" + ], + "package.json": [ + "prettier --write" + ], + "*.vue": [ + "eslint --fix", + "prettier --write", + "stylelint --fix" + ], + "*.{scss,less,styl,html}": [ + "stylelint --fix", + "prettier --write" + ], + "*.md": [ + "prettier --write" + ] + }, + "config": { + "commitizen": { + "path": "node_modules/cz-git" + } + } +} diff --git a/frontend/vben/postcss.config.js b/frontend/vben/postcss.config.js new file mode 100755 index 0000000..a47ef4f --- /dev/null +++ b/frontend/vben/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: { + autoprefixer: {}, + }, +}; diff --git a/frontend/vben/prettier.config.js b/frontend/vben/prettier.config.js new file mode 100644 index 0000000..a5bfe16 --- /dev/null +++ b/frontend/vben/prettier.config.js @@ -0,0 +1,10 @@ +module.exports = { + printWidth: 100, + semi: false, + vueIndentScriptAndStyle: true, + singleQuote: true, + trailingComma: 'all', + proseWrap: 'never', + htmlWhitespaceSensitivity: 'strict', + endOfLine: 'auto', +} diff --git a/frontend/vben/public/favicon.ico b/frontend/vben/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d92e0b8c4963f1ae81021bbed63e94c2699dea66 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?x!2k(<*|Mp73(S^ghaCG}W3micV zd6}gJRR66~2Cn|nK^;8mfr=prt{%vMt3Q887jFKoe=I;N;Of6uAgs8$R~xS7)?Ze* z7G(86jaaP!YD8B5HAMw(#m^dPxRwit(0u_9G`M>FR>0MN^(+15GZl&w=KiVL1wn6T z6kkZ}DT8x=g_XnA|4v>HSO33$3S12u1Fjy#fSC_upeciM zfBAL8wfs)p0oU^X|9`j|GzMHfvK44*kh#ACs}Nd}*5GjrTo*z;*cWhd@)!pg85kNs n7^oeNfqano0bpKwAP>a+3=AJYn4N*)2ax^&6#E0jpkM$1?7KMX literal 0 HcmV?d00001 diff --git a/frontend/vben/public/resource/img/logo.png b/frontend/vben/public/resource/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4c33d8b71f31d32aaed9fefe14f237b81e764f GIT binary patch literal 4042 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 literal 0 HcmV?d00001 diff --git a/frontend/vben/public/resource/img/pwa-192x192.png b/frontend/vben/public/resource/img/pwa-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..00fb815215e1fcb171d1c62fca6c54018663cb72 GIT binary patch literal 12205 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 s+6jerali:not(.tox-checklist--hidden){list-style:none;margin:.25em 0}.tox-checklist>li:not(.tox-checklist--hidden)::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");cursor:pointer;height:1em;margin-left:-1.5em;margin-top:.125em;position:absolute;width:1em}.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A")}[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-left:0;margin-right:-1.5em}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.mce-content-body{overflow-wrap:break-word;word-wrap:break-word}.mce-content-body .mce-visual-caret{background-color:#000;background-color:currentColor;position:absolute}.mce-content-body .mce-visual-caret-hidden{display:none}.mce-content-body [data-mce-caret]{left:-1000px;margin:0;padding:0;position:absolute;right:auto;top:0}.mce-content-body .mce-offscreen-selection{left:-2000000px;max-width:1000000px;position:absolute}.mce-content-body [contentEditable=false]{cursor:default}.mce-content-body [contentEditable=true]{cursor:text}.tox-cursor-format-painter{cursor:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default}.mce-content-body figure.align-left{float:left}.mce-content-body figure.align-right{float:right}.mce-content-body figure.image.align-center{display:table;margin-left:auto;margin-right:auto}.mce-preview-object{border:1px solid gray;display:inline-block;line-height:0;margin:0 2px 0 2px;position:relative}.mce-preview-object .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-object{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border:1px dashed #aaa}.mce-pagebreak{border:1px dashed #aaa;cursor:default;display:block;height:5px;margin-top:15px;page-break-before:always;width:100%}@media print{.mce-pagebreak{border:0}}.tiny-pageembed .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.tiny-pageembed[data-mce-selected="2"] .mce-shim{display:none}.tiny-pageembed{display:inline-block;position:relative}.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{display:block;overflow:hidden;padding:0;position:relative;width:100%}.tiny-pageembed--21by9{padding-top:42.857143%}.tiny-pageembed--16by9{padding-top:56.25%}.tiny-pageembed--4by3{padding-top:75%}.tiny-pageembed--1by1{padding-top:100%}.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{border:0;height:100%;left:0;position:absolute;top:0;width:100%}.mce-content-body[data-mce-placeholder]{position:relative}.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before{color:rgba(34,47,62,.7);content:attr(data-mce-placeholder);position:absolute}.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before{left:1px}.mce-content-body[dir=rtl][data-mce-placeholder]:not(.mce-visualblocks)::before{right:1px}.mce-content-body div.mce-resizehandle{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;height:10px;position:absolute;width:10px;z-index:1298}.mce-content-body div.mce-resizehandle:hover{background-color:#4099ff}.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor:nesw-resize}.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor:nesw-resize}.mce-content-body .mce-resize-backdrop{z-index:10000}.mce-content-body .mce-clonedresizable{cursor:default;opacity:.5;outline:1px dashed #000;position:absolute;z-index:10001}.mce-content-body .mce-clonedresizable.mce-resizetable-columns td,.mce-content-body .mce-clonedresizable.mce-resizetable-columns th{border:0}.mce-content-body .mce-resize-helper{background:#555;background:rgba(0,0,0,.75);border:1px;border-radius:3px;color:#fff;display:none;font-family:sans-serif;font-size:12px;line-height:14px;margin:5px 10px;padding:5px;position:absolute;white-space:nowrap;z-index:10002}.tox-rtc-user-selection{position:relative}.tox-rtc-user-cursor{bottom:0;cursor:default;position:absolute;top:0;width:2px}.tox-rtc-user-cursor::before{background-color:inherit;border-radius:50%;content:'';display:block;height:8px;position:absolute;right:-3px;top:-3px;width:8px}.tox-rtc-user-cursor:hover::after{background-color:inherit;border-radius:100px;box-sizing:border-box;color:#fff;content:attr(data-user);display:block;font-size:12px;font-weight:700;left:-5px;min-height:8px;min-width:8px;padding:0 12px;position:absolute;top:-11px;white-space:nowrap;z-index:1000}.tox-rtc-user-selection--1 .tox-rtc-user-cursor{background-color:#2dc26b}.tox-rtc-user-selection--2 .tox-rtc-user-cursor{background-color:#e03e2d}.tox-rtc-user-selection--3 .tox-rtc-user-cursor{background-color:#f1c40f}.tox-rtc-user-selection--4 .tox-rtc-user-cursor{background-color:#3598db}.tox-rtc-user-selection--5 .tox-rtc-user-cursor{background-color:#b96ad9}.tox-rtc-user-selection--6 .tox-rtc-user-cursor{background-color:#e67e23}.tox-rtc-user-selection--7 .tox-rtc-user-cursor{background-color:#aaa69d}.tox-rtc-user-selection--8 .tox-rtc-user-cursor{background-color:#f368e0}.tox-rtc-remote-image{background:#eaeaea url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A") no-repeat center center;border:1px solid #ccc;min-height:240px;min-width:320px}.mce-match-marker{background:#aaa;color:#fff}.mce-match-marker-selected{background:#39f;color:#fff}.mce-match-marker-selected::-moz-selection{background:#39f;color:#fff}.mce-match-marker-selected::selection{background:#39f;color:#fff}.mce-content-body audio[data-mce-selected],.mce-content-body embed[data-mce-selected],.mce-content-body img[data-mce-selected],.mce-content-body object[data-mce-selected],.mce-content-body table[data-mce-selected],.mce-content-body video[data-mce-selected]{outline:3px solid #b4d7ff}.mce-content-body hr[data-mce-selected]{outline:3px solid #b4d7ff;outline-offset:1px}.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false][data-mce-selected]{cursor:not-allowed;outline:3px solid #b4d7ff}.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline:0}.mce-content-body [data-mce-selected=inline-boundary]{background-color:#b4d7ff}.mce-content-body .mce-edit-focus{outline:3px solid #b4d7ff}.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{position:relative}.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background:0 0}.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background:0 0}.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{outline:0;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{background-color:rgba(180,215,255,.7);border:1px solid rgba(180,215,255,.7);bottom:-1px;content:'';left:-1px;mix-blend-mode:multiply;position:absolute;right:-1px;top:-1px}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{border-color:rgba(0,84,180,.7)}}.mce-content-body img::-moz-selection{background:0 0}.mce-content-body img::selection{background:0 0}.ephox-snooker-resizer-bar{background-color:#b4d7ff;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:1}.mce-spellchecker-word{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.75'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default;height:2rem}.mce-spellchecker-grammar{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%2300A835'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width: 0px"],table[style*="border-width: 0px"] caption,table[style*="border-width: 0px"] td,table[style*="border-width: 0px"] th{border:1px dashed #bbb}.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{background-repeat:no-repeat;border:1px dashed #bbb;margin-left:3px;padding-top:10px}.mce-visualblocks p{background-image:url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7)}.mce-visualblocks h1{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==)}.mce-visualblocks h2{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==)}.mce-visualblocks h3{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7)}.mce-visualblocks h4{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==)}.mce-visualblocks h5{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==)}.mce-visualblocks h6{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==)}.mce-visualblocks div:not([data-mce-bogus]){background-image:url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7)}.mce-visualblocks section{background-image:url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=)}.mce-visualblocks article{background-image:url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7)}.mce-visualblocks blockquote{background-image:url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7)}.mce-visualblocks address{background-image:url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=)}.mce-visualblocks pre{background-image:url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==)}.mce-visualblocks figure{background-image:url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7)}.mce-visualblocks figcaption{border:1px dashed #bbb}.mce-visualblocks hgroup{background-image:url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7)}.mce-visualblocks aside{background-image:url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=)}.mce-visualblocks ul{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==)}.mce-visualblocks ol{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==)}.mce-visualblocks dl{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==)}.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left:3px}.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x:right;margin-right:3px}.mce-nbsp,.mce-shy{background:#aaa}.mce-shy::after{content:'-'} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.min.css new file mode 100644 index 0000000..e27b8a0 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%20fill%3D%22%23cccccc%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;cursor:default;display:inline-block;height:12px!important;padding:0 2px;-webkit-user-modify:read-only;-moz-user-modify:read-only;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all;width:8px!important}.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset:1px}.tox-comments-visible .tox-comment{background-color:#fff0b7}.tox-comments-visible .tox-comment--active{background-color:#ffe168}.tox-checklist>li:not(.tox-checklist--hidden){list-style:none;margin:.25em 0}.tox-checklist>li:not(.tox-checklist--hidden)::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%236d737b%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");cursor:pointer;height:1em;margin-left:-1.5em;margin-top:.125em;position:absolute;width:1em}.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A")}[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-left:0;margin-right:-1.5em}code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#282a36}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#6272a4}.token.punctuation{color:#f8f8f2}.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#ff79c6}.token.boolean,.token.number{color:#bd93f9}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#50fa7b}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#f1fa8c}.token.keyword{color:#8be9fd}.token.important,.token.regex{color:#ffb86c}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.mce-content-body{overflow-wrap:break-word;word-wrap:break-word}.mce-content-body .mce-visual-caret{background-color:#000;background-color:currentColor;position:absolute}.mce-content-body .mce-visual-caret-hidden{display:none}.mce-content-body [data-mce-caret]{left:-1000px;margin:0;padding:0;position:absolute;right:auto;top:0}.mce-content-body .mce-offscreen-selection{left:-2000000px;max-width:1000000px;position:absolute}.mce-content-body [contentEditable=false]{cursor:default}.mce-content-body [contentEditable=true]{cursor:text}.tox-cursor-format-painter{cursor:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default}.mce-content-body figure.align-left{float:left}.mce-content-body figure.align-right{float:right}.mce-content-body figure.image.align-center{display:table;margin-left:auto;margin-right:auto}.mce-preview-object{border:1px solid gray;display:inline-block;line-height:0;margin:0 2px 0 2px;position:relative}.mce-preview-object .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-object{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%20fill%3D%22%23cccccc%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border:1px dashed #aaa}.mce-pagebreak{border:1px dashed #aaa;cursor:default;display:block;height:5px;margin-top:15px;page-break-before:always;width:100%}@media print{.mce-pagebreak{border:0}}.tiny-pageembed .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.tiny-pageembed[data-mce-selected="2"] .mce-shim{display:none}.tiny-pageembed{display:inline-block;position:relative}.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{display:block;overflow:hidden;padding:0;position:relative;width:100%}.tiny-pageembed--21by9{padding-top:42.857143%}.tiny-pageembed--16by9{padding-top:56.25%}.tiny-pageembed--4by3{padding-top:75%}.tiny-pageembed--1by1{padding-top:100%}.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{border:0;height:100%;left:0;position:absolute;top:0;width:100%}.mce-content-body[data-mce-placeholder]{position:relative}.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before{color:rgba(34,47,62,.7);content:attr(data-mce-placeholder);position:absolute}.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before{left:1px}.mce-content-body[dir=rtl][data-mce-placeholder]:not(.mce-visualblocks)::before{right:1px}.mce-content-body div.mce-resizehandle{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;height:10px;position:absolute;width:10px;z-index:1298}.mce-content-body div.mce-resizehandle:hover{background-color:#4099ff}.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor:nesw-resize}.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor:nesw-resize}.mce-content-body .mce-resize-backdrop{z-index:10000}.mce-content-body .mce-clonedresizable{cursor:default;opacity:.5;outline:1px dashed #000;position:absolute;z-index:10001}.mce-content-body .mce-clonedresizable.mce-resizetable-columns td,.mce-content-body .mce-clonedresizable.mce-resizetable-columns th{border:0}.mce-content-body .mce-resize-helper{background:#555;background:rgba(0,0,0,.75);border:1px;border-radius:3px;color:#fff;display:none;font-family:sans-serif;font-size:12px;line-height:14px;margin:5px 10px;padding:5px;position:absolute;white-space:nowrap;z-index:10002}.tox-rtc-user-selection{position:relative}.tox-rtc-user-cursor{bottom:0;cursor:default;position:absolute;top:0;width:2px}.tox-rtc-user-cursor::before{background-color:inherit;border-radius:50%;content:'';display:block;height:8px;position:absolute;right:-3px;top:-3px;width:8px}.tox-rtc-user-cursor:hover::after{background-color:inherit;border-radius:100px;box-sizing:border-box;color:#fff;content:attr(data-user);display:block;font-size:12px;font-weight:700;left:-5px;min-height:8px;min-width:8px;padding:0 12px;position:absolute;top:-11px;white-space:nowrap;z-index:1000}.tox-rtc-user-selection--1 .tox-rtc-user-cursor{background-color:#2dc26b}.tox-rtc-user-selection--2 .tox-rtc-user-cursor{background-color:#e03e2d}.tox-rtc-user-selection--3 .tox-rtc-user-cursor{background-color:#f1c40f}.tox-rtc-user-selection--4 .tox-rtc-user-cursor{background-color:#3598db}.tox-rtc-user-selection--5 .tox-rtc-user-cursor{background-color:#b96ad9}.tox-rtc-user-selection--6 .tox-rtc-user-cursor{background-color:#e67e23}.tox-rtc-user-selection--7 .tox-rtc-user-cursor{background-color:#aaa69d}.tox-rtc-user-selection--8 .tox-rtc-user-cursor{background-color:#f368e0}.tox-rtc-remote-image{background:#eaeaea url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A") no-repeat center center;border:1px solid #ccc;min-height:240px;min-width:320px}.mce-match-marker{background:#aaa;color:#fff}.mce-match-marker-selected{background:#39f;color:#fff}.mce-match-marker-selected::-moz-selection{background:#39f;color:#fff}.mce-match-marker-selected::selection{background:#39f;color:#fff}.mce-content-body audio[data-mce-selected],.mce-content-body embed[data-mce-selected],.mce-content-body img[data-mce-selected],.mce-content-body object[data-mce-selected],.mce-content-body table[data-mce-selected],.mce-content-body video[data-mce-selected]{outline:3px solid #4099ff}.mce-content-body hr[data-mce-selected]{outline:3px solid #4099ff;outline-offset:1px}.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline:3px solid #4099ff}.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline:3px solid #4099ff}.mce-content-body [contentEditable=false][data-mce-selected]{cursor:not-allowed;outline:3px solid #4099ff}.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline:0}.mce-content-body [data-mce-selected=inline-boundary]{background-color:#4099ff}.mce-content-body .mce-edit-focus{outline:3px solid #4099ff}.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{position:relative}.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background:0 0}.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background:0 0}.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{outline:0;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{background-color:rgba(180,215,255,.7);border:1px solid transparent;bottom:-1px;content:'';left:-1px;mix-blend-mode:lighten;position:absolute;right:-1px;top:-1px}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{border-color:rgba(0,84,180,.7)}}.mce-content-body img::-moz-selection{background:0 0}.mce-content-body img::selection{background:0 0}.ephox-snooker-resizer-bar{background-color:#4099ff;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:1}.mce-spellchecker-word{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.75'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default;height:2rem}.mce-spellchecker-grammar{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%2300A835'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width: 0px"],table[style*="border-width: 0px"] caption,table[style*="border-width: 0px"] td,table[style*="border-width: 0px"] th{border:1px dashed #bbb}.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{background-repeat:no-repeat;border:1px dashed #bbb;margin-left:3px;padding-top:10px}.mce-visualblocks p{background-image:url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7)}.mce-visualblocks h1{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==)}.mce-visualblocks h2{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==)}.mce-visualblocks h3{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7)}.mce-visualblocks h4{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==)}.mce-visualblocks h5{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==)}.mce-visualblocks h6{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==)}.mce-visualblocks div:not([data-mce-bogus]){background-image:url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7)}.mce-visualblocks section{background-image:url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=)}.mce-visualblocks article{background-image:url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7)}.mce-visualblocks blockquote{background-image:url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7)}.mce-visualblocks address{background-image:url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=)}.mce-visualblocks pre{background-image:url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==)}.mce-visualblocks figure{background-image:url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7)}.mce-visualblocks figcaption{border:1px dashed #bbb}.mce-visualblocks hgroup{background-image:url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7)}.mce-visualblocks aside{background-image:url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=)}.mce-visualblocks ul{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==)}.mce-visualblocks ol{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==)}.mce-visualblocks dl{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==)}.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left:3px}.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x:right;margin-right:3px}.mce-nbsp,.mce-shy{background:#aaa}.mce-shy::after{content:'-'}body{font-family:sans-serif}table{border-collapse:collapse} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css new file mode 100644 index 0000000..35f7dc0 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css new file mode 100644 index 0000000..e71f6f0 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tox{box-shadow:none;box-sizing:content-box;color:#2a3746;cursor:auto;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:normal;-webkit-tap-highlight-color:transparent;text-decoration:none;text-shadow:none;text-transform:none;vertical-align:initial;white-space:normal}.tox :not(svg):not(rect){box-sizing:inherit;color:inherit;cursor:inherit;direction:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;line-height:inherit;-webkit-tap-highlight-color:inherit;text-align:inherit;text-decoration:inherit;text-shadow:inherit;text-transform:inherit;vertical-align:inherit;white-space:inherit}.tox :not(svg):not(rect){background:0 0;border:0;box-shadow:none;float:none;height:auto;margin:0;max-width:none;outline:0;padding:0;position:static;width:auto}.tox:not([dir=rtl]){direction:ltr;text-align:left}.tox[dir=rtl]{direction:rtl;text-align:right}.tox-tinymce{border:1px solid #000;border-radius:0;box-shadow:none;box-sizing:border-box;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;overflow:hidden;position:relative;visibility:inherit!important}.tox-tinymce-inline{border:none;box-shadow:none}.tox-tinymce-inline .tox-editor-header{background-color:transparent;border:1px solid #000;border-radius:0;box-shadow:none}.tox-tinymce-aux{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;z-index:1300}.tox-tinymce :focus,.tox-tinymce-aux :focus{outline:0}button::-moz-focus-inner{border:0}.tox[dir=rtl] .tox-icon--flip svg{transform:rotateY(180deg)}.tox .accessibility-issue__header{align-items:center;display:flex;margin-bottom:4px}.tox .accessibility-issue__description{align-items:stretch;border:1px solid #000;border-radius:3px;display:flex;justify-content:space-between}.tox .accessibility-issue__description>div{padding-bottom:4px}.tox .accessibility-issue__description>div>div{align-items:center;display:flex;margin-bottom:4px}.tox .accessibility-issue__description>:last-child:not(:only-child){border-color:#000;border-style:solid}.tox .accessibility-issue__repair{margin-top:16px}.tox .tox-dialog__body-content .accessibility-issue--info .accessibility-issue__description{background-color:rgba(32,122,183,.5);border-color:#207ab7;color:#fff}.tox .tox-dialog__body-content .accessibility-issue--info .accessibility-issue__description>:last-child{border-color:#207ab7}.tox .tox-dialog__body-content .accessibility-issue--info .tox-form__group h2{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--info .tox-icon svg{fill:#fff}.tox .tox-dialog__body-content .accessibility-issue--info a .tox-icon{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--warn .accessibility-issue__description{background-color:rgba(255,165,0,.5);border-color:rgba(255,165,0,.8);color:#fff}.tox .tox-dialog__body-content .accessibility-issue--warn .accessibility-issue__description>:last-child{border-color:rgba(255,165,0,.8)}.tox .tox-dialog__body-content .accessibility-issue--warn .tox-form__group h2{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--warn .tox-icon svg{fill:#fff}.tox .tox-dialog__body-content .accessibility-issue--warn a .tox-icon{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--error .accessibility-issue__description{background-color:rgba(204,0,0,.5);border-color:rgba(204,0,0,.8);color:#fff}.tox .tox-dialog__body-content .accessibility-issue--error .accessibility-issue__description>:last-child{border-color:rgba(204,0,0,.8)}.tox .tox-dialog__body-content .accessibility-issue--error .tox-form__group h2{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--error .tox-icon svg{fill:#fff}.tox .tox-dialog__body-content .accessibility-issue--error a .tox-icon{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--success .accessibility-issue__description{background-color:rgba(120,171,70,.5);border-color:rgba(120,171,70,.8);color:#fff}.tox .tox-dialog__body-content .accessibility-issue--success .accessibility-issue__description>:last-child{border-color:rgba(120,171,70,.8)}.tox .tox-dialog__body-content .accessibility-issue--success .tox-form__group h2{color:#fff}.tox .tox-dialog__body-content .accessibility-issue--success .tox-icon svg{fill:#fff}.tox .tox-dialog__body-content .accessibility-issue--success a .tox-icon{color:#fff}.tox .tox-dialog__body-content .accessibility-issue__header h1,.tox .tox-dialog__body-content .tox-form__group .accessibility-issue__description h2{margin-top:0}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__header .tox-button{margin-left:4px}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__header>:nth-last-child(2){margin-left:auto}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__description{padding:4px 4px 4px 8px}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__description>:last-child{border-left-width:1px;padding-left:4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__header .tox-button{margin-right:4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__header>:nth-last-child(2){margin-right:auto}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__description{padding:4px 8px 4px 4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__description>:last-child{border-right-width:1px;padding-right:4px}.tox .tox-anchorbar{display:flex;flex:0 0 auto}.tox .tox-bar{display:flex;flex:0 0 auto}.tox .tox-button{background-color:#207ab7;background-image:none;background-position:0 0;background-repeat:repeat;border-color:#207ab7;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#fff;cursor:pointer;display:inline-block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:14px;font-style:normal;font-weight:700;letter-spacing:normal;line-height:24px;margin:0;outline:0;padding:4px 16px;text-align:center;text-decoration:none;text-transform:none;white-space:nowrap}.tox .tox-button[disabled]{background-color:#207ab7;background-image:none;border-color:#207ab7;box-shadow:none;color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-button:focus:not(:disabled){background-color:#1c6ca1;background-image:none;border-color:#1c6ca1;box-shadow:none;color:#fff}.tox .tox-button:hover:not(:disabled){background-color:#1c6ca1;background-image:none;border-color:#1c6ca1;box-shadow:none;color:#fff}.tox .tox-button:active:not(:disabled){background-color:#185d8c;background-image:none;border-color:#185d8c;box-shadow:none;color:#fff}.tox .tox-button--secondary{background-color:#3d546f;background-image:none;background-position:0 0;background-repeat:repeat;border-color:#3d546f;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;color:#fff;font-size:14px;font-style:normal;font-weight:700;letter-spacing:normal;outline:0;padding:4px 16px;text-decoration:none;text-transform:none}.tox .tox-button--secondary[disabled]{background-color:#3d546f;background-image:none;border-color:#3d546f;box-shadow:none;color:rgba(255,255,255,.5)}.tox .tox-button--secondary:focus:not(:disabled){background-color:#34485f;background-image:none;border-color:#34485f;box-shadow:none;color:#fff}.tox .tox-button--secondary:hover:not(:disabled){background-color:#34485f;background-image:none;border-color:#34485f;box-shadow:none;color:#fff}.tox .tox-button--secondary:active:not(:disabled){background-color:#2b3b4e;background-image:none;border-color:#2b3b4e;box-shadow:none;color:#fff}.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding:4px}.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display:block;fill:currentColor}.tox .tox-button-link{background:0;border:none;box-sizing:border-box;cursor:pointer;display:inline-block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;white-space:nowrap}.tox .tox-button-link--sm{font-size:14px}.tox .tox-button--naked{background-color:transparent;border-color:transparent;box-shadow:unset;color:#fff}.tox .tox-button--naked[disabled]{background-color:#3d546f;border-color:#3d546f;box-shadow:none;color:rgba(255,255,255,.5)}.tox .tox-button--naked:hover:not(:disabled){background-color:#34485f;border-color:#34485f;box-shadow:none;color:#fff}.tox .tox-button--naked:focus:not(:disabled){background-color:#34485f;border-color:#34485f;box-shadow:none;color:#fff}.tox .tox-button--naked:active:not(:disabled){background-color:#2b3b4e;border-color:#2b3b4e;box-shadow:none;color:#fff}.tox .tox-button--naked .tox-icon svg{fill:currentColor}.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color:#fff}.tox .tox-checkbox{align-items:center;border-radius:3px;cursor:pointer;display:flex;height:36px;min-width:36px}.tox .tox-checkbox__input{height:1px;overflow:hidden;position:absolute;top:auto;width:1px}.tox .tox-checkbox__icons{align-items:center;border-radius:3px;box-shadow:0 0 0 2px transparent;box-sizing:content-box;display:flex;height:24px;justify-content:center;padding:calc(4px - 1px);width:24px}.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:block;fill:rgba(255,255,255,.2)}.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display:none;fill:#207ab7}.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display:none;fill:#207ab7}.tox .tox-checkbox--disabled{color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__checked svg{fill:rgba(255,255,255,.5)}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{fill:rgba(255,255,255,.5)}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{fill:rgba(255,255,255,.5)}.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:none}.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display:block}.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:none}.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display:block}.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{border-radius:3px;box-shadow:inset 0 0 0 1px #207ab7;padding:calc(4px - 1px)}.tox:not([dir=rtl]) .tox-checkbox__label{margin-left:4px}.tox:not([dir=rtl]) .tox-checkbox__input{left:-10000px}.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left:4px}.tox[dir=rtl] .tox-checkbox__label{margin-right:4px}.tox[dir=rtl] .tox-checkbox__input{right:-10000px}.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right:4px}.tox .tox-collection--toolbar .tox-collection__group{display:flex;padding:0}.tox .tox-collection--grid .tox-collection__group{display:flex;flex-wrap:wrap;max-height:208px;overflow-x:hidden;overflow-y:auto;padding:0}.tox .tox-collection--list .tox-collection__group{border-bottom-width:0;border-color:#1a1a1a;border-left-width:0;border-right-width:0;border-style:solid;border-top-width:1px;padding:4px 0}.tox .tox-collection--list .tox-collection__group:first-child{border-top-width:0}.tox .tox-collection__group-heading{background-color:#333;color:#fff;cursor:default;font-size:12px;font-style:normal;font-weight:400;margin-bottom:4px;margin-top:-4px;padding:4px 8px;text-transform:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tox .tox-collection__item{align-items:center;color:#fff;cursor:pointer;display:flex;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tox .tox-collection--list .tox-collection__item{padding:4px 8px}.tox .tox-collection--toolbar .tox-collection__item{border-radius:3px;padding:4px}.tox .tox-collection--grid .tox-collection__item{border-radius:3px;padding:4px}.tox .tox-collection--list .tox-collection__item--enabled{background-color:#2b3b4e;color:#fff}.tox .tox-collection--list .tox-collection__item--active{background-color:#4a5562}.tox .tox-collection--toolbar .tox-collection__item--enabled{background-color:#757d87;color:#fff}.tox .tox-collection--toolbar .tox-collection__item--active{background-color:#4a5562}.tox .tox-collection--grid .tox-collection__item--enabled{background-color:#757d87;color:#fff}.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){background-color:#4a5562;color:#fff}.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color:#fff}.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color:#fff}.tox .tox-collection__item-checkmark,.tox .tox-collection__item-icon{align-items:center;display:flex;height:24px;justify-content:center;width:24px}.tox .tox-collection__item-checkmark svg,.tox .tox-collection__item-icon svg{fill:currentColor}.tox .tox-collection--toolbar-lg .tox-collection__item-icon{height:48px;width:48px}.tox .tox-collection__item-label{color:currentColor;display:inline-block;flex:1;-ms-flex-preferred-size:auto;font-size:14px;font-style:normal;font-weight:400;line-height:24px;text-transform:none;word-break:break-all}.tox .tox-collection__item-accessory{color:rgba(255,255,255,.5);display:inline-block;font-size:14px;height:24px;line-height:24px;text-transform:none}.tox .tox-collection__item-caret{align-items:center;display:flex;min-height:24px}.tox .tox-collection__item-caret::after{content:'';font-size:0;min-height:inherit}.tox .tox-collection__item-caret svg{fill:#fff}.tox .tox-collection__item--state-disabled{background-color:transparent;color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-collection__item--state-disabled .tox-collection__item-caret svg{fill:rgba(255,255,255,.5)}.tox .tox-collection--list .tox-collection__item:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display:none}.tox .tox-collection--list .tox-collection__item:not(.tox-collection__item--enabled) .tox-collection__item-accessory+.tox-collection__item-checkmark{display:none}.tox .tox-collection--horizontal{background-color:#2b3b4e;border:1px solid #1a1a1a;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15);display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:nowrap;margin-bottom:0;overflow-x:auto;padding:0}.tox .tox-collection--horizontal .tox-collection__group{align-items:center;display:flex;flex-wrap:nowrap;margin:0;padding:0 4px}.tox .tox-collection--horizontal .tox-collection__item{height:34px;margin:2px 0 3px 0;padding:0 4px}.tox .tox-collection--horizontal .tox-collection__item-label{white-space:nowrap}.tox .tox-collection--horizontal .tox-collection__item-caret{margin-left:4px}.tox .tox-collection__item-container{display:flex}.tox .tox-collection__item-container--row{align-items:center;flex:1 1 auto;flex-direction:row}.tox .tox-collection__item-container--row.tox-collection__item-container--align-left{margin-right:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--align-right{justify-content:flex-end;margin-left:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-top{align-items:flex-start;margin-bottom:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-middle{align-items:center}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-bottom{align-items:flex-end;margin-top:auto}.tox .tox-collection__item-container--column{-ms-grid-row-align:center;align-self:center;flex:1 1 auto;flex-direction:column}.tox .tox-collection__item-container--column.tox-collection__item-container--align-left{align-items:flex-start}.tox .tox-collection__item-container--column.tox-collection__item-container--align-right{align-items:flex-end}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-top{align-self:flex-start}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-middle{-ms-grid-row-align:center;align-self:center}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-bottom{align-self:flex-end}.tox:not([dir=rtl]) .tox-collection--horizontal .tox-collection__group:not(:last-of-type){border-right:1px solid #000}.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left:8px}.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>.tox-collection__item-label:first-child{margin-left:4px}.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left:16px;text-align:right}.tox:not([dir=rtl]) .tox-collection .tox-collection__item-caret{margin-left:16px}.tox[dir=rtl] .tox-collection--horizontal .tox-collection__group:not(:last-of-type){border-left:1px solid #000}.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right:8px}.tox[dir=rtl] .tox-collection--list .tox-collection__item>.tox-collection__item-label:first-child{margin-right:4px}.tox[dir=rtl] .tox-collection__item-accessory{margin-right:16px;text-align:left}.tox[dir=rtl] .tox-collection .tox-collection__item-caret{margin-right:16px;transform:rotateY(180deg)}.tox[dir=rtl] .tox-collection--horizontal .tox-collection__item-caret{margin-right:4px}.tox .tox-color-picker-container{display:flex;flex-direction:row;height:225px;margin:0}.tox .tox-sv-palette{box-sizing:border-box;display:flex;height:100%}.tox .tox-sv-palette-spectrum{height:100%}.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width:225px}.tox .tox-sv-palette-thumb{background:0 0;border:1px solid #000;border-radius:50%;box-sizing:content-box;height:12px;position:absolute;width:12px}.tox .tox-sv-palette-inner-thumb{border:1px solid #fff;border-radius:50%;height:10px;position:absolute;width:10px}.tox .tox-hue-slider{box-sizing:border-box;height:100%;width:25px}.tox .tox-hue-slider-spectrum{background:linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);height:100%;width:100%}.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width:20px}.tox .tox-hue-slider-thumb{background:#fff;border:1px solid #000;box-sizing:content-box;height:4px;width:100%}.tox .tox-rgb-form{display:flex;flex-direction:column;justify-content:space-between}.tox .tox-rgb-form div{align-items:center;display:flex;justify-content:space-between;margin-bottom:5px;width:inherit}.tox .tox-rgb-form input{width:6em}.tox .tox-rgb-form input.tox-invalid{border:1px solid red!important}.tox .tox-rgb-form .tox-rgba-preview{border:1px solid #000;flex-grow:2;margin-bottom:0}.tox:not([dir=rtl]) .tox-sv-palette{margin-right:15px}.tox:not([dir=rtl]) .tox-hue-slider{margin-right:15px}.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left:-1px}.tox:not([dir=rtl]) .tox-rgb-form label{margin-right:.5em}.tox[dir=rtl] .tox-sv-palette{margin-left:15px}.tox[dir=rtl] .tox-hue-slider{margin-left:15px}.tox[dir=rtl] .tox-hue-slider-thumb{margin-right:-1px}.tox[dir=rtl] .tox-rgb-form label{margin-left:.5em}.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin:2px 0 3px 4px}.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{border:0;margin:-4px 0}.tox .tox-swatches__row{display:flex}.tox .tox-swatch{height:30px;transition:transform .15s,box-shadow .15s;width:30px}.tox .tox-swatch:focus,.tox .tox-swatch:hover{box-shadow:0 0 0 1px rgba(127,127,127,.3) inset;transform:scale(.8)}.tox .tox-swatch--remove{align-items:center;display:flex;justify-content:center}.tox .tox-swatch--remove svg path{stroke:#e74c3c}.tox .tox-swatches__picker-btn{align-items:center;background-color:transparent;border:0;cursor:pointer;display:flex;height:30px;justify-content:center;outline:0;padding:0;width:30px}.tox .tox-swatches__picker-btn svg{height:24px;width:24px}.tox .tox-swatches__picker-btn:hover{background:#4a5562}.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left:auto}.tox[dir=rtl] .tox-swatches__picker-btn{margin-right:auto}.tox .tox-comment-thread{background:#2b3b4e;position:relative}.tox .tox-comment-thread>:not(:first-child){margin-top:8px}.tox .tox-comment{background:#2b3b4e;border:1px solid #000;border-radius:3px;box-shadow:0 4px 8px 0 rgba(42,55,70,.1);padding:8px 8px 16px 8px;position:relative}.tox .tox-comment__header{align-items:center;color:#fff;display:flex;justify-content:space-between}.tox .tox-comment__date{color:rgba(255,255,255,.5);font-size:12px}.tox .tox-comment__body{color:#fff;font-size:14px;font-style:normal;font-weight:400;line-height:1.3;margin-top:8px;position:relative;text-transform:initial}.tox .tox-comment__body textarea{resize:none;white-space:normal;width:100%}.tox .tox-comment__expander{padding-top:8px}.tox .tox-comment__expander p{color:rgba(255,255,255,.5);font-size:14px;font-style:normal}.tox .tox-comment__body p{margin:0}.tox .tox-comment__buttonspacing{padding-top:16px;text-align:center}.tox .tox-comment-thread__overlay::after{background:#2b3b4e;bottom:0;content:"";display:flex;left:0;opacity:.9;position:absolute;right:0;top:0;z-index:5}.tox .tox-comment__reply{display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;margin-top:8px}.tox .tox-comment__reply>:first-child{margin-bottom:8px;width:100%}.tox .tox-comment__edit{display:flex;flex-wrap:wrap;justify-content:flex-end;margin-top:16px}.tox .tox-comment__gradient::after{background:linear-gradient(rgba(43,59,78,0),#2b3b4e);bottom:0;content:"";display:block;height:5em;margin-top:-40px;position:absolute;width:100%}.tox .tox-comment__overlay{background:#2b3b4e;bottom:0;display:flex;flex-direction:column;flex-grow:1;left:0;opacity:.9;position:absolute;right:0;text-align:center;top:0;z-index:5}.tox .tox-comment__loading-text{align-items:center;color:#fff;display:flex;flex-direction:column;position:relative}.tox .tox-comment__loading-text>div{padding-bottom:16px}.tox .tox-comment__overlaytext{bottom:0;flex-direction:column;font-size:14px;left:0;padding:1em;position:absolute;right:0;top:0;z-index:10}.tox .tox-comment__overlaytext p{background-color:#2b3b4e;box-shadow:0 0 8px 8px #2b3b4e;color:#fff;text-align:center}.tox .tox-comment__overlaytext div:nth-of-type(2){font-size:.8em}.tox .tox-comment__busy-spinner{align-items:center;background-color:#2b3b4e;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:20}.tox .tox-comment__scroll{display:flex;flex-direction:column;flex-shrink:1;overflow:auto}.tox .tox-conversations{margin:8px}.tox:not([dir=rtl]) .tox-comment__edit{margin-left:8px}.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left:8px}.tox[dir=rtl] .tox-comment__edit{margin-right:8px}.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right:8px}.tox .tox-user{align-items:center;display:flex}.tox .tox-user__avatar svg{fill:rgba(255,255,255,.5)}.tox .tox-user__name{color:rgba(255,255,255,.5);font-size:12px;font-style:normal;font-weight:700;text-transform:uppercase}.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right:8px}.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left:8px}.tox[dir=rtl] .tox-user__avatar svg{margin-left:8px}.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right:8px}.tox .tox-dialog-wrap{align-items:center;bottom:0;display:flex;justify-content:center;left:0;position:fixed;right:0;top:0;z-index:1100}.tox .tox-dialog-wrap__backdrop{background-color:rgba(34,47,62,.75);bottom:0;left:0;position:absolute;right:0;top:0;z-index:1}.tox .tox-dialog-wrap__backdrop--opaque{background-color:#222f3e}.tox .tox-dialog{background-color:#2b3b4e;border-color:#000;border-radius:3px;border-style:solid;border-width:1px;box-shadow:0 16px 16px -10px rgba(42,55,70,.15),0 0 40px 1px rgba(42,55,70,.15);display:flex;flex-direction:column;max-height:100%;max-width:480px;overflow:hidden;position:relative;width:95vw;z-index:2}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog{align-self:flex-start;margin:8px auto;width:calc(100vw - 16px)}}.tox .tox-dialog-inline{z-index:1100}.tox .tox-dialog__header{align-items:center;background-color:#2b3b4e;border-bottom:none;color:#fff;display:flex;font-size:16px;justify-content:space-between;padding:8px 16px 0 16px;position:relative}.tox .tox-dialog__header .tox-button{z-index:1}.tox .tox-dialog__draghandle{cursor:grab;height:100%;left:0;position:absolute;top:0;width:100%}.tox .tox-dialog__draghandle:active{cursor:grabbing}.tox .tox-dialog__dismiss{margin-left:auto}.tox .tox-dialog__title{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1.3;margin:0;text-transform:none}.tox .tox-dialog__body{color:#fff;display:flex;flex:1;-ms-flex-preferred-size:auto;font-size:16px;font-style:normal;font-weight:400;line-height:1.3;min-width:0;text-align:left;text-transform:none}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog__body{flex-direction:column}}.tox .tox-dialog__body-nav{align-items:flex-start;display:flex;flex-direction:column;padding:16px 16px}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog__body-nav{flex-direction:row;-webkit-overflow-scrolling:touch;overflow-x:auto;padding-bottom:0}}.tox .tox-dialog__body-nav-item{border-bottom:2px solid transparent;color:rgba(255,255,255,.5);display:inline-block;font-size:14px;line-height:1.3;margin-bottom:8px;text-decoration:none;white-space:nowrap}.tox .tox-dialog__body-nav-item:focus{background-color:rgba(32,122,183,.1)}.tox .tox-dialog__body-nav-item--active{border-bottom:2px solid #207ab7;color:#207ab7}.tox .tox-dialog__body-content{box-sizing:border-box;display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto;max-height:650px;overflow:auto;-webkit-overflow-scrolling:touch;padding:16px 16px}.tox .tox-dialog__body-content>*{margin-bottom:0;margin-top:16px}.tox .tox-dialog__body-content>:first-child{margin-top:0}.tox .tox-dialog__body-content>:last-child{margin-bottom:0}.tox .tox-dialog__body-content>:only-child{margin-bottom:0;margin-top:0}.tox .tox-dialog__body-content a{color:#207ab7;cursor:pointer;text-decoration:none}.tox .tox-dialog__body-content a:focus,.tox .tox-dialog__body-content a:hover{color:#185d8c;text-decoration:none}.tox .tox-dialog__body-content a:active{color:#185d8c;text-decoration:none}.tox .tox-dialog__body-content svg{fill:#fff}.tox .tox-dialog__body-content ul{display:block;list-style-type:disc;margin-bottom:16px;-webkit-margin-end:0;margin-inline-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-padding-start:2.5rem;padding-inline-start:2.5rem}.tox .tox-dialog__body-content .tox-form__group h1{color:#fff;font-size:20px;font-style:normal;font-weight:700;letter-spacing:normal;margin-bottom:16px;margin-top:2rem;text-transform:none}.tox .tox-dialog__body-content .tox-form__group h2{color:#fff;font-size:16px;font-style:normal;font-weight:700;letter-spacing:normal;margin-bottom:16px;margin-top:2rem;text-transform:none}.tox .tox-dialog__body-content .tox-form__group p{margin-bottom:16px}.tox .tox-dialog__body-content .tox-form__group h1:first-child,.tox .tox-dialog__body-content .tox-form__group h2:first-child,.tox .tox-dialog__body-content .tox-form__group p:first-child{margin-top:0}.tox .tox-dialog__body-content .tox-form__group h1:last-child,.tox .tox-dialog__body-content .tox-form__group h2:last-child,.tox .tox-dialog__body-content .tox-form__group p:last-child{margin-bottom:0}.tox .tox-dialog__body-content .tox-form__group h1:only-child,.tox .tox-dialog__body-content .tox-form__group h2:only-child,.tox .tox-dialog__body-content .tox-form__group p:only-child{margin-bottom:0;margin-top:0}.tox .tox-dialog--width-lg{height:650px;max-width:1200px}.tox .tox-dialog--width-md{max-width:800px}.tox .tox-dialog--width-md .tox-dialog__body-content{overflow:auto}.tox .tox-dialog__body-content--centered{text-align:center}.tox .tox-dialog__footer{align-items:center;background-color:#2b3b4e;border-top:1px solid #000;display:flex;justify-content:space-between;padding:8px 16px}.tox .tox-dialog__footer-end,.tox .tox-dialog__footer-start{display:flex}.tox .tox-dialog__busy-spinner{align-items:center;background-color:rgba(34,47,62,.75);bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:3}.tox .tox-dialog__table{border-collapse:collapse;width:100%}.tox .tox-dialog__table thead th{font-weight:700;padding-bottom:8px}.tox .tox-dialog__table tbody tr{border-bottom:1px solid #000}.tox .tox-dialog__table tbody tr:last-child{border-bottom:none}.tox .tox-dialog__table td{padding-bottom:8px;padding-top:8px}.tox .tox-dialog__popups{position:absolute;width:100%;z-index:1100}.tox .tox-dialog__body-iframe{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-iframe .tox-navobj{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex:1;-ms-flex-preferred-size:auto;height:100%}.tox .tox-dialog-dock-fadeout{opacity:0;visibility:hidden}.tox .tox-dialog-dock-fadein{opacity:1;visibility:visible}.tox .tox-dialog-dock-transition{transition:visibility 0s linear .3s,opacity .3s ease}.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein{transition-delay:0s}.tox.tox-platform-ie .tox-dialog-wrap{position:-ms-device-fixed}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right:0}}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child){margin-left:8px}}.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left:8px}.tox[dir=rtl] .tox-dialog__body{text-align:right}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav{margin-left:0}}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child){margin-right:8px}}.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right:8px}body.tox-dialog__disable-scroll{overflow:hidden}.tox .tox-dropzone-container{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dropzone{align-items:center;background:#fff;border:2px dashed #000;box-sizing:border-box;display:flex;flex-direction:column;flex-grow:1;justify-content:center;min-height:100px;padding:10px}.tox .tox-dropzone p{color:rgba(255,255,255,.5);margin:0 0 16px 0}.tox .tox-edit-area{display:flex;flex:1;-ms-flex-preferred-size:auto;overflow:hidden;position:relative}.tox .tox-edit-area__iframe{background-color:#fff;border:0;box-sizing:border-box;flex:1;-ms-flex-preferred-size:auto;height:100%;position:absolute;width:100%}.tox.tox-inline-edit-area{border:1px dotted #000}.tox .tox-editor-container{display:flex;flex:1 1 auto;flex-direction:column;overflow:hidden}.tox .tox-editor-header{z-index:1}.tox:not(.tox-tinymce-inline) .tox-editor-header{box-shadow:none;transition:box-shadow .5s}.tox.tox-tinymce--toolbar-bottom .tox-editor-header,.tox.tox-tinymce-inline .tox-editor-header{margin-bottom:-1px}.tox.tox-tinymce--toolbar-sticky-on .tox-editor-header{background-color:transparent;box-shadow:0 4px 4px -3px rgba(0,0,0,.25)}.tox-editor-dock-fadeout{opacity:0;visibility:hidden}.tox-editor-dock-fadein{opacity:1;visibility:visible}.tox-editor-dock-transition{transition:visibility 0s linear .25s,opacity .25s ease}.tox-editor-dock-transition.tox-editor-dock-fadein{transition-delay:0s}.tox .tox-control-wrap{flex:1;position:relative}.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display:none}.tox .tox-control-wrap svg{display:block}.tox .tox-control-wrap__status-icon-wrap{position:absolute;top:50%;transform:translateY(-50%)}.tox .tox-control-wrap__status-icon-invalid svg{fill:#c00}.tox .tox-control-wrap__status-icon-unknown svg{fill:orange}.tox .tox-control-wrap__status-icon-valid svg{fill:green}.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right:32px}.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right:4px}.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left:32px}.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left:4px}.tox .tox-autocompleter{max-width:25em}.tox .tox-autocompleter .tox-menu{max-width:25em}.tox .tox-autocompleter .tox-autocompleter-highlight{font-weight:700}.tox .tox-color-input{display:flex;position:relative;z-index:1}.tox .tox-color-input .tox-textfield{z-index:-1}.tox .tox-color-input span{border-color:rgba(42,55,70,.2);border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;height:24px;position:absolute;top:6px;width:24px}.tox .tox-color-input span:focus:not([aria-disabled=true]),.tox .tox-color-input span:hover:not([aria-disabled=true]){border-color:#207ab7;cursor:pointer}.tox .tox-color-input span::before{background-image:linear-gradient(45deg,rgba(255,255,255,.25) 25%,transparent 25%),linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%),linear-gradient(45deg,transparent 75%,rgba(255,255,255,.25) 75%),linear-gradient(-45deg,transparent 75%,rgba(255,255,255,.25) 75%);background-position:0 0,0 6px,6px -6px,-6px 0;background-size:12px 12px;border:1px solid #2b3b4e;border-radius:3px;box-sizing:border-box;content:'';height:24px;left:-1px;position:absolute;top:-1px;width:24px;z-index:-1}.tox .tox-color-input span[aria-disabled=true]{cursor:not-allowed}.tox:not([dir=rtl]) .tox-color-input .tox-textfield{padding-left:36px}.tox:not([dir=rtl]) .tox-color-input span{left:6px}.tox[dir=rtl] .tox-color-input .tox-textfield{padding-right:36px}.tox[dir=rtl] .tox-color-input span{right:6px}.tox .tox-label,.tox .tox-toolbar-label{color:rgba(255,255,255,.5);display:block;font-size:14px;font-style:normal;font-weight:400;line-height:1.3;padding:0 8px 0 0;text-transform:none;white-space:nowrap}.tox .tox-toolbar-label{padding:0 8px}.tox[dir=rtl] .tox-label{padding:0 0 0 8px}.tox .tox-form{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-form__group{box-sizing:border-box;margin-bottom:4px}.tox .tox-form-group--maximize{flex:1}.tox .tox-form__group--error{color:#c00}.tox .tox-form__group--collection{display:flex}.tox .tox-form__grid{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between}.tox .tox-form__grid--2col>.tox-form__group{width:calc(50% - (8px / 2))}.tox .tox-form__grid--3col>.tox-form__group{width:calc(100% / 3 - (8px / 2))}.tox .tox-form__grid--4col>.tox-form__group{width:calc(25% - (8px / 2))}.tox .tox-form__controls-h-stack{align-items:center;display:flex}.tox .tox-form__group--inline{align-items:center;display:flex}.tox .tox-form__group--stretched{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-textarea{flex:1;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-navobj{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex:1;-ms-flex-preferred-size:auto;height:100%}.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left:4px}.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right:4px}.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display:none}.tox .tox-listboxfield .tox-listbox--select,.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#2b3b4e;border-color:#000;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;line-height:24px;margin:0;min-height:34px;outline:0;padding:5px 4.75px;resize:none;width:100%}.tox .tox-textarea[disabled],.tox .tox-textfield[disabled]{background-color:#222f3e;color:rgba(255,255,255,.85);cursor:not-allowed}.tox .tox-listboxfield .tox-listbox--select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{background-color:#2b3b4e;border-color:#207ab7;box-shadow:none;outline:0}.tox .tox-toolbar-textfield{border-width:0;margin-bottom:3px;margin-top:2px;max-width:250px}.tox .tox-naked-btn{background-color:transparent;border:0;border-color:transparent;box-shadow:unset;color:#207ab7;cursor:pointer;display:block;margin:0;padding:0}.tox .tox-naked-btn svg{display:block;fill:#fff}.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left:4px}.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right:4px}.tox .tox-listboxfield{cursor:pointer;position:relative}.tox .tox-listboxfield .tox-listbox--select[disabled]{background-color:#19232e;color:rgba(255,255,255,.85);cursor:not-allowed}.tox .tox-listbox__select-label{cursor:default;flex:1;margin:0 4px}.tox .tox-listbox__select-chevron{align-items:center;display:flex;justify-content:center;width:16px}.tox .tox-listbox__select-chevron svg{fill:#fff}.tox .tox-listboxfield .tox-listbox--select{align-items:center;display:flex}.tox:not([dir=rtl]) .tox-listboxfield svg{right:8px}.tox[dir=rtl] .tox-listboxfield svg{left:8px}.tox .tox-selectfield{cursor:pointer;position:relative}.tox .tox-selectfield select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#2b3b4e;border-color:#000;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;line-height:24px;margin:0;min-height:34px;outline:0;padding:5px 4.75px;resize:none;width:100%}.tox .tox-selectfield select[disabled]{background-color:#19232e;color:rgba(255,255,255,.85);cursor:not-allowed}.tox .tox-selectfield select::-ms-expand{display:none}.tox .tox-selectfield select:focus{background-color:#2b3b4e;border-color:#207ab7;box-shadow:none;outline:0}.tox .tox-selectfield svg{pointer-events:none;position:absolute;top:50%;transform:translateY(-50%)}.tox:not([dir=rtl]) .tox-selectfield select[size="0"],.tox:not([dir=rtl]) .tox-selectfield select[size="1"]{padding-right:24px}.tox:not([dir=rtl]) .tox-selectfield svg{right:8px}.tox[dir=rtl] .tox-selectfield select[size="0"],.tox[dir=rtl] .tox-selectfield select[size="1"]{padding-left:24px}.tox[dir=rtl] .tox-selectfield svg{left:8px}.tox .tox-textarea{-webkit-appearance:textarea;-moz-appearance:textarea;appearance:textarea;white-space:pre-wrap}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}.tox .tox-help__more-link{list-style:none;margin-top:1em}.tox .tox-image-tools{width:100%}.tox .tox-image-tools__toolbar{align-items:center;display:flex;justify-content:center}.tox .tox-image-tools__image{background-color:#666;height:380px;overflow:auto;position:relative;width:100%}.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top:8px}.tox .tox-image-tools__image-bg{background:url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==)}.tox .tox-image-tools__toolbar>.tox-spacer{flex:1;-ms-flex-preferred-size:auto}.tox .tox-croprect-block{background:#000;opacity:.5;position:absolute;zoom:1}.tox .tox-croprect-handle{border:2px solid #fff;height:20px;left:0;position:absolute;top:0;width:20px}.tox .tox-croprect-handle-move{border:0;cursor:move;position:absolute}.tox .tox-croprect-handle-nw{border-width:2px 0 0 2px;cursor:nw-resize;left:100px;margin:-2px 0 0 -2px;top:100px}.tox .tox-croprect-handle-ne{border-width:2px 2px 0 0;cursor:ne-resize;left:200px;margin:-2px 0 0 -20px;top:100px}.tox .tox-croprect-handle-sw{border-width:0 0 2px 2px;cursor:sw-resize;left:100px;margin:-20px 2px 0 -2px;top:200px}.tox .tox-croprect-handle-se{border-width:0 2px 2px 0;cursor:se-resize;left:200px;margin:-20px 0 0 -20px;top:200px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left:8px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left:32px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left:32px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right:8px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right:32px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right:32px}.tox .tox-insert-table-picker{display:flex;flex-wrap:wrap;width:170px}.tox .tox-insert-table-picker>div{border-color:#000;border-style:solid;border-width:0 1px 1px 0;box-sizing:border-box;height:17px;width:17px}.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin:-4px 0}.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color:rgba(32,122,183,.5);border-color:rgba(32,122,183,.5)}.tox .tox-insert-table-picker__label{color:#fff;display:block;font-size:14px;padding:4px;text-align:center;width:100%}.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right:0}.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right:0}.tox .tox-menu{background-color:#2b3b4e;border:1px solid #000;border-radius:3px;box-shadow:0 4px 8px 0 rgba(42,55,70,.1);display:inline-block;overflow:hidden;vertical-align:top;z-index:1150}.tox .tox-menu.tox-collection.tox-collection--list{padding:0}.tox .tox-menu.tox-collection.tox-collection--toolbar{padding:4px}.tox .tox-menu.tox-collection.tox-collection--grid{padding:4px}.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin:0}.tox .tox-menubar{background:url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;background-color:#222f3e;display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:wrap;padding:0 4px 0 4px}.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar{border-top:1px solid #000}.tox .tox-mbtn{align-items:center;background:0 0;border:0;border-radius:3px;box-shadow:none;color:#fff;display:flex;flex:0 0 auto;font-size:14px;font-style:normal;font-weight:400;height:34px;justify-content:center;margin:2px 0 3px 0;outline:0;overflow:hidden;padding:0 4px;text-transform:none;width:auto}.tox .tox-mbtn[disabled]{background-color:transparent;border:0;box-shadow:none;color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-mbtn:focus:not(:disabled){background:#4a5562;border:0;box-shadow:none;color:#fff}.tox .tox-mbtn--active{background:#757d87;border:0;box-shadow:none;color:#fff}.tox .tox-mbtn:hover:not(:disabled):not(.tox-mbtn--active){background:#4a5562;border:0;box-shadow:none;color:#fff}.tox .tox-mbtn__select-label{cursor:default;font-weight:400;margin:0 4px}.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor:not-allowed}.tox .tox-mbtn__select-chevron{align-items:center;display:flex;justify-content:center;width:16px;display:none}.tox .tox-notification{border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;display:-ms-grid;display:grid;font-size:14px;font-weight:400;-ms-grid-columns:minmax(40px,1fr) auto minmax(40px,1fr);grid-template-columns:minmax(40px,1fr) auto minmax(40px,1fr);margin-top:4px;opacity:0;padding:4px;transition:transform .1s ease-in,opacity 150ms ease-in}.tox .tox-notification p{font-size:14px;font-weight:400}.tox .tox-notification a{cursor:pointer;text-decoration:underline}.tox .tox-notification--in{opacity:1}.tox .tox-notification--success{background-color:#e4eeda;border-color:#d7e6c8;color:#fff}.tox .tox-notification--success p{color:#fff}.tox .tox-notification--success a{color:#547831}.tox .tox-notification--success svg{fill:#fff}.tox .tox-notification--error{background-color:#f8dede;border-color:#f2bfbf;color:#fff}.tox .tox-notification--error p{color:#fff}.tox .tox-notification--error a{color:#c00}.tox .tox-notification--error svg{fill:#fff}.tox .tox-notification--warn,.tox .tox-notification--warning{background-color:#fffaea;border-color:#ffe89d;color:#fff}.tox .tox-notification--warn p,.tox .tox-notification--warning p{color:#fff}.tox .tox-notification--warn a,.tox .tox-notification--warning a{color:#fff}.tox .tox-notification--warn svg,.tox .tox-notification--warning svg{fill:#fff}.tox .tox-notification--info{background-color:#d9edf7;border-color:#779ecb;color:#fff}.tox .tox-notification--info p{color:#fff}.tox .tox-notification--info a{color:#fff}.tox .tox-notification--info svg{fill:#fff}.tox .tox-notification__body{-ms-grid-row-align:center;align-self:center;color:#fff;font-size:14px;-ms-grid-column-span:1;grid-column-end:3;-ms-grid-column:2;grid-column-start:2;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;text-align:center;white-space:normal;word-break:break-all;word-break:break-word}.tox .tox-notification__body>*{margin:0}.tox .tox-notification__body>*+*{margin-top:1rem}.tox .tox-notification__icon{-ms-grid-row-align:center;align-self:center;-ms-grid-column-span:1;grid-column-end:2;-ms-grid-column:1;grid-column-start:1;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;-ms-grid-column-align:end;justify-self:end}.tox .tox-notification__icon svg{display:block}.tox .tox-notification__dismiss{-ms-grid-row-align:start;align-self:start;-ms-grid-column-span:1;grid-column-end:4;-ms-grid-column:3;grid-column-start:3;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;-ms-grid-column-align:end;justify-self:end}.tox .tox-notification .tox-progress-bar{-ms-grid-column-span:3;grid-column-end:4;-ms-grid-column:1;grid-column-start:1;-ms-grid-row-span:1;grid-row-end:3;-ms-grid-row:2;grid-row-start:2;-ms-grid-column-align:center;justify-self:center}.tox .tox-pop{display:inline-block;position:relative}.tox .tox-pop--resizing{transition:width .1s ease}.tox .tox-pop--resizing .tox-toolbar,.tox .tox-pop--resizing .tox-toolbar__group{flex-wrap:nowrap}.tox .tox-pop--transition{transition:.15s ease;transition-property:left,right,top,bottom}.tox .tox-pop--transition::after,.tox .tox-pop--transition::before{transition:all .15s,visibility 0s,opacity 75ms ease 75ms}.tox .tox-pop__dialog{background-color:#222f3e;border:1px solid #000;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15);min-width:0;overflow:hidden}.tox .tox-pop__dialog>:not(.tox-toolbar){margin:4px 4px 4px 8px}.tox .tox-pop__dialog .tox-toolbar{background-color:transparent;margin-bottom:-1px}.tox .tox-pop::after,.tox .tox-pop::before{border-style:solid;content:'';display:block;height:0;opacity:1;position:absolute;width:0}.tox .tox-pop.tox-pop--inset::after,.tox .tox-pop.tox-pop--inset::before{opacity:0;transition:all 0s .15s,visibility 0s,opacity 75ms ease}.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{left:50%;top:100%}.tox .tox-pop.tox-pop--bottom::after{border-color:#222f3e transparent transparent transparent;border-width:8px;margin-left:-8px;margin-top:-1px}.tox .tox-pop.tox-pop--bottom::before{border-color:#000 transparent transparent transparent;border-width:9px;margin-left:-9px}.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{left:50%;top:0;transform:translateY(-100%)}.tox .tox-pop.tox-pop--top::after{border-color:transparent transparent #222f3e transparent;border-width:8px;margin-left:-8px;margin-top:1px}.tox .tox-pop.tox-pop--top::before{border-color:transparent transparent #000 transparent;border-width:9px;margin-left:-9px}.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{left:0;top:calc(50% - 1px);transform:translateY(-50%)}.tox .tox-pop.tox-pop--left::after{border-color:transparent #222f3e transparent transparent;border-width:8px;margin-left:-15px}.tox .tox-pop.tox-pop--left::before{border-color:transparent #000 transparent transparent;border-width:10px;margin-left:-19px}.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{left:100%;top:calc(50% + 1px);transform:translateY(-50%)}.tox .tox-pop.tox-pop--right::after{border-color:transparent transparent transparent #222f3e;border-width:8px;margin-left:-1px}.tox .tox-pop.tox-pop--right::before{border-color:transparent transparent transparent #000;border-width:10px;margin-left:-1px}.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left:20px}.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left:calc(100% - 20px)}.tox .tox-sidebar-wrap{display:flex;flex-direction:row;flex-grow:1;-ms-flex-preferred-size:0;min-height:0}.tox .tox-sidebar{background-color:#222f3e;display:flex;flex-direction:row;justify-content:flex-end}.tox .tox-sidebar__slider{display:flex;overflow:hidden}.tox .tox-sidebar__pane-container{display:flex}.tox .tox-sidebar__pane{display:flex}.tox .tox-sidebar--sliding-closed{opacity:0}.tox .tox-sidebar--sliding-open{opacity:1}.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition:width .5s ease,opacity .5s ease}.tox .tox-selector{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;display:inline-block;height:10px;position:absolute;width:10px}.tox.tox-platform-touch .tox-selector{height:12px;width:12px}.tox .tox-slider{align-items:center;display:flex;flex:1;-ms-flex-preferred-size:auto;height:24px;justify-content:center;position:relative}.tox .tox-slider__rail{background-color:transparent;border:1px solid #000;border-radius:3px;height:10px;min-width:120px;width:100%}.tox .tox-slider__handle{background-color:#207ab7;border:2px solid #185d8c;border-radius:3px;box-shadow:none;height:24px;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:14px}.tox .tox-source-code{overflow:auto}.tox .tox-spinner{display:flex}.tox .tox-spinner>div{animation:tam-bouncing-dots 1.5s ease-in-out 0s infinite both;background-color:rgba(255,255,255,.5);border-radius:100%;height:8px;width:8px}.tox .tox-spinner>div:nth-child(1){animation-delay:-.32s}.tox .tox-spinner>div:nth-child(2){animation-delay:-.16s}@keyframes tam-bouncing-dots{0%,100%,80%{transform:scale(0)}40%{transform:scale(1)}}.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left:4px}.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right:4px}.tox .tox-statusbar{align-items:center;background-color:#222f3e;border-top:1px solid #000;color:#fff;display:flex;flex:0 0 auto;font-size:12px;font-weight:400;height:18px;overflow:hidden;padding:0 8px;position:relative;text-transform:uppercase}.tox .tox-statusbar__text-container{display:flex;flex:1 1 auto;justify-content:flex-end;overflow:hidden}.tox .tox-statusbar__path{display:flex;flex:1 1 auto;margin-right:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tox .tox-statusbar__path>*{display:inline;white-space:nowrap}.tox .tox-statusbar__wordcount{flex:0 0 auto;margin-left:1ch}.tox .tox-statusbar a,.tox .tox-statusbar__path-item,.tox .tox-statusbar__wordcount{color:#fff;text-decoration:none}.tox .tox-statusbar a:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar a:hover:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__path-item:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__path-item:hover:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__wordcount:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__wordcount:hover:not(:disabled):not([aria-disabled=true]){cursor:pointer;text-decoration:underline}.tox .tox-statusbar__resize-handle{align-items:flex-end;align-self:stretch;cursor:nwse-resize;display:flex;flex:0 0 auto;justify-content:flex-end;margin-left:auto;margin-right:-8px;padding-left:1ch}.tox .tox-statusbar__resize-handle svg{display:block;fill:#fff}.tox .tox-statusbar__resize-handle:focus svg{background-color:#4a5562;border-radius:1px;box-shadow:0 0 0 2px #4a5562}.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right:4px}.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left:1ch}.tox[dir=rtl] .tox-statusbar{flex-direction:row-reverse}.tox[dir=rtl] .tox-statusbar__path>*{margin-left:4px}.tox .tox-throbber{z-index:1299}.tox .tox-throbber__busy-spinner{align-items:center;background-color:rgba(34,47,62,.6);bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}.tox .tox-tbtn{align-items:center;background:0 0;border:0;border-radius:3px;box-shadow:none;color:#fff;display:flex;flex:0 0 auto;font-size:14px;font-style:normal;font-weight:400;height:34px;justify-content:center;margin:2px 0 3px 0;outline:0;overflow:hidden;padding:0;text-transform:none;width:34px}.tox .tox-tbtn svg{display:block;fill:#fff}.tox .tox-tbtn.tox-tbtn-more{padding-left:5px;padding-right:5px;width:inherit}.tox .tox-tbtn:focus{background:#4a5562;border:0;box-shadow:none}.tox .tox-tbtn:hover{background:#4a5562;border:0;box-shadow:none;color:#fff}.tox .tox-tbtn:hover svg{fill:#fff}.tox .tox-tbtn:active{background:#757d87;border:0;box-shadow:none;color:#fff}.tox .tox-tbtn:active svg{fill:#fff}.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{background:0 0;border:0;box-shadow:none;color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill:rgba(255,255,255,.5)}.tox .tox-tbtn--enabled,.tox .tox-tbtn--enabled:hover{background:#757d87;border:0;box-shadow:none;color:#fff}.tox .tox-tbtn--enabled:hover>*,.tox .tox-tbtn--enabled>*{transform:none}.tox .tox-tbtn--enabled svg,.tox .tox-tbtn--enabled:hover svg{fill:#fff}.tox .tox-tbtn:focus:not(.tox-tbtn--disabled){color:#fff}.tox .tox-tbtn:focus:not(.tox-tbtn--disabled) svg{fill:#fff}.tox .tox-tbtn:active>*{transform:none}.tox .tox-tbtn--md{height:51px;width:51px}.tox .tox-tbtn--lg{flex-direction:column;height:68px;width:68px}.tox .tox-tbtn--return{-ms-grid-row-align:stretch;align-self:stretch;height:unset;width:16px}.tox .tox-tbtn--labeled{padding:0 4px;width:unset}.tox .tox-tbtn__vlabel{display:block;font-size:10px;font-weight:400;letter-spacing:-.025em;margin-bottom:4px;white-space:nowrap}.tox .tox-tbtn--select{margin:2px 0 3px 0;padding:0 4px;width:auto}.tox .tox-tbtn__select-label{cursor:default;font-weight:400;margin:0 4px}.tox .tox-tbtn__select-chevron{align-items:center;display:flex;justify-content:center;width:16px}.tox .tox-tbtn__select-chevron svg{fill:rgba(255,255,255,.5)}.tox .tox-tbtn--bespoke .tox-tbtn__select-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:7em}.tox .tox-split-button{border:0;border-radius:3px;box-sizing:border-box;display:flex;margin:2px 0 3px 0;overflow:hidden}.tox .tox-split-button:hover{box-shadow:0 0 0 1px #4a5562 inset}.tox .tox-split-button:focus{background:#4a5562;box-shadow:none;color:#fff}.tox .tox-split-button>*{border-radius:0}.tox .tox-split-button__chevron{width:16px}.tox .tox-split-button__chevron svg{fill:rgba(255,255,255,.5)}.tox .tox-split-button .tox-tbtn{margin:0}.tox.tox-platform-touch .tox-split-button .tox-tbtn:first-child{width:30px}.tox.tox-platform-touch .tox-split-button__chevron{width:20px}.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{background:0 0;box-shadow:none;color:rgba(255,255,255,.5)}.tox .tox-toolbar-overlord{background-color:#222f3e}.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{background:url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23000000'/%3E%3C/svg%3E") left 0 top 0 #222f3e;background-color:#222f3e;display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:wrap;padding:0 0}.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height:0;opacity:0;padding-bottom:0;padding-top:0;visibility:hidden}.tox .tox-toolbar__overflow--growing{transition:height .3s ease,opacity .2s linear .1s}.tox .tox-toolbar__overflow--shrinking{transition:opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s}.tox .tox-menubar+.tox-toolbar,.tox .tox-menubar+.tox-toolbar-overlord .tox-toolbar__primary{border-top:1px solid #000;margin-top:-1px}.tox .tox-toolbar--scrolling{flex-wrap:nowrap;overflow-x:auto}.tox .tox-pop .tox-toolbar{border-width:0}.tox .tox-toolbar--no-divider{background-image:none}.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar-overlord:first-child .tox-toolbar__primary,.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar:first-child{border-top:1px solid #000}.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color:#222f3e;border:1px solid #000;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15)}.tox .tox-toolbar__group{align-items:center;display:flex;flex-wrap:wrap;margin:0 0;padding:0 4px 0 4px}.tox .tox-toolbar__group--pull-right{margin-left:auto}.tox .tox-toolbar--scrolling .tox-toolbar__group{flex-shrink:0;flex-wrap:nowrap}.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right:1px solid #000}.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left:1px solid #000}.tox .tox-tooltip{display:inline-block;padding:8px;position:relative}.tox .tox-tooltip__body{background-color:#3d546f;border-radius:3px;box-shadow:0 2px 4px rgba(42,55,70,.3);color:rgba(255,255,255,.75);font-size:14px;font-style:normal;font-weight:400;padding:4px 8px;text-transform:none}.tox .tox-tooltip__arrow{position:absolute}.tox .tox-tooltip--down .tox-tooltip__arrow{border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #3d546f;bottom:0;left:50%;position:absolute;transform:translateX(-50%)}.tox .tox-tooltip--up .tox-tooltip__arrow{border-bottom:8px solid #3d546f;border-left:8px solid transparent;border-right:8px solid transparent;left:50%;position:absolute;top:0;transform:translateX(-50%)}.tox .tox-tooltip--right .tox-tooltip__arrow{border-bottom:8px solid transparent;border-left:8px solid #3d546f;border-top:8px solid transparent;position:absolute;right:0;top:50%;transform:translateY(-50%)}.tox .tox-tooltip--left .tox-tooltip__arrow{border-bottom:8px solid transparent;border-right:8px solid #3d546f;border-top:8px solid transparent;left:0;position:absolute;top:50%;transform:translateY(-50%)}.tox .tox-well{border:1px solid #000;border-radius:3px;padding:8px;width:100%}.tox .tox-well>:first-child{margin-top:0}.tox .tox-well>:last-child{margin-bottom:0}.tox .tox-well>:only-child{margin:0}.tox .tox-custom-editor{border:1px solid #000;border-radius:3px;display:flex;flex:1;position:relative}.tox .tox-dialog-loading::before{background-color:rgba(0,0,0,.5);content:"";height:100%;position:absolute;width:100%;z-index:1000}.tox .tox-tab{cursor:pointer}.tox .tox-dialog__content-js{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-content .tox-collection{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-image-tools-edit-panel{height:60px}.tox .tox-image-tools__sidebar{height:60px} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css new file mode 100644 index 0000000..3a45cac --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.mobile.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all:initial;display:block}.tinymce-mobile-outer-container *{border:0;box-sizing:initial;cursor:inherit;float:none;line-height:1;margin:0;outline:0;padding:0;-webkit-tap-highlight-color:transparent;text-shadow:none;white-space:nowrap}.tinymce-mobile-icon-arrow-back::before{content:"\e5cd"}.tinymce-mobile-icon-image::before{content:"\e412"}.tinymce-mobile-icon-cancel-circle::before{content:"\e5c9"}.tinymce-mobile-icon-full-dot::before{content:"\e061"}.tinymce-mobile-icon-align-center::before{content:"\e234"}.tinymce-mobile-icon-align-left::before{content:"\e236"}.tinymce-mobile-icon-align-right::before{content:"\e237"}.tinymce-mobile-icon-bold::before{content:"\e238"}.tinymce-mobile-icon-italic::before{content:"\e23f"}.tinymce-mobile-icon-unordered-list::before{content:"\e241"}.tinymce-mobile-icon-ordered-list::before{content:"\e242"}.tinymce-mobile-icon-font-size::before{content:"\e245"}.tinymce-mobile-icon-underline::before{content:"\e249"}.tinymce-mobile-icon-link::before{content:"\e157"}.tinymce-mobile-icon-unlink::before{content:"\eca2"}.tinymce-mobile-icon-color::before{content:"\e891"}.tinymce-mobile-icon-previous::before{content:"\e314"}.tinymce-mobile-icon-next::before{content:"\e315"}.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content:"\e264"}.tinymce-mobile-icon-undo::before{content:"\e166"}.tinymce-mobile-icon-redo::before{content:"\e15a"}.tinymce-mobile-icon-removeformat::before{content:"\e239"}.tinymce-mobile-icon-small-font::before{content:"\e906"}.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content:"\e5ca"}.tinymce-mobile-icon-small-heading::before{content:"small"}.tinymce-mobile-icon-large-heading::before{content:"large"}.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family:sans-serif;font-size:80%}.tinymce-mobile-mask-edit-icon::before{content:"\e254"}.tinymce-mobile-icon-back::before{content:"\e5c4"}.tinymce-mobile-icon-heading::before{content:"Headings";font-family:sans-serif;font-size:80%;font-weight:700}.tinymce-mobile-icon-h1::before{content:"H1";font-weight:700}.tinymce-mobile-icon-h2::before{content:"H2";font-weight:700}.tinymce-mobile-icon-h3::before{content:"H3";font-weight:700}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{align-items:center;display:flex;justify-content:center;background:rgba(51,51,51,.5);height:100%;position:absolute;top:0;width:100%}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{align-items:center;border-radius:50%;display:flex;flex-direction:column;font-family:sans-serif;font-size:1em;justify-content:space-between}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items:center;display:flex;justify-content:center;flex-direction:column;font-size:1em}@media only screen and (min-device-width:700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size:1.2em}}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em;background-color:#fff;color:#207ab7}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{content:"\e900";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index:2}.tinymce-mobile-android-container.tinymce-mobile-android-maximized{background:#fff;border:none;bottom:0;display:flex;flex-direction:column;left:0;position:fixed;right:0;top:0}.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position:relative}.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display:flex;flex-grow:1}.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display:flex!important;flex-grow:1;height:auto!important}.tinymce-mobile-android-scroll-reload{overflow:hidden}:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top:23px}.tinymce-mobile-toolstrip{background:#fff;display:flex;flex:0 0 auto;z-index:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{align-items:center;background-color:#fff;border-bottom:1px solid #ccc;display:flex;flex:1;height:2.5em;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex-shrink:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background:#f44336}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{align-items:center;display:flex;height:80%;margin-left:2px;margin-right:2px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{background:#c8cbcf;color:#ccc}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{background:#207ab7;color:#eceff1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex:1;padding-bottom:.4em;padding-top:.4em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{display:flex;min-height:1.5em;overflow:hidden;padding-left:0;padding-right:0;position:relative;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display:flex;height:100%;transition:left cubic-bezier(.4,0,1,1) .15s;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display:flex;flex:0 0 auto;justify-content:space-between;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family:Sans-serif}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{display:flex;flex-grow:1;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{-ms-grid-row-align:center;align-self:center;background:inherit;border:none;border-radius:50%;color:#888;font-size:.6em;font-weight:700;height:100%;padding-right:2px;position:absolute;right:0}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display:none}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{align-items:center;display:flex;font-weight:700;height:100%;padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility:hidden}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{color:#ccc;font-size:10px;line-height:10px;margin:0 2px;padding-top:3px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color:#c8cbcf}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-left:.5em;margin-right:.9em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-left:.9em;margin-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{display:flex;flex:1;margin-left:0;margin-right:0;padding:.28em 0;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{background:#ccc;display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-left:2em;padding-right:2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{background:linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{background:#000;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{background:#fff;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{align-items:center;background-clip:padding-box;background-color:#455a64;border:.5em solid rgba(136,136,136,0);border-radius:3em;bottom:0;color:#fff;display:flex;height:.5em;justify-content:center;left:-10px;margin:auto;position:absolute;top:0;transition:border 120ms cubic-bezier(.39,.58,.57,1);width:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border:.5em solid rgba(136,136,136,.39)}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction:column;justify-content:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{background:#fff;border:none;border-radius:0;color:#455a64;flex-grow:1;font-size:.85em;padding-bottom:.1em;padding-left:5px;padding-top:.1em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color:#888}.tinymce-mobile-dropup{background:#fff;display:flex;overflow:hidden;width:100%}.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition:height .3s ease-out}.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition:height .3s ease-in}.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow:0}.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow:1}.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}@media only screen and (orientation:landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:150px}}.tinymce-mobile-styles-menu{font-family:sans-serif;outline:4px solid #000;overflow:hidden;position:relative;width:100%}.tinymce-mobile-styles-menu [role=menu]{display:flex;flex-direction:column;height:100%;position:absolute;width:100%}.tinymce-mobile-styles-menu [role=menu].transitioning{transition:transform .5s ease-in-out}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{border-bottom:1px solid #ddd;color:#455a64;cursor:pointer;display:flex;padding:1em 1em;position:relative}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{color:#455a64;content:"\e314";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{color:#455a64;content:"\e315";font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{align-items:center;background:#fff;border-top:#455a64;color:#455a64;display:flex;min-height:2.5em;padding-left:1em;padding-right:1em}.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform:translate(-100%)}.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform:translate(0)}.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform:translate(100%)}@font-face{font-family:tinymce-mobile;font-style:normal;font-weight:400;src:url(fonts/tinymce-mobile.woff?8x92w3) format('woff')}@media (min-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:25px}}@media (max-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:18px}}.tinymce-mobile-icon{font-family:tinymce-mobile,sans-serif}.mixin-flex-and-centre{align-items:center;display:flex;justify-content:center}.mixin-flex-bar{align-items:center;display:flex;height:100%}.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{background-color:#fff;width:100%}.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{background-color:#207ab7;border-radius:50%;bottom:1em;color:#fff;font-size:1em;height:2.1em;position:fixed;right:2em;width:2.1em;align-items:center;display:flex;justify-content:center}@media only screen and (min-device-width:700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size:1.2em}}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height:300px;overflow:hidden}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height:100%}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display:none}input[type=file]::-webkit-file-upload-button{display:none}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom:50%}} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css new file mode 100644 index 0000000..a0893b9 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.inline.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.inline.min.css new file mode 100644 index 0000000..b4ab9a3 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.inline.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;cursor:default;display:inline-block;height:12px!important;padding:0 2px;-webkit-user-modify:read-only;-moz-user-modify:read-only;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all;width:8px!important}.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset:1px}.tox-comments-visible .tox-comment{background-color:#fff0b7}.tox-comments-visible .tox-comment--active{background-color:#ffe168}.tox-checklist>li:not(.tox-checklist--hidden){list-style:none;margin:.25em 0}.tox-checklist>li:not(.tox-checklist--hidden)::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");cursor:pointer;height:1em;margin-left:-1.5em;margin-top:.125em;position:absolute;width:1em}.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A")}[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-left:0;margin-right:-1.5em}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.mce-content-body{overflow-wrap:break-word;word-wrap:break-word}.mce-content-body .mce-visual-caret{background-color:#000;background-color:currentColor;position:absolute}.mce-content-body .mce-visual-caret-hidden{display:none}.mce-content-body [data-mce-caret]{left:-1000px;margin:0;padding:0;position:absolute;right:auto;top:0}.mce-content-body .mce-offscreen-selection{left:-2000000px;max-width:1000000px;position:absolute}.mce-content-body [contentEditable=false]{cursor:default}.mce-content-body [contentEditable=true]{cursor:text}.tox-cursor-format-painter{cursor:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default}.mce-content-body figure.align-left{float:left}.mce-content-body figure.align-right{float:right}.mce-content-body figure.image.align-center{display:table;margin-left:auto;margin-right:auto}.mce-preview-object{border:1px solid gray;display:inline-block;line-height:0;margin:0 2px 0 2px;position:relative}.mce-preview-object .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-object{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border:1px dashed #aaa}.mce-pagebreak{border:1px dashed #aaa;cursor:default;display:block;height:5px;margin-top:15px;page-break-before:always;width:100%}@media print{.mce-pagebreak{border:0}}.tiny-pageembed .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.tiny-pageembed[data-mce-selected="2"] .mce-shim{display:none}.tiny-pageembed{display:inline-block;position:relative}.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{display:block;overflow:hidden;padding:0;position:relative;width:100%}.tiny-pageembed--21by9{padding-top:42.857143%}.tiny-pageembed--16by9{padding-top:56.25%}.tiny-pageembed--4by3{padding-top:75%}.tiny-pageembed--1by1{padding-top:100%}.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{border:0;height:100%;left:0;position:absolute;top:0;width:100%}.mce-content-body[data-mce-placeholder]{position:relative}.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before{color:rgba(34,47,62,.7);content:attr(data-mce-placeholder);position:absolute}.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before{left:1px}.mce-content-body[dir=rtl][data-mce-placeholder]:not(.mce-visualblocks)::before{right:1px}.mce-content-body div.mce-resizehandle{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;height:10px;position:absolute;width:10px;z-index:1298}.mce-content-body div.mce-resizehandle:hover{background-color:#4099ff}.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor:nesw-resize}.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor:nesw-resize}.mce-content-body .mce-resize-backdrop{z-index:10000}.mce-content-body .mce-clonedresizable{cursor:default;opacity:.5;outline:1px dashed #000;position:absolute;z-index:10001}.mce-content-body .mce-clonedresizable.mce-resizetable-columns td,.mce-content-body .mce-clonedresizable.mce-resizetable-columns th{border:0}.mce-content-body .mce-resize-helper{background:#555;background:rgba(0,0,0,.75);border:1px;border-radius:3px;color:#fff;display:none;font-family:sans-serif;font-size:12px;line-height:14px;margin:5px 10px;padding:5px;position:absolute;white-space:nowrap;z-index:10002}.tox-rtc-user-selection{position:relative}.tox-rtc-user-cursor{bottom:0;cursor:default;position:absolute;top:0;width:2px}.tox-rtc-user-cursor::before{background-color:inherit;border-radius:50%;content:'';display:block;height:8px;position:absolute;right:-3px;top:-3px;width:8px}.tox-rtc-user-cursor:hover::after{background-color:inherit;border-radius:100px;box-sizing:border-box;color:#fff;content:attr(data-user);display:block;font-size:12px;font-weight:700;left:-5px;min-height:8px;min-width:8px;padding:0 12px;position:absolute;top:-11px;white-space:nowrap;z-index:1000}.tox-rtc-user-selection--1 .tox-rtc-user-cursor{background-color:#2dc26b}.tox-rtc-user-selection--2 .tox-rtc-user-cursor{background-color:#e03e2d}.tox-rtc-user-selection--3 .tox-rtc-user-cursor{background-color:#f1c40f}.tox-rtc-user-selection--4 .tox-rtc-user-cursor{background-color:#3598db}.tox-rtc-user-selection--5 .tox-rtc-user-cursor{background-color:#b96ad9}.tox-rtc-user-selection--6 .tox-rtc-user-cursor{background-color:#e67e23}.tox-rtc-user-selection--7 .tox-rtc-user-cursor{background-color:#aaa69d}.tox-rtc-user-selection--8 .tox-rtc-user-cursor{background-color:#f368e0}.tox-rtc-remote-image{background:#eaeaea url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A") no-repeat center center;border:1px solid #ccc;min-height:240px;min-width:320px}.mce-match-marker{background:#aaa;color:#fff}.mce-match-marker-selected{background:#39f;color:#fff}.mce-match-marker-selected::-moz-selection{background:#39f;color:#fff}.mce-match-marker-selected::selection{background:#39f;color:#fff}.mce-content-body audio[data-mce-selected],.mce-content-body embed[data-mce-selected],.mce-content-body img[data-mce-selected],.mce-content-body object[data-mce-selected],.mce-content-body table[data-mce-selected],.mce-content-body video[data-mce-selected]{outline:3px solid #b4d7ff}.mce-content-body hr[data-mce-selected]{outline:3px solid #b4d7ff;outline-offset:1px}.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false][data-mce-selected]{cursor:not-allowed;outline:3px solid #b4d7ff}.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline:0}.mce-content-body [data-mce-selected=inline-boundary]{background-color:#b4d7ff}.mce-content-body .mce-edit-focus{outline:3px solid #b4d7ff}.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{position:relative}.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background:0 0}.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background:0 0}.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{outline:0;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{background-color:rgba(180,215,255,.7);border:1px solid rgba(180,215,255,.7);bottom:-1px;content:'';left:-1px;mix-blend-mode:multiply;position:absolute;right:-1px;top:-1px}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{border-color:rgba(0,84,180,.7)}}.mce-content-body img::-moz-selection{background:0 0}.mce-content-body img::selection{background:0 0}.ephox-snooker-resizer-bar{background-color:#b4d7ff;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:1}.mce-spellchecker-word{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.75'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default;height:2rem}.mce-spellchecker-grammar{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%2300A835'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width: 0px"],table[style*="border-width: 0px"] caption,table[style*="border-width: 0px"] td,table[style*="border-width: 0px"] th{border:1px dashed #bbb}.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{background-repeat:no-repeat;border:1px dashed #bbb;margin-left:3px;padding-top:10px}.mce-visualblocks p{background-image:url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7)}.mce-visualblocks h1{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==)}.mce-visualblocks h2{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==)}.mce-visualblocks h3{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7)}.mce-visualblocks h4{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==)}.mce-visualblocks h5{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==)}.mce-visualblocks h6{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==)}.mce-visualblocks div:not([data-mce-bogus]){background-image:url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7)}.mce-visualblocks section{background-image:url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=)}.mce-visualblocks article{background-image:url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7)}.mce-visualblocks blockquote{background-image:url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7)}.mce-visualblocks address{background-image:url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=)}.mce-visualblocks pre{background-image:url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==)}.mce-visualblocks figure{background-image:url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7)}.mce-visualblocks figcaption{border:1px dashed #bbb}.mce-visualblocks hgroup{background-image:url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7)}.mce-visualblocks aside{background-image:url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=)}.mce-visualblocks ul{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==)}.mce-visualblocks ol{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==)}.mce-visualblocks dl{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==)}.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left:3px}.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x:right;margin-right:3px}.mce-nbsp,.mce-shy{background:#aaa}.mce-shy::after{content:'-'} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.min.css new file mode 100644 index 0000000..844858d --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.mce-content-body .mce-item-anchor{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'8'%20height%3D'12'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20d%3D'M0%200L8%200%208%2012%204.09117821%209%200%2012z'%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;cursor:default;display:inline-block;height:12px!important;padding:0 2px;-webkit-user-modify:read-only;-moz-user-modify:read-only;-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all;width:8px!important}.mce-content-body .mce-item-anchor[data-mce-selected]{outline-offset:1px}.tox-comments-visible .tox-comment{background-color:#fff0b7}.tox-comments-visible .tox-comment--active{background-color:#ffe168}.tox-checklist>li:not(.tox-checklist--hidden){list-style:none;margin:.25em 0}.tox-checklist>li:not(.tox-checklist--hidden)::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-unchecked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2215%22%20height%3D%2215%22%20x%3D%22.5%22%20y%3D%22.5%22%20fill-rule%3D%22nonzero%22%20stroke%3D%22%234C4C4C%22%20rx%3D%222%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A");cursor:pointer;height:1em;margin-left:-1.5em;margin-top:.125em;position:absolute;width:1em}.tox-checklist li:not(.tox-checklist--hidden).tox-checklist--checked::before{content:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cg%20id%3D%22checklist-checked%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Crect%20id%3D%22Rectangle%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22%234099FF%22%20fill-rule%3D%22nonzero%22%20rx%3D%222%22%2F%3E%3Cpath%20id%3D%22Path%22%20fill%3D%22%23FFF%22%20fill-rule%3D%22nonzero%22%20d%3D%22M11.5703186%2C3.14417309%20C11.8516238%2C2.73724603%2012.4164781%2C2.62829933%2012.83558%2C2.89774797%20C13.260121%2C3.17069355%2013.3759736%2C3.72932262%2013.0909105%2C4.14168582%20L7.7580587%2C11.8560195%20C7.43776896%2C12.3193404%206.76483983%2C12.3852142%206.35607322%2C11.9948725%20L3.02491697%2C8.8138662%20C2.66090143%2C8.46625845%202.65798871%2C7.89594698%203.01850234%2C7.54483354%20C3.373942%2C7.19866177%203.94940006%2C7.19592841%204.30829608%2C7.5386474%20L6.85276923%2C9.9684299%20L11.5703186%2C3.14417309%20Z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E%0A")}[dir=rtl] .tox-checklist>li:not(.tox-checklist--hidden)::before{margin-left:0;margin-right:-1.5em}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.mce-content-body{overflow-wrap:break-word;word-wrap:break-word}.mce-content-body .mce-visual-caret{background-color:#000;background-color:currentColor;position:absolute}.mce-content-body .mce-visual-caret-hidden{display:none}.mce-content-body [data-mce-caret]{left:-1000px;margin:0;padding:0;position:absolute;right:auto;top:0}.mce-content-body .mce-offscreen-selection{left:-2000000px;max-width:1000000px;position:absolute}.mce-content-body [contentEditable=false]{cursor:default}.mce-content-body [contentEditable=true]{cursor:text}.tox-cursor-format-painter{cursor:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%3E%0A%20%20%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M15%2C6%20C15%2C5.45%2014.55%2C5%2014%2C5%20L6%2C5%20C5.45%2C5%205%2C5.45%205%2C6%20L5%2C10%20C5%2C10.55%205.45%2C11%206%2C11%20L14%2C11%20C14.55%2C11%2015%2C10.55%2015%2C10%20L15%2C9%20L16%2C9%20L16%2C12%20L9%2C12%20L9%2C19%20C9%2C19.55%209.45%2C20%2010%2C20%20L11%2C20%20C11.55%2C20%2012%2C19.55%2012%2C19%20L12%2C14%20L18%2C14%20L18%2C7%20L15%2C7%20L15%2C6%20Z%22%2F%3E%0A%20%20%20%20%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22nonzero%22%20d%3D%22M1%2C1%20L8.25%2C1%20C8.66421356%2C1%209%2C1.33578644%209%2C1.75%20L9%2C1.75%20C9%2C2.16421356%208.66421356%2C2.5%208.25%2C2.5%20L2.5%2C2.5%20L2.5%2C8.25%20C2.5%2C8.66421356%202.16421356%2C9%201.75%2C9%20L1.75%2C9%20C1.33578644%2C9%201%2C8.66421356%201%2C8.25%20L1%2C1%20Z%22%2F%3E%0A%20%20%3C%2Fg%3E%0A%3C%2Fsvg%3E%0A"),default}.mce-content-body figure.align-left{float:left}.mce-content-body figure.align-right{float:right}.mce-content-body figure.image.align-center{display:table;margin-left:auto;margin-right:auto}.mce-preview-object{border:1px solid gray;display:inline-block;line-height:0;margin:0 2px 0 2px;position:relative}.mce-preview-object .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-object{background:transparent url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%203h16a1%201%200%200%201%201%201v16a1%201%200%200%201-1%201H4a1%201%200%200%201-1-1V4a1%201%200%200%201%201-1zm1%202v14h14V5H5zm4.79%202.565l5.64%204.028a.5.5%200%200%201%200%20.814l-5.64%204.028a.5.5%200%200%201-.79-.407V7.972a.5.5%200%200%201%20.79-.407z%22%2F%3E%3C%2Fsvg%3E%0A") no-repeat center;border:1px dashed #aaa}.mce-pagebreak{border:1px dashed #aaa;cursor:default;display:block;height:5px;margin-top:15px;page-break-before:always;width:100%}@media print{.mce-pagebreak{border:0}}.tiny-pageembed .mce-shim{background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);height:100%;left:0;position:absolute;top:0;width:100%}.tiny-pageembed[data-mce-selected="2"] .mce-shim{display:none}.tiny-pageembed{display:inline-block;position:relative}.tiny-pageembed--16by9,.tiny-pageembed--1by1,.tiny-pageembed--21by9,.tiny-pageembed--4by3{display:block;overflow:hidden;padding:0;position:relative;width:100%}.tiny-pageembed--21by9{padding-top:42.857143%}.tiny-pageembed--16by9{padding-top:56.25%}.tiny-pageembed--4by3{padding-top:75%}.tiny-pageembed--1by1{padding-top:100%}.tiny-pageembed--16by9 iframe,.tiny-pageembed--1by1 iframe,.tiny-pageembed--21by9 iframe,.tiny-pageembed--4by3 iframe{border:0;height:100%;left:0;position:absolute;top:0;width:100%}.mce-content-body[data-mce-placeholder]{position:relative}.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before{color:rgba(34,47,62,.7);content:attr(data-mce-placeholder);position:absolute}.mce-content-body:not([dir=rtl])[data-mce-placeholder]:not(.mce-visualblocks)::before{left:1px}.mce-content-body[dir=rtl][data-mce-placeholder]:not(.mce-visualblocks)::before{right:1px}.mce-content-body div.mce-resizehandle{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;height:10px;position:absolute;width:10px;z-index:1298}.mce-content-body div.mce-resizehandle:hover{background-color:#4099ff}.mce-content-body div.mce-resizehandle:nth-of-type(1){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(2){cursor:nesw-resize}.mce-content-body div.mce-resizehandle:nth-of-type(3){cursor:nwse-resize}.mce-content-body div.mce-resizehandle:nth-of-type(4){cursor:nesw-resize}.mce-content-body .mce-resize-backdrop{z-index:10000}.mce-content-body .mce-clonedresizable{cursor:default;opacity:.5;outline:1px dashed #000;position:absolute;z-index:10001}.mce-content-body .mce-clonedresizable.mce-resizetable-columns td,.mce-content-body .mce-clonedresizable.mce-resizetable-columns th{border:0}.mce-content-body .mce-resize-helper{background:#555;background:rgba(0,0,0,.75);border:1px;border-radius:3px;color:#fff;display:none;font-family:sans-serif;font-size:12px;line-height:14px;margin:5px 10px;padding:5px;position:absolute;white-space:nowrap;z-index:10002}.tox-rtc-user-selection{position:relative}.tox-rtc-user-cursor{bottom:0;cursor:default;position:absolute;top:0;width:2px}.tox-rtc-user-cursor::before{background-color:inherit;border-radius:50%;content:'';display:block;height:8px;position:absolute;right:-3px;top:-3px;width:8px}.tox-rtc-user-cursor:hover::after{background-color:inherit;border-radius:100px;box-sizing:border-box;color:#fff;content:attr(data-user);display:block;font-size:12px;font-weight:700;left:-5px;min-height:8px;min-width:8px;padding:0 12px;position:absolute;top:-11px;white-space:nowrap;z-index:1000}.tox-rtc-user-selection--1 .tox-rtc-user-cursor{background-color:#2dc26b}.tox-rtc-user-selection--2 .tox-rtc-user-cursor{background-color:#e03e2d}.tox-rtc-user-selection--3 .tox-rtc-user-cursor{background-color:#f1c40f}.tox-rtc-user-selection--4 .tox-rtc-user-cursor{background-color:#3598db}.tox-rtc-user-selection--5 .tox-rtc-user-cursor{background-color:#b96ad9}.tox-rtc-user-selection--6 .tox-rtc-user-cursor{background-color:#e67e23}.tox-rtc-user-selection--7 .tox-rtc-user-cursor{background-color:#aaa69d}.tox-rtc-user-selection--8 .tox-rtc-user-cursor{background-color:#f368e0}.tox-rtc-remote-image{background:#eaeaea url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2236%22%20height%3D%2212%22%20viewBox%3D%220%200%2036%2012%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Ccircle%20cx%3D%226%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2218%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.33s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%20%20%3Ccircle%20cx%3D%2230%22%20cy%3D%226%22%20r%3D%223%22%20fill%3D%22rgba(0%2C%200%2C%200%2C%20.2)%22%3E%0A%20%20%20%20%3Canimate%20attributeName%3D%22r%22%20values%3D%223%3B5%3B3%22%20calcMode%3D%22linear%22%20begin%3D%22.66s%22%20dur%3D%221s%22%20repeatCount%3D%22indefinite%22%20%2F%3E%0A%20%20%3C%2Fcircle%3E%0A%3C%2Fsvg%3E%0A") no-repeat center center;border:1px solid #ccc;min-height:240px;min-width:320px}.mce-match-marker{background:#aaa;color:#fff}.mce-match-marker-selected{background:#39f;color:#fff}.mce-match-marker-selected::-moz-selection{background:#39f;color:#fff}.mce-match-marker-selected::selection{background:#39f;color:#fff}.mce-content-body audio[data-mce-selected],.mce-content-body embed[data-mce-selected],.mce-content-body img[data-mce-selected],.mce-content-body object[data-mce-selected],.mce-content-body table[data-mce-selected],.mce-content-body video[data-mce-selected]{outline:3px solid #b4d7ff}.mce-content-body hr[data-mce-selected]{outline:3px solid #b4d7ff;outline-offset:1px}.mce-content-body [contentEditable=false] [contentEditable=true]:focus{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false] [contentEditable=true]:hover{outline:3px solid #b4d7ff}.mce-content-body [contentEditable=false][data-mce-selected]{cursor:not-allowed;outline:3px solid #b4d7ff}.mce-content-body.mce-content-readonly [contentEditable=true]:focus,.mce-content-body.mce-content-readonly [contentEditable=true]:hover{outline:0}.mce-content-body [data-mce-selected=inline-boundary]{background-color:#b4d7ff}.mce-content-body .mce-edit-focus{outline:3px solid #b4d7ff}.mce-content-body td[data-mce-selected],.mce-content-body th[data-mce-selected]{position:relative}.mce-content-body td[data-mce-selected]::-moz-selection,.mce-content-body th[data-mce-selected]::-moz-selection{background:0 0}.mce-content-body td[data-mce-selected]::selection,.mce-content-body th[data-mce-selected]::selection{background:0 0}.mce-content-body td[data-mce-selected] *,.mce-content-body th[data-mce-selected] *{outline:0;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{background-color:rgba(180,215,255,.7);border:1px solid rgba(180,215,255,.7);bottom:-1px;content:'';left:-1px;mix-blend-mode:multiply;position:absolute;right:-1px;top:-1px}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){.mce-content-body td[data-mce-selected]::after,.mce-content-body th[data-mce-selected]::after{border-color:rgba(0,84,180,.7)}}.mce-content-body img::-moz-selection{background:0 0}.mce-content-body img::selection{background:0 0}.ephox-snooker-resizer-bar{background-color:#b4d7ff;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:1}.mce-spellchecker-word{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%23ff0000'%20fill%3D'none'%20stroke-linecap%3D'round'%20stroke-opacity%3D'.75'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default;height:2rem}.mce-spellchecker-grammar{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D'4'%20height%3D'4'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%3E%3Cpath%20stroke%3D'%2300A835'%20fill%3D'none'%20stroke-linecap%3D'round'%20d%3D'M0%203L2%201%204%203'%2F%3E%3C%2Fsvg%3E%0A");background-position:0 calc(100% + 1px);background-repeat:repeat-x;background-size:auto 6px;cursor:default}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-item-table:not([border]),.mce-item-table:not([border]) caption,.mce-item-table:not([border]) td,.mce-item-table:not([border]) th,.mce-item-table[border="0"],.mce-item-table[border="0"] caption,.mce-item-table[border="0"] td,.mce-item-table[border="0"] th,table[style*="border-width: 0px"],table[style*="border-width: 0px"] caption,table[style*="border-width: 0px"] td,table[style*="border-width: 0px"] th{border:1px dashed #bbb}.mce-visualblocks address,.mce-visualblocks article,.mce-visualblocks aside,.mce-visualblocks blockquote,.mce-visualblocks div:not([data-mce-bogus]),.mce-visualblocks dl,.mce-visualblocks figcaption,.mce-visualblocks figure,.mce-visualblocks h1,.mce-visualblocks h2,.mce-visualblocks h3,.mce-visualblocks h4,.mce-visualblocks h5,.mce-visualblocks h6,.mce-visualblocks hgroup,.mce-visualblocks ol,.mce-visualblocks p,.mce-visualblocks pre,.mce-visualblocks section,.mce-visualblocks ul{background-repeat:no-repeat;border:1px dashed #bbb;margin-left:3px;padding-top:10px}.mce-visualblocks p{background-image:url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7)}.mce-visualblocks h1{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==)}.mce-visualblocks h2{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==)}.mce-visualblocks h3{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7)}.mce-visualblocks h4{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==)}.mce-visualblocks h5{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==)}.mce-visualblocks h6{background-image:url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==)}.mce-visualblocks div:not([data-mce-bogus]){background-image:url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7)}.mce-visualblocks section{background-image:url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=)}.mce-visualblocks article{background-image:url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7)}.mce-visualblocks blockquote{background-image:url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7)}.mce-visualblocks address{background-image:url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=)}.mce-visualblocks pre{background-image:url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==)}.mce-visualblocks figure{background-image:url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7)}.mce-visualblocks figcaption{border:1px dashed #bbb}.mce-visualblocks hgroup{background-image:url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7)}.mce-visualblocks aside{background-image:url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=)}.mce-visualblocks ul{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==)}.mce-visualblocks ol{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==)}.mce-visualblocks dl{background-image:url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==)}.mce-visualblocks:not([dir=rtl]) address,.mce-visualblocks:not([dir=rtl]) article,.mce-visualblocks:not([dir=rtl]) aside,.mce-visualblocks:not([dir=rtl]) blockquote,.mce-visualblocks:not([dir=rtl]) div:not([data-mce-bogus]),.mce-visualblocks:not([dir=rtl]) dl,.mce-visualblocks:not([dir=rtl]) figcaption,.mce-visualblocks:not([dir=rtl]) figure,.mce-visualblocks:not([dir=rtl]) h1,.mce-visualblocks:not([dir=rtl]) h2,.mce-visualblocks:not([dir=rtl]) h3,.mce-visualblocks:not([dir=rtl]) h4,.mce-visualblocks:not([dir=rtl]) h5,.mce-visualblocks:not([dir=rtl]) h6,.mce-visualblocks:not([dir=rtl]) hgroup,.mce-visualblocks:not([dir=rtl]) ol,.mce-visualblocks:not([dir=rtl]) p,.mce-visualblocks:not([dir=rtl]) pre,.mce-visualblocks:not([dir=rtl]) section,.mce-visualblocks:not([dir=rtl]) ul{margin-left:3px}.mce-visualblocks[dir=rtl] address,.mce-visualblocks[dir=rtl] article,.mce-visualblocks[dir=rtl] aside,.mce-visualblocks[dir=rtl] blockquote,.mce-visualblocks[dir=rtl] div:not([data-mce-bogus]),.mce-visualblocks[dir=rtl] dl,.mce-visualblocks[dir=rtl] figcaption,.mce-visualblocks[dir=rtl] figure,.mce-visualblocks[dir=rtl] h1,.mce-visualblocks[dir=rtl] h2,.mce-visualblocks[dir=rtl] h3,.mce-visualblocks[dir=rtl] h4,.mce-visualblocks[dir=rtl] h5,.mce-visualblocks[dir=rtl] h6,.mce-visualblocks[dir=rtl] hgroup,.mce-visualblocks[dir=rtl] ol,.mce-visualblocks[dir=rtl] p,.mce-visualblocks[dir=rtl] pre,.mce-visualblocks[dir=rtl] section,.mce-visualblocks[dir=rtl] ul{background-position-x:right;margin-right:3px}.mce-nbsp,.mce-shy{background:#aaa}.mce-shy::after{content:'-'}body{font-family:sans-serif}table{border-collapse:collapse} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css new file mode 100644 index 0000000..35f7dc0 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff b/frontend/vben/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff new file mode 100644 index 0000000000000000000000000000000000000000..1e3be038a607cb7c2544ed8ae3d6621f77bf4c38 GIT binary patch literal 4624 zcmb7IeQaFC5#QN&AGUL{efE7g{=BM1W-|RaVdWQe^e?BC`eGz4^i8S3PQw?Hhd_eQHxTkckXZB zdzU((wCVGko!Qyh+1c6InRotvZ%+>+hNrBQtrFOI4t*}DZ$7=>Sr=uD3c$ZlKuKBQ z8~ervCczs9SOk2!>AAqrz+v$CC}f1JfYPDSqx->|V$6{ekbe8M#Bh3Gkg?)-Fdi3B zeB$}UFqn*$pv&q7*net~hsUOlfG7Ho2zaowY%JPRytMvu{&xRPm(h_~w##F>vqE&a5-ssH##mlfAk}44^ zXRJKd!Ifw&ce{$Y9BAg5c>e>p_Z;t!=P{izddGWie?aHLdKL3Cn9rG=d2vt;esWqH zoD}uAoi3Z~4+LABvADt+so4~t%VlyIJ{O3tm$NC+(!yenQD%NVr*btG$T3+_WX=LH z#1M2ZNEtrO+-x;l2i>M^5o%GQ@s?N+gw*19H@G~vl3Q5Zf*t6jjW0GOTmAmlWYgSS zJeiEo%~LA-FW|YAd_Em$OE#@dw)y*#@p!UtnWa);V1HY3ZBw!>(3gY{iFFa_c6iW9 zIQ@xck^{xu9_o;UyQH#ba@y?L$xW?8J35?$p1z46ZjIctZ8QCKCa29bMC1-t@pT>S zTUT1WMjQz-75d)5zJxv~@Yd)bY)ejQBx_XQiaMJ z>$5`NO3?L*ND{UQeF8%xl)$_>w9tmQpfEebzedazFeh#~d}suN+vzsqLiW~@TLhoe zk1%xEcxP2ZL)FuoXeYzb-J5goljDxPL2@@#RW)d&X#&6QO5U=04_628@ONSvtgpha zDqqmoVep`A4<+PK$V>K+T}}{8Rj+Q|UAzCtl!Fh)uXJg{x$}HMJH7LcBLzj-r{h;< zzote8Id%pcAyE;87D<8glyaFeq#k)OEDB%yA ze%CeZ!?4TEs#pj+%14DBZHn8jxaF2as6}p3+!6p-&@I>5lbP3&N$svcIF-`0R5(o2 zh7la++|;-euckH44a4BAwB++#-cZ z)kFyC=eUS-4D0t}H8LdZY!JD^sW@F85io)%=8HU)ouhEeo-K_dJ3BV+8fo0JXIjlP zZt0H`0=Yv~I|PpRZ)r5_iAYmY9V=wT@BsoN9<3vftB|}TOH;|yNk_e7(2-?y{&cSK zG=E5Nz^Ko4>KxcbY!Q13!=HBS$lM96_+0y3M1yWTAt2u5C;6MWMXbRN?RI{$eHnAx z&t=-PSjZ>Qe2V2-YGs1YWemAq zVHdG{9V$QvsY~Cgq-L*PZqMPGv|px$)K~3<%+fBtG{oIRPL_7ye$-(`C=tS)^xC}% zue73qiF&{nXJ*>-@668G!`IrAeB;ad09shzt{O?7omLE_X@H|#ozGt&64 zb-&_lLkZI8TzigPZvUr=4g2-8M6M8b9EQLgoPswYg)d)j&%gZHJO!2>(?;I*8d>aG z#oS295Kcq{uD4R2@VEG($}WWiF-6YK)kjqks%o_U{CIAVX2;tX7o|unkew5?Gn3(| zOePS^{$(;Xi4ph;`KO#;k+vaLt8n5@doi+OEvH&?*+3(WgqkT9-$b0fTHm;)r=NmR zJnJ9o>UvNR(JMoIdRBf{%kd}jmZ)b)#4>dnDfq0G(?~S%d zv50QeMR$Kzd*S$AEXdp5Fhqe0Pz zZ!oS2e!i-tWEJ2^YoVo}V7S0tV7CujimbVJtVNb#yB&<-f&xpSb@m2=wBZ|qU-_^; z?C{lk+;tlxk&Sh3Pwh(D7~kNh`O=~TMWuRUu^0=9)`CYEVwhvGWUt4Wd3`6*H)Zs>LLYQcC#*~B78EfTt7RQ*l)b{v zqntLNsC`h&zZCY{x*}gfPU4at;nfileU3>zeyLdO7;;lFIft~ zsm6#wb5Jjtv;_VxleU0<%cQON-O*ywHt`@C4fn-Y83}=|hJPOpN>1H%C#7)9etg_yG)$div{padding-bottom:4px}.tox .accessibility-issue__description>div>div{align-items:center;display:flex;margin-bottom:4px}.tox .accessibility-issue__description>:last-child:not(:only-child){border-color:#ccc;border-style:solid}.tox .accessibility-issue__repair{margin-top:16px}.tox .tox-dialog__body-content .accessibility-issue--info .accessibility-issue__description{background-color:rgba(32,122,183,.1);border-color:rgba(32,122,183,.4);color:#222f3e}.tox .tox-dialog__body-content .accessibility-issue--info .accessibility-issue__description>:last-child{border-color:rgba(32,122,183,.4)}.tox .tox-dialog__body-content .accessibility-issue--info .tox-form__group h2{color:#207ab7}.tox .tox-dialog__body-content .accessibility-issue--info .tox-icon svg{fill:#207ab7}.tox .tox-dialog__body-content .accessibility-issue--info a .tox-icon{color:#207ab7}.tox .tox-dialog__body-content .accessibility-issue--warn .accessibility-issue__description{background-color:rgba(255,165,0,.1);border-color:rgba(255,165,0,.5);color:#222f3e}.tox .tox-dialog__body-content .accessibility-issue--warn .accessibility-issue__description>:last-child{border-color:rgba(255,165,0,.5)}.tox .tox-dialog__body-content .accessibility-issue--warn .tox-form__group h2{color:#cc8500}.tox .tox-dialog__body-content .accessibility-issue--warn .tox-icon svg{fill:#cc8500}.tox .tox-dialog__body-content .accessibility-issue--warn a .tox-icon{color:#cc8500}.tox .tox-dialog__body-content .accessibility-issue--error .accessibility-issue__description{background-color:rgba(204,0,0,.1);border-color:rgba(204,0,0,.4);color:#222f3e}.tox .tox-dialog__body-content .accessibility-issue--error .accessibility-issue__description>:last-child{border-color:rgba(204,0,0,.4)}.tox .tox-dialog__body-content .accessibility-issue--error .tox-form__group h2{color:#c00}.tox .tox-dialog__body-content .accessibility-issue--error .tox-icon svg{fill:#c00}.tox .tox-dialog__body-content .accessibility-issue--error a .tox-icon{color:#c00}.tox .tox-dialog__body-content .accessibility-issue--success .accessibility-issue__description{background-color:rgba(120,171,70,.1);border-color:rgba(120,171,70,.4);color:#222f3e}.tox .tox-dialog__body-content .accessibility-issue--success .accessibility-issue__description>:last-child{border-color:rgba(120,171,70,.4)}.tox .tox-dialog__body-content .accessibility-issue--success .tox-form__group h2{color:#78ab46}.tox .tox-dialog__body-content .accessibility-issue--success .tox-icon svg{fill:#78ab46}.tox .tox-dialog__body-content .accessibility-issue--success a .tox-icon{color:#78ab46}.tox .tox-dialog__body-content .accessibility-issue__header h1,.tox .tox-dialog__body-content .tox-form__group .accessibility-issue__description h2{margin-top:0}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__header .tox-button{margin-left:4px}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__header>:nth-last-child(2){margin-left:auto}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__description{padding:4px 4px 4px 8px}.tox:not([dir=rtl]) .tox-dialog__body-content .accessibility-issue__description>:last-child{border-left-width:1px;padding-left:4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__header .tox-button{margin-right:4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__header>:nth-last-child(2){margin-right:auto}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__description{padding:4px 8px 4px 4px}.tox[dir=rtl] .tox-dialog__body-content .accessibility-issue__description>:last-child{border-right-width:1px;padding-right:4px}.tox .tox-anchorbar{display:flex;flex:0 0 auto}.tox .tox-bar{display:flex;flex:0 0 auto}.tox .tox-button{background-color:#207ab7;background-image:none;background-position:0 0;background-repeat:repeat;border-color:#207ab7;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#fff;cursor:pointer;display:inline-block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:14px;font-style:normal;font-weight:700;letter-spacing:normal;line-height:24px;margin:0;outline:0;padding:4px 16px;text-align:center;text-decoration:none;text-transform:none;white-space:nowrap}.tox .tox-button[disabled]{background-color:#207ab7;background-image:none;border-color:#207ab7;box-shadow:none;color:rgba(255,255,255,.5);cursor:not-allowed}.tox .tox-button:focus:not(:disabled){background-color:#1c6ca1;background-image:none;border-color:#1c6ca1;box-shadow:none;color:#fff}.tox .tox-button:hover:not(:disabled){background-color:#1c6ca1;background-image:none;border-color:#1c6ca1;box-shadow:none;color:#fff}.tox .tox-button:active:not(:disabled){background-color:#185d8c;background-image:none;border-color:#185d8c;box-shadow:none;color:#fff}.tox .tox-button--secondary{background-color:#f0f0f0;background-image:none;background-position:0 0;background-repeat:repeat;border-color:#f0f0f0;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;color:#222f3e;font-size:14px;font-style:normal;font-weight:700;letter-spacing:normal;outline:0;padding:4px 16px;text-decoration:none;text-transform:none}.tox .tox-button--secondary[disabled]{background-color:#f0f0f0;background-image:none;border-color:#f0f0f0;box-shadow:none;color:rgba(34,47,62,.5)}.tox .tox-button--secondary:focus:not(:disabled){background-color:#e3e3e3;background-image:none;border-color:#e3e3e3;box-shadow:none;color:#222f3e}.tox .tox-button--secondary:hover:not(:disabled){background-color:#e3e3e3;background-image:none;border-color:#e3e3e3;box-shadow:none;color:#222f3e}.tox .tox-button--secondary:active:not(:disabled){background-color:#d6d6d6;background-image:none;border-color:#d6d6d6;box-shadow:none;color:#222f3e}.tox .tox-button--icon,.tox .tox-button.tox-button--icon,.tox .tox-button.tox-button--secondary.tox-button--icon{padding:4px}.tox .tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--icon .tox-icon svg,.tox .tox-button.tox-button--secondary.tox-button--icon .tox-icon svg{display:block;fill:currentColor}.tox .tox-button-link{background:0;border:none;box-sizing:border-box;cursor:pointer;display:inline-block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;white-space:nowrap}.tox .tox-button-link--sm{font-size:14px}.tox .tox-button--naked{background-color:transparent;border-color:transparent;box-shadow:unset;color:#222f3e}.tox .tox-button--naked[disabled]{background-color:#f0f0f0;border-color:#f0f0f0;box-shadow:none;color:rgba(34,47,62,.5)}.tox .tox-button--naked:hover:not(:disabled){background-color:#e3e3e3;border-color:#e3e3e3;box-shadow:none;color:#222f3e}.tox .tox-button--naked:focus:not(:disabled){background-color:#e3e3e3;border-color:#e3e3e3;box-shadow:none;color:#222f3e}.tox .tox-button--naked:active:not(:disabled){background-color:#d6d6d6;border-color:#d6d6d6;box-shadow:none;color:#222f3e}.tox .tox-button--naked .tox-icon svg{fill:currentColor}.tox .tox-button--naked.tox-button--icon:hover:not(:disabled){color:#222f3e}.tox .tox-checkbox{align-items:center;border-radius:3px;cursor:pointer;display:flex;height:36px;min-width:36px}.tox .tox-checkbox__input{height:1px;overflow:hidden;position:absolute;top:auto;width:1px}.tox .tox-checkbox__icons{align-items:center;border-radius:3px;box-shadow:0 0 0 2px transparent;box-sizing:content-box;display:flex;height:24px;justify-content:center;padding:calc(4px - 1px);width:24px}.tox .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:block;fill:rgba(34,47,62,.3)}.tox .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display:none;fill:#207ab7}.tox .tox-checkbox__icons .tox-checkbox-icon__checked svg{display:none;fill:#207ab7}.tox .tox-checkbox--disabled{color:rgba(34,47,62,.5);cursor:not-allowed}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__checked svg{fill:rgba(34,47,62,.5)}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__unchecked svg{fill:rgba(34,47,62,.5)}.tox .tox-checkbox--disabled .tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{fill:rgba(34,47,62,.5)}.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:none}.tox input.tox-checkbox__input:checked+.tox-checkbox__icons .tox-checkbox-icon__checked svg{display:block}.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__unchecked svg{display:none}.tox input.tox-checkbox__input:indeterminate+.tox-checkbox__icons .tox-checkbox-icon__indeterminate svg{display:block}.tox input.tox-checkbox__input:focus+.tox-checkbox__icons{border-radius:3px;box-shadow:inset 0 0 0 1px #207ab7;padding:calc(4px - 1px)}.tox:not([dir=rtl]) .tox-checkbox__label{margin-left:4px}.tox:not([dir=rtl]) .tox-checkbox__input{left:-10000px}.tox:not([dir=rtl]) .tox-bar .tox-checkbox{margin-left:4px}.tox[dir=rtl] .tox-checkbox__label{margin-right:4px}.tox[dir=rtl] .tox-checkbox__input{right:-10000px}.tox[dir=rtl] .tox-bar .tox-checkbox{margin-right:4px}.tox .tox-collection--toolbar .tox-collection__group{display:flex;padding:0}.tox .tox-collection--grid .tox-collection__group{display:flex;flex-wrap:wrap;max-height:208px;overflow-x:hidden;overflow-y:auto;padding:0}.tox .tox-collection--list .tox-collection__group{border-bottom-width:0;border-color:#ccc;border-left-width:0;border-right-width:0;border-style:solid;border-top-width:1px;padding:4px 0}.tox .tox-collection--list .tox-collection__group:first-child{border-top-width:0}.tox .tox-collection__group-heading{background-color:#e6e6e6;color:rgba(34,47,62,.7);cursor:default;font-size:12px;font-style:normal;font-weight:400;margin-bottom:4px;margin-top:-4px;padding:4px 8px;text-transform:none;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tox .tox-collection__item{align-items:center;color:#222f3e;cursor:pointer;display:flex;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tox .tox-collection--list .tox-collection__item{padding:4px 8px}.tox .tox-collection--toolbar .tox-collection__item{border-radius:3px;padding:4px}.tox .tox-collection--grid .tox-collection__item{border-radius:3px;padding:4px}.tox .tox-collection--list .tox-collection__item--enabled{background-color:#fff;color:#222f3e}.tox .tox-collection--list .tox-collection__item--active{background-color:#dee0e2}.tox .tox-collection--toolbar .tox-collection__item--enabled{background-color:#c8cbcf;color:#222f3e}.tox .tox-collection--toolbar .tox-collection__item--active{background-color:#dee0e2}.tox .tox-collection--grid .tox-collection__item--enabled{background-color:#c8cbcf;color:#222f3e}.tox .tox-collection--grid .tox-collection__item--active:not(.tox-collection__item--state-disabled){background-color:#dee0e2;color:#222f3e}.tox .tox-collection--list .tox-collection__item--active:not(.tox-collection__item--state-disabled){color:#222f3e}.tox .tox-collection--toolbar .tox-collection__item--active:not(.tox-collection__item--state-disabled){color:#222f3e}.tox .tox-collection__item-checkmark,.tox .tox-collection__item-icon{align-items:center;display:flex;height:24px;justify-content:center;width:24px}.tox .tox-collection__item-checkmark svg,.tox .tox-collection__item-icon svg{fill:currentColor}.tox .tox-collection--toolbar-lg .tox-collection__item-icon{height:48px;width:48px}.tox .tox-collection__item-label{color:currentColor;display:inline-block;flex:1;-ms-flex-preferred-size:auto;font-size:14px;font-style:normal;font-weight:400;line-height:24px;text-transform:none;word-break:break-all}.tox .tox-collection__item-accessory{color:rgba(34,47,62,.7);display:inline-block;font-size:14px;height:24px;line-height:24px;text-transform:none}.tox .tox-collection__item-caret{align-items:center;display:flex;min-height:24px}.tox .tox-collection__item-caret::after{content:'';font-size:0;min-height:inherit}.tox .tox-collection__item-caret svg{fill:#222f3e}.tox .tox-collection__item--state-disabled{background-color:transparent;color:rgba(34,47,62,.5);cursor:not-allowed}.tox .tox-collection__item--state-disabled .tox-collection__item-caret svg{fill:rgba(34,47,62,.5)}.tox .tox-collection--list .tox-collection__item:not(.tox-collection__item--enabled) .tox-collection__item-checkmark svg{display:none}.tox .tox-collection--list .tox-collection__item:not(.tox-collection__item--enabled) .tox-collection__item-accessory+.tox-collection__item-checkmark{display:none}.tox .tox-collection--horizontal{background-color:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15);display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:nowrap;margin-bottom:0;overflow-x:auto;padding:0}.tox .tox-collection--horizontal .tox-collection__group{align-items:center;display:flex;flex-wrap:nowrap;margin:0;padding:0 4px}.tox .tox-collection--horizontal .tox-collection__item{height:34px;margin:2px 0 3px 0;padding:0 4px}.tox .tox-collection--horizontal .tox-collection__item-label{white-space:nowrap}.tox .tox-collection--horizontal .tox-collection__item-caret{margin-left:4px}.tox .tox-collection__item-container{display:flex}.tox .tox-collection__item-container--row{align-items:center;flex:1 1 auto;flex-direction:row}.tox .tox-collection__item-container--row.tox-collection__item-container--align-left{margin-right:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--align-right{justify-content:flex-end;margin-left:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-top{align-items:flex-start;margin-bottom:auto}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-middle{align-items:center}.tox .tox-collection__item-container--row.tox-collection__item-container--valign-bottom{align-items:flex-end;margin-top:auto}.tox .tox-collection__item-container--column{-ms-grid-row-align:center;align-self:center;flex:1 1 auto;flex-direction:column}.tox .tox-collection__item-container--column.tox-collection__item-container--align-left{align-items:flex-start}.tox .tox-collection__item-container--column.tox-collection__item-container--align-right{align-items:flex-end}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-top{align-self:flex-start}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-middle{-ms-grid-row-align:center;align-self:center}.tox .tox-collection__item-container--column.tox-collection__item-container--valign-bottom{align-self:flex-end}.tox:not([dir=rtl]) .tox-collection--horizontal .tox-collection__group:not(:last-of-type){border-right:1px solid #ccc}.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>:not(:first-child){margin-left:8px}.tox:not([dir=rtl]) .tox-collection--list .tox-collection__item>.tox-collection__item-label:first-child{margin-left:4px}.tox:not([dir=rtl]) .tox-collection__item-accessory{margin-left:16px;text-align:right}.tox:not([dir=rtl]) .tox-collection .tox-collection__item-caret{margin-left:16px}.tox[dir=rtl] .tox-collection--horizontal .tox-collection__group:not(:last-of-type){border-left:1px solid #ccc}.tox[dir=rtl] .tox-collection--list .tox-collection__item>:not(:first-child){margin-right:8px}.tox[dir=rtl] .tox-collection--list .tox-collection__item>.tox-collection__item-label:first-child{margin-right:4px}.tox[dir=rtl] .tox-collection__item-accessory{margin-right:16px;text-align:left}.tox[dir=rtl] .tox-collection .tox-collection__item-caret{margin-right:16px;transform:rotateY(180deg)}.tox[dir=rtl] .tox-collection--horizontal .tox-collection__item-caret{margin-right:4px}.tox .tox-color-picker-container{display:flex;flex-direction:row;height:225px;margin:0}.tox .tox-sv-palette{box-sizing:border-box;display:flex;height:100%}.tox .tox-sv-palette-spectrum{height:100%}.tox .tox-sv-palette,.tox .tox-sv-palette-spectrum{width:225px}.tox .tox-sv-palette-thumb{background:0 0;border:1px solid #000;border-radius:50%;box-sizing:content-box;height:12px;position:absolute;width:12px}.tox .tox-sv-palette-inner-thumb{border:1px solid #fff;border-radius:50%;height:10px;position:absolute;width:10px}.tox .tox-hue-slider{box-sizing:border-box;height:100%;width:25px}.tox .tox-hue-slider-spectrum{background:linear-gradient(to bottom,red,#ff0080,#f0f,#8000ff,#00f,#0080ff,#0ff,#00ff80,#0f0,#80ff00,#ff0,#ff8000,red);height:100%;width:100%}.tox .tox-hue-slider,.tox .tox-hue-slider-spectrum{width:20px}.tox .tox-hue-slider-thumb{background:#fff;border:1px solid #000;box-sizing:content-box;height:4px;width:100%}.tox .tox-rgb-form{display:flex;flex-direction:column;justify-content:space-between}.tox .tox-rgb-form div{align-items:center;display:flex;justify-content:space-between;margin-bottom:5px;width:inherit}.tox .tox-rgb-form input{width:6em}.tox .tox-rgb-form input.tox-invalid{border:1px solid red!important}.tox .tox-rgb-form .tox-rgba-preview{border:1px solid #000;flex-grow:2;margin-bottom:0}.tox:not([dir=rtl]) .tox-sv-palette{margin-right:15px}.tox:not([dir=rtl]) .tox-hue-slider{margin-right:15px}.tox:not([dir=rtl]) .tox-hue-slider-thumb{margin-left:-1px}.tox:not([dir=rtl]) .tox-rgb-form label{margin-right:.5em}.tox[dir=rtl] .tox-sv-palette{margin-left:15px}.tox[dir=rtl] .tox-hue-slider{margin-left:15px}.tox[dir=rtl] .tox-hue-slider-thumb{margin-right:-1px}.tox[dir=rtl] .tox-rgb-form label{margin-left:.5em}.tox .tox-toolbar .tox-swatches,.tox .tox-toolbar__overflow .tox-swatches,.tox .tox-toolbar__primary .tox-swatches{margin:2px 0 3px 4px}.tox .tox-collection--list .tox-collection__group .tox-swatches-menu{border:0;margin:-4px 0}.tox .tox-swatches__row{display:flex}.tox .tox-swatch{height:30px;transition:transform .15s,box-shadow .15s;width:30px}.tox .tox-swatch:focus,.tox .tox-swatch:hover{box-shadow:0 0 0 1px rgba(127,127,127,.3) inset;transform:scale(.8)}.tox .tox-swatch--remove{align-items:center;display:flex;justify-content:center}.tox .tox-swatch--remove svg path{stroke:#e74c3c}.tox .tox-swatches__picker-btn{align-items:center;background-color:transparent;border:0;cursor:pointer;display:flex;height:30px;justify-content:center;outline:0;padding:0;width:30px}.tox .tox-swatches__picker-btn svg{height:24px;width:24px}.tox .tox-swatches__picker-btn:hover{background:#dee0e2}.tox:not([dir=rtl]) .tox-swatches__picker-btn{margin-left:auto}.tox[dir=rtl] .tox-swatches__picker-btn{margin-right:auto}.tox .tox-comment-thread{background:#fff;position:relative}.tox .tox-comment-thread>:not(:first-child){margin-top:8px}.tox .tox-comment{background:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 4px 8px 0 rgba(34,47,62,.1);padding:8px 8px 16px 8px;position:relative}.tox .tox-comment__header{align-items:center;color:#222f3e;display:flex;justify-content:space-between}.tox .tox-comment__date{color:rgba(34,47,62,.7);font-size:12px}.tox .tox-comment__body{color:#222f3e;font-size:14px;font-style:normal;font-weight:400;line-height:1.3;margin-top:8px;position:relative;text-transform:initial}.tox .tox-comment__body textarea{resize:none;white-space:normal;width:100%}.tox .tox-comment__expander{padding-top:8px}.tox .tox-comment__expander p{color:rgba(34,47,62,.7);font-size:14px;font-style:normal}.tox .tox-comment__body p{margin:0}.tox .tox-comment__buttonspacing{padding-top:16px;text-align:center}.tox .tox-comment-thread__overlay::after{background:#fff;bottom:0;content:"";display:flex;left:0;opacity:.9;position:absolute;right:0;top:0;z-index:5}.tox .tox-comment__reply{display:flex;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;margin-top:8px}.tox .tox-comment__reply>:first-child{margin-bottom:8px;width:100%}.tox .tox-comment__edit{display:flex;flex-wrap:wrap;justify-content:flex-end;margin-top:16px}.tox .tox-comment__gradient::after{background:linear-gradient(rgba(255,255,255,0),#fff);bottom:0;content:"";display:block;height:5em;margin-top:-40px;position:absolute;width:100%}.tox .tox-comment__overlay{background:#fff;bottom:0;display:flex;flex-direction:column;flex-grow:1;left:0;opacity:.9;position:absolute;right:0;text-align:center;top:0;z-index:5}.tox .tox-comment__loading-text{align-items:center;color:#222f3e;display:flex;flex-direction:column;position:relative}.tox .tox-comment__loading-text>div{padding-bottom:16px}.tox .tox-comment__overlaytext{bottom:0;flex-direction:column;font-size:14px;left:0;padding:1em;position:absolute;right:0;top:0;z-index:10}.tox .tox-comment__overlaytext p{background-color:#fff;box-shadow:0 0 8px 8px #fff;color:#222f3e;text-align:center}.tox .tox-comment__overlaytext div:nth-of-type(2){font-size:.8em}.tox .tox-comment__busy-spinner{align-items:center;background-color:#fff;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:20}.tox .tox-comment__scroll{display:flex;flex-direction:column;flex-shrink:1;overflow:auto}.tox .tox-conversations{margin:8px}.tox:not([dir=rtl]) .tox-comment__edit{margin-left:8px}.tox:not([dir=rtl]) .tox-comment__buttonspacing>:last-child,.tox:not([dir=rtl]) .tox-comment__edit>:last-child,.tox:not([dir=rtl]) .tox-comment__reply>:last-child{margin-left:8px}.tox[dir=rtl] .tox-comment__edit{margin-right:8px}.tox[dir=rtl] .tox-comment__buttonspacing>:last-child,.tox[dir=rtl] .tox-comment__edit>:last-child,.tox[dir=rtl] .tox-comment__reply>:last-child{margin-right:8px}.tox .tox-user{align-items:center;display:flex}.tox .tox-user__avatar svg{fill:rgba(34,47,62,.7)}.tox .tox-user__name{color:rgba(34,47,62,.7);font-size:12px;font-style:normal;font-weight:700;text-transform:uppercase}.tox:not([dir=rtl]) .tox-user__avatar svg{margin-right:8px}.tox:not([dir=rtl]) .tox-user__avatar+.tox-user__name{margin-left:8px}.tox[dir=rtl] .tox-user__avatar svg{margin-left:8px}.tox[dir=rtl] .tox-user__avatar+.tox-user__name{margin-right:8px}.tox .tox-dialog-wrap{align-items:center;bottom:0;display:flex;justify-content:center;left:0;position:fixed;right:0;top:0;z-index:1100}.tox .tox-dialog-wrap__backdrop{background-color:rgba(255,255,255,.75);bottom:0;left:0;position:absolute;right:0;top:0;z-index:1}.tox .tox-dialog-wrap__backdrop--opaque{background-color:#fff}.tox .tox-dialog{background-color:#fff;border-color:#ccc;border-radius:3px;border-style:solid;border-width:1px;box-shadow:0 16px 16px -10px rgba(34,47,62,.15),0 0 40px 1px rgba(34,47,62,.15);display:flex;flex-direction:column;max-height:100%;max-width:480px;overflow:hidden;position:relative;width:95vw;z-index:2}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog{align-self:flex-start;margin:8px auto;width:calc(100vw - 16px)}}.tox .tox-dialog-inline{z-index:1100}.tox .tox-dialog__header{align-items:center;background-color:#fff;border-bottom:none;color:#222f3e;display:flex;font-size:16px;justify-content:space-between;padding:8px 16px 0 16px;position:relative}.tox .tox-dialog__header .tox-button{z-index:1}.tox .tox-dialog__draghandle{cursor:grab;height:100%;left:0;position:absolute;top:0;width:100%}.tox .tox-dialog__draghandle:active{cursor:grabbing}.tox .tox-dialog__dismiss{margin-left:auto}.tox .tox-dialog__title{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1.3;margin:0;text-transform:none}.tox .tox-dialog__body{color:#222f3e;display:flex;flex:1;-ms-flex-preferred-size:auto;font-size:16px;font-style:normal;font-weight:400;line-height:1.3;min-width:0;text-align:left;text-transform:none}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog__body{flex-direction:column}}.tox .tox-dialog__body-nav{align-items:flex-start;display:flex;flex-direction:column;padding:16px 16px}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox .tox-dialog__body-nav{flex-direction:row;-webkit-overflow-scrolling:touch;overflow-x:auto;padding-bottom:0}}.tox .tox-dialog__body-nav-item{border-bottom:2px solid transparent;color:rgba(34,47,62,.7);display:inline-block;font-size:14px;line-height:1.3;margin-bottom:8px;text-decoration:none;white-space:nowrap}.tox .tox-dialog__body-nav-item:focus{background-color:rgba(32,122,183,.1)}.tox .tox-dialog__body-nav-item--active{border-bottom:2px solid #207ab7;color:#207ab7}.tox .tox-dialog__body-content{box-sizing:border-box;display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto;max-height:650px;overflow:auto;-webkit-overflow-scrolling:touch;padding:16px 16px}.tox .tox-dialog__body-content>*{margin-bottom:0;margin-top:16px}.tox .tox-dialog__body-content>:first-child{margin-top:0}.tox .tox-dialog__body-content>:last-child{margin-bottom:0}.tox .tox-dialog__body-content>:only-child{margin-bottom:0;margin-top:0}.tox .tox-dialog__body-content a{color:#207ab7;cursor:pointer;text-decoration:none}.tox .tox-dialog__body-content a:focus,.tox .tox-dialog__body-content a:hover{color:#185d8c;text-decoration:none}.tox .tox-dialog__body-content a:active{color:#185d8c;text-decoration:none}.tox .tox-dialog__body-content svg{fill:#222f3e}.tox .tox-dialog__body-content ul{display:block;list-style-type:disc;margin-bottom:16px;-webkit-margin-end:0;margin-inline-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-padding-start:2.5rem;padding-inline-start:2.5rem}.tox .tox-dialog__body-content .tox-form__group h1{color:#222f3e;font-size:20px;font-style:normal;font-weight:700;letter-spacing:normal;margin-bottom:16px;margin-top:2rem;text-transform:none}.tox .tox-dialog__body-content .tox-form__group h2{color:#222f3e;font-size:16px;font-style:normal;font-weight:700;letter-spacing:normal;margin-bottom:16px;margin-top:2rem;text-transform:none}.tox .tox-dialog__body-content .tox-form__group p{margin-bottom:16px}.tox .tox-dialog__body-content .tox-form__group h1:first-child,.tox .tox-dialog__body-content .tox-form__group h2:first-child,.tox .tox-dialog__body-content .tox-form__group p:first-child{margin-top:0}.tox .tox-dialog__body-content .tox-form__group h1:last-child,.tox .tox-dialog__body-content .tox-form__group h2:last-child,.tox .tox-dialog__body-content .tox-form__group p:last-child{margin-bottom:0}.tox .tox-dialog__body-content .tox-form__group h1:only-child,.tox .tox-dialog__body-content .tox-form__group h2:only-child,.tox .tox-dialog__body-content .tox-form__group p:only-child{margin-bottom:0;margin-top:0}.tox .tox-dialog--width-lg{height:650px;max-width:1200px}.tox .tox-dialog--width-md{max-width:800px}.tox .tox-dialog--width-md .tox-dialog__body-content{overflow:auto}.tox .tox-dialog__body-content--centered{text-align:center}.tox .tox-dialog__footer{align-items:center;background-color:#fff;border-top:1px solid #ccc;display:flex;justify-content:space-between;padding:8px 16px}.tox .tox-dialog__footer-end,.tox .tox-dialog__footer-start{display:flex}.tox .tox-dialog__busy-spinner{align-items:center;background-color:rgba(255,255,255,.75);bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0;z-index:3}.tox .tox-dialog__table{border-collapse:collapse;width:100%}.tox .tox-dialog__table thead th{font-weight:700;padding-bottom:8px}.tox .tox-dialog__table tbody tr{border-bottom:1px solid #ccc}.tox .tox-dialog__table tbody tr:last-child{border-bottom:none}.tox .tox-dialog__table td{padding-bottom:8px;padding-top:8px}.tox .tox-dialog__popups{position:absolute;width:100%;z-index:1100}.tox .tox-dialog__body-iframe{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-iframe .tox-navobj{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-iframe .tox-navobj :nth-child(2){flex:1;-ms-flex-preferred-size:auto;height:100%}.tox .tox-dialog-dock-fadeout{opacity:0;visibility:hidden}.tox .tox-dialog-dock-fadein{opacity:1;visibility:visible}.tox .tox-dialog-dock-transition{transition:visibility 0s linear .3s,opacity .3s ease}.tox .tox-dialog-dock-transition.tox-dialog-dock-fadein{transition-delay:0s}.tox.tox-platform-ie .tox-dialog-wrap{position:-ms-device-fixed}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav{margin-right:0}}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox:not([dir=rtl]) .tox-dialog__body-nav-item:not(:first-child){margin-left:8px}}.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-end>*,.tox:not([dir=rtl]) .tox-dialog__footer .tox-dialog__footer-start>*{margin-left:8px}.tox[dir=rtl] .tox-dialog__body{text-align:right}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav{margin-left:0}}@media only screen and (max-width:767px){body:not(.tox-force-desktop) .tox[dir=rtl] .tox-dialog__body-nav-item:not(:first-child){margin-right:8px}}.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-end>*,.tox[dir=rtl] .tox-dialog__footer .tox-dialog__footer-start>*{margin-right:8px}body.tox-dialog__disable-scroll{overflow:hidden}.tox .tox-dropzone-container{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dropzone{align-items:center;background:#fff;border:2px dashed #ccc;box-sizing:border-box;display:flex;flex-direction:column;flex-grow:1;justify-content:center;min-height:100px;padding:10px}.tox .tox-dropzone p{color:rgba(34,47,62,.7);margin:0 0 16px 0}.tox .tox-edit-area{display:flex;flex:1;-ms-flex-preferred-size:auto;overflow:hidden;position:relative}.tox .tox-edit-area__iframe{background-color:#fff;border:0;box-sizing:border-box;flex:1;-ms-flex-preferred-size:auto;height:100%;position:absolute;width:100%}.tox.tox-inline-edit-area{border:1px dotted #ccc}.tox .tox-editor-container{display:flex;flex:1 1 auto;flex-direction:column;overflow:hidden}.tox .tox-editor-header{z-index:1}.tox:not(.tox-tinymce-inline) .tox-editor-header{box-shadow:none;transition:box-shadow .5s}.tox.tox-tinymce--toolbar-bottom .tox-editor-header,.tox.tox-tinymce-inline .tox-editor-header{margin-bottom:-1px}.tox.tox-tinymce--toolbar-sticky-on .tox-editor-header{background-color:transparent;box-shadow:0 4px 4px -3px rgba(0,0,0,.25)}.tox-editor-dock-fadeout{opacity:0;visibility:hidden}.tox-editor-dock-fadein{opacity:1;visibility:visible}.tox-editor-dock-transition{transition:visibility 0s linear .25s,opacity .25s ease}.tox-editor-dock-transition.tox-editor-dock-fadein{transition-delay:0s}.tox .tox-control-wrap{flex:1;position:relative}.tox .tox-control-wrap:not(.tox-control-wrap--status-invalid) .tox-control-wrap__status-icon-invalid,.tox .tox-control-wrap:not(.tox-control-wrap--status-unknown) .tox-control-wrap__status-icon-unknown,.tox .tox-control-wrap:not(.tox-control-wrap--status-valid) .tox-control-wrap__status-icon-valid{display:none}.tox .tox-control-wrap svg{display:block}.tox .tox-control-wrap__status-icon-wrap{position:absolute;top:50%;transform:translateY(-50%)}.tox .tox-control-wrap__status-icon-invalid svg{fill:#c00}.tox .tox-control-wrap__status-icon-unknown svg{fill:orange}.tox .tox-control-wrap__status-icon-valid svg{fill:green}.tox:not([dir=rtl]) .tox-control-wrap--status-invalid .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-unknown .tox-textfield,.tox:not([dir=rtl]) .tox-control-wrap--status-valid .tox-textfield{padding-right:32px}.tox:not([dir=rtl]) .tox-control-wrap__status-icon-wrap{right:4px}.tox[dir=rtl] .tox-control-wrap--status-invalid .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-unknown .tox-textfield,.tox[dir=rtl] .tox-control-wrap--status-valid .tox-textfield{padding-left:32px}.tox[dir=rtl] .tox-control-wrap__status-icon-wrap{left:4px}.tox .tox-autocompleter{max-width:25em}.tox .tox-autocompleter .tox-menu{max-width:25em}.tox .tox-autocompleter .tox-autocompleter-highlight{font-weight:700}.tox .tox-color-input{display:flex;position:relative;z-index:1}.tox .tox-color-input .tox-textfield{z-index:-1}.tox .tox-color-input span{border-color:rgba(34,47,62,.2);border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;height:24px;position:absolute;top:6px;width:24px}.tox .tox-color-input span:focus:not([aria-disabled=true]),.tox .tox-color-input span:hover:not([aria-disabled=true]){border-color:#207ab7;cursor:pointer}.tox .tox-color-input span::before{background-image:linear-gradient(45deg,rgba(0,0,0,.25) 25%,transparent 25%),linear-gradient(-45deg,rgba(0,0,0,.25) 25%,transparent 25%),linear-gradient(45deg,transparent 75%,rgba(0,0,0,.25) 75%),linear-gradient(-45deg,transparent 75%,rgba(0,0,0,.25) 75%);background-position:0 0,0 6px,6px -6px,-6px 0;background-size:12px 12px;border:1px solid #fff;border-radius:3px;box-sizing:border-box;content:'';height:24px;left:-1px;position:absolute;top:-1px;width:24px;z-index:-1}.tox .tox-color-input span[aria-disabled=true]{cursor:not-allowed}.tox:not([dir=rtl]) .tox-color-input .tox-textfield{padding-left:36px}.tox:not([dir=rtl]) .tox-color-input span{left:6px}.tox[dir=rtl] .tox-color-input .tox-textfield{padding-right:36px}.tox[dir=rtl] .tox-color-input span{right:6px}.tox .tox-label,.tox .tox-toolbar-label{color:rgba(34,47,62,.7);display:block;font-size:14px;font-style:normal;font-weight:400;line-height:1.3;padding:0 8px 0 0;text-transform:none;white-space:nowrap}.tox .tox-toolbar-label{padding:0 8px}.tox[dir=rtl] .tox-label{padding:0 0 0 8px}.tox .tox-form{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-form__group{box-sizing:border-box;margin-bottom:4px}.tox .tox-form-group--maximize{flex:1}.tox .tox-form__group--error{color:#c00}.tox .tox-form__group--collection{display:flex}.tox .tox-form__grid{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between}.tox .tox-form__grid--2col>.tox-form__group{width:calc(50% - (8px / 2))}.tox .tox-form__grid--3col>.tox-form__group{width:calc(100% / 3 - (8px / 2))}.tox .tox-form__grid--4col>.tox-form__group{width:calc(25% - (8px / 2))}.tox .tox-form__controls-h-stack{align-items:center;display:flex}.tox .tox-form__group--inline{align-items:center;display:flex}.tox .tox-form__group--stretched{display:flex;flex:1;flex-direction:column;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-textarea{flex:1;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-navobj{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-form__group--stretched .tox-navobj :nth-child(2){flex:1;-ms-flex-preferred-size:auto;height:100%}.tox:not([dir=rtl]) .tox-form__controls-h-stack>:not(:first-child){margin-left:4px}.tox[dir=rtl] .tox-form__controls-h-stack>:not(:first-child){margin-right:4px}.tox .tox-lock.tox-locked .tox-lock-icon__unlock,.tox .tox-lock:not(.tox-locked) .tox-lock-icon__lock{display:none}.tox .tox-listboxfield .tox-listbox--select,.tox .tox-textarea,.tox .tox-textfield,.tox .tox-toolbar-textfield{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#ccc;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#222f3e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;line-height:24px;margin:0;min-height:34px;outline:0;padding:5px 4.75px;resize:none;width:100%}.tox .tox-textarea[disabled],.tox .tox-textfield[disabled]{background-color:#f2f2f2;color:rgba(34,47,62,.85);cursor:not-allowed}.tox .tox-listboxfield .tox-listbox--select:focus,.tox .tox-textarea:focus,.tox .tox-textfield:focus{background-color:#fff;border-color:#207ab7;box-shadow:none;outline:0}.tox .tox-toolbar-textfield{border-width:0;margin-bottom:3px;margin-top:2px;max-width:250px}.tox .tox-naked-btn{background-color:transparent;border:0;border-color:transparent;box-shadow:unset;color:#207ab7;cursor:pointer;display:block;margin:0;padding:0}.tox .tox-naked-btn svg{display:block;fill:#222f3e}.tox:not([dir=rtl]) .tox-toolbar-textfield+*{margin-left:4px}.tox[dir=rtl] .tox-toolbar-textfield+*{margin-right:4px}.tox .tox-listboxfield{cursor:pointer;position:relative}.tox .tox-listboxfield .tox-listbox--select[disabled]{background-color:#f2f2f2;color:rgba(34,47,62,.85);cursor:not-allowed}.tox .tox-listbox__select-label{cursor:default;flex:1;margin:0 4px}.tox .tox-listbox__select-chevron{align-items:center;display:flex;justify-content:center;width:16px}.tox .tox-listbox__select-chevron svg{fill:#222f3e}.tox .tox-listboxfield .tox-listbox--select{align-items:center;display:flex}.tox:not([dir=rtl]) .tox-listboxfield svg{right:8px}.tox[dir=rtl] .tox-listboxfield svg{left:8px}.tox .tox-selectfield{cursor:pointer;position:relative}.tox .tox-selectfield select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#ccc;border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;color:#222f3e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;font-size:16px;line-height:24px;margin:0;min-height:34px;outline:0;padding:5px 4.75px;resize:none;width:100%}.tox .tox-selectfield select[disabled]{background-color:#f2f2f2;color:rgba(34,47,62,.85);cursor:not-allowed}.tox .tox-selectfield select::-ms-expand{display:none}.tox .tox-selectfield select:focus{background-color:#fff;border-color:#207ab7;box-shadow:none;outline:0}.tox .tox-selectfield svg{pointer-events:none;position:absolute;top:50%;transform:translateY(-50%)}.tox:not([dir=rtl]) .tox-selectfield select[size="0"],.tox:not([dir=rtl]) .tox-selectfield select[size="1"]{padding-right:24px}.tox:not([dir=rtl]) .tox-selectfield svg{right:8px}.tox[dir=rtl] .tox-selectfield select[size="0"],.tox[dir=rtl] .tox-selectfield select[size="1"]{padding-left:24px}.tox[dir=rtl] .tox-selectfield svg{left:8px}.tox .tox-textarea{-webkit-appearance:textarea;-moz-appearance:textarea;appearance:textarea;white-space:pre-wrap}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}.tox .tox-help__more-link{list-style:none;margin-top:1em}.tox .tox-image-tools{width:100%}.tox .tox-image-tools__toolbar{align-items:center;display:flex;justify-content:center}.tox .tox-image-tools__image{background-color:#666;height:380px;overflow:auto;position:relative;width:100%}.tox .tox-image-tools__image,.tox .tox-image-tools__image+.tox-image-tools__toolbar{margin-top:8px}.tox .tox-image-tools__image-bg{background:url(data:image/gif;base64,R0lGODdhDAAMAIABAMzMzP///ywAAAAADAAMAAACFoQfqYeabNyDMkBQb81Uat85nxguUAEAOw==)}.tox .tox-image-tools__toolbar>.tox-spacer{flex:1;-ms-flex-preferred-size:auto}.tox .tox-croprect-block{background:#000;opacity:.5;position:absolute;zoom:1}.tox .tox-croprect-handle{border:2px solid #fff;height:20px;left:0;position:absolute;top:0;width:20px}.tox .tox-croprect-handle-move{border:0;cursor:move;position:absolute}.tox .tox-croprect-handle-nw{border-width:2px 0 0 2px;cursor:nw-resize;left:100px;margin:-2px 0 0 -2px;top:100px}.tox .tox-croprect-handle-ne{border-width:2px 2px 0 0;cursor:ne-resize;left:200px;margin:-2px 0 0 -20px;top:100px}.tox .tox-croprect-handle-sw{border-width:0 0 2px 2px;cursor:sw-resize;left:100px;margin:-20px 2px 0 -2px;top:200px}.tox .tox-croprect-handle-se{border-width:0 2px 2px 0;cursor:se-resize;left:200px;margin:-20px 0 0 -20px;top:200px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-left:8px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-left:32px}.tox:not([dir=rtl]) .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-left:32px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider:not(:first-of-type){margin-right:8px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-button+.tox-slider{margin-right:32px}.tox[dir=rtl] .tox-image-tools__toolbar>.tox-slider+.tox-button{margin-right:32px}.tox .tox-insert-table-picker{display:flex;flex-wrap:wrap;width:170px}.tox .tox-insert-table-picker>div{border-color:#ccc;border-style:solid;border-width:0 1px 1px 0;box-sizing:border-box;height:17px;width:17px}.tox .tox-collection--list .tox-collection__group .tox-insert-table-picker{margin:-4px 0}.tox .tox-insert-table-picker .tox-insert-table-picker__selected{background-color:rgba(32,122,183,.5);border-color:rgba(32,122,183,.5)}.tox .tox-insert-table-picker__label{color:rgba(34,47,62,.7);display:block;font-size:14px;padding:4px;text-align:center;width:100%}.tox:not([dir=rtl]) .tox-insert-table-picker>div:nth-child(10n){border-right:0}.tox[dir=rtl] .tox-insert-table-picker>div:nth-child(10n+1){border-right:0}.tox .tox-menu{background-color:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 4px 8px 0 rgba(34,47,62,.1);display:inline-block;overflow:hidden;vertical-align:top;z-index:1150}.tox .tox-menu.tox-collection.tox-collection--list{padding:0}.tox .tox-menu.tox-collection.tox-collection--toolbar{padding:4px}.tox .tox-menu.tox-collection.tox-collection--grid{padding:4px}.tox .tox-menu__label blockquote,.tox .tox-menu__label code,.tox .tox-menu__label h1,.tox .tox-menu__label h2,.tox .tox-menu__label h3,.tox .tox-menu__label h4,.tox .tox-menu__label h5,.tox .tox-menu__label h6,.tox .tox-menu__label p{margin:0}.tox .tox-menubar{background:url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;background-color:#fff;display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:wrap;padding:0 4px 0 4px}.tox.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-menubar{border-top:1px solid #ccc}.tox .tox-mbtn{align-items:center;background:0 0;border:0;border-radius:3px;box-shadow:none;color:#222f3e;display:flex;flex:0 0 auto;font-size:14px;font-style:normal;font-weight:400;height:34px;justify-content:center;margin:2px 0 3px 0;outline:0;overflow:hidden;padding:0 4px;text-transform:none;width:auto}.tox .tox-mbtn[disabled]{background-color:transparent;border:0;box-shadow:none;color:rgba(34,47,62,.5);cursor:not-allowed}.tox .tox-mbtn:focus:not(:disabled){background:#dee0e2;border:0;box-shadow:none;color:#222f3e}.tox .tox-mbtn--active{background:#c8cbcf;border:0;box-shadow:none;color:#222f3e}.tox .tox-mbtn:hover:not(:disabled):not(.tox-mbtn--active){background:#dee0e2;border:0;box-shadow:none;color:#222f3e}.tox .tox-mbtn__select-label{cursor:default;font-weight:400;margin:0 4px}.tox .tox-mbtn[disabled] .tox-mbtn__select-label{cursor:not-allowed}.tox .tox-mbtn__select-chevron{align-items:center;display:flex;justify-content:center;width:16px;display:none}.tox .tox-notification{border-radius:3px;border-style:solid;border-width:1px;box-shadow:none;box-sizing:border-box;display:-ms-grid;display:grid;font-size:14px;font-weight:400;-ms-grid-columns:minmax(40px,1fr) auto minmax(40px,1fr);grid-template-columns:minmax(40px,1fr) auto minmax(40px,1fr);margin-top:4px;opacity:0;padding:4px;transition:transform .1s ease-in,opacity 150ms ease-in}.tox .tox-notification p{font-size:14px;font-weight:400}.tox .tox-notification a{cursor:pointer;text-decoration:underline}.tox .tox-notification--in{opacity:1}.tox .tox-notification--success{background-color:#e4eeda;border-color:#d7e6c8;color:#222f3e}.tox .tox-notification--success p{color:#222f3e}.tox .tox-notification--success a{color:#547831}.tox .tox-notification--success svg{fill:#222f3e}.tox .tox-notification--error{background-color:#f8dede;border-color:#f2bfbf;color:#222f3e}.tox .tox-notification--error p{color:#222f3e}.tox .tox-notification--error a{color:#c00}.tox .tox-notification--error svg{fill:#222f3e}.tox .tox-notification--warn,.tox .tox-notification--warning{background-color:#fffaea;border-color:#ffe89d;color:#222f3e}.tox .tox-notification--warn p,.tox .tox-notification--warning p{color:#222f3e}.tox .tox-notification--warn a,.tox .tox-notification--warning a{color:#222f3e}.tox .tox-notification--warn svg,.tox .tox-notification--warning svg{fill:#222f3e}.tox .tox-notification--info{background-color:#d9edf7;border-color:#779ecb;color:#222f3e}.tox .tox-notification--info p{color:#222f3e}.tox .tox-notification--info a{color:#222f3e}.tox .tox-notification--info svg{fill:#222f3e}.tox .tox-notification__body{-ms-grid-row-align:center;align-self:center;color:#222f3e;font-size:14px;-ms-grid-column-span:1;grid-column-end:3;-ms-grid-column:2;grid-column-start:2;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;text-align:center;white-space:normal;word-break:break-all;word-break:break-word}.tox .tox-notification__body>*{margin:0}.tox .tox-notification__body>*+*{margin-top:1rem}.tox .tox-notification__icon{-ms-grid-row-align:center;align-self:center;-ms-grid-column-span:1;grid-column-end:2;-ms-grid-column:1;grid-column-start:1;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;-ms-grid-column-align:end;justify-self:end}.tox .tox-notification__icon svg{display:block}.tox .tox-notification__dismiss{-ms-grid-row-align:start;align-self:start;-ms-grid-column-span:1;grid-column-end:4;-ms-grid-column:3;grid-column-start:3;-ms-grid-row-span:1;grid-row-end:2;-ms-grid-row:1;grid-row-start:1;-ms-grid-column-align:end;justify-self:end}.tox .tox-notification .tox-progress-bar{-ms-grid-column-span:3;grid-column-end:4;-ms-grid-column:1;grid-column-start:1;-ms-grid-row-span:1;grid-row-end:3;-ms-grid-row:2;grid-row-start:2;-ms-grid-column-align:center;justify-self:center}.tox .tox-pop{display:inline-block;position:relative}.tox .tox-pop--resizing{transition:width .1s ease}.tox .tox-pop--resizing .tox-toolbar,.tox .tox-pop--resizing .tox-toolbar__group{flex-wrap:nowrap}.tox .tox-pop--transition{transition:.15s ease;transition-property:left,right,top,bottom}.tox .tox-pop--transition::after,.tox .tox-pop--transition::before{transition:all .15s,visibility 0s,opacity 75ms ease 75ms}.tox .tox-pop__dialog{background-color:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15);min-width:0;overflow:hidden}.tox .tox-pop__dialog>:not(.tox-toolbar){margin:4px 4px 4px 8px}.tox .tox-pop__dialog .tox-toolbar{background-color:transparent;margin-bottom:-1px}.tox .tox-pop::after,.tox .tox-pop::before{border-style:solid;content:'';display:block;height:0;opacity:1;position:absolute;width:0}.tox .tox-pop.tox-pop--inset::after,.tox .tox-pop.tox-pop--inset::before{opacity:0;transition:all 0s .15s,visibility 0s,opacity 75ms ease}.tox .tox-pop.tox-pop--bottom::after,.tox .tox-pop.tox-pop--bottom::before{left:50%;top:100%}.tox .tox-pop.tox-pop--bottom::after{border-color:#fff transparent transparent transparent;border-width:8px;margin-left:-8px;margin-top:-1px}.tox .tox-pop.tox-pop--bottom::before{border-color:#ccc transparent transparent transparent;border-width:9px;margin-left:-9px}.tox .tox-pop.tox-pop--top::after,.tox .tox-pop.tox-pop--top::before{left:50%;top:0;transform:translateY(-100%)}.tox .tox-pop.tox-pop--top::after{border-color:transparent transparent #fff transparent;border-width:8px;margin-left:-8px;margin-top:1px}.tox .tox-pop.tox-pop--top::before{border-color:transparent transparent #ccc transparent;border-width:9px;margin-left:-9px}.tox .tox-pop.tox-pop--left::after,.tox .tox-pop.tox-pop--left::before{left:0;top:calc(50% - 1px);transform:translateY(-50%)}.tox .tox-pop.tox-pop--left::after{border-color:transparent #fff transparent transparent;border-width:8px;margin-left:-15px}.tox .tox-pop.tox-pop--left::before{border-color:transparent #ccc transparent transparent;border-width:10px;margin-left:-19px}.tox .tox-pop.tox-pop--right::after,.tox .tox-pop.tox-pop--right::before{left:100%;top:calc(50% + 1px);transform:translateY(-50%)}.tox .tox-pop.tox-pop--right::after{border-color:transparent transparent transparent #fff;border-width:8px;margin-left:-1px}.tox .tox-pop.tox-pop--right::before{border-color:transparent transparent transparent #ccc;border-width:10px;margin-left:-1px}.tox .tox-pop.tox-pop--align-left::after,.tox .tox-pop.tox-pop--align-left::before{left:20px}.tox .tox-pop.tox-pop--align-right::after,.tox .tox-pop.tox-pop--align-right::before{left:calc(100% - 20px)}.tox .tox-sidebar-wrap{display:flex;flex-direction:row;flex-grow:1;-ms-flex-preferred-size:0;min-height:0}.tox .tox-sidebar{background-color:#fff;display:flex;flex-direction:row;justify-content:flex-end}.tox .tox-sidebar__slider{display:flex;overflow:hidden}.tox .tox-sidebar__pane-container{display:flex}.tox .tox-sidebar__pane{display:flex}.tox .tox-sidebar--sliding-closed{opacity:0}.tox .tox-sidebar--sliding-open{opacity:1}.tox .tox-sidebar--sliding-growing,.tox .tox-sidebar--sliding-shrinking{transition:width .5s ease,opacity .5s ease}.tox .tox-selector{background-color:#4099ff;border-color:#4099ff;border-style:solid;border-width:1px;box-sizing:border-box;display:inline-block;height:10px;position:absolute;width:10px}.tox.tox-platform-touch .tox-selector{height:12px;width:12px}.tox .tox-slider{align-items:center;display:flex;flex:1;-ms-flex-preferred-size:auto;height:24px;justify-content:center;position:relative}.tox .tox-slider__rail{background-color:transparent;border:1px solid #ccc;border-radius:3px;height:10px;min-width:120px;width:100%}.tox .tox-slider__handle{background-color:#207ab7;border:2px solid #185d8c;border-radius:3px;box-shadow:none;height:24px;left:50%;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:14px}.tox .tox-source-code{overflow:auto}.tox .tox-spinner{display:flex}.tox .tox-spinner>div{animation:tam-bouncing-dots 1.5s ease-in-out 0s infinite both;background-color:rgba(34,47,62,.7);border-radius:100%;height:8px;width:8px}.tox .tox-spinner>div:nth-child(1){animation-delay:-.32s}.tox .tox-spinner>div:nth-child(2){animation-delay:-.16s}@keyframes tam-bouncing-dots{0%,100%,80%{transform:scale(0)}40%{transform:scale(1)}}.tox:not([dir=rtl]) .tox-spinner>div:not(:first-child){margin-left:4px}.tox[dir=rtl] .tox-spinner>div:not(:first-child){margin-right:4px}.tox .tox-statusbar{align-items:center;background-color:#fff;border-top:1px solid #ccc;color:rgba(34,47,62,.7);display:flex;flex:0 0 auto;font-size:12px;font-weight:400;height:18px;overflow:hidden;padding:0 8px;position:relative;text-transform:uppercase}.tox .tox-statusbar__text-container{display:flex;flex:1 1 auto;justify-content:flex-end;overflow:hidden}.tox .tox-statusbar__path{display:flex;flex:1 1 auto;margin-right:auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tox .tox-statusbar__path>*{display:inline;white-space:nowrap}.tox .tox-statusbar__wordcount{flex:0 0 auto;margin-left:1ch}.tox .tox-statusbar a,.tox .tox-statusbar__path-item,.tox .tox-statusbar__wordcount{color:rgba(34,47,62,.7);text-decoration:none}.tox .tox-statusbar a:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar a:hover:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__path-item:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__path-item:hover:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__wordcount:focus:not(:disabled):not([aria-disabled=true]),.tox .tox-statusbar__wordcount:hover:not(:disabled):not([aria-disabled=true]){cursor:pointer;text-decoration:underline}.tox .tox-statusbar__resize-handle{align-items:flex-end;align-self:stretch;cursor:nwse-resize;display:flex;flex:0 0 auto;justify-content:flex-end;margin-left:auto;margin-right:-8px;padding-left:1ch}.tox .tox-statusbar__resize-handle svg{display:block;fill:rgba(34,47,62,.7)}.tox .tox-statusbar__resize-handle:focus svg{background-color:#dee0e2;border-radius:1px;box-shadow:0 0 0 2px #dee0e2}.tox:not([dir=rtl]) .tox-statusbar__path>*{margin-right:4px}.tox:not([dir=rtl]) .tox-statusbar__branding{margin-left:1ch}.tox[dir=rtl] .tox-statusbar{flex-direction:row-reverse}.tox[dir=rtl] .tox-statusbar__path>*{margin-left:4px}.tox .tox-throbber{z-index:1299}.tox .tox-throbber__busy-spinner{align-items:center;background-color:rgba(255,255,255,.6);bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}.tox .tox-tbtn{align-items:center;background:0 0;border:0;border-radius:3px;box-shadow:none;color:#222f3e;display:flex;flex:0 0 auto;font-size:14px;font-style:normal;font-weight:400;height:34px;justify-content:center;margin:2px 0 3px 0;outline:0;overflow:hidden;padding:0;text-transform:none;width:34px}.tox .tox-tbtn svg{display:block;fill:#222f3e}.tox .tox-tbtn.tox-tbtn-more{padding-left:5px;padding-right:5px;width:inherit}.tox .tox-tbtn:focus{background:#dee0e2;border:0;box-shadow:none}.tox .tox-tbtn:hover{background:#dee0e2;border:0;box-shadow:none;color:#222f3e}.tox .tox-tbtn:hover svg{fill:#222f3e}.tox .tox-tbtn:active{background:#c8cbcf;border:0;box-shadow:none;color:#222f3e}.tox .tox-tbtn:active svg{fill:#222f3e}.tox .tox-tbtn--disabled,.tox .tox-tbtn--disabled:hover,.tox .tox-tbtn:disabled,.tox .tox-tbtn:disabled:hover{background:0 0;border:0;box-shadow:none;color:rgba(34,47,62,.5);cursor:not-allowed}.tox .tox-tbtn--disabled svg,.tox .tox-tbtn--disabled:hover svg,.tox .tox-tbtn:disabled svg,.tox .tox-tbtn:disabled:hover svg{fill:rgba(34,47,62,.5)}.tox .tox-tbtn--enabled,.tox .tox-tbtn--enabled:hover{background:#c8cbcf;border:0;box-shadow:none;color:#222f3e}.tox .tox-tbtn--enabled:hover>*,.tox .tox-tbtn--enabled>*{transform:none}.tox .tox-tbtn--enabled svg,.tox .tox-tbtn--enabled:hover svg{fill:#222f3e}.tox .tox-tbtn:focus:not(.tox-tbtn--disabled){color:#222f3e}.tox .tox-tbtn:focus:not(.tox-tbtn--disabled) svg{fill:#222f3e}.tox .tox-tbtn:active>*{transform:none}.tox .tox-tbtn--md{height:51px;width:51px}.tox .tox-tbtn--lg{flex-direction:column;height:68px;width:68px}.tox .tox-tbtn--return{-ms-grid-row-align:stretch;align-self:stretch;height:unset;width:16px}.tox .tox-tbtn--labeled{padding:0 4px;width:unset}.tox .tox-tbtn__vlabel{display:block;font-size:10px;font-weight:400;letter-spacing:-.025em;margin-bottom:4px;white-space:nowrap}.tox .tox-tbtn--select{margin:2px 0 3px 0;padding:0 4px;width:auto}.tox .tox-tbtn__select-label{cursor:default;font-weight:400;margin:0 4px}.tox .tox-tbtn__select-chevron{align-items:center;display:flex;justify-content:center;width:16px}.tox .tox-tbtn__select-chevron svg{fill:rgba(34,47,62,.5)}.tox .tox-tbtn--bespoke .tox-tbtn__select-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:7em}.tox .tox-split-button{border:0;border-radius:3px;box-sizing:border-box;display:flex;margin:2px 0 3px 0;overflow:hidden}.tox .tox-split-button:hover{box-shadow:0 0 0 1px #dee0e2 inset}.tox .tox-split-button:focus{background:#dee0e2;box-shadow:none;color:#222f3e}.tox .tox-split-button>*{border-radius:0}.tox .tox-split-button__chevron{width:16px}.tox .tox-split-button__chevron svg{fill:rgba(34,47,62,.5)}.tox .tox-split-button .tox-tbtn{margin:0}.tox.tox-platform-touch .tox-split-button .tox-tbtn:first-child{width:30px}.tox.tox-platform-touch .tox-split-button__chevron{width:20px}.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:focus,.tox .tox-split-button.tox-tbtn--disabled .tox-tbtn:hover,.tox .tox-split-button.tox-tbtn--disabled:focus,.tox .tox-split-button.tox-tbtn--disabled:hover{background:0 0;box-shadow:none;color:rgba(34,47,62,.5)}.tox .tox-toolbar-overlord{background-color:#fff}.tox .tox-toolbar,.tox .tox-toolbar__overflow,.tox .tox-toolbar__primary{background:url("data:image/svg+xml;charset=utf8,%3Csvg height='39px' viewBox='0 0 40 39px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='38px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E") left 0 top 0 #fff;background-color:#fff;display:flex;flex:0 0 auto;flex-shrink:0;flex-wrap:wrap;padding:0 0}.tox .tox-toolbar__overflow.tox-toolbar__overflow--closed{height:0;opacity:0;padding-bottom:0;padding-top:0;visibility:hidden}.tox .tox-toolbar__overflow--growing{transition:height .3s ease,opacity .2s linear .1s}.tox .tox-toolbar__overflow--shrinking{transition:opacity .3s ease,height .2s linear .1s,visibility 0s linear .3s}.tox .tox-menubar+.tox-toolbar,.tox .tox-menubar+.tox-toolbar-overlord .tox-toolbar__primary{border-top:1px solid #ccc;margin-top:-1px}.tox .tox-toolbar--scrolling{flex-wrap:nowrap;overflow-x:auto}.tox .tox-pop .tox-toolbar{border-width:0}.tox .tox-toolbar--no-divider{background-image:none}.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar-overlord:first-child .tox-toolbar__primary,.tox-tinymce:not(.tox-tinymce-inline) .tox-editor-header:not(:first-child) .tox-toolbar:first-child{border-top:1px solid #ccc}.tox.tox-tinymce-aux .tox-toolbar__overflow{background-color:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 3px rgba(0,0,0,.15)}.tox .tox-toolbar__group{align-items:center;display:flex;flex-wrap:wrap;margin:0 0;padding:0 4px 0 4px}.tox .tox-toolbar__group--pull-right{margin-left:auto}.tox .tox-toolbar--scrolling .tox-toolbar__group{flex-shrink:0;flex-wrap:nowrap}.tox:not([dir=rtl]) .tox-toolbar__group:not(:last-of-type){border-right:1px solid #ccc}.tox[dir=rtl] .tox-toolbar__group:not(:last-of-type){border-left:1px solid #ccc}.tox .tox-tooltip{display:inline-block;padding:8px;position:relative}.tox .tox-tooltip__body{background-color:#222f3e;border-radius:3px;box-shadow:0 2px 4px rgba(34,47,62,.3);color:rgba(255,255,255,.75);font-size:14px;font-style:normal;font-weight:400;padding:4px 8px;text-transform:none}.tox .tox-tooltip__arrow{position:absolute}.tox .tox-tooltip--down .tox-tooltip__arrow{border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #222f3e;bottom:0;left:50%;position:absolute;transform:translateX(-50%)}.tox .tox-tooltip--up .tox-tooltip__arrow{border-bottom:8px solid #222f3e;border-left:8px solid transparent;border-right:8px solid transparent;left:50%;position:absolute;top:0;transform:translateX(-50%)}.tox .tox-tooltip--right .tox-tooltip__arrow{border-bottom:8px solid transparent;border-left:8px solid #222f3e;border-top:8px solid transparent;position:absolute;right:0;top:50%;transform:translateY(-50%)}.tox .tox-tooltip--left .tox-tooltip__arrow{border-bottom:8px solid transparent;border-right:8px solid #222f3e;border-top:8px solid transparent;left:0;position:absolute;top:50%;transform:translateY(-50%)}.tox .tox-well{border:1px solid #ccc;border-radius:3px;padding:8px;width:100%}.tox .tox-well>:first-child{margin-top:0}.tox .tox-well>:last-child{margin-bottom:0}.tox .tox-well>:only-child{margin:0}.tox .tox-custom-editor{border:1px solid #ccc;border-radius:3px;display:flex;flex:1;position:relative}.tox .tox-dialog-loading::before{background-color:rgba(0,0,0,.5);content:"";height:100%;position:absolute;width:100%;z-index:1000}.tox .tox-tab{cursor:pointer}.tox .tox-dialog__content-js{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-dialog__body-content .tox-collection{display:flex;flex:1;-ms-flex-preferred-size:auto}.tox .tox-image-tools-edit-panel{height:60px}.tox .tox-image-tools__sidebar{height:60px} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css new file mode 100644 index 0000000..3a45cac --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.mobile.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +.tinymce-mobile-outer-container{all:initial;display:block}.tinymce-mobile-outer-container *{border:0;box-sizing:initial;cursor:inherit;float:none;line-height:1;margin:0;outline:0;padding:0;-webkit-tap-highlight-color:transparent;text-shadow:none;white-space:nowrap}.tinymce-mobile-icon-arrow-back::before{content:"\e5cd"}.tinymce-mobile-icon-image::before{content:"\e412"}.tinymce-mobile-icon-cancel-circle::before{content:"\e5c9"}.tinymce-mobile-icon-full-dot::before{content:"\e061"}.tinymce-mobile-icon-align-center::before{content:"\e234"}.tinymce-mobile-icon-align-left::before{content:"\e236"}.tinymce-mobile-icon-align-right::before{content:"\e237"}.tinymce-mobile-icon-bold::before{content:"\e238"}.tinymce-mobile-icon-italic::before{content:"\e23f"}.tinymce-mobile-icon-unordered-list::before{content:"\e241"}.tinymce-mobile-icon-ordered-list::before{content:"\e242"}.tinymce-mobile-icon-font-size::before{content:"\e245"}.tinymce-mobile-icon-underline::before{content:"\e249"}.tinymce-mobile-icon-link::before{content:"\e157"}.tinymce-mobile-icon-unlink::before{content:"\eca2"}.tinymce-mobile-icon-color::before{content:"\e891"}.tinymce-mobile-icon-previous::before{content:"\e314"}.tinymce-mobile-icon-next::before{content:"\e315"}.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content:"\e264"}.tinymce-mobile-icon-undo::before{content:"\e166"}.tinymce-mobile-icon-redo::before{content:"\e15a"}.tinymce-mobile-icon-removeformat::before{content:"\e239"}.tinymce-mobile-icon-small-font::before{content:"\e906"}.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content:"\e5ca"}.tinymce-mobile-icon-small-heading::before{content:"small"}.tinymce-mobile-icon-large-heading::before{content:"large"}.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family:sans-serif;font-size:80%}.tinymce-mobile-mask-edit-icon::before{content:"\e254"}.tinymce-mobile-icon-back::before{content:"\e5c4"}.tinymce-mobile-icon-heading::before{content:"Headings";font-family:sans-serif;font-size:80%;font-weight:700}.tinymce-mobile-icon-h1::before{content:"H1";font-weight:700}.tinymce-mobile-icon-h2::before{content:"H2";font-weight:700}.tinymce-mobile-icon-h3::before{content:"H3";font-weight:700}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{align-items:center;display:flex;justify-content:center;background:rgba(51,51,51,.5);height:100%;position:absolute;top:0;width:100%}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{align-items:center;border-radius:50%;display:flex;flex-direction:column;font-family:sans-serif;font-size:1em;justify-content:space-between}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items:center;display:flex;justify-content:center;flex-direction:column;font-size:1em}@media only screen and (min-device-width:700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size:1.2em}}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em;background-color:#fff;color:#207ab7}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{content:"\e900";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index:2}.tinymce-mobile-android-container.tinymce-mobile-android-maximized{background:#fff;border:none;bottom:0;display:flex;flex-direction:column;left:0;position:fixed;right:0;top:0}.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position:relative}.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display:flex;flex-grow:1}.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display:flex!important;flex-grow:1;height:auto!important}.tinymce-mobile-android-scroll-reload{overflow:hidden}:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top:23px}.tinymce-mobile-toolstrip{background:#fff;display:flex;flex:0 0 auto;z-index:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{align-items:center;background-color:#fff;border-bottom:1px solid #ccc;display:flex;flex:1;height:2.5em;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex-shrink:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background:#f44336}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{align-items:center;display:flex;height:80%;margin-left:2px;margin-right:2px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{background:#c8cbcf;color:#ccc}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{background:#207ab7;color:#eceff1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex:1;padding-bottom:.4em;padding-top:.4em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{display:flex;min-height:1.5em;overflow:hidden;padding-left:0;padding-right:0;position:relative;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display:flex;height:100%;transition:left cubic-bezier(.4,0,1,1) .15s;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display:flex;flex:0 0 auto;justify-content:space-between;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family:Sans-serif}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{display:flex;flex-grow:1;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{-ms-grid-row-align:center;align-self:center;background:inherit;border:none;border-radius:50%;color:#888;font-size:.6em;font-weight:700;height:100%;padding-right:2px;position:absolute;right:0}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display:none}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{align-items:center;display:flex;font-weight:700;height:100%;padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility:hidden}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{color:#ccc;font-size:10px;line-height:10px;margin:0 2px;padding-top:3px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color:#c8cbcf}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-left:.5em;margin-right:.9em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-left:.9em;margin-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{display:flex;flex:1;margin-left:0;margin-right:0;padding:.28em 0;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{background:#ccc;display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-left:2em;padding-right:2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{background:linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{background:#000;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{background:#fff;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{align-items:center;background-clip:padding-box;background-color:#455a64;border:.5em solid rgba(136,136,136,0);border-radius:3em;bottom:0;color:#fff;display:flex;height:.5em;justify-content:center;left:-10px;margin:auto;position:absolute;top:0;transition:border 120ms cubic-bezier(.39,.58,.57,1);width:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border:.5em solid rgba(136,136,136,.39)}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction:column;justify-content:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{background:#fff;border:none;border-radius:0;color:#455a64;flex-grow:1;font-size:.85em;padding-bottom:.1em;padding-left:5px;padding-top:.1em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color:#888}.tinymce-mobile-dropup{background:#fff;display:flex;overflow:hidden;width:100%}.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition:height .3s ease-out}.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition:height .3s ease-in}.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow:0}.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow:1}.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}@media only screen and (orientation:landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:150px}}.tinymce-mobile-styles-menu{font-family:sans-serif;outline:4px solid #000;overflow:hidden;position:relative;width:100%}.tinymce-mobile-styles-menu [role=menu]{display:flex;flex-direction:column;height:100%;position:absolute;width:100%}.tinymce-mobile-styles-menu [role=menu].transitioning{transition:transform .5s ease-in-out}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{border-bottom:1px solid #ddd;color:#455a64;cursor:pointer;display:flex;padding:1em 1em;position:relative}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{color:#455a64;content:"\e314";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{color:#455a64;content:"\e315";font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{align-items:center;background:#fff;border-top:#455a64;color:#455a64;display:flex;min-height:2.5em;padding-left:1em;padding-right:1em}.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform:translate(-100%)}.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform:translate(0)}.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform:translate(100%)}@font-face{font-family:tinymce-mobile;font-style:normal;font-weight:400;src:url(fonts/tinymce-mobile.woff?8x92w3) format('woff')}@media (min-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:25px}}@media (max-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:18px}}.tinymce-mobile-icon{font-family:tinymce-mobile,sans-serif}.mixin-flex-and-centre{align-items:center;display:flex;justify-content:center}.mixin-flex-bar{align-items:center;display:flex;height:100%}.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{background-color:#fff;width:100%}.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{background-color:#207ab7;border-radius:50%;bottom:1em;color:#fff;font-size:1em;height:2.1em;position:fixed;right:2em;width:2.1em;align-items:center;display:flex;justify-content:center}@media only screen and (min-device-width:700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size:1.2em}}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height:300px;overflow:hidden}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height:100%}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display:none}input[type=file]::-webkit-file-upload-button{display:none}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom:50%}} diff --git a/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css b/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css new file mode 100644 index 0000000..a0893b9 --- /dev/null +++ b/frontend/vben/public/resource/tinymce/skins/ui/oxide/skin.shadowdom.min.css @@ -0,0 +1,7 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + */ +body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201} diff --git a/frontend/vben/src/App.vue b/frontend/vben/src/App.vue new file mode 100644 index 0000000..b9097b4 --- /dev/null +++ b/frontend/vben/src/App.vue @@ -0,0 +1,21 @@ + + + diff --git a/frontend/vben/src/api/demo/account.ts b/frontend/vben/src/api/demo/account.ts new file mode 100644 index 0000000..3148b44 --- /dev/null +++ b/frontend/vben/src/api/demo/account.ts @@ -0,0 +1,16 @@ +import { defHttp } from '/@/utils/http/axios' +import { GetAccountInfoModel } from './model/accountModel' + +enum Api { + ACCOUNT_INFO = '/account/getAccountInfo', + SESSION_TIMEOUT = '/user/sessionTimeout', + TOKEN_EXPIRED = '/user/tokenExpired', +} + +// Get personal center-basic settings + +export const accountInfoApi = () => defHttp.get({ url: Api.ACCOUNT_INFO }) + +export const sessionTimeoutApi = () => defHttp.post({ url: Api.SESSION_TIMEOUT }) + +export const tokenExpiredApi = () => defHttp.post({ url: Api.TOKEN_EXPIRED }) diff --git a/frontend/vben/src/api/demo/cascader.ts b/frontend/vben/src/api/demo/cascader.ts new file mode 100644 index 0000000..92c0ab3 --- /dev/null +++ b/frontend/vben/src/api/demo/cascader.ts @@ -0,0 +1,9 @@ +import { defHttp } from '/@/utils/http/axios' +import { AreaModel, AreaParams } from '/@/api/demo/model/areaModel' + +enum Api { + AREA_RECORD = '/cascader/getAreaRecord', +} + +export const areaRecord = (data: AreaParams) => + defHttp.post({ url: Api.AREA_RECORD, data }) diff --git a/frontend/vben/src/api/demo/error.ts b/frontend/vben/src/api/demo/error.ts new file mode 100644 index 0000000..b8cfd8e --- /dev/null +++ b/frontend/vben/src/api/demo/error.ts @@ -0,0 +1,12 @@ +import { defHttp } from '/@/utils/http/axios' + +enum Api { + // The address does not exist + Error = '/error', +} + +/** + * @description: Trigger ajax error + */ + +export const fireErrorApi = () => defHttp.get({ url: Api.Error }) diff --git a/frontend/vben/src/api/demo/model/accountModel.ts b/frontend/vben/src/api/demo/model/accountModel.ts new file mode 100644 index 0000000..06c4888 --- /dev/null +++ b/frontend/vben/src/api/demo/model/accountModel.ts @@ -0,0 +1,7 @@ +export interface GetAccountInfoModel { + email: string + name: string + introduction: string + phone: string + address: string +} diff --git a/frontend/vben/src/api/demo/model/areaModel.ts b/frontend/vben/src/api/demo/model/areaModel.ts new file mode 100644 index 0000000..ac40079 --- /dev/null +++ b/frontend/vben/src/api/demo/model/areaModel.ts @@ -0,0 +1,12 @@ +export interface AreaModel { + id: string + code: string + parentCode: string + name: string + levelType: number + [key: string]: string | number +} + +export interface AreaParams { + parentCode: string +} diff --git a/frontend/vben/src/api/demo/model/optionsModel.ts b/frontend/vben/src/api/demo/model/optionsModel.ts new file mode 100644 index 0000000..086e3f7 --- /dev/null +++ b/frontend/vben/src/api/demo/model/optionsModel.ts @@ -0,0 +1,15 @@ +import { BasicFetchResult } from '/@/api/model/baseModel' + +export interface DemoOptionsItem { + label: string + value: string +} + +export interface selectParams { + id: number | string +} + +/** + * @description: Request list return value + */ +export type DemoOptionsGetResultModel = BasicFetchResult diff --git a/frontend/vben/src/api/demo/model/systemModel.ts b/frontend/vben/src/api/demo/model/systemModel.ts new file mode 100644 index 0000000..bb40ad0 --- /dev/null +++ b/frontend/vben/src/api/demo/model/systemModel.ts @@ -0,0 +1,74 @@ +import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel' + +export type AccountParams = BasicPageParams & { + account?: string + nickname?: string +} + +export type RoleParams = { + roleName?: string + status?: string +} + +export type RolePageParams = BasicPageParams & RoleParams + +export type DeptParams = { + deptName?: string + status?: string +} + +export type MenuParams = { + menuName?: string + status?: string +} + +export interface AccountListItem { + id: string + account: string + email: string + nickname: string + role: number + createTime: string + remark: string + status: number +} + +export interface DeptListItem { + id: string + orderNo: string + createTime: string + remark: string + status: number +} + +export interface MenuListItem { + id: string + orderNo: string + createTime: string + status: number + icon: string + component: string + permission: string +} + +export interface RoleListItem { + id: string + roleName: string + roleValue: string + status: number + orderNo: string + createTime: string +} + +/** + * @description: Request list return value + */ +export type AccountListGetResultModel = BasicFetchResult + +export type DeptListGetResultModel = BasicFetchResult + +export type MenuListGetResultModel = BasicFetchResult + +export type RolePageListGetResultModel = BasicFetchResult + +export type RoleListGetResultModel = RoleListItem[] diff --git a/frontend/vben/src/api/demo/model/tableModel.ts b/frontend/vben/src/api/demo/model/tableModel.ts new file mode 100644 index 0000000..d3fa40e --- /dev/null +++ b/frontend/vben/src/api/demo/model/tableModel.ts @@ -0,0 +1,20 @@ +import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel' +/** + * @description: Request list interface parameters + */ +export type DemoParams = BasicPageParams + +export interface DemoListItem { + id: string + beginTime: string + endTime: string + address: string + name: string + no: number + status: number +} + +/** + * @description: Request list return value + */ +export type DemoListGetResultModel = BasicFetchResult diff --git a/frontend/vben/src/api/demo/select.ts b/frontend/vben/src/api/demo/select.ts new file mode 100644 index 0000000..2049f42 --- /dev/null +++ b/frontend/vben/src/api/demo/select.ts @@ -0,0 +1,11 @@ +import { defHttp } from '/@/utils/http/axios' +import { DemoOptionsItem, selectParams } from './model/optionsModel' +enum Api { + OPTIONS_LIST = '/select/getDemoOptions', +} + +/** + * @description: Get sample options value + */ +export const optionsListApi = (params?: selectParams) => + defHttp.get({ url: Api.OPTIONS_LIST, params }) diff --git a/frontend/vben/src/api/demo/system.ts b/frontend/vben/src/api/demo/system.ts new file mode 100644 index 0000000..4233e32 --- /dev/null +++ b/frontend/vben/src/api/demo/system.ts @@ -0,0 +1,44 @@ +import { + AccountParams, + DeptListItem, + MenuParams, + RoleParams, + RolePageParams, + MenuListGetResultModel, + DeptListGetResultModel, + AccountListGetResultModel, + RolePageListGetResultModel, + RoleListGetResultModel, +} from './model/systemModel' +import { defHttp } from '/@/utils/http/axios' + +enum Api { + AccountList = '/system/getAccountList', + IsAccountExist = '/system/accountExist', + DeptList = '/system/getDeptList', + setRoleStatus = '/system/setRoleStatus', + MenuList = '/system/getMenuList', + RolePageList = '/system/getRoleListByPage', + GetAllRoleList = '/system/getAllRoleList', +} + +export const getAccountList = (params: AccountParams) => + defHttp.get({ url: Api.AccountList, params }) + +export const getDeptList = (params?: DeptListItem) => + defHttp.get({ url: Api.DeptList, params }) + +export const getMenuList = (params?: MenuParams) => + defHttp.get({ url: Api.MenuList, params }) + +export const getRoleListByPage = (params?: RolePageParams) => + defHttp.get({ url: Api.RolePageList, params }) + +export const getAllRoleList = (params?: RoleParams) => + defHttp.get({ url: Api.GetAllRoleList, params }) + +export const setRoleStatus = (id: number, status: string) => + defHttp.post({ url: Api.setRoleStatus, params: { id, status } }) + +export const isAccountExist = (account: string) => + defHttp.post({ url: Api.IsAccountExist, params: { account } }, { errorMessageMode: 'none' }) diff --git a/frontend/vben/src/api/demo/table.ts b/frontend/vben/src/api/demo/table.ts new file mode 100644 index 0000000..57f37db --- /dev/null +++ b/frontend/vben/src/api/demo/table.ts @@ -0,0 +1,20 @@ +import { defHttp } from '/@/utils/http/axios' +import { DemoParams, DemoListGetResultModel } from './model/tableModel' + +enum Api { + DEMO_LIST = '/table/getDemoList', +} + +/** + * @description: Get sample list value + */ + +export const demoListApi = (params: DemoParams) => + defHttp.get({ + url: Api.DEMO_LIST, + params, + headers: { + // @ts-ignore + ignoreCancelToken: true, + }, + }) diff --git a/frontend/vben/src/api/demo/tree.ts b/frontend/vben/src/api/demo/tree.ts new file mode 100644 index 0000000..fd3a30b --- /dev/null +++ b/frontend/vben/src/api/demo/tree.ts @@ -0,0 +1,11 @@ +import { defHttp } from '/@/utils/http/axios' + +enum Api { + TREE_OPTIONS_LIST = '/tree/getDemoOptions', +} + +/** + * @description: Get sample options value + */ +export const treeOptionsListApi = (params?: Recordable) => + defHttp.get({ url: Api.TREE_OPTIONS_LIST, params }) diff --git a/frontend/vben/src/api/model/baseModel.ts b/frontend/vben/src/api/model/baseModel.ts new file mode 100644 index 0000000..076b986 --- /dev/null +++ b/frontend/vben/src/api/model/baseModel.ts @@ -0,0 +1,9 @@ +export interface BasicPageParams { + page: number + pageSize: number +} + +export interface BasicFetchResult { + items: T[] + total: number +} diff --git a/frontend/vben/src/api/sys/menu.ts b/frontend/vben/src/api/sys/menu.ts new file mode 100644 index 0000000..e122713 --- /dev/null +++ b/frontend/vben/src/api/sys/menu.ts @@ -0,0 +1,14 @@ +import { defHttp } from '/@/utils/http/axios' +import { getMenuListResultModel } from './model/menuModel' + +enum Api { + GetMenuList = '/getMenuList', +} + +/** + * @description: Get user menu based on id + */ + +export const getMenuList = () => { + return defHttp.get({ url: Api.GetMenuList }) +} diff --git a/frontend/vben/src/api/sys/model/menuModel.ts b/frontend/vben/src/api/sys/model/menuModel.ts new file mode 100644 index 0000000..2d7789f --- /dev/null +++ b/frontend/vben/src/api/sys/model/menuModel.ts @@ -0,0 +1,16 @@ +import type { RouteMeta } from 'vue-router' +export interface RouteItem { + path: string + component: any + meta: RouteMeta + name?: string + alias?: string | string[] + redirect?: string + caseSensitive?: boolean + children?: RouteItem[] +} + +/** + * @description: Get menu return value + */ +export type getMenuListResultModel = RouteItem[] diff --git a/frontend/vben/src/api/sys/model/uploadModel.ts b/frontend/vben/src/api/sys/model/uploadModel.ts new file mode 100644 index 0000000..4d1698f --- /dev/null +++ b/frontend/vben/src/api/sys/model/uploadModel.ts @@ -0,0 +1,5 @@ +export interface UploadApiResult { + message: string + code: number + url: string +} diff --git a/frontend/vben/src/api/sys/model/userModel.ts b/frontend/vben/src/api/sys/model/userModel.ts new file mode 100644 index 0000000..3e3dc97 --- /dev/null +++ b/frontend/vben/src/api/sys/model/userModel.ts @@ -0,0 +1,38 @@ +/** + * @description: Login interface parameters + */ +export interface LoginParams { + username: string + password: string +} + +export interface RoleInfo { + roleName: string + value: string +} + +/** + * @description: Login interface return value + */ +export interface LoginResultModel { + userId: string | number + token: string + role: RoleInfo +} + +/** + * @description: Get user information return value + */ +export interface GetUserInfoModel { + roles: RoleInfo[] + // 用户id + userId: string | number + // 用户名 + username: string + // 真实名字 + realName: string + // 头像 + avatar: string + // 介绍 + desc?: string +} diff --git a/frontend/vben/src/api/sys/user.ts b/frontend/vben/src/api/sys/user.ts new file mode 100644 index 0000000..3963f69 --- /dev/null +++ b/frontend/vben/src/api/sys/user.ts @@ -0,0 +1,55 @@ +import { defHttp } from '/@/utils/http/axios' +import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel' + +import { ErrorMessageMode } from '/#/axios' + +enum Api { + Login = '/login', + Logout = '/logout', + GetUserInfo = '/getUserInfo', + GetPermCode = '/getPermCode', + TestRetry = '/testRetry', +} + +/** + * @description: user login api + */ +export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') { + return defHttp.post( + { + url: Api.Login, + params, + }, + { + errorMessageMode: mode, + }, + ) +} + +/** + * @description: getUserInfo + */ +export function getUserInfo() { + return defHttp.get({ url: Api.GetUserInfo }, { errorMessageMode: 'none' }) +} + +export function getPermCode() { + return defHttp.get({ url: Api.GetPermCode }) +} + +export function doLogout() { + return defHttp.get({ url: Api.Logout }) +} + +export function testRetry() { + return defHttp.get( + { url: Api.TestRetry }, + { + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 1000, + }, + }, + ) +} diff --git a/frontend/vben/src/assets/icons/download-count.svg b/frontend/vben/src/assets/icons/download-count.svg new file mode 100644 index 0000000..1c95195 --- /dev/null +++ b/frontend/vben/src/assets/icons/download-count.svg @@ -0,0 +1 @@ +Asset 91 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-1.svg b/frontend/vben/src/assets/icons/dynamic-avatar-1.svg new file mode 100644 index 0000000..e1553e5 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-1.svg @@ -0,0 +1 @@ +Asset 15 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-2.svg b/frontend/vben/src/assets/icons/dynamic-avatar-2.svg new file mode 100644 index 0000000..c4c1722 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-2.svg @@ -0,0 +1 @@ +Asset 16 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-3.svg b/frontend/vben/src/assets/icons/dynamic-avatar-3.svg new file mode 100644 index 0000000..81145f9 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-3.svg @@ -0,0 +1 @@ +Asset 17 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-4.svg b/frontend/vben/src/assets/icons/dynamic-avatar-4.svg new file mode 100644 index 0000000..e586ed4 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-4.svg @@ -0,0 +1 @@ +Asset 120 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-5.svg b/frontend/vben/src/assets/icons/dynamic-avatar-5.svg new file mode 100644 index 0000000..746e4b8 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-5.svg @@ -0,0 +1 @@ +Asset 110 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/dynamic-avatar-6.svg b/frontend/vben/src/assets/icons/dynamic-avatar-6.svg new file mode 100644 index 0000000..b2432f2 --- /dev/null +++ b/frontend/vben/src/assets/icons/dynamic-avatar-6.svg @@ -0,0 +1 @@ +Asset 100 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/moon.svg b/frontend/vben/src/assets/icons/moon.svg new file mode 100644 index 0000000..e6667f0 --- /dev/null +++ b/frontend/vben/src/assets/icons/moon.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/frontend/vben/src/assets/icons/sun.svg b/frontend/vben/src/assets/icons/sun.svg new file mode 100644 index 0000000..a3997cb --- /dev/null +++ b/frontend/vben/src/assets/icons/sun.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/vben/src/assets/icons/test.svg b/frontend/vben/src/assets/icons/test.svg new file mode 100644 index 0000000..244252d --- /dev/null +++ b/frontend/vben/src/assets/icons/test.svg @@ -0,0 +1,21 @@ + + + + Icon1@3x + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/total-sales.svg b/frontend/vben/src/assets/icons/total-sales.svg new file mode 100644 index 0000000..eff7964 --- /dev/null +++ b/frontend/vben/src/assets/icons/total-sales.svg @@ -0,0 +1 @@ +Asset 500 \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/transaction.svg b/frontend/vben/src/assets/icons/transaction.svg new file mode 100644 index 0000000..7ba9e2f --- /dev/null +++ b/frontend/vben/src/assets/icons/transaction.svg @@ -0,0 +1 @@ +Asset 480% \ No newline at end of file diff --git a/frontend/vben/src/assets/icons/visit-count.svg b/frontend/vben/src/assets/icons/visit-count.svg new file mode 100644 index 0000000..ba2a306 --- /dev/null +++ b/frontend/vben/src/assets/icons/visit-count.svg @@ -0,0 +1 @@ +Asset 510 \ No newline at end of file diff --git a/frontend/vben/src/assets/images/demo.png b/frontend/vben/src/assets/images/demo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a45c9835b7b2c708c114b04fb445e6ef00d8827 GIT binary patch literal 33342 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 K^riIu-2VXLS6svZ literal 0 HcmV?d00001 diff --git a/frontend/vben/src/assets/images/logo.png b/frontend/vben/src/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..16f2e7ab7c74552c5653652547ebce7adc4901dc GIT binary patch literal 28304 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 literal 0 HcmV?d00001 diff --git a/frontend/vben/src/assets/svg/illustration.svg b/frontend/vben/src/assets/svg/illustration.svg new file mode 100644 index 0000000..b45215b --- /dev/null +++ b/frontend/vben/src/assets/svg/illustration.svg @@ -0,0 +1 @@ +Asset 336 \ No newline at end of file diff --git a/frontend/vben/src/assets/svg/login-bg-dark.svg b/frontend/vben/src/assets/svg/login-bg-dark.svg new file mode 100644 index 0000000..888da7a --- /dev/null +++ b/frontend/vben/src/assets/svg/login-bg-dark.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/frontend/vben/src/assets/svg/login-bg.svg b/frontend/vben/src/assets/svg/login-bg.svg new file mode 100644 index 0000000..7b66baf --- /dev/null +++ b/frontend/vben/src/assets/svg/login-bg.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/frontend/vben/src/assets/svg/login-box-bg.svg b/frontend/vben/src/assets/svg/login-box-bg.svg new file mode 100644 index 0000000..ee7dbdc --- /dev/null +++ b/frontend/vben/src/assets/svg/login-box-bg.svg @@ -0,0 +1 @@ +responsive \ No newline at end of file diff --git a/frontend/vben/src/assets/svg/net-error.svg b/frontend/vben/src/assets/svg/net-error.svg new file mode 100644 index 0000000..81f2004 --- /dev/null +++ b/frontend/vben/src/assets/svg/net-error.svg @@ -0,0 +1 @@ +personal settings \ No newline at end of file diff --git a/frontend/vben/src/assets/svg/no-data.svg b/frontend/vben/src/assets/svg/no-data.svg new file mode 100644 index 0000000..2b9f257 --- /dev/null +++ b/frontend/vben/src/assets/svg/no-data.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/vben/src/assets/svg/preview/p-rotate.svg b/frontend/vben/src/assets/svg/preview/p-rotate.svg new file mode 100644 index 0000000..5153a81 --- /dev/null +++ b/frontend/vben/src/assets/svg/preview/p-rotate.svg @@ -0,0 +1 @@ + diff --git a/frontend/vben/src/assets/svg/preview/resume.svg b/frontend/vben/src/assets/svg/preview/resume.svg new file mode 100644 index 0000000..0e86c5f --- /dev/null +++ b/frontend/vben/src/assets/svg/preview/resume.svg @@ -0,0 +1 @@ + diff --git a/frontend/vben/src/assets/svg/preview/scale.svg b/frontend/vben/src/assets/svg/preview/scale.svg new file mode 100644 index 0000000..1f7adae --- /dev/null +++ b/frontend/vben/src/assets/svg/preview/scale.svg @@ -0,0 +1 @@ + diff --git a/frontend/vben/src/assets/svg/preview/unrotate.svg b/frontend/vben/src/assets/svg/preview/unrotate.svg new file mode 100644 index 0000000..e4708be --- /dev/null +++ b/frontend/vben/src/assets/svg/preview/unrotate.svg @@ -0,0 +1 @@ + diff --git a/frontend/vben/src/assets/svg/preview/unscale.svg b/frontend/vben/src/assets/svg/preview/unscale.svg new file mode 100644 index 0000000..1359b34 --- /dev/null +++ b/frontend/vben/src/assets/svg/preview/unscale.svg @@ -0,0 +1 @@ + diff --git a/frontend/vben/src/components/Application/index.ts b/frontend/vben/src/components/Application/index.ts new file mode 100644 index 0000000..f1c7e6f --- /dev/null +++ b/frontend/vben/src/components/Application/index.ts @@ -0,0 +1,15 @@ +import { withInstall } from '/@/utils' + +import appLogo from './src/AppLogo.vue' +import appProvider from './src/AppProvider.vue' +import appSearch from './src/search/AppSearch.vue' +import appLocalePicker from './src/AppLocalePicker.vue' +import appDarkModeToggle from './src/AppDarkModeToggle.vue' + +export { useAppProviderContext } from './src/useAppContext' + +export const AppLogo = withInstall(appLogo) +export const AppProvider = withInstall(appProvider) +export const AppSearch = withInstall(appSearch) +export const AppLocalePicker = withInstall(appLocalePicker) +export const AppDarkModeToggle = withInstall(appDarkModeToggle) diff --git a/frontend/vben/src/components/Application/src/AppDarkModeToggle.vue b/frontend/vben/src/components/Application/src/AppDarkModeToggle.vue new file mode 100644 index 0000000..5c8c5d8 --- /dev/null +++ b/frontend/vben/src/components/Application/src/AppDarkModeToggle.vue @@ -0,0 +1,76 @@ + + + diff --git a/frontend/vben/src/components/Application/src/AppLocalePicker.vue b/frontend/vben/src/components/Application/src/AppLocalePicker.vue new file mode 100644 index 0000000..9204d63 --- /dev/null +++ b/frontend/vben/src/components/Application/src/AppLocalePicker.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/frontend/vben/src/components/Application/src/AppLogo.vue b/frontend/vben/src/components/Application/src/AppLogo.vue new file mode 100644 index 0000000..9d7d99a --- /dev/null +++ b/frontend/vben/src/components/Application/src/AppLogo.vue @@ -0,0 +1,93 @@ + + + + diff --git a/frontend/vben/src/components/Application/src/AppProvider.vue b/frontend/vben/src/components/Application/src/AppProvider.vue new file mode 100644 index 0000000..18250b7 --- /dev/null +++ b/frontend/vben/src/components/Application/src/AppProvider.vue @@ -0,0 +1,82 @@ + diff --git a/frontend/vben/src/components/Application/src/search/AppSearch.vue b/frontend/vben/src/components/Application/src/search/AppSearch.vue new file mode 100644 index 0000000..97eef54 --- /dev/null +++ b/frontend/vben/src/components/Application/src/search/AppSearch.vue @@ -0,0 +1,33 @@ + diff --git a/frontend/vben/src/components/Application/src/search/AppSearchFooter.vue b/frontend/vben/src/components/Application/src/search/AppSearchFooter.vue new file mode 100644 index 0000000..8642c8e --- /dev/null +++ b/frontend/vben/src/components/Application/src/search/AppSearchFooter.vue @@ -0,0 +1,56 @@ + + + + diff --git a/frontend/vben/src/components/Application/src/search/AppSearchKeyItem.vue b/frontend/vben/src/components/Application/src/search/AppSearchKeyItem.vue new file mode 100644 index 0000000..567de61 --- /dev/null +++ b/frontend/vben/src/components/Application/src/search/AppSearchKeyItem.vue @@ -0,0 +1,11 @@ + + diff --git a/frontend/vben/src/components/Application/src/search/AppSearchModal.vue b/frontend/vben/src/components/Application/src/search/AppSearchModal.vue new file mode 100644 index 0000000..b5bd98f --- /dev/null +++ b/frontend/vben/src/components/Application/src/search/AppSearchModal.vue @@ -0,0 +1,267 @@ + + + + diff --git a/frontend/vben/src/components/Application/src/search/useMenuSearch.ts b/frontend/vben/src/components/Application/src/search/useMenuSearch.ts new file mode 100644 index 0000000..d2f5e4a --- /dev/null +++ b/frontend/vben/src/components/Application/src/search/useMenuSearch.ts @@ -0,0 +1,166 @@ +import type { Menu } from '/@/router/types' +import { ref, onBeforeMount, unref, Ref, nextTick } from 'vue' +import { getMenus } from '/@/router/menus' +import { cloneDeep } from 'lodash-es' +import { filter, forEach } from '/@/utils/helper/treeHelper' +import { useGo } from '/@/hooks/web/usePage' +import { useScrollTo } from '/@/hooks/event/useScrollTo' +import { onKeyStroke, useDebounceFn } from '@vueuse/core' +import { useI18n } from '/@/hooks/web/useI18n' + +export interface SearchResult { + name: string + path: string + icon?: string +} + +// Translate special characters +function transform(c: string) { + const code: string[] = ['$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'] + return code.includes(c) ? `\\${c}` : c +} + +function createSearchReg(key: string) { + const keys = [...key].map((item) => transform(item)) + const str = ['', ...keys, ''].join('.*') + return new RegExp(str) +} + +export function useMenuSearch(refs: Ref, scrollWrap: Ref, emit: EmitType) { + const searchResult = ref([]) + const keyword = ref('') + const activeIndex = ref(-1) + + let menuList: Menu[] = [] + + const { t } = useI18n() + const go = useGo() + const handleSearch = useDebounceFn(search, 200) + + onBeforeMount(async () => { + const list = await getMenus() + menuList = cloneDeep(list) + forEach(menuList, (item) => { + item.name = t(item.name) + }) + }) + + function search(e: ChangeEvent) { + e?.stopPropagation() + const key = e.target.value + keyword.value = key.trim() + if (!key) { + searchResult.value = [] + return + } + const reg = createSearchReg(unref(keyword)) + const filterMenu = filter(menuList, (item) => { + return reg.test(item.name) && !item.hideMenu + }) + searchResult.value = handlerSearchResult(filterMenu, reg) + activeIndex.value = 0 + } + + function handlerSearchResult(filterMenu: Menu[], reg: RegExp, parent?: Menu) { + const ret: SearchResult[] = [] + filterMenu.forEach((item) => { + const { name, path, icon, children, hideMenu, meta } = item + if (!hideMenu && reg.test(name) && (!children?.length || meta?.hideChildrenInMenu)) { + ret.push({ + name: parent?.name ? `${parent.name} > ${name}` : name, + path, + icon, + }) + } + if (!meta?.hideChildrenInMenu && Array.isArray(children) && children.length) { + ret.push(...handlerSearchResult(children, reg, item)) + } + }) + return ret + } + + // Activate when the mouse moves to a certain line + function handleMouseenter(e: any) { + const index = e.target.dataset.index + activeIndex.value = Number(index) + } + + // Arrow key up + function handleUp() { + if (!searchResult.value.length) return + activeIndex.value-- + if (activeIndex.value < 0) { + activeIndex.value = searchResult.value.length - 1 + } + handleScroll() + } + + // Arrow key down + function handleDown() { + if (!searchResult.value.length) return + activeIndex.value++ + if (activeIndex.value > searchResult.value.length - 1) { + activeIndex.value = 0 + } + handleScroll() + } + + // When the keyboard up and down keys move to an invisible place + // the scroll bar needs to scroll automatically + function handleScroll() { + const refList = unref(refs) + if (!refList || !Array.isArray(refList) || refList.length === 0 || !unref(scrollWrap)) { + return + } + + const index = unref(activeIndex) + const currentRef = refList[index] + if (!currentRef) { + return + } + const wrapEl = unref(scrollWrap) + if (!wrapEl) { + return + } + const scrollHeight = currentRef.offsetTop + currentRef.offsetHeight + const wrapHeight = wrapEl.offsetHeight + const { start } = useScrollTo({ + el: wrapEl, + duration: 100, + to: scrollHeight - wrapHeight, + }) + start() + } + + // enter keyboard event + async function handleEnter() { + if (!searchResult.value.length) { + return + } + const result = unref(searchResult) + const index = unref(activeIndex) + if (result.length === 0 || index < 0) { + return + } + const to = result[index] + handleClose() + await nextTick() + go(to.path) + } + + // close search modal + function handleClose() { + searchResult.value = [] + emit('close') + } + + // enter search + onKeyStroke('Enter', handleEnter) + // Monitor keyboard arrow keys + onKeyStroke('ArrowUp', handleUp) + onKeyStroke('ArrowDown', handleDown) + // esc close + onKeyStroke('Escape', handleClose) + + return { handleSearch, searchResult, keyword, activeIndex, handleMouseenter, handleEnter } +} diff --git a/frontend/vben/src/components/Application/src/useAppContext.ts b/frontend/vben/src/components/Application/src/useAppContext.ts new file mode 100644 index 0000000..fbd8784 --- /dev/null +++ b/frontend/vben/src/components/Application/src/useAppContext.ts @@ -0,0 +1,17 @@ +import { InjectionKey, Ref } from 'vue' +import { createContext, useContext } from '/@/hooks/core/useContext' + +export interface AppProviderContextProps { + prefixCls: Ref + isMobile: Ref +} + +const key: InjectionKey = Symbol() + +export function createAppProviderContext(context: AppProviderContextProps) { + return createContext(context, key) +} + +export function useAppProviderContext() { + return useContext(key) +} diff --git a/frontend/vben/src/components/Basic/index.ts b/frontend/vben/src/components/Basic/index.ts new file mode 100644 index 0000000..ff04584 --- /dev/null +++ b/frontend/vben/src/components/Basic/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '/@/utils' +import basicArrow from './src/BasicArrow.vue' +import basicTitle from './src/BasicTitle.vue' +import basicHelp from './src/BasicHelp.vue' + +export const BasicArrow = withInstall(basicArrow) +export const BasicTitle = withInstall(basicTitle) +export const BasicHelp = withInstall(basicHelp) diff --git a/frontend/vben/src/components/Basic/src/BasicArrow.vue b/frontend/vben/src/components/Basic/src/BasicArrow.vue new file mode 100644 index 0000000..205a72f --- /dev/null +++ b/frontend/vben/src/components/Basic/src/BasicArrow.vue @@ -0,0 +1,84 @@ + + + + diff --git a/frontend/vben/src/components/Basic/src/BasicHelp.vue b/frontend/vben/src/components/Basic/src/BasicHelp.vue new file mode 100644 index 0000000..2eb3317 --- /dev/null +++ b/frontend/vben/src/components/Basic/src/BasicHelp.vue @@ -0,0 +1,114 @@ + + diff --git a/frontend/vben/src/components/Basic/src/BasicTitle.vue b/frontend/vben/src/components/Basic/src/BasicTitle.vue new file mode 100644 index 0000000..41ec3d8 --- /dev/null +++ b/frontend/vben/src/components/Basic/src/BasicTitle.vue @@ -0,0 +1,76 @@ + + + diff --git a/frontend/vben/src/components/Button/index.ts b/frontend/vben/src/components/Button/index.ts new file mode 100644 index 0000000..b53e565 --- /dev/null +++ b/frontend/vben/src/components/Button/index.ts @@ -0,0 +1,9 @@ +import { withInstall } from '/@/utils' +import type { ExtractPropTypes } from 'vue' +import button from './src/BasicButton.vue' +import popConfirmButton from './src/PopConfirmButton.vue' +import { buttonProps } from './src/props' + +export const Button = withInstall(button) +export const PopConfirmButton = withInstall(popConfirmButton) +export declare type ButtonProps = Partial> diff --git a/frontend/vben/src/components/Button/src/BasicButton.vue b/frontend/vben/src/components/Button/src/BasicButton.vue new file mode 100644 index 0000000..adb5e66 --- /dev/null +++ b/frontend/vben/src/components/Button/src/BasicButton.vue @@ -0,0 +1,40 @@ + + + + diff --git a/frontend/vben/src/components/Button/src/PopConfirmButton.vue b/frontend/vben/src/components/Button/src/PopConfirmButton.vue new file mode 100644 index 0000000..3ad7f06 --- /dev/null +++ b/frontend/vben/src/components/Button/src/PopConfirmButton.vue @@ -0,0 +1,54 @@ + diff --git a/frontend/vben/src/components/Button/src/props.ts b/frontend/vben/src/components/Button/src/props.ts new file mode 100644 index 0000000..c08fd2d --- /dev/null +++ b/frontend/vben/src/components/Button/src/props.ts @@ -0,0 +1,19 @@ +export const buttonProps = { + color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) }, + loading: { type: Boolean }, + disabled: { type: Boolean }, + /** + * Text before icon. + */ + preIcon: { type: String }, + /** + * Text after icon. + */ + postIcon: { type: String }, + /** + * preIcon and postIcon icon size. + * @default: 14 + */ + iconSize: { type: Number, default: 14 }, + onClick: { type: Function as PropType<(...args) => any>, default: null }, +} diff --git a/frontend/vben/src/components/Container/index.ts b/frontend/vben/src/components/Container/index.ts new file mode 100644 index 0000000..20c0e96 --- /dev/null +++ b/frontend/vben/src/components/Container/index.ts @@ -0,0 +1,10 @@ +import { withInstall } from '/@/utils' +import collapseContainer from './src/collapse/CollapseContainer.vue' +import scrollContainer from './src/ScrollContainer.vue' +import lazyContainer from './src/LazyContainer.vue' + +export const CollapseContainer = withInstall(collapseContainer) +export const ScrollContainer = withInstall(scrollContainer) +export const LazyContainer = withInstall(lazyContainer) + +export * from './src/typing' diff --git a/frontend/vben/src/components/Container/src/LazyContainer.vue b/frontend/vben/src/components/Container/src/LazyContainer.vue new file mode 100644 index 0000000..3f43389 --- /dev/null +++ b/frontend/vben/src/components/Container/src/LazyContainer.vue @@ -0,0 +1,145 @@ + + diff --git a/frontend/vben/src/components/Container/src/ScrollContainer.vue b/frontend/vben/src/components/Container/src/ScrollContainer.vue new file mode 100644 index 0000000..afdba24 --- /dev/null +++ b/frontend/vben/src/components/Container/src/ScrollContainer.vue @@ -0,0 +1,93 @@ + + + + diff --git a/frontend/vben/src/components/Container/src/collapse/CollapseContainer.vue b/frontend/vben/src/components/Container/src/collapse/CollapseContainer.vue new file mode 100644 index 0000000..754f3c5 --- /dev/null +++ b/frontend/vben/src/components/Container/src/collapse/CollapseContainer.vue @@ -0,0 +1,110 @@ + + + diff --git a/frontend/vben/src/components/Container/src/collapse/CollapseHeader.vue b/frontend/vben/src/components/Container/src/collapse/CollapseHeader.vue new file mode 100644 index 0000000..e3a0e6b --- /dev/null +++ b/frontend/vben/src/components/Container/src/collapse/CollapseHeader.vue @@ -0,0 +1,38 @@ + + diff --git a/frontend/vben/src/components/Container/src/typing.ts b/frontend/vben/src/components/Container/src/typing.ts new file mode 100644 index 0000000..57c7922 --- /dev/null +++ b/frontend/vben/src/components/Container/src/typing.ts @@ -0,0 +1,17 @@ +export type ScrollType = 'default' | 'main' + +export interface CollapseContainerOptions { + canExpand?: boolean + title?: string + helpMessage?: Array | string +} +export interface ScrollContainerOptions { + enableScroll?: boolean + type?: ScrollType +} + +export type ScrollActionType = RefType<{ + scrollBottom: () => void + getScrollWrap: () => Nullable + scrollTo: (top: number) => void +}> diff --git a/frontend/vben/src/components/CountDown/index.ts b/frontend/vben/src/components/CountDown/index.ts new file mode 100644 index 0000000..430e4bb --- /dev/null +++ b/frontend/vben/src/components/CountDown/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils' +import countButton from './src/CountButton.vue' +import countdownInput from './src/CountdownInput.vue' + +export const CountdownInput = withInstall(countdownInput) +export const CountButton = withInstall(countButton) diff --git a/frontend/vben/src/components/CountDown/src/CountButton.vue b/frontend/vben/src/components/CountDown/src/CountButton.vue new file mode 100644 index 0000000..5a785ab --- /dev/null +++ b/frontend/vben/src/components/CountDown/src/CountButton.vue @@ -0,0 +1,62 @@ + + diff --git a/frontend/vben/src/components/CountDown/src/CountdownInput.vue b/frontend/vben/src/components/CountDown/src/CountdownInput.vue new file mode 100644 index 0000000..9cb058e --- /dev/null +++ b/frontend/vben/src/components/CountDown/src/CountdownInput.vue @@ -0,0 +1,54 @@ + + + diff --git a/frontend/vben/src/components/CountDown/src/useCountdown.ts b/frontend/vben/src/components/CountDown/src/useCountdown.ts new file mode 100644 index 0000000..2feb6f2 --- /dev/null +++ b/frontend/vben/src/components/CountDown/src/useCountdown.ts @@ -0,0 +1,51 @@ +import { ref, unref } from 'vue' +import { tryOnUnmounted } from '@vueuse/core' + +export function useCountdown(count: number) { + const currentCount = ref(count) + + const isStart = ref(false) + + let timerId: ReturnType | null + + function clear() { + timerId && window.clearInterval(timerId) + } + + function stop() { + isStart.value = false + clear() + timerId = null + } + + function start() { + if (unref(isStart) || !!timerId) { + return + } + isStart.value = true + timerId = setInterval(() => { + if (unref(currentCount) === 1) { + stop() + currentCount.value = count + } else { + currentCount.value -= 1 + } + }, 1000) + } + + function reset() { + currentCount.value = count + stop() + } + + function restart() { + reset() + start() + } + + tryOnUnmounted(() => { + reset() + }) + + return { start, reset, restart, clear, stop, currentCount, isStart } +} diff --git a/frontend/vben/src/components/Description/index.ts b/frontend/vben/src/components/Description/index.ts new file mode 100644 index 0000000..074babf --- /dev/null +++ b/frontend/vben/src/components/Description/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils' +import description from './src/Description.vue' + +export * from './src/typing' +export { useDescription } from './src/useDescription' +export const Description = withInstall(description) diff --git a/frontend/vben/src/components/Description/src/Description.vue b/frontend/vben/src/components/Description/src/Description.vue new file mode 100644 index 0000000..dddf133 --- /dev/null +++ b/frontend/vben/src/components/Description/src/Description.vue @@ -0,0 +1,184 @@ + diff --git a/frontend/vben/src/components/Description/src/typing.ts b/frontend/vben/src/components/Description/src/typing.ts new file mode 100644 index 0000000..1fc0655 --- /dev/null +++ b/frontend/vben/src/components/Description/src/typing.ts @@ -0,0 +1,50 @@ +import type { VNode, CSSProperties } from 'vue' +import type { CollapseContainerOptions } from '/@/components/Container/index' +import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index' + +export interface DescItem { + labelMinWidth?: number + contentMinWidth?: number + labelStyle?: CSSProperties + field: string + label: string | VNode | JSX.Element + // Merge column + span?: number + show?: (...arg: any) => boolean + // render + render?: ( + val: any, + data: Recordable, + ) => VNode | undefined | JSX.Element | Element | string | number +} + +export interface DescriptionProps extends DescriptionsProps { + // Whether to include the collapse component + useCollapse?: boolean + /** + * item configuration + * @type DescItem + */ + schema: DescItem[] + /** + * 数据 + * @type object + */ + data: Recordable + /** + * Built-in CollapseContainer component configuration + * @type CollapseContainerOptions + */ + collapseOptions?: CollapseContainerOptions +} + +export interface DescInstance { + setDescProps(descProps: Partial): void +} + +export type Register = (descInstance: DescInstance) => void + +/** + * @description: + */ +export type UseDescReturnType = [Register, DescInstance] diff --git a/frontend/vben/src/components/Description/src/useDescription.ts b/frontend/vben/src/components/Description/src/useDescription.ts new file mode 100644 index 0000000..07bb11a --- /dev/null +++ b/frontend/vben/src/components/Description/src/useDescription.ts @@ -0,0 +1,28 @@ +import type { DescriptionProps, DescInstance, UseDescReturnType } from './typing' +import { ref, getCurrentInstance, unref } from 'vue' +import { isProdMode } from '/@/utils/env' + +export function useDescription(props?: Partial): UseDescReturnType { + if (!getCurrentInstance()) { + throw new Error('useDescription() can only be used inside setup() or functional components!') + } + const desc = ref>(null) + const loaded = ref(false) + + function register(instance: DescInstance) { + if (unref(loaded) && isProdMode()) { + return + } + desc.value = instance + props && instance.setDescProps(props) + loaded.value = true + } + + const methods: DescInstance = { + setDescProps: (descProps: Partial): void => { + unref(desc)?.setDescProps(descProps) + }, + } + + return [register, methods] +} diff --git a/frontend/vben/src/components/Drawer/index.ts b/frontend/vben/src/components/Drawer/index.ts new file mode 100644 index 0000000..73e4a49 --- /dev/null +++ b/frontend/vben/src/components/Drawer/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from '/@/utils' +import basicDrawer from './src/BasicDrawer.vue' + +export const BasicDrawer = withInstall(basicDrawer) +export * from './src/typing' +export { useDrawer, useDrawerInner } from './src/useDrawer' diff --git a/frontend/vben/src/components/Drawer/src/BasicDrawer.vue b/frontend/vben/src/components/Drawer/src/BasicDrawer.vue new file mode 100644 index 0000000..bcd3537 --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/BasicDrawer.vue @@ -0,0 +1,256 @@ + + + diff --git a/frontend/vben/src/components/Drawer/src/components/DrawerFooter.vue b/frontend/vben/src/components/Drawer/src/components/DrawerFooter.vue new file mode 100644 index 0000000..de319fb --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/components/DrawerFooter.vue @@ -0,0 +1,82 @@ + + + + diff --git a/frontend/vben/src/components/Drawer/src/components/DrawerHeader.vue b/frontend/vben/src/components/Drawer/src/components/DrawerHeader.vue new file mode 100644 index 0000000..6ad453c --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/components/DrawerHeader.vue @@ -0,0 +1,74 @@ + + + + diff --git a/frontend/vben/src/components/Drawer/src/props.ts b/frontend/vben/src/components/Drawer/src/props.ts new file mode 100644 index 0000000..1931788 --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/props.ts @@ -0,0 +1,44 @@ +import type { PropType } from 'vue' + +import { useI18n } from '/@/hooks/web/useI18n' +const { t } = useI18n() + +export const footerProps = { + confirmLoading: { type: Boolean }, + /** + * @description: Show close button + */ + showCancelBtn: { type: Boolean, default: true }, + cancelButtonProps: Object as PropType, + cancelText: { type: String, default: t('common.cancelText') }, + /** + * @description: Show confirmation button + */ + showOkBtn: { type: Boolean, default: true }, + okButtonProps: Object as PropType, + okText: { type: String, default: t('common.okText') }, + okType: { type: String, default: 'primary' }, + showFooter: { type: Boolean }, + footerHeight: { + type: [String, Number] as PropType, + default: 60, + }, +} +export const basicProps = { + isDetail: { type: Boolean }, + title: { type: String, default: '' }, + loadingText: { type: String }, + showDetailBack: { type: Boolean, default: true }, + visible: { type: Boolean }, + loading: { type: Boolean }, + maskClosable: { type: Boolean, default: true }, + getContainer: { + type: [Object, String] as PropType, + }, + closeFunc: { + type: [Function, Object] as PropType, + default: null, + }, + destroyOnClose: { type: Boolean }, + ...footerProps, +} diff --git a/frontend/vben/src/components/Drawer/src/typing.ts b/frontend/vben/src/components/Drawer/src/typing.ts new file mode 100644 index 0000000..a58134e --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/typing.ts @@ -0,0 +1,193 @@ +import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes' +import type { CSSProperties, VNodeChild, ComputedRef } from 'vue' +import type { ScrollContainerOptions } from '/@/components/Container/index' + +export interface DrawerInstance { + setDrawerProps: (props: Partial | boolean) => void + emitVisible?: (visible: boolean, uid: number) => void +} + +export interface ReturnMethods extends DrawerInstance { + openDrawer: (visible?: boolean, data?: T, openOnSet?: boolean) => void + closeDrawer: () => void + getVisible?: ComputedRef +} + +export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void + +export interface ReturnInnerMethods extends DrawerInstance { + closeDrawer: () => void + changeLoading: (loading: boolean) => void + changeOkLoading: (loading: boolean) => void + getVisible?: ComputedRef +} + +export type UseDrawerReturnType = [RegisterFn, ReturnMethods] + +export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods] + +export interface DrawerFooterProps { + showOkBtn: boolean + showCancelBtn: boolean + /** + * Text of the Cancel button + * @default 'cancel' + * @type string + */ + cancelText: string + /** + * Text of the OK button + * @default 'OK' + * @type string + */ + okText: string + + /** + * Button type of the OK button + * @default 'primary' + * @type string + */ + okType: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default' + /** + * The ok button props, follow jsx rules + * @type object + */ + okButtonProps: { props: ButtonProps; on: {} } + + /** + * The cancel button props, follow jsx rules + * @type object + */ + cancelButtonProps: { props: ButtonProps; on: {} } + /** + * Whether to apply loading visual effect for OK button or not + * @default false + * @type boolean + */ + confirmLoading: boolean + + showFooter: boolean + footerHeight: string | number +} +export interface DrawerProps extends DrawerFooterProps { + isDetail?: boolean + loading?: boolean + showDetailBack?: boolean + visible?: boolean + /** + * Built-in ScrollContainer component configuration + * @type ScrollContainerOptions + */ + scrollOptions?: ScrollContainerOptions + closeFunc?: () => Promise + triggerWindowResize?: boolean + /** + * Whether a close (x) button is visible on top right of the Drawer dialog or not. + * @default true + * @type boolean + */ + closable?: boolean + + /** + * Whether to unmount child components on closing drawer or not. + * @default false + * @type boolean + */ + destroyOnClose?: boolean + + /** + * Return the mounted node for Drawer. + * @default 'body' + * @type any ( HTMLElement| () => HTMLElement | string) + */ + getContainer?: () => HTMLElement | string + + /** + * Whether to show mask or not. + * @default true + * @type boolean + */ + mask?: boolean + + /** + * Clicking on the mask (area outside the Drawer) to close the Drawer or not. + * @default true + * @type boolean + */ + maskClosable?: boolean + + /** + * Style for Drawer's mask element. + * @default {} + * @type object + */ + maskStyle?: CSSProperties + + /** + * The title for Drawer. + * @type any (string | slot) + */ + title?: VNodeChild | JSX.Element + /** + * The class name of the container of the Drawer dialog. + * @type string + */ + wrapClassName?: string + class?: string + /** + * Style of wrapper element which **contains mask** compare to `drawerStyle` + * @type object + */ + wrapStyle?: CSSProperties + + /** + * Style of the popup layer element + * @type object + */ + drawerStyle?: CSSProperties + + /** + * Style of floating layer, typically used for adjusting its position. + * @type object + */ + bodyStyle?: CSSProperties + headerStyle?: CSSProperties + + /** + * Width of the Drawer dialog. + * @default 256 + * @type string | number + */ + width?: string | number + + /** + * placement is top or bottom, height of the Drawer dialog. + * @type string | number + */ + height?: string | number + + /** + * The z-index of the Drawer. + * @default 1000 + * @type number + */ + zIndex?: number + + /** + * The placement of the Drawer. + * @default 'right' + * @type string + */ + placement?: 'top' | 'right' | 'bottom' | 'left' + afterVisibleChange?: (visible?: boolean) => void + keyboard?: boolean + /** + * Specify a callback that will be called when a user clicks mask, close button or Cancel button. + */ + onClose?: (e?: Event) => void +} +export interface DrawerActionType { + scrollBottom: () => void + scrollTo: (to: number) => void + getScrollWrap: () => Element | null +} diff --git a/frontend/vben/src/components/Drawer/src/useDrawer.ts b/frontend/vben/src/components/Drawer/src/useDrawer.ts new file mode 100644 index 0000000..20c7fcf --- /dev/null +++ b/frontend/vben/src/components/Drawer/src/useDrawer.ts @@ -0,0 +1,161 @@ +import type { + UseDrawerReturnType, + DrawerInstance, + ReturnMethods, + DrawerProps, + UseDrawerInnerReturnType, +} from './typing' +import { + ref, + getCurrentInstance, + unref, + reactive, + watchEffect, + nextTick, + toRaw, + computed, +} from 'vue' +import { isProdMode } from '/@/utils/env' +import { isFunction } from '/@/utils/is' +import { tryOnUnmounted } from '@vueuse/core' +import { isEqual } from 'lodash-es' +import { error } from '/@/utils/log' + +const dataTransferRef = reactive({}) + +const visibleData = reactive<{ [key: number]: boolean }>({}) + +/** + * @description: Applicable to separate drawer and call outside + */ +export function useDrawer(): UseDrawerReturnType { + if (!getCurrentInstance()) { + throw new Error('useDrawer() can only be used inside setup() or functional components!') + } + const drawer = ref(null) + const loaded = ref>(false) + const uid = ref('') + + function register(drawerInstance: DrawerInstance, uuid: string) { + isProdMode() && + tryOnUnmounted(() => { + drawer.value = null + loaded.value = null + dataTransferRef[unref(uid)] = null + }) + + if (unref(loaded) && isProdMode() && drawerInstance === unref(drawer)) { + return + } + uid.value = uuid + drawer.value = drawerInstance + loaded.value = true + + drawerInstance.emitVisible = (visible: boolean, uid: number) => { + visibleData[uid] = visible + } + } + + const getInstance = () => { + const instance = unref(drawer) + if (!instance) { + error('useDrawer instance is undefined!') + } + return instance + } + + const methods: ReturnMethods = { + setDrawerProps: (props: Partial): void => { + getInstance()?.setDrawerProps(props) + }, + + getVisible: computed((): boolean => { + return visibleData[~~unref(uid)] + }), + + openDrawer: (visible = true, data?: T, openOnSet = true): void => { + getInstance()?.setDrawerProps({ + visible: visible, + }) + if (!data) return + + if (openOnSet) { + dataTransferRef[unref(uid)] = null + dataTransferRef[unref(uid)] = toRaw(data) + return + } + const equal = isEqual(toRaw(dataTransferRef[unref(uid)]), toRaw(data)) + if (!equal) { + dataTransferRef[unref(uid)] = toRaw(data) + } + }, + closeDrawer: () => { + getInstance()?.setDrawerProps({ visible: false }) + }, + } + + return [register, methods] +} + +export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => { + const drawerInstanceRef = ref>(null) + const currentInstance = getCurrentInstance() + const uidRef = ref('') + + if (!getCurrentInstance()) { + throw new Error('useDrawerInner() can only be used inside setup() or functional components!') + } + + const getInstance = () => { + const instance = unref(drawerInstanceRef) + if (!instance) { + error('useDrawerInner instance is undefined!') + return + } + return instance + } + + const register = (modalInstance: DrawerInstance, uuid: string) => { + isProdMode() && + tryOnUnmounted(() => { + drawerInstanceRef.value = null + }) + + uidRef.value = uuid + drawerInstanceRef.value = modalInstance + currentInstance?.emit('register', modalInstance, uuid) + } + + watchEffect(() => { + const data = dataTransferRef[unref(uidRef)] + if (!data) return + if (!callbackFn || !isFunction(callbackFn)) return + nextTick(() => { + callbackFn(data) + }) + }) + + return [ + register, + { + changeLoading: (loading = true) => { + getInstance()?.setDrawerProps({ loading }) + }, + + changeOkLoading: (loading = true) => { + getInstance()?.setDrawerProps({ confirmLoading: loading }) + }, + getVisible: computed((): boolean => { + return visibleData[~~unref(uidRef)] + }), + + closeDrawer: () => { + getInstance()?.setDrawerProps({ visible: false }) + }, + + setDrawerProps: (props: Partial) => { + getInstance()?.setDrawerProps(props) + }, + }, + ] +} diff --git a/frontend/vben/src/components/Dropdown/index.ts b/frontend/vben/src/components/Dropdown/index.ts new file mode 100644 index 0000000..57a51c8 --- /dev/null +++ b/frontend/vben/src/components/Dropdown/index.ts @@ -0,0 +1,5 @@ +import { withInstall } from '/@/utils' +import dropdown from './src/Dropdown.vue' + +export * from './src/typing' +export const Dropdown = withInstall(dropdown) diff --git a/frontend/vben/src/components/Dropdown/src/Dropdown.vue b/frontend/vben/src/components/Dropdown/src/Dropdown.vue new file mode 100644 index 0000000..a656940 --- /dev/null +++ b/frontend/vben/src/components/Dropdown/src/Dropdown.vue @@ -0,0 +1,96 @@ + + + diff --git a/frontend/vben/src/components/Dropdown/src/typing.ts b/frontend/vben/src/components/Dropdown/src/typing.ts new file mode 100644 index 0000000..4ccead6 --- /dev/null +++ b/frontend/vben/src/components/Dropdown/src/typing.ts @@ -0,0 +1,9 @@ +export interface DropMenu { + onClick?: Fn + to?: string + icon?: string + event: string | number + text: string + disabled?: boolean + divider?: boolean +} diff --git a/frontend/vben/src/components/Icon/data/icons.data.ts b/frontend/vben/src/components/Icon/data/icons.data.ts new file mode 100644 index 0000000..a7ab42a --- /dev/null +++ b/frontend/vben/src/components/Icon/data/icons.data.ts @@ -0,0 +1,786 @@ +export default { + prefix: 'ant-design', + icons: [ + 'account-book-filled', + 'account-book-outlined', + 'account-book-twotone', + 'aim-outlined', + 'alert-filled', + 'alert-outlined', + 'alert-twotone', + 'alibaba-outlined', + 'align-center-outlined', + 'align-left-outlined', + 'align-right-outlined', + 'alipay-circle-filled', + 'alipay-circle-outlined', + 'alipay-outlined', + 'alipay-square-filled', + 'aliwangwang-filled', + 'aliwangwang-outlined', + 'aliyun-outlined', + 'amazon-circle-filled', + 'amazon-outlined', + 'amazon-square-filled', + 'android-filled', + 'android-outlined', + 'ant-cloud-outlined', + 'ant-design-outlined', + 'apartment-outlined', + 'api-filled', + 'api-outlined', + 'api-twotone', + 'apple-filled', + 'apple-outlined', + 'appstore-add-outlined', + 'appstore-filled', + 'appstore-outlined', + 'appstore-twotone', + 'area-chart-outlined', + 'arrow-down-outlined', + 'arrow-left-outlined', + 'arrow-right-outlined', + 'arrow-up-outlined', + 'arrows-alt-outlined', + 'audio-filled', + 'audio-muted-outlined', + 'audio-outlined', + 'audio-twotone', + 'audit-outlined', + 'backward-filled', + 'backward-outlined', + 'bank-filled', + 'bank-outlined', + 'bank-twotone', + 'bar-chart-outlined', + 'barcode-outlined', + 'bars-outlined', + 'behance-circle-filled', + 'behance-outlined', + 'behance-square-filled', + 'behance-square-outlined', + 'bell-filled', + 'bell-outlined', + 'bell-twotone', + 'bg-colors-outlined', + 'block-outlined', + 'bold-outlined', + 'book-filled', + 'book-outlined', + 'book-twotone', + 'border-bottom-outlined', + 'border-horizontal-outlined', + 'border-inner-outlined', + 'border-left-outlined', + 'border-outer-outlined', + 'border-outlined', + 'border-right-outlined', + 'border-top-outlined', + 'border-verticle-outlined', + 'borderless-table-outlined', + 'box-plot-filled', + 'box-plot-outlined', + 'box-plot-twotone', + 'branches-outlined', + 'bug-filled', + 'bug-outlined', + 'bug-twotone', + 'build-filled', + 'build-outlined', + 'build-twotone', + 'bulb-filled', + 'bulb-outlined', + 'bulb-twotone', + 'calculator-filled', + 'calculator-outlined', + 'calculator-twotone', + 'calendar-filled', + 'calendar-outlined', + 'calendar-twotone', + 'camera-filled', + 'camera-outlined', + 'camera-twotone', + 'car-filled', + 'car-outlined', + 'car-twotone', + 'caret-down-filled', + 'caret-down-outlined', + 'caret-left-filled', + 'caret-left-outlined', + 'caret-right-filled', + 'caret-right-outlined', + 'caret-up-filled', + 'caret-up-outlined', + 'carry-out-filled', + 'carry-out-outlined', + 'carry-out-twotone', + 'check-circle-filled', + 'check-circle-outlined', + 'check-circle-twotone', + 'check-outlined', + 'check-square-filled', + 'check-square-outlined', + 'check-square-twotone', + 'chrome-filled', + 'chrome-outlined', + 'ci-circle-filled', + 'ci-circle-outlined', + 'ci-circle-twotone', + 'ci-outlined', + 'ci-twotone', + 'clear-outlined', + 'clock-circle-filled', + 'clock-circle-outlined', + 'clock-circle-twotone', + 'close-circle-filled', + 'close-circle-outlined', + 'close-circle-twotone', + 'close-outlined', + 'close-square-filled', + 'close-square-outlined', + 'close-square-twotone', + 'cloud-download-outlined', + 'cloud-filled', + 'cloud-outlined', + 'cloud-server-outlined', + 'cloud-sync-outlined', + 'cloud-twotone', + 'cloud-upload-outlined', + 'cluster-outlined', + 'code-filled', + 'code-outlined', + 'code-sandbox-circle-filled', + 'code-sandbox-outlined', + 'code-sandbox-square-filled', + 'code-twotone', + 'codepen-circle-filled', + 'codepen-circle-outlined', + 'codepen-outlined', + 'codepen-square-filled', + 'coffee-outlined', + 'column-height-outlined', + 'column-width-outlined', + 'comment-outlined', + 'compass-filled', + 'compass-outlined', + 'compass-twotone', + 'compress-outlined', + 'console-sql-outlined', + 'contacts-filled', + 'contacts-outlined', + 'contacts-twotone', + 'container-filled', + 'container-outlined', + 'container-twotone', + 'control-filled', + 'control-outlined', + 'control-twotone', + 'copy-filled', + 'copy-outlined', + 'copy-twotone', + 'copyright-circle-filled', + 'copyright-circle-outlined', + 'copyright-circle-twotone', + 'copyright-outlined', + 'copyright-twotone', + 'credit-card-filled', + 'credit-card-outlined', + 'credit-card-twotone', + 'crown-filled', + 'crown-outlined', + 'crown-twotone', + 'customer-service-filled', + 'customer-service-outlined', + 'customer-service-twotone', + 'dash-outlined', + 'dashboard-filled', + 'dashboard-outlined', + 'dashboard-twotone', + 'database-filled', + 'database-outlined', + 'database-twotone', + 'delete-column-outlined', + 'delete-filled', + 'delete-outlined', + 'delete-row-outlined', + 'delete-twotone', + 'delivered-procedure-outlined', + 'deployment-unit-outlined', + 'desktop-outlined', + 'diff-filled', + 'diff-outlined', + 'diff-twotone', + 'dingding-outlined', + 'dingtalk-circle-filled', + 'dingtalk-outlined', + 'dingtalk-square-filled', + 'disconnect-outlined', + 'dislike-filled', + 'dislike-outlined', + 'dislike-twotone', + 'dollar-circle-filled', + 'dollar-circle-outlined', + 'dollar-circle-twotone', + 'dollar-outlined', + 'dollar-twotone', + 'dot-chart-outlined', + 'double-left-outlined', + 'double-right-outlined', + 'down-circle-filled', + 'down-circle-outlined', + 'down-circle-twotone', + 'down-outlined', + 'down-square-filled', + 'down-square-outlined', + 'down-square-twotone', + 'download-outlined', + 'drag-outlined', + 'dribbble-circle-filled', + 'dribbble-outlined', + 'dribbble-square-filled', + 'dribbble-square-outlined', + 'dropbox-circle-filled', + 'dropbox-outlined', + 'dropbox-square-filled', + 'edit-filled', + 'edit-outlined', + 'edit-twotone', + 'ellipsis-outlined', + 'enter-outlined', + 'environment-filled', + 'environment-outlined', + 'environment-twotone', + 'euro-circle-filled', + 'euro-circle-outlined', + 'euro-circle-twotone', + 'euro-outlined', + 'euro-twotone', + 'exception-outlined', + 'exclamation-circle-filled', + 'exclamation-circle-outlined', + 'exclamation-circle-twotone', + 'exclamation-outlined', + 'expand-alt-outlined', + 'expand-outlined', + 'experiment-filled', + 'experiment-outlined', + 'experiment-twotone', + 'export-outlined', + 'eye-filled', + 'eye-invisible-filled', + 'eye-invisible-outlined', + 'eye-invisible-twotone', + 'eye-outlined', + 'eye-twotone', + 'facebook-filled', + 'facebook-outlined', + 'fall-outlined', + 'fast-backward-filled', + 'fast-backward-outlined', + 'fast-forward-filled', + 'fast-forward-outlined', + 'field-binary-outlined', + 'field-number-outlined', + 'field-string-outlined', + 'field-time-outlined', + 'file-add-filled', + 'file-add-outlined', + 'file-add-twotone', + 'file-done-outlined', + 'file-excel-filled', + 'file-excel-outlined', + 'file-excel-twotone', + 'file-exclamation-filled', + 'file-exclamation-outlined', + 'file-exclamation-twotone', + 'file-filled', + 'file-gif-outlined', + 'file-image-filled', + 'file-image-outlined', + 'file-image-twotone', + 'file-jpg-outlined', + 'file-markdown-filled', + 'file-markdown-outlined', + 'file-markdown-twotone', + 'file-outlined', + 'file-pdf-filled', + 'file-pdf-outlined', + 'file-pdf-twotone', + 'file-ppt-filled', + 'file-ppt-outlined', + 'file-ppt-twotone', + 'file-protect-outlined', + 'file-search-outlined', + 'file-sync-outlined', + 'file-text-filled', + 'file-text-outlined', + 'file-text-twotone', + 'file-twotone', + 'file-unknown-filled', + 'file-unknown-outlined', + 'file-unknown-twotone', + 'file-word-filled', + 'file-word-outlined', + 'file-word-twotone', + 'file-zip-filled', + 'file-zip-outlined', + 'file-zip-twotone', + 'filter-filled', + 'filter-outlined', + 'filter-twotone', + 'fire-filled', + 'fire-outlined', + 'fire-twotone', + 'flag-filled', + 'flag-outlined', + 'flag-twotone', + 'folder-add-filled', + 'folder-add-outlined', + 'folder-add-twotone', + 'folder-filled', + 'folder-open-filled', + 'folder-open-outlined', + 'folder-open-twotone', + 'folder-outlined', + 'folder-twotone', + 'folder-view-outlined', + 'font-colors-outlined', + 'font-size-outlined', + 'fork-outlined', + 'form-outlined', + 'format-painter-filled', + 'format-painter-outlined', + 'forward-filled', + 'forward-outlined', + 'frown-filled', + 'frown-outlined', + 'frown-twotone', + 'fullscreen-exit-outlined', + 'fullscreen-outlined', + 'function-outlined', + 'fund-filled', + 'fund-outlined', + 'fund-projection-screen-outlined', + 'fund-twotone', + 'fund-view-outlined', + 'funnel-plot-filled', + 'funnel-plot-outlined', + 'funnel-plot-twotone', + 'gateway-outlined', + 'gif-outlined', + 'gift-filled', + 'gift-outlined', + 'gift-twotone', + 'github-filled', + 'github-outlined', + 'gitlab-filled', + 'gitlab-outlined', + 'global-outlined', + 'gold-filled', + 'gold-outlined', + 'gold-twotone', + 'golden-filled', + 'google-circle-filled', + 'google-outlined', + 'google-plus-circle-filled', + 'google-plus-outlined', + 'google-plus-square-filled', + 'google-square-filled', + 'group-outlined', + 'hdd-filled', + 'hdd-outlined', + 'hdd-twotone', + 'heart-filled', + 'heart-outlined', + 'heart-twotone', + 'heat-map-outlined', + 'highlight-filled', + 'highlight-outlined', + 'highlight-twotone', + 'history-outlined', + 'home-filled', + 'home-outlined', + 'home-twotone', + 'hourglass-filled', + 'hourglass-outlined', + 'hourglass-twotone', + 'html5-filled', + 'html5-outlined', + 'html5-twotone', + 'idcard-filled', + 'idcard-outlined', + 'idcard-twotone', + 'ie-circle-filled', + 'ie-outlined', + 'ie-square-filled', + 'import-outlined', + 'inbox-outlined', + 'info-circle-filled', + 'info-circle-outlined', + 'info-circle-twotone', + 'info-outlined', + 'insert-row-above-outlined', + 'insert-row-below-outlined', + 'insert-row-left-outlined', + 'insert-row-right-outlined', + 'instagram-filled', + 'instagram-outlined', + 'insurance-filled', + 'insurance-outlined', + 'insurance-twotone', + 'interaction-filled', + 'interaction-outlined', + 'interaction-twotone', + 'issues-close-outlined', + 'italic-outlined', + 'key-outlined', + 'laptop-outlined', + 'layout-filled', + 'layout-outlined', + 'layout-twotone', + 'left-circle-filled', + 'left-circle-outlined', + 'left-circle-twotone', + 'left-outlined', + 'left-square-filled', + 'left-square-outlined', + 'left-square-twotone', + 'like-filled', + 'like-outlined', + 'like-twotone', + 'line-chart-outlined', + 'line-height-outlined', + 'line-outlined', + 'link-outlined', + 'linkedin-filled', + 'linkedin-outlined', + 'loading-3-quarters-outlined', + 'loading-outlined', + 'login-outlined', + 'logout-outlined', + 'mac-command-filled', + 'mac-command-outlined', + 'mail-filled', + 'mail-outlined', + 'mail-twotone', + 'man-outlined', + 'medicine-box-filled', + 'medicine-box-outlined', + 'medicine-box-twotone', + 'medium-circle-filled', + 'medium-outlined', + 'medium-square-filled', + 'medium-workmark-outlined', + 'meh-filled', + 'meh-outlined', + 'meh-twotone', + 'menu-fold-outlined', + 'menu-outlined', + 'menu-unfold-outlined', + 'merge-cells-outlined', + 'message-filled', + 'message-outlined', + 'message-twotone', + 'minus-circle-filled', + 'minus-circle-outlined', + 'minus-circle-twotone', + 'minus-outlined', + 'minus-square-filled', + 'minus-square-outlined', + 'minus-square-twotone', + 'mobile-filled', + 'mobile-outlined', + 'mobile-twotone', + 'money-collect-filled', + 'money-collect-outlined', + 'money-collect-twotone', + 'monitor-outlined', + 'more-outlined', + 'node-collapse-outlined', + 'node-expand-outlined', + 'node-index-outlined', + 'notification-filled', + 'notification-outlined', + 'notification-twotone', + 'number-outlined', + 'one-to-one-outlined', + 'ordered-list-outlined', + 'paper-clip-outlined', + 'partition-outlined', + 'pause-circle-filled', + 'pause-circle-outlined', + 'pause-circle-twotone', + 'pause-outlined', + 'pay-circle-filled', + 'pay-circle-outlined', + 'percentage-outlined', + 'phone-filled', + 'phone-outlined', + 'phone-twotone', + 'pic-center-outlined', + 'pic-left-outlined', + 'pic-right-outlined', + 'picture-filled', + 'picture-outlined', + 'picture-twotone', + 'pie-chart-filled', + 'pie-chart-outlined', + 'pie-chart-twotone', + 'play-circle-filled', + 'play-circle-outlined', + 'play-circle-twotone', + 'play-square-filled', + 'play-square-outlined', + 'play-square-twotone', + 'plus-circle-filled', + 'plus-circle-outlined', + 'plus-circle-twotone', + 'plus-outlined', + 'plus-square-filled', + 'plus-square-outlined', + 'plus-square-twotone', + 'pound-circle-filled', + 'pound-circle-outlined', + 'pound-circle-twotone', + 'pound-outlined', + 'poweroff-outlined', + 'printer-filled', + 'printer-outlined', + 'printer-twotone', + 'profile-filled', + 'profile-outlined', + 'profile-twotone', + 'project-filled', + 'project-outlined', + 'project-twotone', + 'property-safety-filled', + 'property-safety-outlined', + 'property-safety-twotone', + 'pull-request-outlined', + 'pushpin-filled', + 'pushpin-outlined', + 'pushpin-twotone', + 'qq-circle-filled', + 'qq-outlined', + 'qq-square-filled', + 'question-circle-filled', + 'question-circle-outlined', + 'question-circle-twotone', + 'question-outlined', + 'radar-chart-outlined', + 'radius-bottomleft-outlined', + 'radius-bottomright-outlined', + 'radius-setting-outlined', + 'radius-upleft-outlined', + 'radius-upright-outlined', + 'read-filled', + 'read-outlined', + 'reconciliation-filled', + 'reconciliation-outlined', + 'reconciliation-twotone', + 'red-envelope-filled', + 'red-envelope-outlined', + 'red-envelope-twotone', + 'reddit-circle-filled', + 'reddit-outlined', + 'reddit-square-filled', + 'redo-outlined', + 'reload-outlined', + 'rest-filled', + 'rest-outlined', + 'rest-twotone', + 'retweet-outlined', + 'right-circle-filled', + 'right-circle-outlined', + 'right-circle-twotone', + 'right-outlined', + 'right-square-filled', + 'right-square-outlined', + 'right-square-twotone', + 'rise-outlined', + 'robot-filled', + 'robot-outlined', + 'rocket-filled', + 'rocket-outlined', + 'rocket-twotone', + 'rollback-outlined', + 'rotate-left-outlined', + 'rotate-right-outlined', + 'safety-certificate-filled', + 'safety-certificate-outlined', + 'safety-certificate-twotone', + 'safety-outlined', + 'save-filled', + 'save-outlined', + 'save-twotone', + 'scan-outlined', + 'schedule-filled', + 'schedule-outlined', + 'schedule-twotone', + 'scissor-outlined', + 'search-outlined', + 'security-scan-filled', + 'security-scan-outlined', + 'security-scan-twotone', + 'select-outlined', + 'send-outlined', + 'setting-filled', + 'setting-outlined', + 'setting-twotone', + 'shake-outlined', + 'share-alt-outlined', + 'shop-filled', + 'shop-outlined', + 'shop-twotone', + 'shopping-cart-outlined', + 'shopping-filled', + 'shopping-outlined', + 'shopping-twotone', + 'shrink-outlined', + 'signal-filled', + 'sisternode-outlined', + 'sketch-circle-filled', + 'sketch-outlined', + 'sketch-square-filled', + 'skin-filled', + 'skin-outlined', + 'skin-twotone', + 'skype-filled', + 'skype-outlined', + 'slack-circle-filled', + 'slack-outlined', + 'slack-square-filled', + 'slack-square-outlined', + 'sliders-filled', + 'sliders-outlined', + 'sliders-twotone', + 'small-dash-outlined', + 'smile-filled', + 'smile-outlined', + 'smile-twotone', + 'snippets-filled', + 'snippets-outlined', + 'snippets-twotone', + 'solution-outlined', + 'sort-ascending-outlined', + 'sort-descending-outlined', + 'sound-filled', + 'sound-outlined', + 'sound-twotone', + 'split-cells-outlined', + 'star-filled', + 'star-outlined', + 'star-twotone', + 'step-backward-filled', + 'step-backward-outlined', + 'step-forward-filled', + 'step-forward-outlined', + 'stock-outlined', + 'stop-filled', + 'stop-outlined', + 'stop-twotone', + 'strikethrough-outlined', + 'subnode-outlined', + 'swap-left-outlined', + 'swap-outlined', + 'swap-right-outlined', + 'switcher-filled', + 'switcher-outlined', + 'switcher-twotone', + 'sync-outlined', + 'table-outlined', + 'tablet-filled', + 'tablet-outlined', + 'tablet-twotone', + 'tag-filled', + 'tag-outlined', + 'tag-twotone', + 'tags-filled', + 'tags-outlined', + 'tags-twotone', + 'taobao-circle-filled', + 'taobao-circle-outlined', + 'taobao-outlined', + 'taobao-square-filled', + 'team-outlined', + 'thunderbolt-filled', + 'thunderbolt-outlined', + 'thunderbolt-twotone', + 'to-top-outlined', + 'tool-filled', + 'tool-outlined', + 'tool-twotone', + 'trademark-circle-filled', + 'trademark-circle-outlined', + 'trademark-circle-twotone', + 'trademark-outlined', + 'transaction-outlined', + 'translation-outlined', + 'trophy-filled', + 'trophy-outlined', + 'trophy-twotone', + 'twitter-circle-filled', + 'twitter-outlined', + 'twitter-square-filled', + 'underline-outlined', + 'undo-outlined', + 'ungroup-outlined', + 'unordered-list-outlined', + 'up-circle-filled', + 'up-circle-outlined', + 'up-circle-twotone', + 'up-outlined', + 'up-square-filled', + 'up-square-outlined', + 'up-square-twotone', + 'upload-outlined', + 'usb-filled', + 'usb-outlined', + 'usb-twotone', + 'user-add-outlined', + 'user-delete-outlined', + 'user-outlined', + 'user-switch-outlined', + 'usergroup-add-outlined', + 'usergroup-delete-outlined', + 'verified-outlined', + 'vertical-align-bottom-outlined', + 'vertical-align-middle-outlined', + 'vertical-align-top-outlined', + 'vertical-left-outlined', + 'vertical-right-outlined', + 'video-camera-add-outlined', + 'video-camera-filled', + 'video-camera-outlined', + 'video-camera-twotone', + 'wallet-filled', + 'wallet-outlined', + 'wallet-twotone', + 'warning-filled', + 'warning-outlined', + 'warning-twotone', + 'wechat-filled', + 'wechat-outlined', + 'weibo-circle-filled', + 'weibo-circle-outlined', + 'weibo-outlined', + 'weibo-square-filled', + 'weibo-square-outlined', + 'whats-app-outlined', + 'wifi-outlined', + 'windows-filled', + 'windows-outlined', + 'woman-outlined', + 'yahoo-filled', + 'yahoo-outlined', + 'youtube-filled', + 'youtube-outlined', + 'yuque-filled', + 'yuque-outlined', + 'zhihu-circle-filled', + 'zhihu-outlined', + 'zhihu-square-filled', + 'zoom-in-outlined', + 'zoom-out-outlined', + ], +} diff --git a/frontend/vben/src/components/Icon/index.ts b/frontend/vben/src/components/Icon/index.ts new file mode 100644 index 0000000..bda6c81 --- /dev/null +++ b/frontend/vben/src/components/Icon/index.ts @@ -0,0 +1,7 @@ +import Icon from './src/Icon.vue' +import SvgIcon from './src/SvgIcon.vue' +import IconPicker from './src/IconPicker.vue' + +export { Icon, IconPicker, SvgIcon } + +export default Icon diff --git a/frontend/vben/src/components/Icon/src/Icon.vue b/frontend/vben/src/components/Icon/src/Icon.vue new file mode 100644 index 0000000..5dfb671 --- /dev/null +++ b/frontend/vben/src/components/Icon/src/Icon.vue @@ -0,0 +1,121 @@ + + + diff --git a/frontend/vben/src/components/Icon/src/IconPicker.vue b/frontend/vben/src/components/Icon/src/IconPicker.vue new file mode 100644 index 0000000..4c4472a --- /dev/null +++ b/frontend/vben/src/components/Icon/src/IconPicker.vue @@ -0,0 +1,188 @@ + + + diff --git a/frontend/vben/src/components/Icon/src/SvgIcon.vue b/frontend/vben/src/components/Icon/src/SvgIcon.vue new file mode 100644 index 0000000..7d6cee1 --- /dev/null +++ b/frontend/vben/src/components/Icon/src/SvgIcon.vue @@ -0,0 +1,65 @@ + + + diff --git a/frontend/vben/src/components/Loading/index.ts b/frontend/vben/src/components/Loading/index.ts new file mode 100644 index 0000000..0a9b22c --- /dev/null +++ b/frontend/vben/src/components/Loading/index.ts @@ -0,0 +1,5 @@ +import Loading from './src/Loading.vue' + +export { Loading } +export { useLoading } from './src/useLoading' +export { createLoading } from './src/createLoading' diff --git a/frontend/vben/src/components/Loading/src/Loading.vue b/frontend/vben/src/components/Loading/src/Loading.vue new file mode 100644 index 0000000..9a0e861 --- /dev/null +++ b/frontend/vben/src/components/Loading/src/Loading.vue @@ -0,0 +1,79 @@ + + + diff --git a/frontend/vben/src/components/Loading/src/createLoading.ts b/frontend/vben/src/components/Loading/src/createLoading.ts new file mode 100644 index 0000000..9381382 --- /dev/null +++ b/frontend/vben/src/components/Loading/src/createLoading.ts @@ -0,0 +1,65 @@ +import { VNode, defineComponent } from 'vue' +import type { LoadingProps } from './typing' + +import { createVNode, render, reactive, h } from 'vue' +import Loading from './Loading.vue' + +export function createLoading(props?: Partial, target?: HTMLElement, wait = false) { + let vm: Nullable = null + const data = reactive({ + tip: '', + loading: true, + ...props, + }) + + const LoadingWrap = defineComponent({ + render() { + return h(Loading, { ...data }) + }, + }) + + vm = createVNode(LoadingWrap) + + if (wait) { + // TODO fix https://github.com/anncwb/vue-vben-admin/issues/438 + setTimeout(() => { + render(vm, document.createElement('div')) + }, 0) + } else { + render(vm, document.createElement('div')) + } + + function close() { + if (vm?.el && vm.el.parentNode) { + vm.el.parentNode.removeChild(vm.el) + } + } + + function open(target: HTMLElement = document.body) { + if (!vm || !vm.el) { + return + } + target.appendChild(vm.el as HTMLElement) + } + + if (target) { + open(target) + } + return { + vm, + close, + open, + setTip: (tip: string) => { + data.tip = tip + }, + setLoading: (loading: boolean) => { + data.loading = loading + }, + get loading() { + return data.loading + }, + get $el() { + return vm?.el as HTMLElement + }, + } +} diff --git a/frontend/vben/src/components/Loading/src/typing.ts b/frontend/vben/src/components/Loading/src/typing.ts new file mode 100644 index 0000000..284a315 --- /dev/null +++ b/frontend/vben/src/components/Loading/src/typing.ts @@ -0,0 +1,10 @@ +import { SizeEnum } from '/@/enums/sizeEnum' + +export interface LoadingProps { + tip: string + size: SizeEnum + absolute: boolean + loading: boolean + background: string + theme: 'dark' | 'light' +} diff --git a/frontend/vben/src/components/Loading/src/useLoading.ts b/frontend/vben/src/components/Loading/src/useLoading.ts new file mode 100644 index 0000000..718aef1 --- /dev/null +++ b/frontend/vben/src/components/Loading/src/useLoading.ts @@ -0,0 +1,49 @@ +import { unref } from 'vue' +import { createLoading } from './createLoading' +import type { LoadingProps } from './typing' +import type { Ref } from 'vue' + +export interface UseLoadingOptions { + target?: any + props?: Partial +} + +interface Fn { + (): void +} + +export function useLoading(props: Partial): [Fn, Fn, (string) => void] +export function useLoading(opt: Partial): [Fn, Fn, (string) => void] + +export function useLoading( + opt: Partial | Partial, +): [Fn, Fn, (string) => void] { + let props: Partial + let target: HTMLElement | Ref = document.body + + if (Reflect.has(opt, 'target') || Reflect.has(opt, 'props')) { + const options = opt as Partial + props = options.props || {} + target = options.target || document.body + } else { + props = opt as Partial + } + + const instance = createLoading(props, undefined, true) + + const open = (): void => { + const t = unref(target as Ref) + if (!t) return + instance.open(t) + } + + const close = (): void => { + instance.close() + } + + const setTip = (tip: string) => { + instance.setTip(tip) + } + + return [open, close, setTip] +} diff --git a/frontend/vben/src/components/Menu/index.ts b/frontend/vben/src/components/Menu/index.ts new file mode 100644 index 0000000..42f45c9 --- /dev/null +++ b/frontend/vben/src/components/Menu/index.ts @@ -0,0 +1,3 @@ +import BasicMenu from './src/BasicMenu.vue' + +export { BasicMenu } diff --git a/frontend/vben/src/components/Menu/src/BasicMenu.vue b/frontend/vben/src/components/Menu/src/BasicMenu.vue new file mode 100644 index 0000000..0e3301c --- /dev/null +++ b/frontend/vben/src/components/Menu/src/BasicMenu.vue @@ -0,0 +1,164 @@ + + + diff --git a/frontend/vben/src/components/Menu/src/components/BasicMenuItem.vue b/frontend/vben/src/components/Menu/src/components/BasicMenuItem.vue new file mode 100644 index 0000000..ab48f40 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/components/BasicMenuItem.vue @@ -0,0 +1,20 @@ + + diff --git a/frontend/vben/src/components/Menu/src/components/BasicSubMenuItem.vue b/frontend/vben/src/components/Menu/src/components/BasicSubMenuItem.vue new file mode 100644 index 0000000..31b0e62 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/components/BasicSubMenuItem.vue @@ -0,0 +1,55 @@ + + diff --git a/frontend/vben/src/components/Menu/src/components/MenuItemContent.vue b/frontend/vben/src/components/Menu/src/components/MenuItemContent.vue new file mode 100644 index 0000000..4518b59 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/components/MenuItemContent.vue @@ -0,0 +1,34 @@ + + diff --git a/frontend/vben/src/components/Menu/src/index.less b/frontend/vben/src/components/Menu/src/index.less new file mode 100644 index 0000000..8bfbb0d --- /dev/null +++ b/frontend/vben/src/components/Menu/src/index.less @@ -0,0 +1,74 @@ +@basic-menu-prefix-cls: ~'@{namespace}-basic-menu'; + +.app-top-menu-popup { + min-width: 150px; +} + +.@{basic-menu-prefix-cls} { + width: 100%; + + .ant-menu-item { + transition: unset; + } + + &__sidebar-hor { + &.ant-menu-horizontal { + display: flex; + align-items: center; + + &.ant-menu-dark { + background-color: transparent; + + .ant-menu-submenu:hover, + .ant-menu-item-open, + .ant-menu-submenu-open, + .ant-menu-item-selected, + .ant-menu-submenu-selected, + .ant-menu-item:hover, + .ant-menu-item-active, + .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, + .ant-menu-submenu-active, + .ant-menu-submenu-title:hover { + color: #fff; + background-color: @top-menu-active-bg-color !important; + } + + .ant-menu-item:hover, + .ant-menu-item-active, + .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, + .ant-menu-submenu-active, + .ant-menu-submenu-title:hover { + background-color: @top-menu-active-bg-color; + } + + .@{basic-menu-prefix-cls}-item__level1 { + background-color: transparent; + + &.ant-menu-item-selected, + &.ant-menu-submenu-selected { + background-color: @top-menu-active-bg-color !important; + } + } + + .ant-menu-item, + .ant-menu-submenu { + &.@{basic-menu-prefix-cls}-item__level1, + .ant-menu-submenu-title { + height: @header-height; + line-height: @header-height; + } + } + } + } + } + + .ant-menu-submenu, + .ant-menu-submenu-inline { + transition: unset; + } + + .ant-menu-inline.ant-menu-sub { + box-shadow: unset !important; + transition: unset; + } +} diff --git a/frontend/vben/src/components/Menu/src/props.ts b/frontend/vben/src/components/Menu/src/props.ts new file mode 100644 index 0000000..0c913f1 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/props.ts @@ -0,0 +1,60 @@ +import type { Menu } from '/@/router/types' +import type { PropType } from 'vue' + +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum' +import { ThemeEnum } from '/@/enums/appEnum' +import { propTypes } from '/@/utils/propTypes' +import type { MenuTheme } from 'ant-design-vue' +import type { MenuMode } from 'ant-design-vue/lib/menu/src/interface' +export const basicProps = { + items: { + type: Array as PropType, + default: () => [], + }, + collapsedShowTitle: propTypes.bool, + // 最好是4 倍数 + inlineIndent: propTypes.number.def(20), + // 菜单组件的mode属性 + mode: { + type: String as PropType, + default: MenuModeEnum.INLINE, + }, + + type: { + type: String as PropType, + default: MenuTypeEnum.MIX, + }, + theme: { + type: String as PropType, + default: ThemeEnum.DARK, + }, + inlineCollapsed: propTypes.bool, + mixSider: propTypes.bool, + + isHorizontal: propTypes.bool, + accordion: propTypes.bool.def(true), + beforeClickFn: { + type: Function as PropType<(key: string) => Promise>, + }, +} + +export const itemProps = { + item: { + type: Object as PropType, + default: {}, + }, + level: propTypes.number, + theme: propTypes.oneOf(['dark', 'light']), + showTitle: propTypes.bool, + isHorizontal: propTypes.bool, +} + +export const contentProps = { + item: { + type: Object as PropType, + default: null, + }, + showTitle: propTypes.bool.def(true), + level: propTypes.number.def(0), + isHorizontal: propTypes.bool.def(true), +} diff --git a/frontend/vben/src/components/Menu/src/types.ts b/frontend/vben/src/components/Menu/src/types.ts new file mode 100644 index 0000000..ecd5518 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/types.ts @@ -0,0 +1,25 @@ +// import { ComputedRef } from 'vue'; +// import { ThemeEnum } from '/@/enums/appEnum'; +// import { MenuModeEnum } from '/@/enums/menuEnum'; +export interface MenuState { + // 默认选中的列表 + defaultSelectedKeys: string[] + + // 模式 + // mode: MenuModeEnum; + + // // 主题 + // theme: ComputedRef | ThemeEnum; + + // 缩进 + inlineIndent?: number + + // 展开数组 + openKeys: string[] + + // 当前选中的菜单项 key 数组 + selectedKeys: string[] + + // 收缩状态下展开的数组 + collapsedOpenKeys: string[] +} diff --git a/frontend/vben/src/components/Menu/src/useOpenKeys.ts b/frontend/vben/src/components/Menu/src/useOpenKeys.ts new file mode 100644 index 0000000..2673ad8 --- /dev/null +++ b/frontend/vben/src/components/Menu/src/useOpenKeys.ts @@ -0,0 +1,83 @@ +import { MenuModeEnum } from '/@/enums/menuEnum' +import type { Menu as MenuType } from '/@/router/types' +import type { MenuState } from './types' + +import { computed, Ref, toRaw } from 'vue' + +import { unref } from 'vue' +import { uniq } from 'lodash-es' +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting' +import { getAllParentPath } from '/@/router/helper/menuHelper' +import { useTimeoutFn } from '/@/hooks/core/useTimeout' + +export function useOpenKeys( + menuState: MenuState, + menus: Ref, + mode: Ref, + accordion: Ref, +) { + const { getCollapsed, getIsMixSidebar } = useMenuSetting() + + async function setOpenKeys(path: string) { + if (mode.value === MenuModeEnum.HORIZONTAL) { + return + } + const native = unref(getIsMixSidebar) + useTimeoutFn( + () => { + const menuList = toRaw(menus.value) + if (menuList?.length === 0) { + menuState.openKeys = [] + return + } + if (!unref(accordion)) { + menuState.openKeys = uniq([...menuState.openKeys, ...getAllParentPath(menuList, path)]) + } else { + menuState.openKeys = getAllParentPath(menuList, path) + } + }, + 16, + !native, + ) + } + + const getOpenKeys = computed(() => { + const collapse = unref(getIsMixSidebar) ? false : unref(getCollapsed) + + return collapse ? menuState.collapsedOpenKeys : menuState.openKeys + }) + + /** + * @description: 重置值 + */ + function resetKeys() { + menuState.selectedKeys = [] + menuState.openKeys = [] + } + + function handleOpenChange(openKeys: string[]) { + if (unref(mode) === MenuModeEnum.HORIZONTAL || !unref(accordion) || unref(getIsMixSidebar)) { + menuState.openKeys = openKeys + } else { + // const menuList = toRaw(menus.value); + // getAllParentPath(menuList, path); + const rootSubMenuKeys: string[] = [] + for (const { children, path } of unref(menus)) { + if (children && children.length > 0) { + rootSubMenuKeys.push(path) + } + } + if (!unref(getCollapsed)) { + const latestOpenKey = openKeys.find((key) => menuState.openKeys.indexOf(key) === -1) + if (rootSubMenuKeys.indexOf(latestOpenKey as string) === -1) { + menuState.openKeys = openKeys + } else { + menuState.openKeys = latestOpenKey ? [latestOpenKey] : [] + } + } else { + menuState.collapsedOpenKeys = openKeys + } + } + } + return { setOpenKeys, resetKeys, getOpenKeys, handleOpenChange } +} diff --git a/frontend/vben/src/components/Modal/index.ts b/frontend/vben/src/components/Modal/index.ts new file mode 100644 index 0000000..e9054f7 --- /dev/null +++ b/frontend/vben/src/components/Modal/index.ts @@ -0,0 +1,8 @@ +import { withInstall } from '/@/utils' +import './src/index.less' +import basicModal from './src/BasicModal.vue' + +export const BasicModal = withInstall(basicModal) +export { useModalContext } from './src/hooks/useModalContext' +export { useModal, useModalInner } from './src/hooks/useModal' +export * from './src/typing' diff --git a/frontend/vben/src/components/Modal/src/BasicModal.vue b/frontend/vben/src/components/Modal/src/BasicModal.vue new file mode 100644 index 0000000..b70c32d --- /dev/null +++ b/frontend/vben/src/components/Modal/src/BasicModal.vue @@ -0,0 +1,242 @@ + + diff --git a/frontend/vben/src/components/Modal/src/components/Modal.tsx b/frontend/vben/src/components/Modal/src/components/Modal.tsx new file mode 100644 index 0000000..1e3e7e0 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/components/Modal.tsx @@ -0,0 +1,31 @@ +import { Modal } from 'ant-design-vue' +import { defineComponent, toRefs, unref } from 'vue' +import { basicProps } from '../props' +import { useModalDragMove } from '../hooks/useModalDrag' +import { useAttrs } from '/@/hooks/core/useAttrs' +import { extendSlots } from '/@/utils/helper/tsxHelper' + +export default defineComponent({ + name: 'Modal', + inheritAttrs: false, + props: basicProps, + emits: ['cancel'], + setup(props, { slots, emit }) { + const { visible, draggable, destroyOnClose } = toRefs(props) + const attrs = useAttrs() + useModalDragMove({ + visible, + destroyOnClose, + draggable, + }) + + const onCancel = (e: Event) => { + emit('cancel', e) + } + + return () => { + const propsData = { ...unref(attrs), ...props, onCancel } as Recordable + return {extendSlots(slots)} + } + }, +}) diff --git a/frontend/vben/src/components/Modal/src/components/ModalClose.vue b/frontend/vben/src/components/Modal/src/components/ModalClose.vue new file mode 100644 index 0000000..87533a9 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/components/ModalClose.vue @@ -0,0 +1,106 @@ + + + diff --git a/frontend/vben/src/components/Modal/src/components/ModalFooter.vue b/frontend/vben/src/components/Modal/src/components/ModalFooter.vue new file mode 100644 index 0000000..3d86553 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/components/ModalFooter.vue @@ -0,0 +1,40 @@ + + diff --git a/frontend/vben/src/components/Modal/src/components/ModalHeader.vue b/frontend/vben/src/components/Modal/src/components/ModalHeader.vue new file mode 100644 index 0000000..107e5ac --- /dev/null +++ b/frontend/vben/src/components/Modal/src/components/ModalHeader.vue @@ -0,0 +1,22 @@ + + diff --git a/frontend/vben/src/components/Modal/src/components/ModalWrapper.vue b/frontend/vben/src/components/Modal/src/components/ModalWrapper.vue new file mode 100644 index 0000000..8fc25b7 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/components/ModalWrapper.vue @@ -0,0 +1,169 @@ + + diff --git a/frontend/vben/src/components/Modal/src/hooks/useModal.ts b/frontend/vben/src/components/Modal/src/hooks/useModal.ts new file mode 100644 index 0000000..721cef3 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/hooks/useModal.ts @@ -0,0 +1,163 @@ +import type { + UseModalReturnType, + ModalMethods, + ModalProps, + ReturnMethods, + UseModalInnerReturnType, +} from '../typing' +import { + ref, + onUnmounted, + unref, + getCurrentInstance, + reactive, + watchEffect, + nextTick, + toRaw, +} from 'vue' +import { isProdMode } from '/@/utils/env' +import { isFunction } from '/@/utils/is' +import { isEqual } from 'lodash-es' +import { tryOnUnmounted } from '@vueuse/core' +import { error } from '/@/utils/log' +import { computed } from 'vue' + +const dataTransfer = reactive({}) + +const visibleData = reactive<{ [key: number]: boolean }>({}) + +/** + * @description: Applicable to independent modal and call outside + */ +export function useModal(): UseModalReturnType { + const modal = ref>(null) + const loaded = ref>(false) + const uid = ref('') + + function register(modalMethod: ModalMethods, uuid: string) { + if (!getCurrentInstance()) { + throw new Error('useModal() can only be used inside setup() or functional components!') + } + uid.value = uuid + isProdMode() && + onUnmounted(() => { + modal.value = null + loaded.value = false + dataTransfer[unref(uid)] = null + }) + if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return + + modal.value = modalMethod + loaded.value = true + modalMethod.emitVisible = (visible: boolean, uid: number) => { + visibleData[uid] = visible + } + } + + const getInstance = () => { + const instance = unref(modal) + if (!instance) { + error('useModal instance is undefined!') + } + return instance + } + + const methods: ReturnMethods = { + setModalProps: (props: Partial): void => { + getInstance()?.setModalProps(props) + }, + + getVisible: computed((): boolean => { + return visibleData[~~unref(uid)] + }), + + redoModalHeight: () => { + getInstance()?.redoModalHeight?.() + }, + + openModal: (visible = true, data?: T, openOnSet = true): void => { + getInstance()?.setModalProps({ + visible: visible, + }) + + if (!data) return + const id = unref(uid) + if (openOnSet) { + dataTransfer[id] = null + dataTransfer[id] = toRaw(data) + return + } + const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data)) + if (!equal) { + dataTransfer[id] = toRaw(data) + } + }, + + closeModal: () => { + getInstance()?.setModalProps({ visible: false }) + }, + } + return [register, methods] +} + +export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType => { + const modalInstanceRef = ref>(null) + const currentInstance = getCurrentInstance() + const uidRef = ref('') + + const getInstance = () => { + const instance = unref(modalInstanceRef) + if (!instance) { + error('useModalInner instance is undefined!') + } + return instance + } + + const register = (modalInstance: ModalMethods, uuid: string) => { + isProdMode() && + tryOnUnmounted(() => { + modalInstanceRef.value = null + }) + uidRef.value = uuid + modalInstanceRef.value = modalInstance + currentInstance?.emit('register', modalInstance, uuid) + } + + watchEffect(() => { + const data = dataTransfer[unref(uidRef)] + if (!data) return + if (!callbackFn || !isFunction(callbackFn)) return + nextTick(() => { + callbackFn(data) + }) + }) + + return [ + register, + { + changeLoading: (loading = true) => { + getInstance()?.setModalProps({ loading }) + }, + getVisible: computed((): boolean => { + return visibleData[~~unref(uidRef)] + }), + + changeOkLoading: (loading = true) => { + getInstance()?.setModalProps({ confirmLoading: loading }) + }, + + closeModal: () => { + getInstance()?.setModalProps({ visible: false }) + }, + + setModalProps: (props: Partial) => { + getInstance()?.setModalProps(props) + }, + + redoModalHeight: () => { + const callRedo = getInstance()?.redoModalHeight + callRedo && callRedo() + }, + }, + ] +} diff --git a/frontend/vben/src/components/Modal/src/hooks/useModalContext.ts b/frontend/vben/src/components/Modal/src/hooks/useModalContext.ts new file mode 100644 index 0000000..e56531a --- /dev/null +++ b/frontend/vben/src/components/Modal/src/hooks/useModalContext.ts @@ -0,0 +1,16 @@ +import { InjectionKey } from 'vue' +import { createContext, useContext } from '/@/hooks/core/useContext' + +export interface ModalContextProps { + redoModalHeight: () => void +} + +const key: InjectionKey = Symbol() + +export function createModalContext(context: ModalContextProps) { + return createContext(context, key) +} + +export function useModalContext() { + return useContext(key) +} diff --git a/frontend/vben/src/components/Modal/src/hooks/useModalDrag.ts b/frontend/vben/src/components/Modal/src/hooks/useModalDrag.ts new file mode 100644 index 0000000..bab9c07 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/hooks/useModalDrag.ts @@ -0,0 +1,107 @@ +import { Ref, unref, watchEffect } from 'vue' +import { useTimeoutFn } from '/@/hooks/core/useTimeout' + +export interface UseModalDragMoveContext { + draggable: Ref + destroyOnClose: Ref | undefined + visible: Ref +} + +export function useModalDragMove(context: UseModalDragMoveContext) { + const getStyle = (dom: any, attr: any) => { + return getComputedStyle(dom)[attr] + } + const drag = (wrap: any) => { + if (!wrap) return + wrap.setAttribute('data-drag', unref(context.draggable)) + const dialogHeaderEl = wrap.querySelector('.ant-modal-header') + const dragDom = wrap.querySelector('.ant-modal') + + if (!dialogHeaderEl || !dragDom || !unref(context.draggable)) return + + dialogHeaderEl.style.cursor = 'move' + + dialogHeaderEl.onmousedown = (e: any) => { + if (!e) return + // 鼠标按下,计算当前元素距离可视区的距离 + const disX = e.clientX + const disY = e.clientY + const screenWidth = document.body.clientWidth // body当前宽度 + const screenHeight = document.documentElement.clientHeight // 可见区域高度(应为body高度,可某些环境下无法获取) + + const dragDomWidth = dragDom.offsetWidth // 对话框宽度 + const dragDomheight = dragDom.offsetHeight // 对话框高度 + + const minDragDomLeft = dragDom.offsetLeft + + const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth + const minDragDomTop = dragDom.offsetTop + const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight + // 获取到的值带px 正则匹配替换 + const domLeft = getStyle(dragDom, 'left') + const domTop = getStyle(dragDom, 'top') + let styL = +domLeft + let styT = +domTop + + // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px + if (domLeft.includes('%')) { + styL = +document.body.clientWidth * (+domLeft.replace(/%/g, '') / 100) + styT = +document.body.clientHeight * (+domTop.replace(/%/g, '') / 100) + } else { + styL = +domLeft.replace(/px/g, '') + styT = +domTop.replace(/px/g, '') + } + + document.onmousemove = function (e) { + // 通过事件委托,计算移动的距离 + let left = e.clientX - disX + let top = e.clientY - disY + + // 边界处理 + if (-left > minDragDomLeft) { + left = -minDragDomLeft + } else if (left > maxDragDomLeft) { + left = maxDragDomLeft + } + + if (-top > minDragDomTop) { + top = -minDragDomTop + } else if (top > maxDragDomTop) { + top = maxDragDomTop + } + + // 移动当前元素 + dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;` + } + + document.onmouseup = () => { + document.onmousemove = null + document.onmouseup = null + } + } + } + + const handleDrag = () => { + const dragWraps = document.querySelectorAll('.ant-modal-wrap') + for (const wrap of Array.from(dragWraps)) { + if (!wrap) continue + const display = getStyle(wrap, 'display') + const draggable = wrap.getAttribute('data-drag') + if (display !== 'none') { + // 拖拽位置 + if (draggable === null || unref(context.destroyOnClose)) { + drag(wrap) + } + } + } + } + + watchEffect(() => { + if (!unref(context.visible) || !unref(context.draggable)) { + return + } + useTimeoutFn(() => { + handleDrag() + }, 30) + }) +} diff --git a/frontend/vben/src/components/Modal/src/hooks/useModalFullScreen.ts b/frontend/vben/src/components/Modal/src/hooks/useModalFullScreen.ts new file mode 100644 index 0000000..1e2c49c --- /dev/null +++ b/frontend/vben/src/components/Modal/src/hooks/useModalFullScreen.ts @@ -0,0 +1,43 @@ +import { computed, Ref, ref, unref } from 'vue' + +export interface UseFullScreenContext { + wrapClassName: Ref + modalWrapperRef: Ref + extHeightRef: Ref +} + +export function useFullScreen(context: UseFullScreenContext) { + // const formerHeightRef = ref(0); + const fullScreenRef = ref(false) + + const getWrapClassName = computed(() => { + const clsName = unref(context.wrapClassName) || '' + return unref(fullScreenRef) ? `fullscreen-modal ${clsName} ` : unref(clsName) + }) + + function handleFullScreen(e: Event) { + e && e.stopPropagation() + fullScreenRef.value = !unref(fullScreenRef) + + // const modalWrapper = unref(context.modalWrapperRef); + + // if (!modalWrapper) return; + + // const wrapperEl = modalWrapper.$el as HTMLElement; + // if (!wrapperEl) return; + // const modalWrapSpinEl = wrapperEl.querySelector('.ant-spin-nested-loading') as HTMLElement; + + // if (!modalWrapSpinEl) return; + + // if (!unref(formerHeightRef) && unref(fullScreenRef)) { + // formerHeightRef.value = modalWrapSpinEl.offsetHeight; + // } + + // if (unref(fullScreenRef)) { + // modalWrapSpinEl.style.height = `${window.innerHeight - unref(context.extHeightRef)}px`; + // } else { + // modalWrapSpinEl.style.height = `${unref(formerHeightRef)}px`; + // } + } + return { getWrapClassName, handleFullScreen, fullScreenRef } +} diff --git a/frontend/vben/src/components/Modal/src/index.less b/frontend/vben/src/components/Modal/src/index.less new file mode 100644 index 0000000..a23be29 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/index.less @@ -0,0 +1,127 @@ +.fullscreen-modal { + overflow: hidden; + + .ant-modal { + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100%; + + &-content { + height: 100%; + } + } +} + +.ant-modal { + width: 520px; + padding-bottom: 0; + + .ant-modal-body > .scrollbar { + padding: 14px; + } + + &-title { + font-size: 16px; + font-weight: bold; + + .base-title { + cursor: move !important; + } + } + + .ant-modal-body { + padding: 0; + + > .scrollbar > .scrollbar__bar.is-horizontal { + display: none; + } + } + + &-large { + top: 60px; + + &--mini { + top: 16px; + } + } + + &-header { + padding: 16px; + } + + &-content { + box-shadow: 0 4px 8px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%); + } + + &-footer { + button + button { + margin-left: 10px; + } + } + + &-close { + font-weight: normal; + outline: none; + } + + &-close-x { + display: inline-block; + width: 96px; + height: 56px; + line-height: 56px; + } + + &-confirm-body { + .ant-modal-confirm-content { + // color: #fff; + + > * { + color: @text-color-help-dark; + } + } + } + + &-confirm-confirm.error .ant-modal-confirm-body > .anticon { + color: @error-color; + } + + &-confirm-btns { + .ant-btn:last-child { + margin-right: 0; + } + } + + &-confirm-info { + .ant-modal-confirm-body > .anticon { + color: @warning-color; + } + } + + &-confirm-confirm.success { + .ant-modal-confirm-body > .anticon { + color: @success-color; + } + } +} + +.ant-modal-confirm .ant-modal-body { + padding: 24px !important; +} +@media screen and (max-height: 600px) { + .ant-modal { + top: 60px; + } +} +@media screen and (max-height: 540px) { + .ant-modal { + top: 30px; + } +} +@media screen and (max-height: 480px) { + .ant-modal { + top: 10px; + } +} diff --git a/frontend/vben/src/components/Modal/src/props.ts b/frontend/vben/src/components/Modal/src/props.ts new file mode 100644 index 0000000..a46c4a6 --- /dev/null +++ b/frontend/vben/src/components/Modal/src/props.ts @@ -0,0 +1,83 @@ +import type { PropType, CSSProperties } from 'vue' +import type { ModalWrapperProps } from './typing' +import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes' +import { useI18n } from '/@/hooks/web/useI18n' + +const { t } = useI18n() + +export const modalProps = { + visible: { type: Boolean }, + scrollTop: { type: Boolean, default: true }, + height: { type: Number }, + minHeight: { type: Number }, + // open drag + draggable: { type: Boolean, default: true }, + centered: { type: Boolean }, + cancelText: { type: String, default: t('common.cancelText') }, + okText: { type: String, default: t('common.okText') }, + + closeFunc: Function as PropType<() => Promise>, +} + +export const basicProps = Object.assign({}, modalProps, { + defaultFullscreen: { type: Boolean }, + // Can it be full screen + canFullscreen: { type: Boolean, default: true }, + // After enabling the wrapper, the bottom can be increased in height + wrapperFooterOffset: { type: Number, default: 0 }, + // Warm reminder message + helpMessage: [String, Array] as PropType, + // Whether to setting wrapper + useWrapper: { type: Boolean, default: true }, + loading: { type: Boolean }, + loadingTip: { type: String }, + /** + * @description: Show close button + */ + showCancelBtn: { type: Boolean, default: true }, + /** + * @description: Show confirmation button + */ + showOkBtn: { type: Boolean, default: true }, + + wrapperProps: Object as PropType>, + + afterClose: Function as PropType<() => Promise>, + + bodyStyle: Object as PropType, + + closable: { type: Boolean, default: true }, + + closeIcon: Object as PropType, + + confirmLoading: { type: Boolean }, + + destroyOnClose: { type: Boolean }, + + footer: Object as PropType, + + getContainer: Function as PropType<() => any>, + + mask: { type: Boolean, default: true }, + + maskClosable: { type: Boolean, default: true }, + keyboard: { type: Boolean, default: true }, + + maskStyle: Object as PropType, + + okType: { type: String, default: 'primary' }, + + okButtonProps: Object as PropType, + + cancelButtonProps: Object as PropType, + + title: { type: String }, + + visible: { type: Boolean }, + + width: [String, Number] as PropType, + + wrapClassName: { type: String }, + + zIndex: { type: Number }, +}) diff --git a/frontend/vben/src/components/Modal/src/typing.ts b/frontend/vben/src/components/Modal/src/typing.ts new file mode 100644 index 0000000..03a9a4d --- /dev/null +++ b/frontend/vben/src/components/Modal/src/typing.ts @@ -0,0 +1,209 @@ +import type { ButtonProps } from 'ant-design-vue/lib/button/buttonTypes' +import type { CSSProperties, VNodeChild, ComputedRef } from 'vue' +/** + * @description: 弹窗对外暴露的方法 + */ +export interface ModalMethods { + setModalProps: (props: Partial) => void + emitVisible?: (visible: boolean, uid: number) => void + redoModalHeight?: () => void +} + +export type RegisterFn = (modalMethods: ModalMethods, uuid?: string) => void + +export interface ReturnMethods extends ModalMethods { + openModal: (props?: boolean, data?: T, openOnSet?: boolean) => void + closeModal: () => void + getVisible?: ComputedRef +} + +export type UseModalReturnType = [RegisterFn, ReturnMethods] + +export interface ReturnInnerMethods extends ModalMethods { + closeModal: () => void + changeLoading: (loading: boolean) => void + changeOkLoading: (loading: boolean) => void + getVisible?: ComputedRef + redoModalHeight: () => void +} + +export type UseModalInnerReturnType = [RegisterFn, ReturnInnerMethods] + +export interface ModalProps { + minHeight?: number + height?: number + // 启用wrapper后 底部可以适当增加高度 + wrapperFooterOffset?: number + draggable?: boolean + scrollTop?: boolean + + // 是否可以进行全屏 + canFullscreen?: boolean + defaultFullscreen?: boolean + visible?: boolean + // 温馨提醒信息 + helpMessage: string | string[] + + // 是否使用modalWrapper + useWrapper: boolean + + loading: boolean + loadingTip?: string + + wrapperProps: Omit + + showOkBtn: boolean + showCancelBtn: boolean + closeFunc: () => Promise + + /** + * Specify a function that will be called when modal is closed completely. + * @type Function + */ + afterClose?: () => any + + /** + * Body style for modal body element. Such as height, padding etc. + * @default {} + * @type object + */ + bodyStyle?: CSSProperties + + /** + * Text of the Cancel button + * @default 'cancel' + * @type string + */ + cancelText?: string + + /** + * Centered Modal + * @default false + * @type boolean + */ + centered?: boolean + + /** + * Whether a close (x) button is visible on top right of the modal dialog or not + * @default true + * @type boolean + */ + closable?: boolean + /** + * Whether a close (x) button is visible on top right of the modal dialog or not + */ + closeIcon?: VNodeChild | JSX.Element + + /** + * Whether to apply loading visual effect for OK button or not + * @default false + * @type boolean + */ + confirmLoading?: boolean + + /** + * Whether to unmount child components on onClose + * @default false + * @type boolean + */ + destroyOnClose?: boolean + + /** + * Footer content, set as :footer="null" when you don't need default buttons + * @default OK and Cancel buttons + * @type any (string | slot) + */ + footer?: VNodeChild | JSX.Element + + /** + * Return the mount node for Modal + * @default () => document.body + * @type Function + */ + getContainer?: (instance: any) => HTMLElement + + /** + * Whether show mask or not. + * @default true + * @type boolean + */ + mask?: boolean + + /** + * Whether to close the modal dialog when the mask (area outside the modal) is clicked + * @default true + * @type boolean + */ + maskClosable?: boolean + + /** + * Style for modal's mask element. + * @default {} + * @type object + */ + maskStyle?: CSSProperties + + /** + * Text of the OK button + * @default 'OK' + * @type string + */ + okText?: string + + /** + * Button type of the OK button + * @default 'primary' + * @type string + */ + okType?: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default' + + /** + * The ok button props, follow jsx rules + * @type object + */ + okButtonProps?: ButtonProps + + /** + * The cancel button props, follow jsx rules + * @type object + */ + cancelButtonProps?: ButtonProps + + /** + * The modal dialog's title + * @type any (string | slot) + */ + title?: VNodeChild | JSX.Element + + /** + * Width of the modal dialog + * @default 520 + * @type string | number + */ + width?: string | number + + /** + * The class name of the container of the modal dialog + * @type string + */ + wrapClassName?: string + + /** + * The z-index of the Modal + * @default 1000 + * @type number + */ + zIndex?: number +} + +export interface ModalWrapperProps { + footerOffset?: number + loading: boolean + modalHeaderHeight: number + modalFooterHeight: number + minHeight: number + height: number + visible: boolean + fullScreen: boolean + useWrapper: boolean +} diff --git a/frontend/vben/src/components/Page/index.ts b/frontend/vben/src/components/Page/index.ts new file mode 100644 index 0000000..a04d23b --- /dev/null +++ b/frontend/vben/src/components/Page/index.ts @@ -0,0 +1,9 @@ +import { withInstall } from '/@/utils' + +import pageFooter from './src/PageFooter.vue' +import pageWrapper from './src/PageWrapper.vue' + +export const PageFooter = withInstall(pageFooter) +export const PageWrapper = withInstall(pageWrapper) + +export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight' diff --git a/frontend/vben/src/components/Page/src/PageFooter.vue b/frontend/vben/src/components/Page/src/PageFooter.vue new file mode 100644 index 0000000..699dfe8 --- /dev/null +++ b/frontend/vben/src/components/Page/src/PageFooter.vue @@ -0,0 +1,50 @@ + + + diff --git a/frontend/vben/src/components/Page/src/PageWrapper.vue b/frontend/vben/src/components/Page/src/PageWrapper.vue new file mode 100644 index 0000000..bd27dee --- /dev/null +++ b/frontend/vben/src/components/Page/src/PageWrapper.vue @@ -0,0 +1,191 @@ + + + diff --git a/frontend/vben/src/components/Scrollbar/index.ts b/frontend/vben/src/components/Scrollbar/index.ts new file mode 100644 index 0000000..1c567ff --- /dev/null +++ b/frontend/vben/src/components/Scrollbar/index.ts @@ -0,0 +1,8 @@ +/** + * copy from element-ui + */ + +import Scrollbar from './src/Scrollbar.vue' + +export { Scrollbar } +export type { ScrollbarType } from './src/types' diff --git a/frontend/vben/src/components/Scrollbar/src/Scrollbar.vue b/frontend/vben/src/components/Scrollbar/src/Scrollbar.vue new file mode 100644 index 0000000..91197d1 --- /dev/null +++ b/frontend/vben/src/components/Scrollbar/src/Scrollbar.vue @@ -0,0 +1,206 @@ + + + diff --git a/frontend/vben/src/components/Scrollbar/src/bar.ts b/frontend/vben/src/components/Scrollbar/src/bar.ts new file mode 100644 index 0000000..ff08bb5 --- /dev/null +++ b/frontend/vben/src/components/Scrollbar/src/bar.ts @@ -0,0 +1,110 @@ +import { + defineComponent, + h, + computed, + ref, + getCurrentInstance, + onUnmounted, + inject, + Ref, +} from 'vue' +import { on, off } from '/@/utils/domUtils' + +import { renderThumbStyle, BAR_MAP } from './util' + +export default defineComponent({ + name: 'Bar', + + props: { + vertical: Boolean, + size: String, + move: Number, + }, + + setup(props) { + const instance = getCurrentInstance() + const thumb = ref() + const wrap = inject('scroll-bar-wrap', {} as Ref>) as any + const bar = computed(() => { + return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'] + }) + const barStore = ref({}) + const cursorDown = ref() + const clickThumbHandler = (e: any) => { + // prevent click event of right button + if (e.ctrlKey || e.button === 2) { + return + } + window.getSelection()?.removeAllRanges() + startDrag(e) + barStore.value[bar.value.axis] = + e.currentTarget[bar.value.offset] - + (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]) + } + + const clickTrackHandler = (e: any) => { + const offset = Math.abs( + e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client], + ) + const thumbHalf = thumb.value[bar.value.offset] / 2 + const thumbPositionPercentage = + ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset] + + wrap.value[bar.value.scroll] = + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100 + } + const startDrag = (e: any) => { + e.stopImmediatePropagation() + cursorDown.value = true + on(document, 'mousemove', mouseMoveDocumentHandler) + on(document, 'mouseup', mouseUpDocumentHandler) + document.onselectstart = () => false + } + + const mouseMoveDocumentHandler = (e: any) => { + if (cursorDown.value === false) return + const prevPage = barStore.value[bar.value.axis] + + if (!prevPage) return + + const offset = + (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * + -1 + const thumbClickPosition = thumb.value[bar.value.offset] - prevPage + const thumbPositionPercentage = + ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset] + wrap.value[bar.value.scroll] = + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100 + } + + function mouseUpDocumentHandler() { + cursorDown.value = false + barStore.value[bar.value.axis] = 0 + off(document, 'mousemove', mouseMoveDocumentHandler) + document.onselectstart = null + } + + onUnmounted(() => { + off(document, 'mouseup', mouseUpDocumentHandler) + }) + + return () => + h( + 'div', + { + class: ['scrollbar__bar', 'is-' + bar.value.key], + onMousedown: clickTrackHandler, + }, + h('div', { + ref: thumb, + class: 'scrollbar__thumb', + onMousedown: clickThumbHandler, + style: renderThumbStyle({ + size: props.size, + move: props.move, + bar: bar.value, + }), + }), + ) + }, +}) diff --git a/frontend/vben/src/components/Scrollbar/src/types.d.ts b/frontend/vben/src/components/Scrollbar/src/types.d.ts new file mode 100644 index 0000000..7d67ccf --- /dev/null +++ b/frontend/vben/src/components/Scrollbar/src/types.d.ts @@ -0,0 +1,18 @@ +export interface BarMapItem { + offset: string + scroll: string + scrollSize: string + size: string + key: string + axis: string + client: string + direction: string +} +export interface BarMap { + vertical: BarMapItem + horizontal: BarMapItem +} + +export interface ScrollbarType { + wrap: ElRef +} diff --git a/frontend/vben/src/components/Scrollbar/src/util.ts b/frontend/vben/src/components/Scrollbar/src/util.ts new file mode 100644 index 0000000..e38a036 --- /dev/null +++ b/frontend/vben/src/components/Scrollbar/src/util.ts @@ -0,0 +1,50 @@ +import type { BarMap } from './types' +export const BAR_MAP: BarMap = { + vertical: { + offset: 'offsetHeight', + scroll: 'scrollTop', + scrollSize: 'scrollHeight', + size: 'height', + key: 'vertical', + axis: 'Y', + client: 'clientY', + direction: 'top', + }, + horizontal: { + offset: 'offsetWidth', + scroll: 'scrollLeft', + scrollSize: 'scrollWidth', + size: 'width', + key: 'horizontal', + axis: 'X', + client: 'clientX', + direction: 'left', + }, +} + +// @ts-ignore +export function renderThumbStyle({ move, size, bar }) { + const style = {} as any + const translate = `translate${bar.axis}(${move}%)` + + style[bar.size] = size + style.transform = translate + style.msTransform = translate + style.webkitTransform = translate + + return style +} + +function extend(to: T, _from: K): T & K { + return Object.assign(to, _from) +} + +export function toObject(arr: Array): Recordable { + const res = {} + for (let i = 0; i < arr.length; i++) { + if (arr[i]) { + extend(res, arr[i]) + } + } + return res +} diff --git a/frontend/vben/src/components/SimpleMenu/index.ts b/frontend/vben/src/components/SimpleMenu/index.ts new file mode 100644 index 0000000..7c0301b --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/index.ts @@ -0,0 +1,2 @@ +export { default as SimpleMenu } from './src/SimpleMenu.vue' +export { default as SimpleMenuTag } from './src/SimpleMenuTag.vue' diff --git a/frontend/vben/src/components/SimpleMenu/src/SimpleMenu.vue b/frontend/vben/src/components/SimpleMenu/src/SimpleMenu.vue new file mode 100644 index 0000000..2554f09 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/SimpleMenu.vue @@ -0,0 +1,160 @@ + + + diff --git a/frontend/vben/src/components/SimpleMenu/src/SimpleMenuTag.vue b/frontend/vben/src/components/SimpleMenu/src/SimpleMenuTag.vue new file mode 100644 index 0000000..64e611e --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/SimpleMenuTag.vue @@ -0,0 +1,68 @@ + + diff --git a/frontend/vben/src/components/SimpleMenu/src/SimpleSubMenu.vue b/frontend/vben/src/components/SimpleMenu/src/SimpleSubMenu.vue new file mode 100644 index 0000000..a095190 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/SimpleSubMenu.vue @@ -0,0 +1,116 @@ + + diff --git a/frontend/vben/src/components/SimpleMenu/src/components/Menu.vue b/frontend/vben/src/components/SimpleMenu/src/components/Menu.vue new file mode 100644 index 0000000..9af9212 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/Menu.vue @@ -0,0 +1,158 @@ + + + + diff --git a/frontend/vben/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue b/frontend/vben/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue new file mode 100644 index 0000000..78f8644 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/MenuCollapseTransition.vue @@ -0,0 +1,78 @@ + + diff --git a/frontend/vben/src/components/SimpleMenu/src/components/MenuItem.vue b/frontend/vben/src/components/SimpleMenu/src/components/MenuItem.vue new file mode 100644 index 0000000..ccc49a6 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/MenuItem.vue @@ -0,0 +1,107 @@ + + + diff --git a/frontend/vben/src/components/SimpleMenu/src/components/SubMenuItem.vue b/frontend/vben/src/components/SimpleMenu/src/components/SubMenuItem.vue new file mode 100644 index 0000000..3a0a7b1 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/SubMenuItem.vue @@ -0,0 +1,333 @@ + + + diff --git a/frontend/vben/src/components/SimpleMenu/src/components/menu.less b/frontend/vben/src/components/SimpleMenu/src/components/menu.less new file mode 100644 index 0000000..0c4c5ca --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/menu.less @@ -0,0 +1,309 @@ +@menu-prefix-cls: ~'@{namespace}-menu'; +@menu-popup-prefix-cls: ~'@{namespace}-menu-popup'; +@submenu-popup-prefix-cls: ~'@{namespace}-menu-submenu-popup'; + +@transition-time: 0.2s; +@menu-dark-subsidiary-color: rgba(255, 255, 255, 0.7); + +.light-border { + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + display: block; + width: 2px; + content: ''; + background-color: @primary-color; + } +} + +.@{menu-prefix-cls}-menu-popover { + .ant-popover-arrow { + display: none; + } + + .ant-popover-inner-content { + padding: 0; + } + + .@{menu-prefix-cls} { + &-opened > * > &-submenu-title-icon { + transform: translateY(-50%) rotate(90deg) !important; + } + + &-item, + &-submenu-title { + position: relative; + z-index: 1; + padding: 12px 20px; + color: @menu-dark-subsidiary-color; + cursor: pointer; + transition: all @transition-time @ease-in-out; + + &-icon { + position: absolute; + top: 50%; + right: 18px; + transition: transform @transition-time @ease-in-out; + transform: translateY(-50%) rotate(-90deg); + } + } + + &-dark { + .@{menu-prefix-cls}-item, + .@{menu-prefix-cls}-submenu-title { + color: @menu-dark-subsidiary-color; + // background: @menu-dark-active-bg; + + &:hover { + color: #fff; + } + + &-selected { + color: #fff; + background-color: @primary-color !important; + } + } + } + + &-light { + .@{menu-prefix-cls}-item, + .@{menu-prefix-cls}-submenu-title { + color: @text-color-base; + + &:hover { + color: @primary-color; + } + + &-selected { + z-index: 2; + color: @primary-color; + background-color: fade(@primary-color, 10); + + .light-border(); + } + } + } + } +} + +.content(); +.content() { + .@{menu-prefix-cls} { + position: relative; + display: block; + width: 100%; + padding: 0; + margin: 0; + font-size: @font-size-base; + color: @text-color-base; + list-style: none; + outline: none; + + // .collapse-transition { + // transition: @transition-time height ease-in-out, @transition-time padding-top ease-in-out, + // @transition-time padding-bottom ease-in-out; + // } + + &-light { + background-color: #fff; + + .@{menu-prefix-cls}-submenu-active { + color: @primary-color !important; + + &-border { + .light-border(); + } + } + } + + &-dark { + .@{menu-prefix-cls}-submenu-active { + color: #fff !important; + } + } + + &-item { + position: relative; + z-index: 1; + display: flex; + align-items: center; + font-size: @font-size-base; + color: inherit; + list-style: none; + cursor: pointer; + outline: none; + + &:hover, + &:active { + color: inherit; + } + } + + &-item > i { + margin-right: 6px; + } + + &-submenu-title > i, + &-submenu-title span > i { + margin-right: 8px; + } + + // vertical + &-vertical &-item, + &-vertical &-submenu-title { + position: relative; + z-index: 1; + padding: 14px 24px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; + + &:hover { + color: @primary-color; + } + + .@{menu-prefix-cls}-tooltip { + width: calc(100% - 0px); + padding: 12px 0; + text-align: center; + } + .@{menu-prefix-cls}-submenu-popup { + padding: 12px 0; + } + } + + &-vertical &-submenu-collapse { + .@{submenu-popup-prefix-cls} { + display: flex; + align-items: center; + justify-content: center; + } + .@{menu-prefix-cls}-submenu-collapsed-show-tit { + flex-direction: column; + } + } + + &-vertical&-collapse &-item, + &-vertical&-collapse &-submenu-title { + padding: 0; + } + + &-vertical &-submenu-title-icon { + position: absolute; + top: 50%; + right: 18px; + transform: translateY(-50%); + } + + &-submenu-title-icon { + transition: transform @transition-time @ease-in-out; + } + + &-vertical &-opened > * > &-submenu-title-icon { + transform: translateY(-50%) rotate(180deg); + } + + &-vertical &-submenu { + &-nested { + padding-left: 20px; + } + .@{menu-prefix-cls}-item { + padding-left: 43px; + } + } + + &-light&-vertical &-item { + &-active:not(.@{menu-prefix-cls}-submenu) { + z-index: 2; + color: @primary-color; + background-color: fade(@primary-color, 10); + + .light-border(); + } + &-active.@{menu-prefix-cls}-submenu { + color: @primary-color; + } + } + + &-light&-vertical&-collapse { + > li.@{menu-prefix-cls}-item-active, + .@{menu-prefix-cls}-submenu-active { + position: relative; + background-color: fade(@primary-color, 5); + + &::after { + display: none; + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 3px; + height: 100%; + content: ''; + background-color: @primary-color; + } + } + } + + &-dark&-vertical &-item, + &-dark&-vertical &-submenu-title { + color: @menu-dark-subsidiary-color; + &-active:not(.@{menu-prefix-cls}-submenu) { + color: #fff !important; + background-color: @primary-color !important; + } + + &:hover { + color: #fff; + } + } + + &-dark&-vertical&-collapse { + > li.@{menu-prefix-cls}-item-active, + .@{menu-prefix-cls}-submenu-active { + position: relative; + color: #fff !important; + background-color: @sider-dark-darken-bg-color !important; + + &::before { + position: absolute; + top: 0; + left: 0; + width: 3px; + height: 100%; + content: ''; + background-color: @primary-color; + } + + .@{menu-prefix-cls}-submenu-collapse { + background-color: transparent; + } + } + } + + &-dark&-vertical &-submenu &-item { + &-active, + &-active:hover { + color: #fff; + border-right: none; + } + } + + &-dark&-vertical &-child-item-active > &-submenu-title { + color: #fff; + } + + &-dark&-vertical &-opened { + .@{menu-prefix-cls}-submenu-has-parent-submenu { + .@{menu-prefix-cls}-submenu-title { + background-color: transparent; + } + } + } + } +} diff --git a/frontend/vben/src/components/SimpleMenu/src/components/types.ts b/frontend/vben/src/components/SimpleMenu/src/components/types.ts new file mode 100644 index 0000000..d828e89 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/types.ts @@ -0,0 +1,25 @@ +import { Ref } from 'vue'; + +export interface Props { + theme: string; + activeName?: string | number | undefined; + openNames: string[]; + accordion: boolean; + width: string; + collapsedWidth: string; + indentSize: number; + collapse: boolean; + activeSubMenuNames: (string | number)[]; +} + +export interface SubMenuProvider { + addSubMenu: (name: string | number, update?: boolean) => void; + removeSubMenu: (name: string | number, update?: boolean) => void; + removeAll: () => void; + sliceIndex: (index: number) => void; + isRemoveAllPopup: Ref; + getOpenNames: () => (string | number)[]; + handleMouseleave?: Fn; + level: number; + props: Props; +} diff --git a/frontend/vben/src/components/SimpleMenu/src/components/useMenu.ts b/frontend/vben/src/components/SimpleMenu/src/components/useMenu.ts new file mode 100644 index 0000000..8faa231 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/useMenu.ts @@ -0,0 +1,84 @@ +import { computed, ComponentInternalInstance, unref } from 'vue' +import type { CSSProperties } from 'vue' + +export function useMenuItem(instance: ComponentInternalInstance | null) { + const getParentMenu = computed(() => { + return findParentMenu(['Menu', 'SubMenu']) + }) + + const getParentRootMenu = computed(() => { + return findParentMenu(['Menu']) + }) + + const getParentSubMenu = computed(() => { + return findParentMenu(['SubMenu']) + }) + + const getItemStyle = computed((): CSSProperties => { + let parent = instance?.parent + if (!parent) return {} + const indentSize = (unref(getParentRootMenu)?.props.indentSize as number) ?? 20 + let padding = indentSize + + if (unref(getParentRootMenu)?.props.collapse) { + padding = indentSize + } else { + while (parent && parent.type.name !== 'Menu') { + if (parent.type.name === 'SubMenu') { + padding += indentSize + } + parent = parent.parent + } + } + return { paddingLeft: padding + 'px' } + }) + + function findParentMenu(name: string[]) { + let parent = instance?.parent + if (!parent) return null + while (parent && name.indexOf(parent.type.name!) === -1) { + parent = parent.parent + } + return parent + } + + function getParentList() { + let parent = instance + if (!parent) + return { + uidList: [], + list: [], + } + const ret: any[] = [] + while (parent && parent.type.name !== 'Menu') { + if (parent.type.name === 'SubMenu') { + ret.push(parent) + } + parent = parent.parent + } + return { + uidList: ret.map((item) => item.uid), + list: ret, + } + } + + function getParentInstance(instance: ComponentInternalInstance, name = 'SubMenu') { + let parent = instance.parent + while (parent) { + if (parent.type.name !== name) { + return parent + } + parent = parent.parent + } + return parent + } + + return { + getParentMenu, + getParentInstance, + getParentRootMenu, + getParentList, + getParentSubMenu, + getItemStyle, + } +} diff --git a/frontend/vben/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts b/frontend/vben/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts new file mode 100644 index 0000000..810ae8a --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/components/useSimpleMenuContext.ts @@ -0,0 +1,18 @@ +import type { InjectionKey, Ref } from 'vue' +import type { Emitter } from '/@/utils/mitt' +import { createContext, useContext } from '/@/hooks/core/useContext' + +export interface SimpleRootMenuContextProps { + rootMenuEmitter: Emitter + activeName: Ref +} + +const key: InjectionKey = Symbol() + +export function createSimpleRootMenuContext(context: SimpleRootMenuContextProps) { + return createContext(context, key, { readonly: false, native: true }) +} + +export function useSimpleRootMenuContext() { + return useContext(key) +} diff --git a/frontend/vben/src/components/SimpleMenu/src/index.less b/frontend/vben/src/components/SimpleMenu/src/index.less new file mode 100644 index 0000000..4f9c9ce --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/index.less @@ -0,0 +1,77 @@ +@simple-prefix-cls: ~'@{namespace}-simple-menu'; +@prefix-cls: ~'@{namespace}-menu'; + +.@{prefix-cls} { + &-dark&-vertical .@{simple-prefix-cls}__parent { + background-color: @sider-dark-bg-color; + > .@{prefix-cls}-submenu-title { + background-color: @sider-dark-bg-color; + } + } + + &-dark&-vertical .@{simple-prefix-cls}__children, + &-dark&-popup .@{simple-prefix-cls}__children { + background-color: @sider-dark-lighten-bg-color; + > .@{prefix-cls}-submenu-title { + background-color: @sider-dark-lighten-bg-color; + } + } + + .collapse-title { + overflow: hidden; + font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; + } +} + +.@{simple-prefix-cls} { + &-sub-title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + transition: all 0.3s; + } + + &-tag { + position: absolute; + top: calc(50% - 8px); + right: 30px; + display: inline-block; + padding: 2px 3px; + margin-right: 4px; + font-size: 10px; + line-height: 14px; + color: #fff; + border-radius: 2px; + + &--collapse { + top: 6px !important; + right: 2px; + } + + &--dot { + top: calc(50% - 2px); + width: 6px; + height: 6px; + padding: 0; + border-radius: 50%; + } + + &--primary { + background-color: @primary-color; + } + + &--error { + background-color: @error-color; + } + + &--success { + background-color: @success-color; + } + + &--warn { + background-color: @warning-color; + } + } +} diff --git a/frontend/vben/src/components/SimpleMenu/src/types.ts b/frontend/vben/src/components/SimpleMenu/src/types.ts new file mode 100644 index 0000000..1c7bbee --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/types.ts @@ -0,0 +1,5 @@ +export interface MenuState { + activeName: string + openNames: string[] + activeSubMenuNames: string[] +} diff --git a/frontend/vben/src/components/SimpleMenu/src/useOpenKeys.ts b/frontend/vben/src/components/SimpleMenu/src/useOpenKeys.ts new file mode 100644 index 0000000..8d4f6c8 --- /dev/null +++ b/frontend/vben/src/components/SimpleMenu/src/useOpenKeys.ts @@ -0,0 +1,50 @@ +import type { Menu as MenuType } from '/@/router/types' +import type { MenuState } from './types' + +import { computed, Ref, toRaw } from 'vue' + +import { unref } from 'vue' +import { uniq } from 'lodash-es' +import { getAllParentPath } from '/@/router/helper/menuHelper' + +import { useTimeoutFn } from '/@/hooks/core/useTimeout' +import { useDebounceFn } from '@vueuse/core' + +export function useOpenKeys( + menuState: MenuState, + menus: Ref, + accordion: Ref, + mixSider: Ref, + collapse: Ref, +) { + const debounceSetOpenKeys = useDebounceFn(setOpenKeys, 50) + async function setOpenKeys(path: string) { + const native = !mixSider.value + const menuList = toRaw(menus.value) + useTimeoutFn( + () => { + if (menuList?.length === 0) { + menuState.activeSubMenuNames = [] + menuState.openNames = [] + return + } + const keys = getAllParentPath(menuList, path) + + if (!unref(accordion)) { + menuState.openNames = uniq([...menuState.openNames, ...keys]) + } else { + menuState.openNames = keys + } + menuState.activeSubMenuNames = menuState.openNames + }, + 30, + native, + ) + } + + const getOpenKeys = computed(() => { + return unref(collapse) ? [] : menuState.openNames + }) + + return { setOpenKeys: debounceSetOpenKeys, getOpenKeys } +} diff --git a/frontend/vben/src/components/StrengthMeter/index.ts b/frontend/vben/src/components/StrengthMeter/index.ts new file mode 100644 index 0000000..b009b2d --- /dev/null +++ b/frontend/vben/src/components/StrengthMeter/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '/@/utils' +import strengthMeter from './src/StrengthMeter.vue' + +export const StrengthMeter = withInstall(strengthMeter) diff --git a/frontend/vben/src/components/StrengthMeter/src/StrengthMeter.vue b/frontend/vben/src/components/StrengthMeter/src/StrengthMeter.vue new file mode 100644 index 0000000..04e5339 --- /dev/null +++ b/frontend/vben/src/components/StrengthMeter/src/StrengthMeter.vue @@ -0,0 +1,142 @@ + + + + diff --git a/frontend/vben/src/components/Transition/index.ts b/frontend/vben/src/components/Transition/index.ts new file mode 100644 index 0000000..411bb02 --- /dev/null +++ b/frontend/vben/src/components/Transition/index.ts @@ -0,0 +1,27 @@ +import { createSimpleTransition, createJavascriptTransition } from './src/CreateTransition' + +import ExpandTransitionGenerator from './src/ExpandTransition' + +export { default as CollapseTransition } from './src/CollapseTransition.vue' + +export const FadeTransition = createSimpleTransition('fade-transition') +export const ScaleTransition = createSimpleTransition('scale-transition') +export const SlideYTransition = createSimpleTransition('slide-y-transition') +export const ScrollYTransition = createSimpleTransition('scroll-y-transition') +export const SlideYReverseTransition = createSimpleTransition('slide-y-reverse-transition') +export const ScrollYReverseTransition = createSimpleTransition('scroll-y-reverse-transition') +export const SlideXTransition = createSimpleTransition('slide-x-transition') +export const ScrollXTransition = createSimpleTransition('scroll-x-transition') +export const SlideXReverseTransition = createSimpleTransition('slide-x-reverse-transition') +export const ScrollXReverseTransition = createSimpleTransition('scroll-x-reverse-transition') +export const ScaleRotateTransition = createSimpleTransition('scale-rotate-transition') + +export const ExpandXTransition = createJavascriptTransition( + 'expand-x-transition', + ExpandTransitionGenerator('', true), +) + +export const ExpandTransition = createJavascriptTransition( + 'expand-transition', + ExpandTransitionGenerator(''), +) diff --git a/frontend/vben/src/components/Transition/src/CollapseTransition.vue b/frontend/vben/src/components/Transition/src/CollapseTransition.vue new file mode 100644 index 0000000..a320e85 --- /dev/null +++ b/frontend/vben/src/components/Transition/src/CollapseTransition.vue @@ -0,0 +1,78 @@ + + diff --git a/frontend/vben/src/components/Transition/src/CreateTransition.tsx b/frontend/vben/src/components/Transition/src/CreateTransition.tsx new file mode 100644 index 0000000..6b49e93 --- /dev/null +++ b/frontend/vben/src/components/Transition/src/CreateTransition.tsx @@ -0,0 +1,73 @@ +import type { PropType } from 'vue' + +import { defineComponent, Transition, TransitionGroup } from 'vue' +import { getSlot } from '/@/utils/helper/tsxHelper' + +type Mode = 'in-out' | 'out-in' | 'default' | undefined + +export function createSimpleTransition(name: string, origin = 'top center 0', mode?: Mode) { + return defineComponent({ + name, + props: { + group: { + type: Boolean as PropType, + default: false, + }, + mode: { + type: String as PropType, + default: mode, + }, + origin: { + type: String as PropType, + default: origin, + }, + }, + setup(props, { slots, attrs }) { + const onBeforeEnter = (el: HTMLElement) => { + el.style.transformOrigin = props.origin + } + + return () => { + const Tag = !props.group ? Transition : TransitionGroup + return ( + + {() => getSlot(slots)} + + ) + } + }, + }) +} +export function createJavascriptTransition( + name: string, + functions: Recordable, + mode: Mode = 'in-out', +) { + return defineComponent({ + name, + props: { + mode: { + type: String as PropType, + default: mode, + }, + }, + setup(props, { attrs, slots }) { + return () => { + return ( + + {() => getSlot(slots)} + + ) + } + }, + }) +} diff --git a/frontend/vben/src/components/Transition/src/ExpandTransition.ts b/frontend/vben/src/components/Transition/src/ExpandTransition.ts new file mode 100644 index 0000000..226daa0 --- /dev/null +++ b/frontend/vben/src/components/Transition/src/ExpandTransition.ts @@ -0,0 +1,89 @@ +/** + * Makes the first character of a string uppercase + */ +export function upperFirst(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1) +} + +interface HTMLExpandElement extends HTMLElement { + _parent?: (Node & ParentNode & HTMLElement) | null + _initialStyle: { + transition: string + overflow: string | null + height?: string | null + width?: string | null + } +} + +export default function (expandedParentClass = '', x = false) { + const sizeProperty = x ? 'width' : ('height' as 'width' | 'height') + const offsetProperty = `offset${upperFirst(sizeProperty)}` as 'offsetHeight' | 'offsetWidth' + + return { + beforeEnter(el: HTMLExpandElement) { + el._parent = el.parentNode as (Node & ParentNode & HTMLElement) | null + el._initialStyle = { + transition: el.style.transition, + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + } + }, + + enter(el: HTMLExpandElement) { + const initialStyle = el._initialStyle + + el.style.setProperty('transition', 'none', 'important') + el.style.overflow = 'hidden' + // const offset = `${el[offsetProperty]}px`; + + // el.style[sizeProperty] = '0'; + + void el.offsetHeight // force reflow + + el.style.transition = initialStyle.transition + + if (expandedParentClass && el._parent) { + el._parent.classList.add(expandedParentClass) + } + + requestAnimationFrame(() => { + // el.style[sizeProperty] = offset; + }) + }, + + afterEnter: resetStyles, + enterCancelled: resetStyles, + + leave(el: HTMLExpandElement) { + el._initialStyle = { + transition: '', + overflow: el.style.overflow, + [sizeProperty]: el.style[sizeProperty], + } + + el.style.overflow = 'hidden' + el.style[sizeProperty] = `${el[offsetProperty]}px` + /* eslint-disable-next-line */ + void el.offsetHeight // force reflow + + requestAnimationFrame(() => (el.style[sizeProperty] = '0')) + }, + + afterLeave, + leaveCancelled: afterLeave, + } + + function afterLeave(el: HTMLExpandElement) { + if (expandedParentClass && el._parent) { + el._parent.classList.remove(expandedParentClass) + } + resetStyles(el) + } + + function resetStyles(el: HTMLExpandElement) { + const size = el._initialStyle[sizeProperty] + el.style.overflow = el._initialStyle.overflow! + if (size != null) el.style[sizeProperty] = size + Reflect.deleteProperty(el, '_initialStyle') + } +} diff --git a/frontend/vben/src/components/registerGlobComp.ts b/frontend/vben/src/components/registerGlobComp.ts new file mode 100644 index 0000000..2109973 --- /dev/null +++ b/frontend/vben/src/components/registerGlobComp.ts @@ -0,0 +1,7 @@ +import type { App } from 'vue' +import { Button } from './Button' +import { Input, Layout } from 'ant-design-vue' + +export function registerGlobComp(app: App) { + app.use(Input).use(Button).use(Layout) +} diff --git a/frontend/vben/src/design/ant/btn.less b/frontend/vben/src/design/ant/btn.less new file mode 100644 index 0000000..c997d01 --- /dev/null +++ b/frontend/vben/src/design/ant/btn.less @@ -0,0 +1,285 @@ +// button reset +.ant-btn { + &-link:hover, + &-link:focus, + &-link:active { + border-color: transparent !important; + } + + &-primary { + color: @white; + background-color: @button-primary-color; + + &:hover, + &:focus { + color: @white; + background-color: @button-primary-hover-color; + } + } + + &-primary:not(&-background-ghost):not([disabled]) { + color: @white; + } + + &-default { + color: @button-cancel-color; + background-color: @button-cancel-bg-color; + border-color: @button-cancel-border-color; + + &:hover, + &:focus { + color: @button-cancel-hover-color; + background-color: @button-cancel-hover-bg-color; + border-color: @button-cancel-hover-border-color; + } + // + //&[disabled], + //&[disabled]:hover { + // color: fade(@button-cancel-color, 40%) !important; + // background: fade(@button-cancel-bg-color, 40%) !important; + // border-color: fade(@button-cancel-border-color, 40%) !important; + //} + } + + [data-theme='light'] &.ant-btn-link.is-disabled { + color: rgb(0 0 0 / 25%); + text-shadow: none; + cursor: not-allowed !important; + background-color: transparent !important; + border-color: transparent !important; + box-shadow: none; + } + + [data-theme='dark'] &.ant-btn-link.is-disabled { + color: rgb(255 255 255 / 25%) !important; + text-shadow: none; + cursor: not-allowed !important; + background-color: transparent !important; + border-color: transparent !important; + box-shadow: none; + } + + // color: @white; + + &-success.ant-btn-link:not([disabled='disabled']) { + color: @button-success-color; + + &:hover, + &:focus { + color: @button-success-hover-color; + border-color: transparent; + } + + &:active { + color: @button-success-active-color; + } + } + + &-success.ant-btn-link.ant-btn-loading, + &-warning.ant-btn-link.ant-btn-loading, + &-error.ant-btn-link.ant-btn-loading, + &-background-ghost.ant-btn-link.ant-btn-loading, + &.ant-btn-link.ant-btn-loading { + &::before { + background: transparent; + } + } + + &-success:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-success-color; + border-color: @button-success-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-success-hover-color; + border-color: @button-success-hover-color; + } + + &:active { + background-color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-warning.ant-btn-link:not([disabled='disabled']) { + color: @button-warn-color; + + &:hover, + &:focus { + color: @button-warn-hover-color; + border-color: transparent; + } + + &:active { + color: @button-warn-active-color; + } + } + + &-warning:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-warn-color; + border-color: @button-warn-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-warn-hover-color; + border-color: @button-warn-hover-color; + } + + &:active { + background-color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-warn-color, 40%); + // border-color: fade(@button-warn-color, 40%); + //} + } + + &-error.ant-btn-link:not([disabled='disabled']) { + color: @button-error-color; + + &:hover, + &:focus { + color: @button-error-hover-color; + border-color: transparent; + } + + &:active { + color: @button-error-active-color; + } + } + + &-error:not(.ant-btn-link, .is-disabled) { + color: @white; + background-color: @button-error-color; + border-color: @button-error-color; + //border-width: 0; + + &:hover, + &:focus { + color: @white; + background-color: @button-error-hover-color; + border-color: @button-error-hover-color; + } + + &:active { + background-color: @button-error-active-color; + border-color: @button-error-active-color; + } + + //&[disabled], + //&[disabled]:hover { + // color: @white; + // background-color: fade(@button-error-color, 40%); + // border-color: fade(@button-error-color, 40%); + //} + } + + &-background-ghost { + border-width: 1px; + background-color: transparent !important; + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + background-color: transparent !important; + border-color: fade(@white, 40%) !important; + } + } + + &-dashed&-background-ghost, + &-default&-background-ghost { + color: @button-ghost-color; + border-color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: @button-ghost-hover-color; + } + + &:active { + color: @button-ghost-active-color; + border-color: @button-ghost-active-color; + } + + &[disabled], + &[disabled]:hover { + color: fade(@white, 40%) !important; + border-color: fade(@white, 40%) !important; + } + } + + &-background-ghost&-success:not(.ant-btn-link) { + color: @button-success-color; + background-color: transparent; + border-color: @button-success-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-success-hover-color !important; + border-color: @button-success-hover-color; + } + + &:active { + color: @button-success-active-color; + border-color: @button-success-active-color; + } + } + + &-background-ghost&-warning:not(.ant-btn-link) { + color: @button-warn-color; + background-color: transparent; + border-color: @button-warn-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-warn-hover-color !important; + border-color: @button-warn-hover-color; + } + + &:active { + color: @button-warn-active-color; + border-color: @button-warn-active-color; + } + } + + &-background-ghost&-error:not(.ant-btn-link) { + color: @button-error-color; + background-color: transparent; + border-color: @button-error-color; + border-width: 1px; + + &:hover, + &:focus { + color: @button-error-hover-color !important; + border-color: @button-error-hover-color; + } + + &:active { + color: @button-error-active-color; + border-color: @button-error-active-color; + } + } + + &-ghost.ant-btn-link:not([disabled='disabled']) { + color: @button-ghost-color; + + &:hover, + &:focus { + color: @button-ghost-hover-color; + border-color: transparent; + } + } +} diff --git a/frontend/vben/src/design/ant/index.less b/frontend/vben/src/design/ant/index.less new file mode 100644 index 0000000..1cc8165 --- /dev/null +++ b/frontend/vben/src/design/ant/index.less @@ -0,0 +1,67 @@ +@import './pagination.less'; +@import './input.less'; +@import './btn.less'; + +.ant-image-preview-root { + img { + display: unset; + } +} + +span.anticon:not(.app-iconify) { + vertical-align: 0.125em !important; +} + +.ant-back-top { + right: 20px; + bottom: 20px; +} + +.collapse-container__body { + > .ant-descriptions { + margin-left: 6px; + } +} + +.ant-image-preview-operations { + background-color: rgb(0 0 0 / 30%); +} + +.ant-popover { + &-content { + box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%); + } +} + +// ================================= +// ==============modal message====== +// ================================= +.modal-icon-warning { + color: @warning-color !important; +} + +.modal-icon-success { + color: @success-color !important; +} + +.modal-icon-error { + color: @error-color !important; +} + +.modal-icon-info { + color: @primary-color !important; +} + +.ant-checkbox-checked .ant-checkbox-inner::after, +.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after { + border-top: 0 !important; + border-left: 0 !important; +} + +.ant-form-item-control-input-content { + > div { + > div { + max-width: 100%; + } + } +} diff --git a/frontend/vben/src/design/ant/input.less b/frontend/vben/src/design/ant/input.less new file mode 100644 index 0000000..645afb3 --- /dev/null +++ b/frontend/vben/src/design/ant/input.less @@ -0,0 +1,31 @@ +@import (reference) '../color.less'; + +// input +.ant-input { + &-number { + min-width: 110px; + } +} + +.ant-input-affix-wrapper .ant-input-suffix { + right: 9px; +} + +.ant-input-clear-icon { + margin-right: 5px; +} + +.ant-input-affix-wrapper-textarea-with-clear-btn { + padding: 0 !important; + + textarea.ant-input { + padding: 4px; + } +} + +.ant-input-number { + width: 100% !important; + max-width: 100%; +} + + diff --git a/frontend/vben/src/design/ant/pagination.less b/frontend/vben/src/design/ant/pagination.less new file mode 100644 index 0000000..b3580f9 --- /dev/null +++ b/frontend/vben/src/design/ant/pagination.less @@ -0,0 +1,96 @@ +html[data-theme='dark'] { + .ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + background-color: rgb(255 255 255 / 4%) !important; + + a { + color: #8b949e !important; + } + } + + .ant-select-arrow { + color: @text-color-secondary !important; + } + + .ant-pagination-item-active { + background-color: @primary-color !important; + border: none; + border-radius: none !important; + + a { + color: @white !important; + } + } + } + } +} + +.ant-pagination { + &.mini { + .ant-pagination-prev, + .ant-pagination-next { + font-size: 12px; + color: @text-color-base; + border: 1px solid; + } + + .ant-pagination-prev:hover, + .ant-pagination-next:hover, + .ant-pagination-item:focus, + .ant-pagination-item:hover { + a { + color: @primary-color; + } + } + + .ant-pagination-prev, + .ant-pagination-next, + .ant-pagination-item { + margin: 0 4px !important; + background-color: #f4f4f5 !important; + border: none; + border-radius: none !important; + + a { + margin-top: 1px; + color: #606266; + } + + &:last-child { + margin-right: 0 !important; + } + } + + .ant-pagination-item-active { + background-color: @primary-color !important; + border: none; + border-radius: none !important; + + a { + color: @white !important; + } + } + + .ant-pagination-options { + margin-left: 12px; + } + + .ant-pagination-options-quick-jumper input { + height: 22px; + margin: 0 6px; + line-height: 22px; + text-align: center; + } + + .ant-select-arrow { + color: @border-color-shallow-dark; + } + } + + &-disabled { + display: none !important; + } +} diff --git a/frontend/vben/src/design/ant/table.less b/frontend/vben/src/design/ant/table.less new file mode 100644 index 0000000..ee62b99 --- /dev/null +++ b/frontend/vben/src/design/ant/table.less @@ -0,0 +1,76 @@ +@prefix-cls: ~'@{namespace}-basic-table'; + +// fix table unnecessary scrollbar +.@{prefix-cls} { + .hide-scrollbar-y { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-hide-scrollbar { + overflow-y: auto !important; + } + + .ant-table-body { + overflow-y: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-y: auto !important; + } + } + } + } + } + } + } + } + + .hide-scrollbar-x { + .ant-spin-nested-loading { + .ant-spin-container { + .ant-table { + .ant-table-content { + .ant-table-scroll { + .ant-table-hide-scrollbar { + //overflow-x: auto !important; + } + + .ant-table-body { + overflow: auto !important; + } + } + + .ant-table-fixed-right { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + + .ant-table-fixed-left { + .ant-table-body-outer { + .ant-table-body-inner { + overflow-x: auto !important; + } + } + } + } + } + } + } + } +} diff --git a/frontend/vben/src/design/color.less b/frontend/vben/src/design/color.less new file mode 100644 index 0000000..9d2138c --- /dev/null +++ b/frontend/vben/src/design/color.less @@ -0,0 +1,138 @@ +html { + // header + --header-bg-color: #394664; + --header-bg-hover-color: #273352; + --header-active-menu-bg-color: #273352; + + // sider + --sider-dark-bg-color: #273352; + --sider-dark-darken-bg-color: #273352; + --sider-dark-lighten-bg-color: #273352; +} + +@white: #fff; + +@content-bg: #f4f7f9; + +// :export { +// name: "less"; +// mainColor: @mainColor; +// fontSize: @fontSize; +// } +@iconify-bg-color: #5551; + +// ================================= +// ==============border-color======= +// ================================= + +// Dark-dark +@border-color-dark: #b6b7b9; + +// Dark-light +@border-color-shallow-dark: #cececd; + +// Light-dark +@border-color-light: @border-color-base; + +// ================================= +// ==============message============== +// ================================= + +// success-bg-color +@success-background-color: #f1f9ec; +// info-bg-color +@info-background-color: #e8eff8; +// warn-bg-color +@warning-background-color: #fdf6ed; +// danger-bg-color +@danger-background-color: #fef0f0; + +// ================================= +// ==============Header============= +// ================================= + +@header-dark-bg-color: var(--header-bg-color); +@header-dark-bg-hover-color: var(--header-bg-hover-color); +@header-light-bg-hover-color: #f6f6f6; +@header-light-desc-color: #7c8087; +@header-light-bottom-border-color: #eee; +// top-menu +@top-menu-active-bg-color: var(--header-active-menu-bg-color); + +// ================================= +// ==============Menu============ +// ================================= + +// let -menu +@sider-dark-bg-color: var(--sider-dark-bg-color); +@sider-dark-darken-bg-color: var(--sider-dark-darken-bg-color); +@sider-dark-lighten-bg-color: var(--sider-dark-lighten-bg-color); + +// trigger +@trigger-dark-hover-bg-color: rgba(255, 255, 255, 0.2); +@trigger-dark-bg-color: rgba(255, 255, 255, 0.1); + +// ================================= +// ==============tree============ +// ================================= +// tree item hover background +@tree-hover-background-color: #f5f7fa; +// tree item hover font color +@tree-hover-font-color: #f5f7fa; + +// ================================= +// ==============link============ +// ================================= +@link-hover-color: @primary-color; +@link-active-color: darken(@primary-color, 10%); + +// ================================= +// ==============Text color-============= +// ================================= + +// Main text color +@text-color-base: @text-color; + +// Label color +@text-color-call-out: #606266; + +// Auxiliary information color-dark +@text-color-help-dark: #909399; + +// ================================= +// ==============breadcrumb========= +// ================================= +@breadcrumb-item-normal-color: #999; +// ================================= +// ==============button============= +// ================================= + +@button-primary-color: @primary-color; +@button-primary-hover-color: lighten(@primary-color, 5%); +@button-primary-active-color: darken(@primary-color, 5%); + +@button-ghost-color: @white; +@button-ghost-hover-color: lighten(@white, 10%); +@button-ghost-hover-bg-color: #e1ebf6; +@button-ghost-active-color: darken(@white, 10%); + +@button-success-color: @success-color; +@button-success-hover-color: lighten(@success-color, 10%); +@button-success-active-color: darken(@success-color, 10%); + +@button-warn-color: @warning-color; +@button-warn-hover-color: lighten(@warning-color, 10%); +@button-warn-active-color: darken(@warning-color, 10%); + +@button-error-color: @error-color; +@button-error-hover-color: lighten(@error-color, 10%); +@button-error-active-color: darken(@error-color, 10%); + +@button-cancel-color: @text-color-call-out; +@button-cancel-bg-color: @white; +@button-cancel-border-color: @border-color-shallow-dark; + +// Mouse over +@button-cancel-hover-color: @primary-color; +@button-cancel-hover-bg-color: @white; +@button-cancel-hover-border-color: @primary-color; diff --git a/frontend/vben/src/design/config.less b/frontend/vben/src/design/config.less new file mode 100644 index 0000000..64c33f6 --- /dev/null +++ b/frontend/vben/src/design/config.less @@ -0,0 +1,2 @@ +@import (reference) 'color.less'; +@import (reference) 'var/index.less'; diff --git a/frontend/vben/src/design/index.less b/frontend/vben/src/design/index.less new file mode 100644 index 0000000..7727586 --- /dev/null +++ b/frontend/vben/src/design/index.less @@ -0,0 +1,44 @@ +@import 'transition/index.less'; +@import 'var/index.less'; +@import 'public.less'; +@import 'ant/index.less'; +@import './theme.less'; + +input:-webkit-autofill { + box-shadow: 0 0 0 1000px white inset !important; +} + +:-webkit-autofill { + transition: background-color 5000s ease-in-out 0s !important; +} + +html { + overflow: hidden; + text-size-adjust: 100%; +} + +html, +body { + width: 100%; + height: 100%; + overflow: visible; + overflow-x: hidden; + + &.color-weak { + filter: invert(80%); + } + + &.gray-mode { + filter: grayscale(100%); + filter: progid:dximagetransform.microsoft.basicimage(grayscale=1); + } +} + +a:focus, +a:active, +button, +div, +svg, +span { + outline: none; +} diff --git a/frontend/vben/src/design/public.less b/frontend/vben/src/design/public.less new file mode 100644 index 0000000..644bfab --- /dev/null +++ b/frontend/vben/src/design/public.less @@ -0,0 +1,51 @@ +#app { + width: 100%; + height: 100%; +} + +// ================================= +// ==============scrollbar========== +// ================================= + +::-webkit-scrollbar { + width: 7px; + height: 8px; +} + +// ::-webkit-scrollbar-track { +// background: transparent; +// } + +::-webkit-scrollbar-track { + background-color: rgb(0 0 0 / 5%); +} + +::-webkit-scrollbar-thumb { + // background: rgba(0, 0, 0, 0.6); + background-color: rgb(144 147 153 / 30%); + // background-color: rgba(144, 147, 153, 0.3); + border-radius: 2px; + box-shadow: inset 0 0 6px rgb(0 0 0 / 20%); +} + +::-webkit-scrollbar-thumb:hover { + background-color: @border-color-dark; +} + +// ================================= +// ==============nprogress========== +// ================================= +#nprogress { + pointer-events: none; + + .bar { + position: fixed; + top: 0; + left: 0; + z-index: 99999; + width: 100%; + height: 2px; + background-color: @primary-color; + opacity: 0.75; + } +} diff --git a/frontend/vben/src/design/theme.less b/frontend/vben/src/design/theme.less new file mode 100644 index 0000000..aa05033 --- /dev/null +++ b/frontend/vben/src/design/theme.less @@ -0,0 +1,52 @@ +.bg-white { + background-color: @component-background !important; +} + +html[data-theme='light'] { + .text-secondary { + color: rgb(0 0 0 / 45%); + } + + .ant-alert-success { + background-color: #f6ffed; + border: 1px solid #b7eb8f; + } + + .ant-alert-error { + background-color: #fff2f0; + border: 1px solid #ffccc7; + } + + .ant-alert-warning { + background-color: #fffbe6; + border: 1px solid #ffe58f; + } + + :not(:root):fullscreen::backdrop { + background-color: @layout-body-background !important; + } +} + +[data-theme='dark'] { + .text-secondary { + color: #8b949e; + } + + .ant-card-grid-hoverable:hover { + box-shadow: 0 3px 6px -4px rgb(0 0 0 / 48%), 0 6px 16px 0 rgb(0 0 0 / 32%), + 0 9px 28px 8px rgb(0 0 0 / 20%); + } + + .ant-card-grid { + box-shadow: 1px 0 0 0 #434343, 0 1px 0 0 #434343, 1px 1px 0 0 #434343, 1px 0 0 0 #434343 inset, + 0 1px 0 0 #434343 inset; + } + + .ant-calendar-selected-day .ant-calendar-date { + color: rgb(0 0 0 / 80%); + } + + .ant-select-tree li .ant-select-tree-node-content-wrapper.ant-select-tree-node-selected { + color: rgb(0 0 0 / 90%); + } +} diff --git a/frontend/vben/src/design/transition/base.less b/frontend/vben/src/design/transition/base.less new file mode 100644 index 0000000..7944c8b --- /dev/null +++ b/frontend/vben/src/design/transition/base.less @@ -0,0 +1,18 @@ +.transition-default() { + &-enter-active, + &-leave-active { + transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; + } + + &-move { + transition: transform 0.4s; + } +} + +.expand-transition { + .transition-default(); +} + +.expand-x-transition { + .transition-default(); +} diff --git a/frontend/vben/src/design/transition/fade.less b/frontend/vben/src/design/transition/fade.less new file mode 100644 index 0000000..6ed1771 --- /dev/null +++ b/frontend/vben/src/design/transition/fade.less @@ -0,0 +1,93 @@ +.fade-transition { + &-enter-active, + &-leave-active { + transition: opacity 0.2s ease-in-out; + } + + &-enter-from, + &-leave-to { + opacity: 0; + } +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +/* fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + opacity: 0; + transform: translateX(-30px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translateX(30px); +} + +// /////////////////////////////////////////////// +// Fade Bottom +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-bottom-enter-active, +.fade-bottom-leave-active { + transition: opacity 0.25s, transform 0.3s; +} + +.fade-bottom-enter-from { + opacity: 0; + transform: translateY(-10%); +} + +.fade-bottom-leave-to { + opacity: 0; + transform: translateY(10%); +} + +// fade-scale +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} + +.fade-scale-enter-from { + opacity: 0; + transform: scale(1.2); +} + +.fade-scale-leave-to { + opacity: 0; + transform: scale(0.8); +} + +// /////////////////////////////////////////////// +// Fade Top +// /////////////////////////////////////////////// + +// Speed: 1x +.fade-top-enter-active, +.fade-top-leave-active { + transition: opacity 0.2s, transform 0.25s; +} + +.fade-top-enter-from { + opacity: 0; + transform: translateY(8%); +} + +.fade-top-leave-to { + opacity: 0; + transform: translateY(-8%); +} diff --git a/frontend/vben/src/design/transition/index.less b/frontend/vben/src/design/transition/index.less new file mode 100644 index 0000000..e372b25 --- /dev/null +++ b/frontend/vben/src/design/transition/index.less @@ -0,0 +1,10 @@ +@import './base.less'; +@import './fade.less'; +@import './scale.less'; +@import './slide.less'; +@import './scroll.less'; +@import './zoom.less'; + +.collapse-transition { + transition: 0.2s height ease-in-out, 0.2s padding-top ease-in-out, 0.2s padding-bottom ease-in-out; +} diff --git a/frontend/vben/src/design/transition/scale.less b/frontend/vben/src/design/transition/scale.less new file mode 100644 index 0000000..c965493 --- /dev/null +++ b/frontend/vben/src/design/transition/scale.less @@ -0,0 +1,21 @@ +.scale-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + opacity: 0; + transform: scale(0); + } +} + +.scale-rotate-transition { + .transition-default(); + + &-enter-from, + &-leave, + &-leave-to { + opacity: 0; + transform: scale(0) rotate(-45deg); + } +} diff --git a/frontend/vben/src/design/transition/scroll.less b/frontend/vben/src/design/transition/scroll.less new file mode 100644 index 0000000..a5f45e4 --- /dev/null +++ b/frontend/vben/src/design/transition/scroll.less @@ -0,0 +1,67 @@ +.scroll-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(-15px); + } + + &-leave-to { + transform: translateY(15px); + } +} + +.scroll-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateY(15px); + } + + &-leave-to { + transform: translateY(-15px); + } +} + +.scroll-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(-15px); + } + + &-leave-to { + transform: translateX(15px); + } +} + +.scroll-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + } + + &-enter-from { + transform: translateX(15px); + } + + &-leave-to { + transform: translateX(-15px); + } +} diff --git a/frontend/vben/src/design/transition/slide.less b/frontend/vben/src/design/transition/slide.less new file mode 100644 index 0000000..79b00df --- /dev/null +++ b/frontend/vben/src/design/transition/slide.less @@ -0,0 +1,39 @@ +.slide-y-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + transform: translateY(-15px); + } +} + +.slide-y-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + transform: translateY(15px); + } +} + +.slide-x-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + transform: translateX(-15px); + } +} + +.slide-x-reverse-transition { + .transition-default(); + + &-enter-from, + &-leave-to { + opacity: 0; + transform: translateX(15px); + } +} diff --git a/frontend/vben/src/design/transition/zoom.less b/frontend/vben/src/design/transition/zoom.less new file mode 100644 index 0000000..2ea378c --- /dev/null +++ b/frontend/vben/src/design/transition/zoom.less @@ -0,0 +1,27 @@ +// zoom-out +.zoom-out-enter-active, +.zoom-out-leave-active { + transition: opacity 0.1 ease-in-out, transform 0.15s ease-out; +} + +.zoom-out-enter-from, +.zoom-out-leave-to { + opacity: 0; + transform: scale(0); +} + +// zoom-fade +.zoom-fade-enter-active, +.zoom-fade-leave-active { + transition: transform 0.2s, opacity 0.3s ease-out; +} + +.zoom-fade-enter-from { + opacity: 0; + transform: scale(0.92); +} + +.zoom-fade-leave-to { + opacity: 0; + transform: scale(1.06); +} diff --git a/frontend/vben/src/design/var/breakpoint.less b/frontend/vben/src/design/var/breakpoint.less new file mode 100644 index 0000000..793e826 --- /dev/null +++ b/frontend/vben/src/design/var/breakpoint.less @@ -0,0 +1,33 @@ +// ================================= +// ==============屏幕断点============ +// ================================= + +// Extra small screen / phone +@screen-xs: 480px; +@screen-xs-min: @screen-xs; + +// Small screen / tablet +@screen-sm: 576px; +@screen-sm-min: @screen-sm; + +// Medium screen / desktop +@screen-md: 768px; +@screen-md-min: @screen-md; + +// Large screen / wide desktop +@screen-lg: 992px; +@screen-lg-min: @screen-lg; + +// Extra large screen / full hd +@screen-xl: 1200px; +@screen-xl-min: @screen-xl; + +// Extra extra large screen / large desktop +@screen-2xl: 1600px; +@screen-2xl-min: @screen-2xl; + +@screen-xs-max: (@screen-sm-min - 1px); +@screen-sm-max: (@screen-md-min - 1px); +@screen-md-max: (@screen-lg-min - 1px); +@screen-lg-max: (@screen-xl-min - 1px); +@screen-xl-max: (@screen-2xl-min - 1px); diff --git a/frontend/vben/src/design/var/easing.less b/frontend/vben/src/design/var/easing.less new file mode 100644 index 0000000..e19735f --- /dev/null +++ b/frontend/vben/src/design/var/easing.less @@ -0,0 +1,18 @@ +// ================================= +// ==============动画函数-=========== +// ================================= + +@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); +@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); +@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); +@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); +@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); +@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); +@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); +@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); +@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); +@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); +@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); +@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); +@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); +@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); diff --git a/frontend/vben/src/design/var/index.less b/frontend/vben/src/design/var/index.less new file mode 100644 index 0000000..1689f76 --- /dev/null +++ b/frontend/vben/src/design/var/index.less @@ -0,0 +1,39 @@ +@import (reference) '../color.less'; +@import 'easing'; +@import 'breakpoint'; + +@namespace: vben; + +// tabs +@multiple-height: 30px; + +// headers +@header-height: 48px; + +// logo width +@logo-width: 32px; + +// +@side-drag-z-index: 200; + +@page-loading-z-index: 10000; + +@lock-page-z-index: 3000; + +@layout-header-fixed-z-index: 500; + +@multiple-tab-fixed-z-index: 505; + +@layout-sider-fixed-z-index: 510; + +@layout-mix-sider-fixed-z-index: 550; + +@preview-comp-z-index: 1000; + +@page-footer-z-index: 99; + +.bem(@n; @content) { + @{namespace}-@{n} { + @content(); + } +} diff --git a/frontend/vben/src/directives/clickOutside.ts b/frontend/vben/src/directives/clickOutside.ts new file mode 100644 index 0000000..948b50c --- /dev/null +++ b/frontend/vben/src/directives/clickOutside.ts @@ -0,0 +1,86 @@ +import { on } from '/@/utils/domUtils' +import { isServer } from '/@/utils/is' +import type { ComponentPublicInstance, DirectiveBinding, ObjectDirective } from 'vue' + +type DocumentHandler = (mouseup: T, mousedown: T) => void + +type FlushList = Map< + HTMLElement, + { + documentHandler: DocumentHandler + bindingFn: (...args: unknown[]) => unknown + } +> + +const nodeList: FlushList = new Map() + +let startClick: MouseEvent + +if (!isServer) { + on(document, 'mousedown', (e: MouseEvent) => (startClick = e)) + on(document, 'mouseup', (e: MouseEvent) => { + for (const { documentHandler } of nodeList.values()) { + documentHandler(e, startClick) + } + }) +} + +function createDocumentHandler(el: HTMLElement, binding: DirectiveBinding): DocumentHandler { + let excludes: HTMLElement[] = [] + if (Array.isArray(binding.arg)) { + excludes = binding.arg + } else { + // due to current implementation on binding type is wrong the type casting is necessary here + excludes.push(binding.arg as unknown as HTMLElement) + } + return function (mouseup, mousedown) { + const popperRef = ( + binding.instance as ComponentPublicInstance<{ + popperRef: Nullable + }> + ).popperRef + const mouseUpTarget = mouseup.target as Node + const mouseDownTarget = mousedown.target as Node + const isBound = !binding || !binding.instance + const isTargetExists = !mouseUpTarget || !mouseDownTarget + const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget) + const isSelf = el === mouseUpTarget + + const isTargetExcluded = + (excludes.length && excludes.some((item) => item?.contains(mouseUpTarget))) || + (excludes.length && excludes.includes(mouseDownTarget as HTMLElement)) + const isContainedByPopper = + popperRef && (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget)) + if ( + isBound || + isTargetExists || + isContainedByEl || + isSelf || + isTargetExcluded || + isContainedByPopper + ) { + return + } + binding.value() + } +} + +const ClickOutside: ObjectDirective = { + beforeMount(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }) + }, + updated(el, binding) { + nodeList.set(el, { + documentHandler: createDocumentHandler(el, binding), + bindingFn: binding.value, + }) + }, + unmounted(el) { + nodeList.delete(el) + }, +} + +export default ClickOutside diff --git a/frontend/vben/src/directives/index.ts b/frontend/vben/src/directives/index.ts new file mode 100644 index 0000000..11df442 --- /dev/null +++ b/frontend/vben/src/directives/index.ts @@ -0,0 +1,11 @@ +/** + * Configure and register global directives + */ +import type { App } from 'vue' +import { setupPermissionDirective } from './permission' +import { setupLoadingDirective } from './loading' + +export function setupGlobDirectives(app: App) { + setupPermissionDirective(app) + setupLoadingDirective(app) +} diff --git a/frontend/vben/src/directives/loading.ts b/frontend/vben/src/directives/loading.ts new file mode 100644 index 0000000..4b445a6 --- /dev/null +++ b/frontend/vben/src/directives/loading.ts @@ -0,0 +1,39 @@ +import { createLoading } from '/@/components/Loading' +import type { Directive, App } from 'vue' + +const loadingDirective: Directive = { + mounted(el, binding) { + const tip = el.getAttribute('loading-tip') + const background = el.getAttribute('loading-background') + const size = el.getAttribute('loading-size') + const fullscreen = !!binding.modifiers.fullscreen + const instance = createLoading( + { + tip, + background, + size: size || 'large', + loading: !!binding.value, + absolute: !fullscreen, + }, + fullscreen ? document.body : el, + ) + el.instance = instance + }, + updated(el, binding) { + const instance = el.instance + if (!instance) return + instance.setTip(el.getAttribute('loading-tip')) + if (binding.oldValue !== binding.value) { + instance.setLoading?.(binding.value && !instance.loading) + } + }, + unmounted(el) { + el?.instance?.close() + }, +} + +export function setupLoadingDirective(app: App) { + app.directive('loading', loadingDirective) +} + +export default loadingDirective diff --git a/frontend/vben/src/directives/permission.ts b/frontend/vben/src/directives/permission.ts new file mode 100644 index 0000000..dbdf540 --- /dev/null +++ b/frontend/vben/src/directives/permission.ts @@ -0,0 +1,32 @@ +/** + * Global authority directive + * Used for fine-grained control of component permissions + * @Example v-auth="RoleEnum.TEST" + */ +import type { App, Directive, DirectiveBinding } from 'vue' + +import { usePermission } from '/@/hooks/web/usePermission' + +function isAuth(el: Element, binding: any) { + const { hasPermission } = usePermission() + + const value = binding.value + if (!value) return + if (!hasPermission(value)) { + el.parentNode?.removeChild(el) + } +} + +const mounted = (el: Element, binding: DirectiveBinding) => { + isAuth(el, binding) +} + +const authDirective: Directive = { + mounted, +} + +export function setupPermissionDirective(app: App) { + app.directive('auth', authDirective) +} + +export default authDirective diff --git a/frontend/vben/src/directives/repeatClick.ts b/frontend/vben/src/directives/repeatClick.ts new file mode 100644 index 0000000..9324e9e --- /dev/null +++ b/frontend/vben/src/directives/repeatClick.ts @@ -0,0 +1,31 @@ +/** + * Prevent repeated clicks + * @Example v-repeat-click="()=>{}" + */ +import { on, once } from '/@/utils/domUtils' +import type { Directive, DirectiveBinding } from 'vue' + +const repeatDirective: Directive = { + beforeMount(el: Element, binding: DirectiveBinding) { + let interval: Nullable = null + let startTime = 0 + const handler = (): void => binding?.value() + const clear = (): void => { + if (Date.now() - startTime < 100) { + handler() + } + interval && clearInterval(interval) + interval = null + } + + on(el, 'mousedown', (e: MouseEvent): void => { + if ((e as any).button !== 0) return + startTime = Date.now() + once(document as any, 'mouseup', clear) + interval && clearInterval(interval) + interval = setInterval(handler, 100) + }) + }, +} + +export default repeatDirective diff --git a/frontend/vben/src/directives/ripple/index.less b/frontend/vben/src/directives/ripple/index.less new file mode 100644 index 0000000..9c0718e --- /dev/null +++ b/frontend/vben/src/directives/ripple/index.less @@ -0,0 +1,21 @@ +.ripple-container { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; + overflow: hidden; + pointer-events: none; +} + +.ripple-effect { + position: relative; + z-index: 9999; + width: 1px; + height: 1px; + margin-top: 0; + margin-left: 0; + pointer-events: none; + border-radius: 50%; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); +} diff --git a/frontend/vben/src/directives/ripple/index.ts b/frontend/vben/src/directives/ripple/index.ts new file mode 100644 index 0000000..bc88992 --- /dev/null +++ b/frontend/vben/src/directives/ripple/index.ts @@ -0,0 +1,191 @@ +import type { Directive } from 'vue' +import './index.less' +export interface RippleOptions { + event: string + transition: number +} + +export interface RippleProto { + background?: string + zIndex?: string +} + +export type EventType = Event & MouseEvent & TouchEvent + +const options: RippleOptions = { + event: 'mousedown', + transition: 400, +} + +const RippleDirective: Directive & RippleProto = { + beforeMount: (el: HTMLElement, binding) => { + if (binding.value === false) return + + const bg = el.getAttribute('ripple-background') + setProps(Object.keys(binding.modifiers), options) + + const background = bg || RippleDirective.background + const zIndex = RippleDirective.zIndex + + el.addEventListener(options.event, (event: EventType) => { + rippler({ + event, + el, + background, + zIndex, + }) + }) + }, + updated(el, binding) { + if (!binding.value) { + el?.clearRipple?.() + return + } + const bg = el.getAttribute('ripple-background') + el?.setBackground?.(bg) + }, +} + +function rippler({ + event, + el, + zIndex, + background, +}: { event: EventType; el: HTMLElement } & RippleProto) { + const targetBorder = parseInt(getComputedStyle(el).borderWidth.replace('px', '')) + const clientX = event.clientX || event.touches[0].clientX + const clientY = event.clientY || event.touches[0].clientY + + const rect = el.getBoundingClientRect() + const { left, top } = rect + const { offsetWidth: width, offsetHeight: height } = el + const { transition } = options + const dx = clientX - left + const dy = clientY - top + const maxX = Math.max(dx, width - dx) + const maxY = Math.max(dy, height - dy) + const style = window.getComputedStyle(el) + const radius = Math.sqrt(maxX * maxX + maxY * maxY) + const border = targetBorder > 0 ? targetBorder : 0 + + const ripple = document.createElement('div') + const rippleContainer = document.createElement('div') + + // Styles for ripple + ripple.className = 'ripple' + + Object.assign(ripple.style ?? {}, { + marginTop: '0px', + marginLeft: '0px', + width: '1px', + height: '1px', + transition: `all ${transition}ms cubic-bezier(0.4, 0, 0.2, 1)`, + borderRadius: '50%', + pointerEvents: 'none', + position: 'relative', + zIndex: zIndex ?? '9999', + backgroundColor: background ?? 'rgba(0, 0, 0, 0.12)', + }) + + // Styles for rippleContainer + rippleContainer.className = 'ripple-container' + Object.assign(rippleContainer.style ?? {}, { + position: 'absolute', + left: `${0 - border}px`, + top: `${0 - border}px`, + height: '0', + width: '0', + pointerEvents: 'none', + overflow: 'hidden', + }) + + const storedTargetPosition = + el.style.position.length > 0 ? el.style.position : getComputedStyle(el).position + + if (storedTargetPosition !== 'relative') { + el.style.position = 'relative' + } + + rippleContainer.appendChild(ripple) + el.appendChild(rippleContainer) + + Object.assign(ripple.style, { + marginTop: `${dy}px`, + marginLeft: `${dx}px`, + }) + + const { + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + } = style + Object.assign(rippleContainer.style, { + width: `${width}px`, + height: `${height}px`, + direction: 'ltr', + borderTopLeftRadius, + borderTopRightRadius, + borderBottomLeftRadius, + borderBottomRightRadius, + }) + + setTimeout(() => { + const wh = `${radius * 2}px` + Object.assign(ripple.style ?? {}, { + width: wh, + height: wh, + marginLeft: `${dx - radius}px`, + marginTop: `${dy - radius}px`, + }) + }, 0) + + function clearRipple() { + setTimeout(() => { + ripple.style.backgroundColor = 'rgba(0, 0, 0, 0)' + }, 250) + + setTimeout(() => { + rippleContainer?.parentNode?.removeChild(rippleContainer) + }, 850) + el.removeEventListener('mouseup', clearRipple, false) + el.removeEventListener('mouseleave', clearRipple, false) + el.removeEventListener('dragstart', clearRipple, false) + setTimeout(() => { + let clearPosition = true + for (let i = 0; i < el.childNodes.length; i++) { + if ((el.childNodes[i] as Recordable).className === 'ripple-container') { + clearPosition = false + } + } + + if (clearPosition) { + el.style.position = storedTargetPosition !== 'static' ? storedTargetPosition : '' + } + }, options.transition + 260) + } + + if (event.type === 'mousedown') { + el.addEventListener('mouseup', clearRipple, false) + el.addEventListener('mouseleave', clearRipple, false) + el.addEventListener('dragstart', clearRipple, false) + } else { + clearRipple() + } + + ;(el as Recordable).setBackground = (bgColor: string) => { + if (!bgColor) { + return + } + ripple.style.backgroundColor = bgColor + } +} + +function setProps(modifiers: Recordable, props: Recordable) { + modifiers.forEach((item: Recordable) => { + if (isNaN(Number(item))) props.event = item + else props.transition = item + }) +} + +export default RippleDirective diff --git a/frontend/vben/src/enums/appEnum.ts b/frontend/vben/src/enums/appEnum.ts new file mode 100644 index 0000000..0b3a1ae --- /dev/null +++ b/frontend/vben/src/enums/appEnum.ts @@ -0,0 +1,52 @@ +export const SIDE_BAR_MINI_WIDTH = 48 +export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80 + +export enum ContentEnum { + // auto width + FULL = 'full', + // fixed width + FIXED = 'fixed', +} + +// menu theme enum +export enum ThemeEnum { + DARK = 'dark', + LIGHT = 'light', +} + +export enum SettingButtonPositionEnum { + AUTO = 'auto', + HEADER = 'header', + FIXED = 'fixed', +} + +export enum SessionTimeoutProcessingEnum { + ROUTE_JUMP, + PAGE_COVERAGE, +} + +/** + * 权限模式 + */ +export enum PermissionModeEnum { + // role + // 角色权限 + ROLE = 'ROLE', + // black + // 后端 + BACK = 'BACK', + // route mapping + // 路由映射 + ROUTE_MAPPING = 'ROUTE_MAPPING', +} + +// Route switching animation +// 路由切换动画 +export enum RouterTransitionEnum { + ZOOM_FADE = 'zoom-fade', + ZOOM_OUT = 'zoom-out', + FADE_SIDE = 'fade-slide', + FADE = 'fade', + FADE_BOTTOM = 'fade-bottom', + FADE_SCALE = 'fade-scale', +} diff --git a/frontend/vben/src/enums/breakpointEnum.ts b/frontend/vben/src/enums/breakpointEnum.ts new file mode 100644 index 0000000..fa42ea3 --- /dev/null +++ b/frontend/vben/src/enums/breakpointEnum.ts @@ -0,0 +1,28 @@ +export enum sizeEnum { + XS = 'XS', + SM = 'SM', + MD = 'MD', + LG = 'LG', + XL = 'XL', + XXL = 'XXL', +} + +export enum screenEnum { + XS = 480, + SM = 576, + MD = 768, + LG = 992, + XL = 1200, + XXL = 1600, +} + +const screenMap = new Map() + +screenMap.set(sizeEnum.XS, screenEnum.XS) +screenMap.set(sizeEnum.SM, screenEnum.SM) +screenMap.set(sizeEnum.MD, screenEnum.MD) +screenMap.set(sizeEnum.LG, screenEnum.LG) +screenMap.set(sizeEnum.XL, screenEnum.XL) +screenMap.set(sizeEnum.XXL, screenEnum.XXL) + +export { screenMap } diff --git a/frontend/vben/src/enums/cacheEnum.ts b/frontend/vben/src/enums/cacheEnum.ts new file mode 100644 index 0000000..c7d59b9 --- /dev/null +++ b/frontend/vben/src/enums/cacheEnum.ts @@ -0,0 +1,28 @@ +// token key +export const TOKEN_KEY = 'TOKEN__' + +export const LOCALE_KEY = 'LOCALE__' + +// user info key +export const USER_INFO_KEY = 'USER__INFO__' + +// role info key +export const ROLES_KEY = 'ROLES__KEY__' + +// project config key +export const PROJ_CFG_KEY = 'PROJ__CFG__KEY__' + +export const MULTIPLE_TABS_KEY = 'MULTIPLE_TABS__KEY__' + +export const APP_DARK_MODE_KEY_ = '__APP__DARK__MODE__' + +// base global local key +export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__' + +// base global session key +export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__' + +export enum CacheTypeEnum { + SESSION, + LOCAL, +} diff --git a/frontend/vben/src/enums/exceptionEnum.ts b/frontend/vben/src/enums/exceptionEnum.ts new file mode 100644 index 0000000..d28f4d0 --- /dev/null +++ b/frontend/vben/src/enums/exceptionEnum.ts @@ -0,0 +1,27 @@ +/** + * @description: Exception related enumeration + */ +export enum ExceptionEnum { + // page not access + PAGE_NOT_ACCESS = 403, + + // page not found + PAGE_NOT_FOUND = 404, + + // error + ERROR = 500, + + // net work error + NET_WORK_ERROR = 10000, + + // No data on the page. In fact, it is not an exception page + PAGE_NOT_DATA = 10100, +} + +export enum ErrorTypeEnum { + VUE = 'vue', + SCRIPT = 'script', + RESOURCE = 'resource', + AJAX = 'ajax', + PROMISE = 'promise', +} diff --git a/frontend/vben/src/enums/httpEnum.ts b/frontend/vben/src/enums/httpEnum.ts new file mode 100644 index 0000000..c7548cc --- /dev/null +++ b/frontend/vben/src/enums/httpEnum.ts @@ -0,0 +1,31 @@ +/** + * @description: Request result set + */ +export enum ResultEnum { + SUCCESS = 0, + ERROR = -1, + TIMEOUT = 401, + TYPE = 'success', +} + +/** + * @description: request method + */ +export enum RequestEnum { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +/** + * @description: contentType + */ +export enum ContentTypeEnum { + // json + JSON = 'application/json;charset=UTF-8', + // form-data qs + FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', + // form-data upload + FORM_DATA = 'multipart/form-data;charset=UTF-8', +} diff --git a/frontend/vben/src/enums/menuEnum.ts b/frontend/vben/src/enums/menuEnum.ts new file mode 100644 index 0000000..215c849 --- /dev/null +++ b/frontend/vben/src/enums/menuEnum.ts @@ -0,0 +1,50 @@ +/** + * @description: menu type + */ +export enum MenuTypeEnum { + // left menu + SIDEBAR = 'sidebar', + + MIX_SIDEBAR = 'mix-sidebar', + // mixin menu + MIX = 'mix', + // top menu + TOP_MENU = 'top-menu', +} + +// 折叠触发器位置 +export enum TriggerEnum { + // 不显示 + NONE = 'NONE', + // 菜单底部 + FOOTER = 'FOOTER', + // 头部 + HEADER = 'HEADER', +} + +export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline' + +// menu mode +export enum MenuModeEnum { + VERTICAL = 'vertical', + HORIZONTAL = 'horizontal', + VERTICAL_RIGHT = 'vertical-right', + INLINE = 'inline', +} + +export enum MenuSplitTyeEnum { + NONE, + TOP, + LEFT, +} + +export enum TopMenuAlignEnum { + CENTER = 'center', + START = 'start', + END = 'end', +} + +export enum MixSidebarTriggerEnum { + HOVER = 'hover', + CLICK = 'click', +} diff --git a/frontend/vben/src/enums/pageEnum.ts b/frontend/vben/src/enums/pageEnum.ts new file mode 100644 index 0000000..c7ca363 --- /dev/null +++ b/frontend/vben/src/enums/pageEnum.ts @@ -0,0 +1,10 @@ +export enum PageEnum { + // basic login path + BASE_LOGIN = '/login', + // basic home path + BASE_HOME = '/dashboard', + // error page path + ERROR_PAGE = '/exception', + // error log page path + ERROR_LOG_PAGE = '/error-log/list', +} diff --git a/frontend/vben/src/enums/roleEnum.ts b/frontend/vben/src/enums/roleEnum.ts new file mode 100644 index 0000000..857868d --- /dev/null +++ b/frontend/vben/src/enums/roleEnum.ts @@ -0,0 +1,7 @@ +export enum RoleEnum { + // super admin + SUPER = 'super', + + // tester + TEST = 'test', +} diff --git a/frontend/vben/src/enums/sizeEnum.ts b/frontend/vben/src/enums/sizeEnum.ts new file mode 100644 index 0000000..73b8409 --- /dev/null +++ b/frontend/vben/src/enums/sizeEnum.ts @@ -0,0 +1,19 @@ +export enum SizeEnum { + DEFAULT = 'default', + SMALL = 'small', + LARGE = 'large', +} + +export enum SizeNumberEnum { + DEFAULT = 48, + SMALL = 16, + LARGE = 64, +} + +export const sizeMap: Map = (() => { + const map = new Map() + map.set(SizeEnum.DEFAULT, SizeNumberEnum.DEFAULT) + map.set(SizeEnum.SMALL, SizeNumberEnum.SMALL) + map.set(SizeEnum.LARGE, SizeNumberEnum.LARGE) + return map +})() diff --git a/frontend/vben/src/hooks/component/useFormItem.ts b/frontend/vben/src/hooks/component/useFormItem.ts new file mode 100644 index 0000000..43f5524 --- /dev/null +++ b/frontend/vben/src/hooks/component/useFormItem.ts @@ -0,0 +1,60 @@ +import type { UnwrapRef, Ref, WritableComputedRef, DeepReadonly } from 'vue' +import { + reactive, + readonly, + computed, + getCurrentInstance, + watchEffect, + unref, + nextTick, + toRaw, +} from 'vue' + +import { isEqual } from 'lodash-es' + +export function useRuleFormItem>( + props: T, + key?: K, + changeEvent?, + emitData?: Ref, +): [WritableComputedRef, (val: V) => void, DeepReadonly] + +export function useRuleFormItem( + props: T, + key: keyof T = 'value', + changeEvent = 'change', + emitData?: Ref, +) { + const instance = getCurrentInstance() + const emit = instance?.emit + + const innerState = reactive({ + value: props[key], + }) + + const defaultState = readonly(innerState) + + const setState = (val: UnwrapRef): void => { + innerState.value = val as T[keyof T] + } + + watchEffect(() => { + innerState.value = props[key] + }) + + const state: any = computed({ + get() { + return innerState.value + }, + set(value) { + if (isEqual(value, defaultState.value)) return + + innerState.value = value as T[keyof T] + nextTick(() => { + emit?.(changeEvent, value, ...(toRaw(unref(emitData)) || [])) + }) + }, + }) + + return [state, setState, defaultState] +} diff --git a/frontend/vben/src/hooks/component/usePageContext.ts b/frontend/vben/src/hooks/component/usePageContext.ts new file mode 100644 index 0000000..7e78b4d --- /dev/null +++ b/frontend/vben/src/hooks/component/usePageContext.ts @@ -0,0 +1,18 @@ +import type { InjectionKey, ComputedRef, Ref } from 'vue' +import { createContext, useContext } from '/@/hooks/core/useContext' + +export interface PageContextProps { + contentHeight: ComputedRef + pageHeight: Ref + setPageHeight: (height: number) => Promise +} + +const key: InjectionKey = Symbol() + +export function createPageContext(context: PageContextProps) { + return createContext(context, key, { native: true }) +} + +export function usePageContext() { + return useContext(key) +} diff --git a/frontend/vben/src/hooks/core/onMountedOrActivated.ts b/frontend/vben/src/hooks/core/onMountedOrActivated.ts new file mode 100644 index 0000000..2c92181 --- /dev/null +++ b/frontend/vben/src/hooks/core/onMountedOrActivated.ts @@ -0,0 +1,18 @@ +import { nextTick, onMounted, onActivated } from 'vue' + +export function onMountedOrActivated(hook: Fn) { + let mounted: boolean + + onMounted(() => { + hook() + nextTick(() => { + mounted = true + }) + }) + + onActivated(() => { + if (mounted) { + hook() + } + }) +} diff --git a/frontend/vben/src/hooks/core/useAttrs.ts b/frontend/vben/src/hooks/core/useAttrs.ts new file mode 100644 index 0000000..1bd3509 --- /dev/null +++ b/frontend/vben/src/hooks/core/useAttrs.ts @@ -0,0 +1,40 @@ +import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue' +import type { Ref } from 'vue' +interface Params { + excludeListeners?: boolean + excludeKeys?: string[] + excludeDefaultKeys?: boolean +} + +const DEFAULT_EXCLUDE_KEYS = ['class', 'style'] +const LISTENER_PREFIX = /^on[A-Z]/ + +export function entries(obj: Recordable): [string, T][] { + return Object.keys(obj).map((key: string) => [key, obj[key]]) +} + +export function useAttrs(params: Params = {}): Ref | {} { + const instance = getCurrentInstance() + if (!instance) return {} + + const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = params + const attrs = shallowRef({}) + const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []) + + // Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance + instance.attrs = reactive(instance.attrs) + + watchEffect(() => { + const res = entries(instance.attrs).reduce((acm, [key, val]) => { + if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) { + acm[key] = val + } + + return acm + }, {} as Recordable) + + attrs.value = res + }) + + return attrs +} diff --git a/frontend/vben/src/hooks/core/useContext.ts b/frontend/vben/src/hooks/core/useContext.ts new file mode 100644 index 0000000..f138960 --- /dev/null +++ b/frontend/vben/src/hooks/core/useContext.ts @@ -0,0 +1,44 @@ +import { + InjectionKey, + provide, + inject, + reactive, + readonly as defineReadonly, + // defineComponent, + UnwrapRef, +} from 'vue' + +export interface CreateContextOptions { + readonly?: boolean + createProvider?: boolean + native?: boolean +} + +type ShallowUnwrap = { + [P in keyof T]: UnwrapRef +} + +export function createContext( + context: any, + key: InjectionKey = Symbol(), + options: CreateContextOptions = {}, +) { + const { readonly = true, createProvider = false, native = false } = options + + const state = reactive(context) + const provideData = readonly ? defineReadonly(state) : state + !createProvider && provide(key, native ? context : provideData) + + return { + state, + } +} + +export function useContext(key: InjectionKey, native?: boolean): T + +export function useContext( + key: InjectionKey = Symbol(), + defaultValue?: any, +): ShallowUnwrap { + return inject(key, defaultValue || {}) +} diff --git a/frontend/vben/src/hooks/core/useRefs.ts b/frontend/vben/src/hooks/core/useRefs.ts new file mode 100644 index 0000000..6ffb351 --- /dev/null +++ b/frontend/vben/src/hooks/core/useRefs.ts @@ -0,0 +1,16 @@ +import type { Ref } from 'vue' +import { ref, onBeforeUpdate } from 'vue' + +export function useRefs(): [Ref, (index: number) => (el: HTMLElement) => void] { + const refs = ref([]) as Ref + + onBeforeUpdate(() => { + refs.value = [] + }) + + const setRefs = (index: number) => (el: HTMLElement) => { + refs.value[index] = el + } + + return [refs, setRefs] +} diff --git a/frontend/vben/src/hooks/core/useTimeout.ts b/frontend/vben/src/hooks/core/useTimeout.ts new file mode 100644 index 0000000..6bb0f5c --- /dev/null +++ b/frontend/vben/src/hooks/core/useTimeout.ts @@ -0,0 +1,45 @@ +import { ref, watch } from 'vue' +import { tryOnUnmounted } from '@vueuse/core' +import { isFunction } from '/@/utils/is' + +export function useTimeoutFn(handle: Fn, wait: number, native = false) { + if (!isFunction(handle)) { + throw new Error('handle is not Function!') + } + + const { readyRef, stop, start } = useTimeoutRef(wait) + if (native) { + handle() + } else { + watch( + readyRef, + (maturity) => { + maturity && handle() + }, + { immediate: false }, + ) + } + return { readyRef, stop, start } +} + +export function useTimeoutRef(wait: number) { + const readyRef = ref(false) + + let timer: TimeoutHandle + function stop(): void { + readyRef.value = false + timer && window.clearTimeout(timer) + } + function start(): void { + stop() + timer = setTimeout(() => { + readyRef.value = true + }, wait) + } + + start() + + tryOnUnmounted(stop) + + return { readyRef, stop, start } +} diff --git a/frontend/vben/src/hooks/event/useBreakpoint.ts b/frontend/vben/src/hooks/event/useBreakpoint.ts new file mode 100644 index 0000000..343e1f5 --- /dev/null +++ b/frontend/vben/src/hooks/event/useBreakpoint.ts @@ -0,0 +1,89 @@ +import { ref, computed, ComputedRef, unref } from 'vue' +import { useEventListener } from '/@/hooks/event/useEventListener' +import { screenMap, sizeEnum, screenEnum } from '/@/enums/breakpointEnum' + +let globalScreenRef: ComputedRef +let globalWidthRef: ComputedRef +let globalRealWidthRef: ComputedRef + +export interface CreateCallbackParams { + screen: ComputedRef + width: ComputedRef + realWidth: ComputedRef + screenEnum: typeof screenEnum + screenMap: Map + sizeEnum: typeof sizeEnum +} + +export function useBreakpoint() { + return { + screenRef: computed(() => unref(globalScreenRef)), + widthRef: globalWidthRef, + screenEnum, + realWidthRef: globalRealWidthRef, + } +} + +// Just call it once +export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void) { + const screenRef = ref(sizeEnum.XL) + const realWidthRef = ref(window.innerWidth) + + function getWindowWidth() { + const width = document.body.clientWidth + const xs = screenMap.get(sizeEnum.XS)! + const sm = screenMap.get(sizeEnum.SM)! + const md = screenMap.get(sizeEnum.MD)! + const lg = screenMap.get(sizeEnum.LG)! + const xl = screenMap.get(sizeEnum.XL)! + if (width < xs) { + screenRef.value = sizeEnum.XS + } else if (width < sm) { + screenRef.value = sizeEnum.SM + } else if (width < md) { + screenRef.value = sizeEnum.MD + } else if (width < lg) { + screenRef.value = sizeEnum.LG + } else if (width < xl) { + screenRef.value = sizeEnum.XL + } else { + screenRef.value = sizeEnum.XXL + } + realWidthRef.value = width + } + + useEventListener({ + el: window, + name: 'resize', + + listener: () => { + getWindowWidth() + resizeFn() + }, + // wait: 100, + }) + + getWindowWidth() + globalScreenRef = computed(() => unref(screenRef)) + globalWidthRef = computed((): number => screenMap.get(unref(screenRef)!)!) + globalRealWidthRef = computed((): number => unref(realWidthRef)) + + function resizeFn() { + fn?.({ + screen: globalScreenRef, + width: globalWidthRef, + realWidth: globalRealWidthRef, + screenEnum, + screenMap, + sizeEnum, + }) + } + + resizeFn() + return { + screenRef: globalScreenRef, + screenEnum, + widthRef: globalWidthRef, + realWidthRef: globalRealWidthRef, + } +} diff --git a/frontend/vben/src/hooks/event/useEventListener.ts b/frontend/vben/src/hooks/event/useEventListener.ts new file mode 100644 index 0000000..6926eef --- /dev/null +++ b/frontend/vben/src/hooks/event/useEventListener.ts @@ -0,0 +1,58 @@ +import type { Ref } from 'vue' +import { ref, watch, unref } from 'vue' +import { useThrottleFn, useDebounceFn } from '@vueuse/core' + +export type RemoveEventFn = () => void +export interface UseEventParams { + el?: Element | Ref | Window | any + name: string + listener: EventListener + options?: boolean | AddEventListenerOptions + autoRemove?: boolean + isDebounce?: boolean + wait?: number +} +export function useEventListener({ + el = window, + name, + listener, + options, + autoRemove = true, + isDebounce = true, + wait = 80, +}: UseEventParams): { removeEvent: RemoveEventFn } { + /* eslint-disable-next-line */ + let remove: RemoveEventFn = () => {} + const isAddRef = ref(false) + + if (el) { + const element = ref(el as Element) as Ref + + const handler = isDebounce ? useDebounceFn(listener, wait) : useThrottleFn(listener, wait) + const realHandler = wait ? handler : listener + const removeEventListener = (e: Element) => { + isAddRef.value = true + e.removeEventListener(name, realHandler, options) + } + const addEventListener = (e: Element) => e.addEventListener(name, realHandler, options) + + const removeWatch = watch( + element, + (v, _ov, cleanUp) => { + if (v) { + !unref(isAddRef) && addEventListener(v) + cleanUp(() => { + autoRemove && removeEventListener(v) + }) + } + }, + { immediate: true }, + ) + + remove = () => { + removeEventListener(element.value) + removeWatch() + } + } + return { removeEvent: remove } +} diff --git a/frontend/vben/src/hooks/event/useIntersectionObserver.ts b/frontend/vben/src/hooks/event/useIntersectionObserver.ts new file mode 100644 index 0000000..9329366 --- /dev/null +++ b/frontend/vben/src/hooks/event/useIntersectionObserver.ts @@ -0,0 +1,48 @@ +import { Ref, watchEffect, ref } from 'vue' + +interface IntersectionObserverProps { + target: Ref + root?: Ref + onIntersect: IntersectionObserverCallback + rootMargin?: string + threshold?: number +} + +export function useIntersectionObserver({ + target, + root, + onIntersect, + rootMargin = '0px', + threshold = 0.1, +}: IntersectionObserverProps) { + let cleanup = () => {} + const observer: Ref> = ref(null) + const stopEffect = watchEffect(() => { + cleanup() + + observer.value = new IntersectionObserver(onIntersect, { + root: root ? root.value : null, + rootMargin, + threshold, + }) + + const current = target.value + + current && observer.value.observe(current) + + cleanup = () => { + if (observer.value) { + observer.value.disconnect() + target.value && observer.value.unobserve(target.value) + } + } + }) + + return { + observer, + stop: () => { + cleanup() + stopEffect() + }, + } +} diff --git a/frontend/vben/src/hooks/event/useScroll.ts b/frontend/vben/src/hooks/event/useScroll.ts new file mode 100644 index 0000000..b82c46f --- /dev/null +++ b/frontend/vben/src/hooks/event/useScroll.ts @@ -0,0 +1,65 @@ +import type { Ref } from 'vue' + +import { ref, onMounted, watch, onUnmounted } from 'vue' +import { isWindow, isObject } from '/@/utils/is' +import { useThrottleFn } from '@vueuse/core' + +export function useScroll( + refEl: Ref, + options?: { + wait?: number + leading?: boolean + trailing?: boolean + }, +) { + const refX = ref(0) + const refY = ref(0) + let handler = () => { + if (isWindow(refEl.value)) { + refX.value = refEl.value.scrollX + refY.value = refEl.value.scrollY + } else if (refEl.value) { + refX.value = (refEl.value as Element).scrollLeft + refY.value = (refEl.value as Element).scrollTop + } + } + + if (isObject(options)) { + let wait = 0 + if (options.wait && options.wait > 0) { + wait = options.wait + Reflect.deleteProperty(options, 'wait') + } + + handler = useThrottleFn(handler, wait) + } + + let stopWatch: () => void + onMounted(() => { + stopWatch = watch( + refEl, + (el, prevEl, onCleanup) => { + if (el) { + el.addEventListener('scroll', handler) + } else if (prevEl) { + prevEl.removeEventListener('scroll', handler) + } + onCleanup(() => { + refX.value = refY.value = 0 + el && el.removeEventListener('scroll', handler) + }) + }, + { immediate: true }, + ) + }) + + onUnmounted(() => { + refEl.value && refEl.value.removeEventListener('scroll', handler) + }) + + function stop() { + stopWatch && stopWatch() + } + + return { refX, refY, stop } +} diff --git a/frontend/vben/src/hooks/event/useScrollTo.ts b/frontend/vben/src/hooks/event/useScrollTo.ts new file mode 100644 index 0000000..6e1b455 --- /dev/null +++ b/frontend/vben/src/hooks/event/useScrollTo.ts @@ -0,0 +1,59 @@ +import { isFunction, isUnDef } from '/@/utils/is' +import { ref, unref } from 'vue' + +export interface ScrollToParams { + el: any + to: number + duration?: number + callback?: () => any +} + +const easeInOutQuad = (t: number, b: number, c: number, d: number) => { + t /= d / 2 + if (t < 1) { + return (c / 2) * t * t + b + } + t-- + return (-c / 2) * (t * (t - 2) - 1) + b +} +const move = (el: HTMLElement, amount: number) => { + el.scrollTop = amount +} + +const position = (el: HTMLElement) => { + return el.scrollTop +} +export function useScrollTo({ el, to, duration = 500, callback }: ScrollToParams) { + const isActiveRef = ref(false) + const start = position(el) + const change = to - start + const increment = 20 + let currentTime = 0 + duration = isUnDef(duration) ? 500 : duration + + const animateScroll = function () { + if (!unref(isActiveRef)) { + return + } + currentTime += increment + const val = easeInOutQuad(currentTime, start, change, duration) + move(el, val) + if (currentTime < duration && unref(isActiveRef)) { + requestAnimationFrame(animateScroll) + } else { + if (callback && isFunction(callback)) { + callback() + } + } + } + const run = () => { + isActiveRef.value = true + animateScroll() + } + + const stop = () => { + isActiveRef.value = false + } + + return { start: run, stop } +} diff --git a/frontend/vben/src/hooks/event/useWindowSizeFn.ts b/frontend/vben/src/hooks/event/useWindowSizeFn.ts new file mode 100644 index 0000000..14c437c --- /dev/null +++ b/frontend/vben/src/hooks/event/useWindowSizeFn.ts @@ -0,0 +1,35 @@ +import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core' + +interface WindowSizeOptions { + once?: boolean + immediate?: boolean + listenerOptions?: AddEventListenerOptions | boolean +} + +export function useWindowSizeFn(fn: Fn, wait = 150, options?: WindowSizeOptions) { + let handler = () => { + fn() + } + const handleSize = useDebounceFn(handler, wait) + handler = handleSize + + const start = () => { + if (options && options.immediate) { + handler() + } + window.addEventListener('resize', handler) + } + + const stop = () => { + window.removeEventListener('resize', handler) + } + + tryOnMounted(() => { + start() + }) + + tryOnUnmounted(() => { + stop() + }) + return [start, stop] +} diff --git a/frontend/vben/src/hooks/setting/index.ts b/frontend/vben/src/hooks/setting/index.ts new file mode 100644 index 0000000..d0780db --- /dev/null +++ b/frontend/vben/src/hooks/setting/index.ts @@ -0,0 +1,30 @@ +import type { GlobConfig } from '/#/config' + +import { warn } from '/@/utils/log' +import { getAppEnvConfig } from '/@/utils/env' + +export const useGlobSetting = (): Readonly => { + const { + VITE_GLOB_APP_TITLE, + VITE_GLOB_API_URL, + VITE_GLOB_APP_SHORT_NAME, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + } = getAppEnvConfig() + + if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) { + warn( + `VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`, + ) + } + + // Take global configuration + const glob: Readonly = { + title: VITE_GLOB_APP_TITLE, + apiUrl: VITE_GLOB_API_URL, + shortName: VITE_GLOB_APP_SHORT_NAME, + urlPrefix: VITE_GLOB_API_URL_PREFIX, + uploadUrl: VITE_GLOB_UPLOAD_URL, + } + return glob as Readonly +} diff --git a/frontend/vben/src/hooks/setting/useHeaderSetting.ts b/frontend/vben/src/hooks/setting/useHeaderSetting.ts new file mode 100644 index 0000000..bbb8f89 --- /dev/null +++ b/frontend/vben/src/hooks/setting/useHeaderSetting.ts @@ -0,0 +1,102 @@ +import type { HeaderSetting } from '/#/config' + +import { computed, unref } from 'vue' + +import { useAppStore } from '/@/store/modules/app' + +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting' +import { useRootSetting } from '/@/hooks/setting/useRootSetting' +import { useFullContent } from '/@/hooks/web/useFullContent' +import { MenuModeEnum } from '/@/enums/menuEnum' + +export function useHeaderSetting() { + const { getFullContent } = useFullContent() + const appStore = useAppStore() + + const getShowFullHeaderRef = computed(() => { + return ( + !unref(getFullContent) && + unref(getShowMixHeaderRef) && + unref(getShowHeader) && + !unref(getIsTopMenu) && + !unref(getIsMixSidebar) + ) + }) + + const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef)) + + const getShowInsetHeaderRef = computed(() => { + const need = !unref(getFullContent) && unref(getShowHeader) + return ( + (need && !unref(getShowMixHeaderRef)) || + (need && unref(getIsTopMenu)) || + (need && unref(getIsMixSidebar)) + ) + }) + + const { + getMenuMode, + getSplit, + getShowHeaderTrigger, + getIsSidebarType, + getIsMixSidebar, + getIsTopMenu, + } = useMenuSetting() + const { getShowBreadCrumb, getShowLogo } = useRootSetting() + + const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader)) + + const getShowDoc = computed(() => appStore.getHeaderSetting.showDoc) + + const getHeaderTheme = computed(() => appStore.getHeaderSetting.theme) + + const getShowHeader = computed(() => appStore.getHeaderSetting.show) + + const getFixed = computed(() => appStore.getHeaderSetting.fixed) + + const getHeaderBgColor = computed(() => appStore.getHeaderSetting.bgColor) + + const getShowSearch = computed(() => appStore.getHeaderSetting.showSearch) + + const getShowFullScreen = computed(() => appStore.getHeaderSetting.showFullScreen) + + const getShowNotice = computed(() => appStore.getHeaderSetting.showNotice) + + const getShowBread = computed(() => { + return ( + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit) + ) + }) + + const getShowHeaderLogo = computed(() => { + return unref(getShowLogo) && !unref(getIsSidebarType) && !unref(getIsMixSidebar) + }) + + const getShowContent = computed(() => { + return unref(getShowBread) || unref(getShowHeaderTrigger) + }) + + // Set header configuration + function setHeaderSetting(headerSetting: Partial) { + appStore.setProjectConfig({ headerSetting }) + } + return { + setHeaderSetting, + + getShowDoc, + getShowSearch, + getHeaderTheme, + getShowFullScreen, + getShowNotice, + getShowBread, + getShowContent, + getShowHeaderLogo, + getShowHeader, + getFixed, + getShowMixHeaderRef, + getShowFullHeaderRef, + getShowInsetHeaderRef, + getUnFixedAndFull, + getHeaderBgColor, + } +} diff --git a/frontend/vben/src/hooks/setting/useMenuSetting.ts b/frontend/vben/src/hooks/setting/useMenuSetting.ts new file mode 100644 index 0000000..9d74f1b --- /dev/null +++ b/frontend/vben/src/hooks/setting/useMenuSetting.ts @@ -0,0 +1,164 @@ +import type { MenuSetting } from '/#/config' + +import { computed, unref, ref } from 'vue' + +import { useAppStore } from '/@/store/modules/app' + +import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum' +import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum' +import { useFullContent } from '/@/hooks/web/useFullContent' + +const mixSideHasChildren = ref(false) + +export function useMenuSetting() { + const { getFullContent: fullContent } = useFullContent() + const appStore = useAppStore() + + const getShowSidebar = computed(() => { + return ( + unref(getSplit) || + (unref(getShowMenu) && unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && !unref(fullContent)) + ) + }) + + const getCollapsed = computed(() => appStore.getMenuSetting.collapsed) + + const getMenuType = computed(() => appStore.getMenuSetting.type) + + const getMenuMode = computed(() => appStore.getMenuSetting.mode) + + const getMenuFixed = computed(() => appStore.getMenuSetting.fixed) + + const getShowMenu = computed(() => appStore.getMenuSetting.show) + + const getMenuHidden = computed(() => appStore.getMenuSetting.hidden) + + const getMenuWidth = computed(() => appStore.getMenuSetting.menuWidth) + + const getTrigger = computed(() => appStore.getMenuSetting.trigger) + + const getMenuTheme = computed(() => appStore.getMenuSetting.theme) + + const getSplit = computed(() => appStore.getMenuSetting.split) + + const getMenuBgColor = computed(() => appStore.getMenuSetting.bgColor) + + const getMixSideTrigger = computed(() => appStore.getMenuSetting.mixSideTrigger) + + const getCanDrag = computed(() => appStore.getMenuSetting.canDrag) + + const getAccordion = computed(() => appStore.getMenuSetting.accordion) + + const getMixSideFixed = computed(() => appStore.getMenuSetting.mixSideFixed) + + const getTopMenuAlign = computed(() => appStore.getMenuSetting.topMenuAlign) + + const getCloseMixSidebarOnChange = computed(() => appStore.getMenuSetting.closeMixSidebarOnChange) + + const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR) + + const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU) + + const getCollapsedShowTitle = computed(() => appStore.getMenuSetting.collapsedShowTitle) + + const getShowTopMenu = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit) + }) + + const getShowHeaderTrigger = computed(() => { + if ( + unref(getMenuType) === MenuTypeEnum.TOP_MENU || + !unref(getShowMenu) || + unref(getMenuHidden) + ) { + return false + } + + return unref(getTrigger) === TriggerEnum.HEADER + }) + + const getIsHorizontal = computed(() => { + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL + }) + + const getIsMixSidebar = computed(() => { + return unref(getMenuType) === MenuTypeEnum.MIX_SIDEBAR + }) + + const getIsMixMode = computed(() => { + return unref(getMenuMode) === MenuModeEnum.INLINE && unref(getMenuType) === MenuTypeEnum.MIX + }) + + const getRealWidth = computed(() => { + if (unref(getIsMixSidebar)) { + return unref(getCollapsed) && !unref(getMixSideFixed) + ? unref(getMiniWidthNumber) + : unref(getMenuWidth) + } + return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth) + }) + + const getMiniWidthNumber = computed(() => { + const { collapsedShowTitle, siderHidden } = appStore.getMenuSetting + return siderHidden ? 0 : collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH + }) + + const getCalcContentWidth = computed(() => { + const width = + unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && unref(getMenuHidden)) + ? 0 + : unref(getIsMixSidebar) + ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH) + + (unref(getMixSideFixed) && unref(mixSideHasChildren) ? unref(getRealWidth) : 0) + : unref(getRealWidth) + + return `calc(100% - ${unref(width)}px)` + }) + + // Set menu configuration + function setMenuSetting(menuSetting: Partial): void { + appStore.setProjectConfig({ menuSetting }) + } + + function toggleCollapsed() { + setMenuSetting({ + collapsed: !unref(getCollapsed), + }) + } + return { + setMenuSetting, + + toggleCollapsed, + + getMenuFixed, + getRealWidth, + getMenuType, + getMenuMode, + getShowMenu, + getCollapsed, + getMiniWidthNumber, + getCalcContentWidth, + getMenuWidth, + getTrigger, + getSplit, + getMenuTheme, + getCanDrag, + getCollapsedShowTitle, + getIsHorizontal, + getIsSidebarType, + getAccordion, + getShowTopMenu, + getShowHeaderTrigger, + getTopMenuAlign, + getMenuHidden, + getIsTopMenu, + getMenuBgColor, + getShowSidebar, + getIsMixMode, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + mixSideHasChildren, + } +} diff --git a/frontend/vben/src/hooks/setting/useMultipleTabSetting.ts b/frontend/vben/src/hooks/setting/useMultipleTabSetting.ts new file mode 100644 index 0000000..b8f23f4 --- /dev/null +++ b/frontend/vben/src/hooks/setting/useMultipleTabSetting.ts @@ -0,0 +1,28 @@ +import type { MultiTabsSetting } from '/#/config' + +import { computed } from 'vue' + +import { useAppStore } from '/@/store/modules/app' + +export function useMultipleTabSetting() { + const appStore = useAppStore() + + const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show) + + const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick) + + const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo) + + const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold) + + function setMultipleTabSetting(multiTabsSetting: Partial) { + appStore.setProjectConfig({ multiTabsSetting }) + } + return { + setMultipleTabSetting, + getShowMultipleTab, + getShowQuick, + getShowRedo, + getShowFold, + } +} diff --git a/frontend/vben/src/hooks/setting/useRootSetting.ts b/frontend/vben/src/hooks/setting/useRootSetting.ts new file mode 100644 index 0000000..162617c --- /dev/null +++ b/frontend/vben/src/hooks/setting/useRootSetting.ts @@ -0,0 +1,92 @@ +import type { ProjectConfig } from '/#/config' + +import { computed } from 'vue' + +import { useAppStore } from '/@/store/modules/app' +import { ContentEnum, ThemeEnum } from '/@/enums/appEnum' + +type RootSetting = Omit< + ProjectConfig, + 'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting' +> + +export function useRootSetting() { + const appStore = useAppStore() + + const getPageLoading = computed(() => appStore.getPageLoading) + + const getOpenKeepAlive = computed(() => appStore.getProjectConfig.openKeepAlive) + + const getSettingButtonPosition = computed(() => appStore.getProjectConfig.settingButtonPosition) + + const getCanEmbedIFramePage = computed(() => appStore.getProjectConfig.canEmbedIFramePage) + + const getPermissionMode = computed(() => appStore.getProjectConfig.permissionMode) + + const getShowLogo = computed(() => appStore.getProjectConfig.showLogo) + + const getContentMode = computed(() => appStore.getProjectConfig.contentMode) + + const getUseOpenBackTop = computed(() => appStore.getProjectConfig.useOpenBackTop) + + const getShowSettingButton = computed(() => appStore.getProjectConfig.showSettingButton) + + const getUseErrorHandle = computed(() => appStore.getProjectConfig.useErrorHandle) + + const getShowFooter = computed(() => appStore.getProjectConfig.showFooter) + + const getShowBreadCrumb = computed(() => appStore.getProjectConfig.showBreadCrumb) + + const getThemeColor = computed(() => appStore.getProjectConfig.themeColor) + + const getShowBreadCrumbIcon = computed(() => appStore.getProjectConfig.showBreadCrumbIcon) + + const getFullContent = computed(() => appStore.getProjectConfig.fullContent) + + const getColorWeak = computed(() => appStore.getProjectConfig.colorWeak) + + const getGrayMode = computed(() => appStore.getProjectConfig.grayMode) + + const getShowDarkModeToggle = computed(() => appStore.getProjectConfig.showDarkModeToggle) + + const getDarkMode = computed(() => appStore.getDarkMode) + + const getLayoutContentMode = computed(() => + appStore.getProjectConfig.contentMode === ContentEnum.FULL + ? ContentEnum.FULL + : ContentEnum.FIXED, + ) + + function setRootSetting(setting: Partial) { + appStore.setProjectConfig(setting) + } + + function setDarkMode(mode: ThemeEnum) { + appStore.setDarkMode(mode) + } + return { + setRootSetting, + + getSettingButtonPosition, + getFullContent, + getColorWeak, + getGrayMode, + getLayoutContentMode, + getPageLoading, + getOpenKeepAlive, + getCanEmbedIFramePage, + getPermissionMode, + getShowLogo, + getUseErrorHandle, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getUseOpenBackTop, + getShowSettingButton, + getShowFooter, + getContentMode, + getThemeColor, + getDarkMode, + setDarkMode, + getShowDarkModeToggle, + } +} diff --git a/frontend/vben/src/hooks/setting/useTransitionSetting.ts b/frontend/vben/src/hooks/setting/useTransitionSetting.ts new file mode 100644 index 0000000..f6848a4 --- /dev/null +++ b/frontend/vben/src/hooks/setting/useTransitionSetting.ts @@ -0,0 +1,31 @@ +import type { TransitionSetting } from '/#/config' + +import { computed } from 'vue' + +import { useAppStore } from '/@/store/modules/app' + +export function useTransitionSetting() { + const appStore = useAppStore() + + const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable) + + const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress) + + const getOpenPageLoading = computed((): boolean => { + return !!appStore.getTransitionSetting?.openPageLoading + }) + + const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition) + + function setTransitionSetting(transitionSetting: Partial) { + appStore.setProjectConfig({ transitionSetting }) + } + return { + setTransitionSetting, + + getEnableTransition, + getOpenNProgress, + getOpenPageLoading, + getBasicTransition, + } +} diff --git a/frontend/vben/src/hooks/web/useAppInject.ts b/frontend/vben/src/hooks/web/useAppInject.ts new file mode 100644 index 0000000..9657130 --- /dev/null +++ b/frontend/vben/src/hooks/web/useAppInject.ts @@ -0,0 +1,10 @@ +import { useAppProviderContext } from '/@/components/Application' +import { computed, unref } from 'vue' + +export function useAppInject() { + const values = useAppProviderContext() + + return { + getIsMobile: computed(() => unref(values.isMobile)), + } +} diff --git a/frontend/vben/src/hooks/web/useContentHeight.ts b/frontend/vben/src/hooks/web/useContentHeight.ts new file mode 100644 index 0000000..59d977a --- /dev/null +++ b/frontend/vben/src/hooks/web/useContentHeight.ts @@ -0,0 +1,191 @@ +import { ComputedRef, isRef, nextTick, Ref, ref, unref, watch } from 'vue' +import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated' +import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn' +import { useLayoutHeight } from '/@/layouts/default/content/useContentViewHeight' +import { getViewportOffset } from '/@/utils/domUtils' +import { isNumber, isString } from '/@/utils/is' + +export interface CompensationHeight { + // 使用 layout Footer 高度作为判断补偿高度的条件 + useLayoutFooter: boolean + // refs HTMLElement + elements?: Ref[] +} + +type Upward = number | string | null | undefined + +/** + * 动态计算内容高度,根据锚点dom最下坐标到屏幕最下坐标,根据传入dom的高度、padding、margin等值进行动态计算 + * 最终获取合适的内容高度 + * + * @param flag 用于开启计算的响应式标识 + * @param anchorRef 锚点组件 Ref + * @param subtractHeightRefs 待减去高度的组件列表 Ref + * @param substractSpaceRefs 待减去空闲空间(margins/paddings)的组件列表 Ref + * @param offsetHeightRef 计算偏移的响应式高度,计算高度时将直接减去此值 + * @param upwardSpace 向上递归减去空闲空间的 层级 或 直到指定class为止 数值为2代表向上递归两次|数值为ant-layout表示向上递归直到碰见.ant-layout为止 + * @returns 响应式高度 + */ +export function useContentHeight( + flag: ComputedRef, + anchorRef: Ref, + subtractHeightRefs: Ref[], + substractSpaceRefs: Ref[], + upwardSpace: Ref | ComputedRef | Upward = 0, + offsetHeightRef: Ref = ref(0), +) { + const contentHeight: Ref> = ref(null) + const { footerHeightRef: layoutFooterHeightRef } = useLayoutHeight() + let compensationHeight: CompensationHeight = { + useLayoutFooter: true, + } + + const setCompensation = (params: CompensationHeight) => { + compensationHeight = params + } + + function redoHeight() { + nextTick(() => { + calcContentHeight() + }) + } + + function calcSubtractSpace( + element: Element | null | undefined, + direction: 'all' | 'top' | 'bottom' = 'all', + ): number { + function numberPx(px: string) { + return Number(px.replace(/[^\d]/g, '')) + } + let subtractHeight = 0 + const ZERO_PX = '0px' + if (element) { + const cssStyle = getComputedStyle(element) + const marginTop = numberPx(cssStyle?.marginTop ?? ZERO_PX) + const marginBottom = numberPx(cssStyle?.marginBottom ?? ZERO_PX) + const paddingTop = numberPx(cssStyle?.paddingTop ?? ZERO_PX) + const paddingBottom = numberPx(cssStyle?.paddingBottom ?? ZERO_PX) + if (direction === 'all') { + subtractHeight += marginTop + subtractHeight += marginBottom + subtractHeight += paddingTop + subtractHeight += paddingBottom + } else if (direction === 'top') { + subtractHeight += marginTop + subtractHeight += paddingTop + } else { + subtractHeight += marginBottom + subtractHeight += paddingBottom + } + } + return subtractHeight + } + + function getEl(element: any): Nullable { + if (element == null) { + return null + } + return (element instanceof HTMLDivElement ? element : element.$el) as HTMLDivElement + } + + async function calcContentHeight() { + if (!flag.value) { + return + } + // Add a delay to get the correct height + await nextTick() + + const anchorEl = getEl(unref(anchorRef)) + if (!anchorEl) { + return + } + const { bottomIncludeBody } = getViewportOffset(anchorEl) + + // substract elements height + let substractHeight = 0 + subtractHeightRefs.forEach((item) => { + substractHeight += getEl(unref(item))?.offsetHeight ?? 0 + }) + + // subtract margins / paddings + let substractSpaceHeight = calcSubtractSpace(anchorEl) ?? 0 + substractSpaceRefs.forEach((item) => { + substractSpaceHeight += calcSubtractSpace(getEl(unref(item))) + }) + + // upwardSpace + let upwardSpaceHeight = 0 + function upward(element: Element | null, upwardLvlOrClass: number | string | null | undefined) { + if (element && upwardLvlOrClass) { + const parent = element.parentElement + if (parent) { + if (isString(upwardLvlOrClass)) { + if (!parent.classList.contains(upwardLvlOrClass)) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom') + upward(parent, upwardLvlOrClass) + } else { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom') + } + } else if (isNumber(upwardLvlOrClass)) { + if (upwardLvlOrClass > 0) { + upwardSpaceHeight += calcSubtractSpace(parent, 'bottom') + upward(parent, --upwardLvlOrClass) + } + } + } + } + } + if (isRef(upwardSpace)) { + upward(anchorEl, unref(upwardSpace)) + } else { + upward(anchorEl, upwardSpace) + } + + let height = + bottomIncludeBody - + unref(layoutFooterHeightRef) - + unref(offsetHeightRef) - + substractHeight - + substractSpaceHeight - + upwardSpaceHeight + + // compensation height + const calcCompensationHeight = () => { + compensationHeight.elements?.forEach((item) => { + height += getEl(unref(item))?.offsetHeight ?? 0 + }) + } + if (compensationHeight.useLayoutFooter && unref(layoutFooterHeightRef) > 0) { + calcCompensationHeight() + } else { + calcCompensationHeight() + } + + contentHeight.value = height + } + + onMountedOrActivated(() => { + nextTick(() => { + calcContentHeight() + }) + }) + useWindowSizeFn( + () => { + calcContentHeight() + }, + 50, + { immediate: true }, + ) + watch( + () => [layoutFooterHeightRef.value], + () => { + calcContentHeight() + }, + { + flush: 'post', + immediate: true, + }, + ) + + return { redoHeight, setCompensation, contentHeight } +} diff --git a/frontend/vben/src/hooks/web/useCopyToClipboard.ts b/frontend/vben/src/hooks/web/useCopyToClipboard.ts new file mode 100644 index 0000000..ebe1a8c --- /dev/null +++ b/frontend/vben/src/hooks/web/useCopyToClipboard.ts @@ -0,0 +1,68 @@ +import { ref, watch } from 'vue' + +import { isDef } from '/@/utils/is' +interface Options { + target?: HTMLElement +} +export function useCopyToClipboard(initial?: string) { + const clipboardRef = ref(initial || '') + const isSuccessRef = ref(false) + const copiedRef = ref(false) + + watch( + clipboardRef, + (str?: string) => { + if (isDef(str)) { + copiedRef.value = true + isSuccessRef.value = copyTextToClipboard(str) + } + }, + { immediate: !!initial, flush: 'sync' }, + ) + + return { clipboardRef, isSuccessRef, copiedRef } +} + +export function copyTextToClipboard(input: string, { target = document.body }: Options = {}) { + const element = document.createElement('textarea') + const previouslyFocusedElement = document.activeElement + + element.value = input + + element.setAttribute('readonly', '') + ;(element.style as any).contain = 'strict' + element.style.position = 'absolute' + element.style.left = '-9999px' + element.style.fontSize = '12pt' + + const selection = document.getSelection() + let originalRange + if (selection && selection.rangeCount > 0) { + originalRange = selection.getRangeAt(0) + } + + target.append(element) + element.select() + + element.selectionStart = 0 + element.selectionEnd = input.length + + let isSuccess = false + try { + isSuccess = document.execCommand('copy') + } catch (e: any) { + throw new Error(e) + } + + element.remove() + + if (originalRange && selection) { + selection.removeAllRanges() + selection.addRange(originalRange) + } + + if (previouslyFocusedElement) { + ;(previouslyFocusedElement as HTMLElement).focus() + } + return isSuccess +} diff --git a/frontend/vben/src/hooks/web/useDesign.ts b/frontend/vben/src/hooks/web/useDesign.ts new file mode 100644 index 0000000..f32b146 --- /dev/null +++ b/frontend/vben/src/hooks/web/useDesign.ts @@ -0,0 +1,22 @@ +import { useAppProviderContext } from '/@/components/Application' +// import { computed } from 'vue'; +// import { lowerFirst } from 'lodash-es'; +export function useDesign(scope: string) { + const values = useAppProviderContext() + // const $style = cssModule ? useCssModule() : {}; + + // const style: Record = {}; + // if (cssModule) { + // Object.keys($style).forEach((key) => { + // // const moduleCls = $style[key]; + // const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), ''); + // style[lowerFirst(k)] = $style[key]; + // }); + // } + return { + // prefixCls: computed(() => `${values.prefixCls}-${scope}`), + prefixCls: `${values.prefixCls}-${scope}`, + prefixVar: values.prefixCls, + // style, + } +} diff --git a/frontend/vben/src/hooks/web/useECharts.ts b/frontend/vben/src/hooks/web/useECharts.ts new file mode 100644 index 0000000..13b3b94 --- /dev/null +++ b/frontend/vben/src/hooks/web/useECharts.ts @@ -0,0 +1,121 @@ +import type { EChartsOption } from 'echarts' +import type { Ref } from 'vue' +import { useTimeoutFn } from '/@/hooks/core/useTimeout' +import { tryOnUnmounted } from '@vueuse/core' +import { unref, nextTick, watch, computed, ref } from 'vue' +import { useDebounceFn } from '@vueuse/core' +import { useEventListener } from '/@/hooks/event/useEventListener' +import { useBreakpoint } from '/@/hooks/event/useBreakpoint' +import echarts from '/@/utils/lib/echarts' +import { useRootSetting } from '/@/hooks/setting/useRootSetting' + +export function useECharts( + elRef: Ref, + theme: 'light' | 'dark' | 'default' = 'default', +) { + const { getDarkMode: getSysDarkMode } = useRootSetting() + + const getDarkMode = computed(() => { + return theme === 'default' ? getSysDarkMode.value : theme + }) + let chartInstance: echarts.ECharts | null = null + let resizeFn: Fn = resize + const cacheOptions = ref({}) as Ref + let removeResizeFn: Fn = () => {} + + resizeFn = useDebounceFn(resize, 200) + + const getOptions = computed(() => { + if (getDarkMode.value !== 'dark') { + return cacheOptions.value as EChartsOption + } + return { + backgroundColor: 'transparent', + ...cacheOptions.value, + } as EChartsOption + }) + + function initCharts(t = theme) { + const el = unref(elRef) + if (!el || !unref(el)) { + return + } + + chartInstance = echarts.init(el, t) + const { removeEvent } = useEventListener({ + el: window, + name: 'resize', + listener: resizeFn, + }) + removeResizeFn = removeEvent + const { widthRef, screenEnum } = useBreakpoint() + if (unref(widthRef) <= screenEnum.MD || el.offsetHeight === 0) { + useTimeoutFn(() => { + resizeFn() + }, 30) + } + } + + function setOptions(options: EChartsOption, clear = true) { + cacheOptions.value = options + if (unref(elRef)?.offsetHeight === 0) { + useTimeoutFn(() => { + setOptions(unref(getOptions)) + }, 30) + return + } + nextTick(() => { + useTimeoutFn(() => { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default') + + if (!chartInstance) return + } + clear && chartInstance?.clear() + + chartInstance?.setOption(unref(getOptions)) + }, 30) + }) + } + + function resize() { + chartInstance?.resize({ + animation: { + duration: 300, + easing: 'quadraticIn', + }, + }) + } + + watch( + () => getDarkMode.value, + (theme) => { + if (chartInstance) { + chartInstance.dispose() + initCharts(theme as 'default') + setOptions(cacheOptions.value) + } + }, + ) + + tryOnUnmounted(() => { + if (!chartInstance) return + removeResizeFn() + chartInstance.dispose() + chartInstance = null + }) + + function getInstance(): echarts.ECharts | null { + if (!chartInstance) { + initCharts(getDarkMode.value as 'default') + } + return chartInstance + } + + return { + setOptions, + resize, + echarts, + getInstance, + } +} diff --git a/frontend/vben/src/hooks/web/useFullContent.ts b/frontend/vben/src/hooks/web/useFullContent.ts new file mode 100644 index 0000000..d6ca5eb --- /dev/null +++ b/frontend/vben/src/hooks/web/useFullContent.ts @@ -0,0 +1,28 @@ +import { computed, unref } from 'vue' + +import { useAppStore } from '/@/store/modules/app' + +import { useRouter } from 'vue-router' + +/** + * @description: Full screen display content + */ +export const useFullContent = () => { + const appStore = useAppStore() + const router = useRouter() + const { currentRoute } = router + + // Whether to display the content in full screen without displaying the menu + const getFullContent = computed(() => { + // Query parameters, the full screen is displayed when the address bar has a full parameter + const route = unref(currentRoute) + const query = route.query + if (query && Reflect.has(query, '__full__')) { + return true + } + // Return to the configuration in the configuration file + return appStore.getProjectConfig.fullContent + }) + + return { getFullContent } +} diff --git a/frontend/vben/src/hooks/web/useI18n.ts b/frontend/vben/src/hooks/web/useI18n.ts new file mode 100644 index 0000000..e1a960e --- /dev/null +++ b/frontend/vben/src/hooks/web/useI18n.ts @@ -0,0 +1,55 @@ +import { i18n } from '/@/locales/setupI18n' + +type I18nGlobalTranslation = { + (key: string): string + (key: string, locale: string): string + (key: string, locale: string, list: unknown[]): string + (key: string, locale: string, named: Record): string + (key: string, list: unknown[]): string + (key: string, named: Record): string +} + +type I18nTranslationRestParameters = [string, any] + +function getKey(namespace: string | undefined, key: string) { + if (!namespace) { + return key + } + if (key.startsWith(namespace)) { + return key + } + return `${namespace}.${key}` +} + +export function useI18n(namespace?: string): { + t: I18nGlobalTranslation +} { + const normalFn = { + t: (key: string) => { + return getKey(namespace, key) + }, + } + + if (!i18n) { + return normalFn + } + + const { t, ...methods } = i18n.global + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) return '' + if (!key.includes('.') && !namespace) return key + return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) + } + return { + ...methods, + t: tFn, + } +} + +// Why write this function? +// Mainly to configure the vscode i18nn ally plugin. This function is only used for routing and menus. Please use useI18n for other places + +// 为什么要编写此函数? +// 主要用于配合vscode i18nn ally插件。此功能仅用于路由和菜单。请在其他地方使用useI18n +export const t = (key: string) => key diff --git a/frontend/vben/src/hooks/web/useMessage.tsx b/frontend/vben/src/hooks/web/useMessage.tsx new file mode 100644 index 0000000..23fe44b --- /dev/null +++ b/frontend/vben/src/hooks/web/useMessage.tsx @@ -0,0 +1,123 @@ +import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal' + +import { Modal, message as Message, notification } from 'ant-design-vue' +import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue' + +import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification' +import { useI18n } from './useI18n' +import { isString } from '/@/utils/is' + +export interface NotifyApi { + info(config: NotificationArgsProps): void + success(config: NotificationArgsProps): void + error(config: NotificationArgsProps): void + warn(config: NotificationArgsProps): void + warning(config: NotificationArgsProps): void + open(args: NotificationArgsProps): void + close(key: String): void + config(options: ConfigProps): void + destroy(): void +} + +export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' +export declare type IconType = 'success' | 'info' | 'error' | 'warning' +export interface ModalOptionsEx extends Omit { + iconType: 'warning' | 'success' | 'error' | 'info' +} +export type ModalOptionsPartial = Partial & Pick + +interface ConfirmOptions { + info: ModalFunc + success: ModalFunc + error: ModalFunc + warn: ModalFunc + warning: ModalFunc +} + +function getIcon(iconType: string) { + if (iconType === 'warning') { + return + } else if (iconType === 'success') { + return + } else if (iconType === 'info') { + return + } else { + return + } +} + +function renderContent({ content }: Pick) { + if (isString(content)) { + return
${content as string}
`}> + } else { + return content + } +} + +/** + * @description: Create confirmation box + */ +function createConfirm(options: ModalOptionsEx): ConfirmOptions { + const iconType = options.iconType || 'warning' + Reflect.deleteProperty(options, 'iconType') + const opt: ModalFuncProps = { + centered: true, + icon: getIcon(iconType), + ...options, + content: renderContent(options), + } + return Modal.confirm(opt) as unknown as ConfirmOptions +} + +const getBaseOptions = () => { + const { t } = useI18n() + return { + okText: t('common.okText'), + centered: true, + } +} + +function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial { + return { + ...getBaseOptions(), + ...options, + content: renderContent(options), + icon: getIcon(icon), + } +} + +function createSuccessModal(options: ModalOptionsPartial) { + return Modal.success(createModalOptions(options, 'success')) +} + +function createErrorModal(options: ModalOptionsPartial) { + return Modal.error(createModalOptions(options, 'close')) +} + +function createInfoModal(options: ModalOptionsPartial) { + return Modal.info(createModalOptions(options, 'info')) +} + +function createWarningModal(options: ModalOptionsPartial) { + return Modal.warning(createModalOptions(options, 'warning')) +} + +notification.config({ + placement: 'topRight', + duration: 3, +}) + +/** + * @description: message + */ +export function useMessage() { + return { + createMessage: Message, + notification: notification as NotifyApi, + createConfirm: createConfirm, + createSuccessModal, + createErrorModal, + createInfoModal, + createWarningModal, + } +} diff --git a/frontend/vben/src/hooks/web/usePage.ts b/frontend/vben/src/hooks/web/usePage.ts new file mode 100644 index 0000000..78a405d --- /dev/null +++ b/frontend/vben/src/hooks/web/usePage.ts @@ -0,0 +1,53 @@ +import type { RouteLocationRaw, Router } from 'vue-router' + +import { PageEnum } from '/@/enums/pageEnum' +import { unref } from 'vue' + +import { useRouter } from 'vue-router' +import { REDIRECT_NAME } from '/@/router/constant' + +export type PathAsPageEnum = T extends { path: string } ? T & { path: PageEnum } : T +export type RouteLocationRawEx = PathAsPageEnum + +function handleError(e: Error) { + console.error(e) +} + +/** + * page switch + */ +export function useGo(_router?: Router) { + const { push, replace } = _router || useRouter() + function go(opt: RouteLocationRawEx = PageEnum.BASE_HOME, isReplace = false) { + if (!opt) { + return + } + isReplace ? replace(opt).catch(handleError) : push(opt).catch(handleError) + } + return go +} + +/** + * @description: redo current page + */ +export const useRedo = (_router?: Router) => { + const { replace, currentRoute } = _router || useRouter() + const { query, params = {}, name, fullPath } = unref(currentRoute.value) + function redo(): Promise { + return new Promise((resolve) => { + if (name === REDIRECT_NAME) { + resolve(false) + return + } + if (name && Object.keys(params).length > 0) { + params['_redirect_type'] = 'name' + params['path'] = String(name) + } else { + params['_redirect_type'] = 'path' + params['path'] = fullPath + } + replace({ name: REDIRECT_NAME, params, query }).then(() => resolve(true)) + }) + } + return redo +} diff --git a/frontend/vben/src/hooks/web/usePagination.ts b/frontend/vben/src/hooks/web/usePagination.ts new file mode 100644 index 0000000..bf63078 --- /dev/null +++ b/frontend/vben/src/hooks/web/usePagination.ts @@ -0,0 +1,34 @@ +import type { Ref } from 'vue' +import { ref, unref, computed } from 'vue' + +function pagination(list: T[], pageNo: number, pageSize: number): T[] { + const offset = (pageNo - 1) * Number(pageSize) + const ret = + offset + Number(pageSize) >= list.length + ? list.slice(offset, list.length) + : list.slice(offset, offset + Number(pageSize)) + return ret +} + +export function usePagination(list: Ref, pageSize: number) { + const currentPage = ref(1) + const pageSizeRef = ref(pageSize) + + const getPaginationList = computed(() => { + return pagination(unref(list), unref(currentPage), unref(pageSizeRef)) + }) + + const getTotal = computed(() => { + return unref(list).length + }) + + function setCurrentPage(page: number) { + currentPage.value = page + } + + function setPageSize(pageSize: number) { + pageSizeRef.value = pageSize + } + + return { setCurrentPage, getTotal, setPageSize, getPaginationList } +} diff --git a/frontend/vben/src/hooks/web/usePermission.ts b/frontend/vben/src/hooks/web/usePermission.ts new file mode 100644 index 0000000..069e753 --- /dev/null +++ b/frontend/vben/src/hooks/web/usePermission.ts @@ -0,0 +1,111 @@ +import type { RouteRecordRaw } from 'vue-router' + +import { useAppStore } from '/@/store/modules/app' +import { usePermissionStore } from '/@/store/modules/permission' +import { useUserStore } from '/@/store/modules/user' + +import { useTabs } from './useTabs' + +import { router, resetRouter } from '/@/router' +// import { RootRoute } from '/@/router/routes'; + +import projectSetting from '/@/settings/projectSetting' +import { PermissionModeEnum } from '/@/enums/appEnum' +import { RoleEnum } from '/@/enums/roleEnum' + +import { intersection } from 'lodash-es' +import { isArray } from '/@/utils/is' +import { useMultipleTabStore } from '/@/store/modules/multipleTab' + +// User permissions related operations +export function usePermission() { + const userStore = useUserStore() + const appStore = useAppStore() + const permissionStore = usePermissionStore() + const { closeAll } = useTabs(router) + + /** + * Change permission mode + */ + async function togglePermissionMode() { + appStore.setProjectConfig({ + permissionMode: + projectSetting.permissionMode === PermissionModeEnum.BACK + ? PermissionModeEnum.ROUTE_MAPPING + : PermissionModeEnum.BACK, + }) + location.reload() + } + + /** + * Reset and regain authority resource information + * 重置和重新获得权限资源信息 + * @param id + */ + async function resume() { + const tabStore = useMultipleTabStore() + tabStore.clearCacheTabs() + resetRouter() + const routes = await permissionStore.buildRoutesAction() + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) + }) + permissionStore.setLastBuildMenuTime() + closeAll() + } + + /** + * Determine whether there is permission + */ + function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean { + // Visible by default + if (!value) { + return def + } + + const permMode = projectSetting.permissionMode + + if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) { + if (!isArray(value)) { + return userStore.getRoleList?.includes(value as RoleEnum) + } + return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0 + } + + if (PermissionModeEnum.BACK === permMode) { + const allCodeList = permissionStore.getPermCodeList as string[] + if (!isArray(value)) { + return allCodeList.includes(value) + } + return (intersection(value, allCodeList) as string[]).length > 0 + } + return true + } + + /** + * Change roles + * @param roles + */ + async function changeRole(roles: RoleEnum | RoleEnum[]): Promise { + if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) { + throw new Error( + 'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!', + ) + } + + if (!isArray(roles)) { + roles = [roles] + } + userStore.setRoleList(roles) + await resume() + } + + /** + * refresh menu data + */ + async function refreshMenu() { + resume() + } + + return { changeRole, hasPermission, togglePermissionMode, refreshMenu } +} diff --git a/frontend/vben/src/hooks/web/useScript.ts b/frontend/vben/src/hooks/web/useScript.ts new file mode 100644 index 0000000..70f8afe --- /dev/null +++ b/frontend/vben/src/hooks/web/useScript.ts @@ -0,0 +1,46 @@ +import { onMounted, onUnmounted, ref } from 'vue' + +interface ScriptOptions { + src: string +} + +export function useScript(opts: ScriptOptions) { + const isLoading = ref(false) + const error = ref(false) + const success = ref(false) + let script: HTMLScriptElement + + const promise = new Promise((resolve, reject) => { + onMounted(() => { + script = document.createElement('script') + script.type = 'text/javascript' + script.onload = function () { + isLoading.value = false + success.value = true + error.value = false + resolve('') + } + + script.onerror = function (err) { + isLoading.value = false + success.value = false + error.value = true + reject(err) + } + + script.src = opts.src + document.head.appendChild(script) + }) + }) + + onUnmounted(() => { + script && script.remove() + }) + + return { + isLoading, + error, + success, + toPromise: () => promise, + } +} diff --git a/frontend/vben/src/hooks/web/useSortable.ts b/frontend/vben/src/hooks/web/useSortable.ts new file mode 100644 index 0000000..626fbbd --- /dev/null +++ b/frontend/vben/src/hooks/web/useSortable.ts @@ -0,0 +1,21 @@ +import { nextTick, unref } from 'vue' +import type { Ref } from 'vue' +import type { Options } from 'sortablejs' + +export function useSortable(el: HTMLElement | Ref, options?: Options) { + function initSortable() { + nextTick(async () => { + if (!el) return + + const Sortable = (await import('sortablejs')).default + Sortable.create(unref(el), { + animation: 500, + delay: 400, + delayOnTouchOnly: true, + ...options, + }) + }) + } + + return { initSortable } +} diff --git a/frontend/vben/src/hooks/web/useTabs.ts b/frontend/vben/src/hooks/web/useTabs.ts new file mode 100644 index 0000000..d716384 --- /dev/null +++ b/frontend/vben/src/hooks/web/useTabs.ts @@ -0,0 +1,103 @@ +import type { RouteLocationNormalized, Router } from 'vue-router' + +import { useRouter } from 'vue-router' +import { unref } from 'vue' + +import { useMultipleTabStore } from '/@/store/modules/multipleTab' +import { useAppStore } from '/@/store/modules/app' + +enum TableActionEnum { + REFRESH, + CLOSE_ALL, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_CURRENT, + CLOSE, +} + +export function useTabs(_router?: Router) { + const appStore = useAppStore() + + function canIUseTabs(): boolean { + const { show } = appStore.getMultiTabsSetting + if (!show) { + throw new Error('The multi-tab page is currently not open, please open it in the settings!') + } + return !!show + } + + const tabStore = useMultipleTabStore() + const router = _router || useRouter() + + const { currentRoute } = router + + function getCurrentTab() { + const route = unref(currentRoute) + return tabStore.getTabList.find((item) => item.fullPath === route.fullPath)! + } + + async function updateTabTitle(title: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs + if (!canIUse) { + return + } + const targetTab = tab || getCurrentTab() + await tabStore.setTabTitle(title, targetTab) + } + + async function updateTabPath(path: string, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs + if (!canIUse) { + return + } + const targetTab = tab || getCurrentTab() + await tabStore.updateTabPath(path, targetTab) + } + + async function handleTabAction(action: TableActionEnum, tab?: RouteLocationNormalized) { + const canIUse = canIUseTabs + if (!canIUse) { + return + } + const currentTab = getCurrentTab() + switch (action) { + case TableActionEnum.REFRESH: + await tabStore.refreshPage(router) + break + + case TableActionEnum.CLOSE_ALL: + await tabStore.closeAllTab(router) + break + + case TableActionEnum.CLOSE_LEFT: + await tabStore.closeLeftTabs(currentTab, router) + break + + case TableActionEnum.CLOSE_RIGHT: + await tabStore.closeRightTabs(currentTab, router) + break + + case TableActionEnum.CLOSE_OTHER: + await tabStore.closeOtherTabs(currentTab, router) + break + + case TableActionEnum.CLOSE_CURRENT: + case TableActionEnum.CLOSE: + await tabStore.closeTab(tab || currentTab, router) + break + } + } + + return { + refreshPage: () => handleTabAction(TableActionEnum.REFRESH), + closeAll: () => handleTabAction(TableActionEnum.CLOSE_ALL), + closeLeft: () => handleTabAction(TableActionEnum.CLOSE_LEFT), + closeRight: () => handleTabAction(TableActionEnum.CLOSE_RIGHT), + closeOther: () => handleTabAction(TableActionEnum.CLOSE_OTHER), + closeCurrent: () => handleTabAction(TableActionEnum.CLOSE_CURRENT), + close: (tab?: RouteLocationNormalized) => handleTabAction(TableActionEnum.CLOSE, tab), + setTitle: (title: string, tab?: RouteLocationNormalized) => updateTabTitle(title, tab), + updatePath: (fullPath: string, tab?: RouteLocationNormalized) => updateTabPath(fullPath, tab), + } +} diff --git a/frontend/vben/src/hooks/web/useTitle.ts b/frontend/vben/src/hooks/web/useTitle.ts new file mode 100644 index 0000000..13b7845 --- /dev/null +++ b/frontend/vben/src/hooks/web/useTitle.ts @@ -0,0 +1,35 @@ +import { watch, unref } from 'vue' +import { useI18n } from '/@/hooks/web/useI18n' +import { useTitle as usePageTitle } from '@vueuse/core' +import { useGlobSetting } from '/@/hooks/setting' +import { useRouter } from 'vue-router' +import { useLocaleStore } from '/@/store/modules/locale' + +import { REDIRECT_NAME } from '/@/router/constant' + +/** + * Listening to page changes and dynamically changing site titles + */ +export function useTitle() { + const { title } = useGlobSetting() + const { t } = useI18n() + const { currentRoute } = useRouter() + const localeStore = useLocaleStore() + + const pageTitle = usePageTitle() + + watch( + [() => currentRoute.value.path, () => localeStore.getLocale], + () => { + const route = unref(currentRoute) + + if (route.name === REDIRECT_NAME) { + return + } + + const tTitle = t(route?.meta?.title as string) + pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}` + }, + { immediate: true }, + ) +} diff --git a/frontend/vben/src/hooks/web/useWatermark.ts b/frontend/vben/src/hooks/web/useWatermark.ts new file mode 100644 index 0000000..e5ddee9 --- /dev/null +++ b/frontend/vben/src/hooks/web/useWatermark.ts @@ -0,0 +1,100 @@ +import { getCurrentInstance, onBeforeUnmount, ref, Ref, shallowRef, unref } from 'vue' +import { useRafThrottle } from '/@/utils/domUtils' +import { addResizeListener, removeResizeListener } from '/@/utils/event' +import { isDef } from '/@/utils/is' + +const domSymbol = Symbol('watermark-dom') + +export function useWatermark( + appendEl: Ref = ref(document.body) as Ref, +) { + const func = useRafThrottle(function () { + const el = unref(appendEl) + if (!el) return + const { clientHeight: height, clientWidth: width } = el + updateWatermark({ height, width }) + }) + const id = domSymbol.toString() + const watermarkEl = shallowRef() + + const clear = () => { + const domId = unref(watermarkEl) + watermarkEl.value = undefined + const el = unref(appendEl) + if (!el) return + domId && el.removeChild(domId) + removeResizeListener(el, func) + } + + function createBase64(str: string) { + const can = document.createElement('canvas') + const width = 300 + const height = 240 + Object.assign(can, { width, height }) + + const cans = can.getContext('2d') + if (cans) { + cans.rotate((-20 * Math.PI) / 120) + cans.font = '15px Vedana' + cans.fillStyle = 'rgba(0, 0, 0, 0.15)' + cans.textAlign = 'left' + cans.textBaseline = 'middle' + cans.fillText(str, width / 20, height) + } + return can.toDataURL('image/png') + } + + function updateWatermark( + options: { + width?: number + height?: number + str?: string + } = {}, + ) { + const el = unref(watermarkEl) + if (!el) return + if (isDef(options.width)) { + el.style.width = `${options.width}px` + } + if (isDef(options.height)) { + el.style.height = `${options.height}px` + } + if (isDef(options.str)) { + el.style.background = `url(${createBase64(options.str)}) left top repeat` + } + } + + const createWatermark = (str: string) => { + if (unref(watermarkEl)) { + updateWatermark({ str }) + return id + } + const div = document.createElement('div') + watermarkEl.value = div + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '0px' + div.style.left = '0px' + div.style.position = 'absolute' + div.style.zIndex = '100000' + const el = unref(appendEl) + if (!el) return id + const { clientHeight: height, clientWidth: width } = el + updateWatermark({ str, width, height }) + el.appendChild(div) + return id + } + + function setWatermark(str: string) { + createWatermark(str) + addResizeListener(document.documentElement, func) + const instance = getCurrentInstance() + if (instance) { + onBeforeUnmount(() => { + clear() + }) + } + } + + return { setWatermark, clear } +} diff --git a/frontend/vben/src/layouts/default/content/index.vue b/frontend/vben/src/layouts/default/content/index.vue new file mode 100644 index 0000000..989ac77 --- /dev/null +++ b/frontend/vben/src/layouts/default/content/index.vue @@ -0,0 +1,51 @@ + + + diff --git a/frontend/vben/src/layouts/default/content/useContentContext.ts b/frontend/vben/src/layouts/default/content/useContentContext.ts new file mode 100644 index 0000000..f5fda82 --- /dev/null +++ b/frontend/vben/src/layouts/default/content/useContentContext.ts @@ -0,0 +1,17 @@ +import type { InjectionKey, ComputedRef } from 'vue' +import { createContext, useContext } from '/@/hooks/core/useContext' + +export interface ContentContextProps { + contentHeight: ComputedRef + setPageHeight: (height: number) => Promise +} + +const key: InjectionKey = Symbol() + +export function createContentContext(context: ContentContextProps) { + return createContext(context, key, { native: true }) +} + +export function useContentContext() { + return useContext(key) +} diff --git a/frontend/vben/src/layouts/default/content/useContentViewHeight.ts b/frontend/vben/src/layouts/default/content/useContentViewHeight.ts new file mode 100644 index 0000000..1aa84d8 --- /dev/null +++ b/frontend/vben/src/layouts/default/content/useContentViewHeight.ts @@ -0,0 +1,42 @@ +import { ref, computed, unref } from 'vue' +import { createPageContext } from '/@/hooks/component/usePageContext' +import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn' + +const headerHeightRef = ref(0) +const footerHeightRef = ref(0) + +export function useLayoutHeight() { + function setHeaderHeight(val) { + headerHeightRef.value = val + } + function setFooterHeight(val) { + footerHeightRef.value = val + } + return { headerHeightRef, footerHeightRef, setHeaderHeight, setFooterHeight } +} + +export function useContentViewHeight() { + const contentHeight = ref(window.innerHeight) + const pageHeight = ref(window.innerHeight) + const getViewHeight = computed(() => { + return unref(contentHeight) - unref(headerHeightRef) - unref(footerHeightRef) || 0 + }) + + useWindowSizeFn( + () => { + contentHeight.value = window.innerHeight + }, + 100, + { immediate: true }, + ) + + async function setPageHeight(height: number) { + pageHeight.value = height + } + + createPageContext({ + contentHeight: getViewHeight, + setPageHeight, + pageHeight, + }) +} diff --git a/frontend/vben/src/layouts/default/feature/index.vue b/frontend/vben/src/layouts/default/feature/index.vue new file mode 100644 index 0000000..1ce8831 --- /dev/null +++ b/frontend/vben/src/layouts/default/feature/index.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/frontend/vben/src/layouts/default/footer/index.vue b/frontend/vben/src/layouts/default/footer/index.vue new file mode 100644 index 0000000..75d60fa --- /dev/null +++ b/frontend/vben/src/layouts/default/footer/index.vue @@ -0,0 +1,95 @@ + + + + diff --git a/frontend/vben/src/layouts/default/header/MultipleHeader.vue b/frontend/vben/src/layouts/default/header/MultipleHeader.vue new file mode 100644 index 0000000..b4232fb --- /dev/null +++ b/frontend/vben/src/layouts/default/header/MultipleHeader.vue @@ -0,0 +1,126 @@ + + + diff --git a/frontend/vben/src/layouts/default/header/components/Breadcrumb.vue b/frontend/vben/src/layouts/default/header/components/Breadcrumb.vue new file mode 100644 index 0000000..4644143 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/Breadcrumb.vue @@ -0,0 +1,204 @@ + + + diff --git a/frontend/vben/src/layouts/default/header/components/FullScreen.vue b/frontend/vben/src/layouts/default/header/components/FullScreen.vue new file mode 100644 index 0000000..d9fbc66 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/FullScreen.vue @@ -0,0 +1,37 @@ + + diff --git a/frontend/vben/src/layouts/default/header/components/index.ts b/frontend/vben/src/layouts/default/header/components/index.ts new file mode 100644 index 0000000..c8a6a02 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/index.ts @@ -0,0 +1,12 @@ +import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent' +import FullScreen from './FullScreen.vue' + +export const UserDropDown = createAsyncComponent(() => import('./user-dropdown/index.vue'), { + loading: true, +}) + +export const LayoutBreadcrumb = createAsyncComponent(() => import('./Breadcrumb.vue')) + +export const Notify = createAsyncComponent(() => import('./notify/index.vue')) + +export { FullScreen } diff --git a/frontend/vben/src/layouts/default/header/components/notify/NoticeList.vue b/frontend/vben/src/layouts/default/header/components/notify/NoticeList.vue new file mode 100644 index 0000000..7e474b2 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/notify/NoticeList.vue @@ -0,0 +1,189 @@ + + + diff --git a/frontend/vben/src/layouts/default/header/components/notify/data.ts b/frontend/vben/src/layouts/default/header/components/notify/data.ts new file mode 100644 index 0000000..c18f3d0 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/notify/data.ts @@ -0,0 +1,193 @@ +export interface ListItem { + id: string + avatar: string + // 通知的标题内容 + title: string + // 是否在标题上显示删除线 + titleDelete?: boolean + datetime: string + type: string + read?: boolean + description: string + clickClose?: boolean + extra?: string + color?: string +} + +export interface TabItem { + key: string + name: string + list: ListItem[] + unreadlist?: ListItem[] +} + +export const tabListData: TabItem[] = [ + { + key: '1', + name: '通知', + list: [ + { + id: '000000001', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', + title: '你收到了 14 份新周报', + description: '', + datetime: '2017-08-09', + type: '1', + }, + { + id: '000000002', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', + title: '你推荐的 曲妮妮 已通过第三轮面试', + description: '', + datetime: '2017-08-08', + type: '1', + }, + { + id: '000000003', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', + title: '这种模板可以区分多种通知类型', + description: '', + datetime: '2017-08-07', + // read: true, + type: '1', + }, + { + id: '000000004', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000005', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: + '标题可以设置自动显示省略号,本例中标题行数已设为1行,如果内容超过1行将自动截断并支持tooltip显示完整标题。', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000006', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000007', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000008', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000009', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + { + id: '000000010', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', + title: '左侧图标用于区分不同的类型', + description: '', + datetime: '2017-08-07', + type: '1', + }, + ], + }, + { + key: '2', + name: '消息', + list: [ + { + id: '000000006', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '曲丽丽 评论了你', + description: '描述信息描述信息描述信息', + datetime: '2017-08-07', + type: '2', + clickClose: true, + }, + { + id: '000000007', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '朱偏右 回复了你', + description: '这种模板用于提醒谁与你发生了互动', + datetime: '2017-08-07', + type: '2', + clickClose: true, + }, + { + id: '000000008', + avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', + title: '标题', + description: + '请将鼠标移动到此处,以便测试超长的消息在此处将如何处理。本例中设置的描述最大行数为2,超过2行的描述内容将被省略并且可以通过tooltip查看完整内容', + datetime: '2017-08-07', + type: '2', + clickClose: true, + }, + ], + }, + { + key: '3', + name: '待办', + list: [ + { + id: '000000009', + avatar: '', + title: '任务名称', + description: '任务需要在 2017-01-12 20:00 前启动', + datetime: '', + extra: '未开始', + color: '', + type: '3', + }, + { + id: '000000010', + avatar: '', + title: '第三方紧急代码变更', + description: '冠霖 需在 2017-01-07 前完成代码变更任务', + datetime: '', + extra: '马上到期', + color: 'red', + type: '3', + }, + { + id: '000000011', + avatar: '', + title: '信息安全考试', + description: '指派竹尔于 2017-01-09 前完成更新并发布', + datetime: '', + extra: '已耗时 8 天', + color: 'gold', + type: '3', + }, + { + id: '000000012', + avatar: '', + title: 'ABCD 版本发布', + description: '指派竹尔于 2017-01-09 前完成更新并发布', + datetime: '', + extra: '进行中', + color: 'blue', + type: '3', + }, + ], + }, +] diff --git a/frontend/vben/src/layouts/default/header/components/notify/index.vue b/frontend/vben/src/layouts/default/header/components/notify/index.vue new file mode 100644 index 0000000..7e257b5 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/notify/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/frontend/vben/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue b/frontend/vben/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue new file mode 100644 index 0000000..3b774f6 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue @@ -0,0 +1,32 @@ + + diff --git a/frontend/vben/src/layouts/default/header/components/user-dropdown/index.vue b/frontend/vben/src/layouts/default/header/components/user-dropdown/index.vue new file mode 100644 index 0000000..0473f53 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/components/user-dropdown/index.vue @@ -0,0 +1,161 @@ + + + diff --git a/frontend/vben/src/layouts/default/header/index.less b/frontend/vben/src/layouts/default/header/index.less new file mode 100644 index 0000000..b16007e --- /dev/null +++ b/frontend/vben/src/layouts/default/header/index.less @@ -0,0 +1,196 @@ +@header-trigger-prefix-cls: ~'@{namespace}-layout-header-trigger'; +@header-prefix-cls: ~'@{namespace}-layout-header'; +@breadcrumb-prefix-cls: ~'@{namespace}-layout-breadcrumb'; +@logo-prefix-cls: ~'@{namespace}-app-logo'; + +.@{header-prefix-cls} { + display: flex; + height: @header-height; + padding: 0; + margin-left: -1px; + line-height: @header-height; + color: @white; + background-color: @white; + align-items: center; + justify-content: space-between; + + &--mobile { + .@{breadcrumb-prefix-cls}, + .error-action, + .notify-item, + .fullscreen-item { + display: none; + } + + .@{logo-prefix-cls} { + min-width: unset; + padding-right: 0; + + &__title { + display: none; + } + } + .@{header-trigger-prefix-cls} { + padding: 0 4px 0 8px !important; + } + .@{header-prefix-cls}-action { + padding-right: 4px; + } + } + + &--fixed { + position: fixed; + top: 0; + left: 0; + z-index: @layout-header-fixed-z-index; + width: 100%; + } + + &-logo { + height: @header-height; + min-width: 192px; + padding: 0 10px; + font-size: 14px; + + img { + width: @logo-width; + height: @logo-width; + margin-right: 2px; + } + } + + &-left { + display: flex; + height: 100%; + align-items: center; + + .@{header-trigger-prefix-cls} { + display: flex; + height: 100%; + padding: 1px 10px 0; + cursor: pointer; + align-items: center; + + .anticon { + font-size: 16px; + } + + &.light { + &:hover { + background-color: @header-light-bg-hover-color; + } + + svg { + fill: #000; + } + } + + &.dark { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } + + &-menu { + height: 100%; + min-width: 0; + flex: 1; + align-items: center; + } + + &-action { + display: flex; + min-width: 180px; + // padding-right: 12px; + align-items: center; + + &__item { + display: flex !important; + height: @header-height; + padding: 0 2px; + font-size: 1.2em; + cursor: pointer; + align-items: center; + + .ant-badge { + height: @header-height; + line-height: @header-height; + } + + .ant-badge-dot { + top: 10px; + right: 2px; + } + } + + span[role='img'] { + padding: 0 8px; + } + } + + &--light { + background-color: @white !important; + border-bottom: 1px solid @header-light-bottom-border-color; + border-left: 1px solid @header-light-bottom-border-color; + + .@{header-prefix-cls}-logo { + color: @text-color-base; + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + color: @text-color-base; + + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + &:hover { + background-color: @header-light-bg-hover-color; + } + } + + &-icon, + span[role='img'] { + color: @text-color-base; + } + } + } + + &--dark { + background-color: @header-dark-bg-color !important; + // border-bottom: 1px solid @border-color-base; + border-left: 1px solid @border-color-base; + .@{header-prefix-cls}-logo { + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + + .@{header-prefix-cls}-action { + &__item { + .app-iconify { + padding: 0 10px; + font-size: 16px !important; + } + + .ant-badge { + span { + color: @white; + } + } + + &:hover { + background-color: @header-dark-bg-hover-color; + } + } + } + } +} diff --git a/frontend/vben/src/layouts/default/header/index.vue b/frontend/vben/src/layouts/default/header/index.vue new file mode 100644 index 0000000..45669b3 --- /dev/null +++ b/frontend/vben/src/layouts/default/header/index.vue @@ -0,0 +1,197 @@ + + + diff --git a/frontend/vben/src/layouts/default/index.vue b/frontend/vben/src/layouts/default/index.vue new file mode 100644 index 0000000..52f256b --- /dev/null +++ b/frontend/vben/src/layouts/default/index.vue @@ -0,0 +1,87 @@ + + + + diff --git a/frontend/vben/src/layouts/default/menu/index.vue b/frontend/vben/src/layouts/default/menu/index.vue new file mode 100644 index 0000000..dfed419 --- /dev/null +++ b/frontend/vben/src/layouts/default/menu/index.vue @@ -0,0 +1,197 @@ + + diff --git a/frontend/vben/src/layouts/default/menu/useLayoutMenu.ts b/frontend/vben/src/layouts/default/menu/useLayoutMenu.ts new file mode 100644 index 0000000..e767dcd --- /dev/null +++ b/frontend/vben/src/layouts/default/menu/useLayoutMenu.ts @@ -0,0 +1,109 @@ +import type { Menu } from '/@/router/types' +import type { Ref } from 'vue' +import { watch, unref, ref, computed } from 'vue' +import { useRouter } from 'vue-router' +import { MenuSplitTyeEnum } from '/@/enums/menuEnum' +import { useThrottleFn } from '@vueuse/core' +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting' +import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus' +import { usePermissionStore } from '/@/store/modules/permission' +import { useAppInject } from '/@/hooks/web/useAppInject' + +export function useSplitMenu(splitType: Ref) { + // Menu array + const menusRef = ref([]) + const { currentRoute } = useRouter() + const { getIsMobile } = useAppInject() + const permissionStore = usePermissionStore() + const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting() + + const throttleHandleSplitLeftMenu = useThrottleFn(handleSplitLeftMenu, 50) + + const splitNotLeft = computed( + () => unref(splitType) !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontal), + ) + + const getSplitLeft = computed( + () => !unref(getSplit) || unref(splitType) !== MenuSplitTyeEnum.LEFT, + ) + + const getSpiltTop = computed(() => unref(splitType) === MenuSplitTyeEnum.TOP) + + const normalType = computed(() => { + return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit) + }) + + watch( + [() => unref(currentRoute).path, () => unref(splitType)], + async ([path]: [string, MenuSplitTyeEnum]) => { + if (unref(splitNotLeft) || unref(getIsMobile)) return + + const { meta } = unref(currentRoute) + const currentActiveMenu = meta.currentActiveMenu as string + let parentPath = await getCurrentParentPath(path) + if (!parentPath) { + parentPath = await getCurrentParentPath(currentActiveMenu) + } + parentPath && throttleHandleSplitLeftMenu(parentPath) + }, + { + immediate: true, + }, + ) + + // Menu changes + watch( + [() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList], + () => { + genMenus() + }, + { + immediate: true, + }, + ) + + // split Menu changes + watch( + () => getSplit.value, + () => { + if (unref(splitNotLeft)) return + genMenus() + }, + ) + + // Handle left menu split + async function handleSplitLeftMenu(parentPath: string) { + if (unref(getSplitLeft) || unref(getIsMobile)) return + + // spilt mode left + const children = await getChildrenMenus(parentPath) + + if (!children || !children.length) { + setMenuSetting({ hidden: true }) + menusRef.value = [] + return + } + + setMenuSetting({ hidden: false }) + menusRef.value = children + } + + // get menus + async function genMenus() { + // normal mode + if (unref(normalType) || unref(getIsMobile)) { + menusRef.value = await getMenus() + return + } + + // split-top + if (unref(getSpiltTop)) { + const shallowMenus = await getShallowMenus() + + menusRef.value = shallowMenus + return + } + } + + return { menusRef } +} diff --git a/frontend/vben/src/layouts/default/setting/SettingDrawer.tsx b/frontend/vben/src/layouts/default/setting/SettingDrawer.tsx new file mode 100644 index 0000000..6632885 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/SettingDrawer.tsx @@ -0,0 +1,415 @@ +import { defineComponent, computed, unref } from 'vue' +import { BasicDrawer } from '/@/components/Drawer/index' +import { Divider } from 'ant-design-vue' +import { + TypePicker, + ThemeColorPicker, + SettingFooter, + SwitchItem, + SelectItem, + InputNumberItem, +} from './components' + +import { AppDarkModeToggle } from '/@/components/Application' + +import { MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum' + +import { useRootSetting } from '/@/hooks/setting/useRootSetting' +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting' +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting' +import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting' +import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting' +import { useI18n } from '/@/hooks/web/useI18n' + +import { baseHandler } from './handler' + +import { + HandlerEnum, + contentModeOptions, + topMenuAlignOptions, + getMenuTriggerOptions, + routerTransitionOptions, + menuTypeList, + mixSidebarTriggerOptions, +} from './enum' + +import { + HEADER_PRESET_BG_COLOR_LIST, + SIDE_BAR_BG_COLOR_LIST, + APP_PRESET_COLOR_LIST, +} from '/@/settings/designSetting' + +const { t } = useI18n() + +export default defineComponent({ + name: 'SettingDrawer', + setup(_, { attrs }) { + const { + getContentMode, + getShowFooter, + getShowBreadCrumb, + getShowBreadCrumbIcon, + getShowLogo, + getFullContent, + getColorWeak, + getGrayMode, + getShowDarkModeToggle, + getThemeColor, + } = useRootSetting() + + const { getOpenPageLoading, getBasicTransition, getEnableTransition, getOpenNProgress } = + useTransitionSetting() + + const { + getIsHorizontal, + getShowMenu, + getMenuType, + getTrigger, + getCollapsedShowTitle, + getMenuFixed, + getCollapsed, + getCanDrag, + getTopMenuAlign, + getAccordion, + getMenuWidth, + getMenuBgColor, + getIsTopMenu, + getSplit, + getIsMixSidebar, + getCloseMixSidebarOnChange, + getMixSideTrigger, + getMixSideFixed, + } = useMenuSetting() + + const { + getShowHeader, + getFixed: getHeaderFixed, + getHeaderBgColor, + getShowSearch, + } = useHeaderSetting() + + const { getShowMultipleTab, getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting() + + const getShowMenuRef = computed(() => { + return unref(getShowMenu) && !unref(getIsHorizontal) + }) + + function renderSidebar() { + return ( + <> + { + baseHandler(HandlerEnum.CHANGE_LAYOUT, { + mode: item.mode, + type: item.type, + split: unref(getIsHorizontal) ? false : undefined, + }) + }} + def={unref(getMenuType)} + /> + + ) + } + + function renderHeaderTheme() { + return ( + + ) + } + + function renderSiderTheme() { + return ( + + ) + } + + function renderMainTheme() { + return ( + + ) + } + + /** + * @description: + */ + function renderFeatures() { + let triggerDef = unref(getTrigger) + + const triggerOptions = getMenuTriggerOptions(unref(getSplit)) + const some = triggerOptions.some((item) => item.value === triggerDef) + if (!some) { + triggerDef = TriggerEnum.FOOTER + } + + return ( + <> + + + + + + + + + + + + + + + + + + + `${parseInt(value)}px`} + /> + + ) + } + + function renderContent() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + ) + } + + function renderTransition() { + return ( + <> + + + + + + + + ) + } + + return () => ( + + {unref(getShowDarkModeToggle) && {() => t('layout.setting.darkMode')}} + {unref(getShowDarkModeToggle) && } + {() => t('layout.setting.navMode')} + {renderSidebar()} + {() => t('layout.setting.sysTheme')} + {renderMainTheme()} + {() => t('layout.setting.headerTheme')} + {renderHeaderTheme()} + {() => t('layout.setting.sidebarTheme')} + {renderSiderTheme()} + {() => t('layout.setting.interfaceFunction')} + {renderFeatures()} + {() => t('layout.setting.interfaceDisplay')} + {renderContent()} + {() => t('layout.setting.animation')} + {renderTransition()} + + + + ) + }, +}) diff --git a/frontend/vben/src/layouts/default/setting/components/InputNumberItem.vue b/frontend/vben/src/layouts/default/setting/components/InputNumberItem.vue new file mode 100644 index 0000000..b16f2e2 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/InputNumberItem.vue @@ -0,0 +1,56 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/SelectItem.vue b/frontend/vben/src/layouts/default/setting/components/SelectItem.vue new file mode 100644 index 0000000..d7fdd09 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/SelectItem.vue @@ -0,0 +1,75 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/SettingFooter.vue b/frontend/vben/src/layouts/default/setting/components/SettingFooter.vue new file mode 100644 index 0000000..faee04e --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/SettingFooter.vue @@ -0,0 +1,99 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/SwitchItem.vue b/frontend/vben/src/layouts/default/setting/components/SwitchItem.vue new file mode 100644 index 0000000..41476a2 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/SwitchItem.vue @@ -0,0 +1,66 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/ThemeColorPicker.vue b/frontend/vben/src/layouts/default/setting/components/ThemeColorPicker.vue new file mode 100644 index 0000000..b345ef4 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/ThemeColorPicker.vue @@ -0,0 +1,88 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/TypePicker.vue b/frontend/vben/src/layouts/default/setting/components/TypePicker.vue new file mode 100644 index 0000000..b98d5ec --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/TypePicker.vue @@ -0,0 +1,178 @@ + + + diff --git a/frontend/vben/src/layouts/default/setting/components/index.ts b/frontend/vben/src/layouts/default/setting/components/index.ts new file mode 100644 index 0000000..ad42800 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/components/index.ts @@ -0,0 +1,8 @@ +import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent' + +export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue')) +export const ThemeColorPicker = createAsyncComponent(() => import('./ThemeColorPicker.vue')) +export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue')) +export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')) +export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')) +export const InputNumberItem = createAsyncComponent(() => import('./InputNumberItem.vue')) diff --git a/frontend/vben/src/layouts/default/setting/enum.ts b/frontend/vben/src/layouts/default/setting/enum.ts new file mode 100644 index 0000000..fd30f9d --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/enum.ts @@ -0,0 +1,155 @@ +import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum' +import { + MenuModeEnum, + MenuTypeEnum, + TopMenuAlignEnum, + TriggerEnum, + MixSidebarTriggerEnum, +} from '/@/enums/menuEnum' + +import { useI18n } from '/@/hooks/web/useI18n' + +const { t } = useI18n() + +export enum HandlerEnum { + CHANGE_LAYOUT, + CHANGE_THEME_COLOR, + CHANGE_THEME, + // menu + MENU_HAS_DRAG, + MENU_ACCORDION, + MENU_TRIGGER, + MENU_TOP_ALIGN, + MENU_COLLAPSED, + MENU_COLLAPSED_SHOW_TITLE, + MENU_WIDTH, + MENU_SHOW_SIDEBAR, + MENU_THEME, + MENU_SPLIT, + MENU_FIXED, + MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE, + MENU_TRIGGER_MIX_SIDEBAR, + MENU_FIXED_MIX_SIDEBAR, + + // header + HEADER_SHOW, + HEADER_THEME, + HEADER_FIXED, + + HEADER_SEARCH, + + TABS_SHOW_QUICK, + TABS_SHOW_REDO, + TABS_SHOW, + TABS_SHOW_FOLD, + + FULL_CONTENT, + CONTENT_MODE, + SHOW_BREADCRUMB, + SHOW_BREADCRUMB_ICON, + GRAY_MODE, + COLOR_WEAK, + SHOW_LOGO, + SHOW_FOOTER, + + ROUTER_TRANSITION, + OPEN_PROGRESS, + OPEN_PAGE_LOADING, + OPEN_ROUTE_TRANSITION, +} + +export const contentModeOptions = [ + { + value: ContentEnum.FULL, + label: t('layout.setting.contentModeFull'), + }, + { + value: ContentEnum.FIXED, + label: t('layout.setting.contentModeFixed'), + }, +] + +export const topMenuAlignOptions = [ + { + value: TopMenuAlignEnum.CENTER, + label: t('layout.setting.topMenuAlignRight'), + }, + { + value: TopMenuAlignEnum.START, + label: t('layout.setting.topMenuAlignLeft'), + }, + { + value: TopMenuAlignEnum.END, + label: t('layout.setting.topMenuAlignCenter'), + }, +] + +export const getMenuTriggerOptions = (hideTop: boolean) => { + return [ + { + value: TriggerEnum.NONE, + label: t('layout.setting.menuTriggerNone'), + }, + { + value: TriggerEnum.FOOTER, + label: t('layout.setting.menuTriggerBottom'), + }, + ...(hideTop + ? [] + : [ + { + value: TriggerEnum.HEADER, + label: t('layout.setting.menuTriggerTop'), + }, + ]), + ] +} + +export const routerTransitionOptions = [ + RouterTransitionEnum.ZOOM_FADE, + RouterTransitionEnum.FADE, + RouterTransitionEnum.ZOOM_OUT, + RouterTransitionEnum.FADE_SIDE, + RouterTransitionEnum.FADE_BOTTOM, + RouterTransitionEnum.FADE_SCALE, +].map((item) => { + return { + label: item, + value: item, + } +}) + +export const menuTypeList = [ + { + title: t('layout.setting.menuTypeSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.SIDEBAR, + }, + { + title: t('layout.setting.menuTypeMix'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX, + }, + + { + title: t('layout.setting.menuTypeTopMenu'), + mode: MenuModeEnum.HORIZONTAL, + type: MenuTypeEnum.TOP_MENU, + }, + { + title: t('layout.setting.menuTypeMixSidebar'), + mode: MenuModeEnum.INLINE, + type: MenuTypeEnum.MIX_SIDEBAR, + }, +] + +export const mixSidebarTriggerOptions = [ + { + value: MixSidebarTriggerEnum.HOVER, + label: t('layout.setting.triggerHover'), + }, + { + value: MixSidebarTriggerEnum.CLICK, + label: t('layout.setting.triggerClick'), + }, +] diff --git a/frontend/vben/src/layouts/default/setting/handler.ts b/frontend/vben/src/layouts/default/setting/handler.ts new file mode 100644 index 0000000..38394dc --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/handler.ts @@ -0,0 +1,171 @@ +import { HandlerEnum } from './enum' +import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground' +import { updateColorWeak } from '/@/logics/theme/updateColorWeak' +import { updateGrayMode } from '/@/logics/theme/updateGrayMode' + +import { useAppStore } from '/@/store/modules/app' +import { ProjectConfig } from '/#/config' +import { changeTheme } from '/@/logics/theme' +import { updateDarkTheme } from '/@/logics/theme/dark' +import { useRootSetting } from '/@/hooks/setting/useRootSetting' + +export function baseHandler(event: HandlerEnum, value: any) { + const appStore = useAppStore() + const config = handler(event, value) + appStore.setProjectConfig(config) + if (event === HandlerEnum.CHANGE_THEME) { + updateHeaderBgColor() + updateSidebarBgColor() + } +} + +export function handler(event: HandlerEnum, value: any): DeepPartial { + const appStore = useAppStore() + + const { getThemeColor, getDarkMode } = useRootSetting() + switch (event) { + case HandlerEnum.CHANGE_LAYOUT: + const { mode, type, split } = value + const splitOpt = split === undefined ? { split } : {} + + return { + menuSetting: { + mode, + type, + collapsed: false, + show: true, + hidden: false, + ...splitOpt, + }, + } + + case HandlerEnum.CHANGE_THEME_COLOR: + if (getThemeColor.value === value) { + return {} + } + changeTheme(value) + + return { themeColor: value } + + case HandlerEnum.CHANGE_THEME: + if (getDarkMode.value === value) { + return {} + } + updateDarkTheme(value) + + return {} + + case HandlerEnum.MENU_HAS_DRAG: + return { menuSetting: { canDrag: value } } + + case HandlerEnum.MENU_ACCORDION: + return { menuSetting: { accordion: value } } + + case HandlerEnum.MENU_TRIGGER: + return { menuSetting: { trigger: value } } + + case HandlerEnum.MENU_TOP_ALIGN: + return { menuSetting: { topMenuAlign: value } } + + case HandlerEnum.MENU_COLLAPSED: + return { menuSetting: { collapsed: value } } + + case HandlerEnum.MENU_WIDTH: + return { menuSetting: { menuWidth: value } } + + case HandlerEnum.MENU_SHOW_SIDEBAR: + return { menuSetting: { show: value } } + + case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: + return { menuSetting: { collapsedShowTitle: value } } + + case HandlerEnum.MENU_THEME: + updateSidebarBgColor(value) + return { menuSetting: { bgColor: value } } + + case HandlerEnum.MENU_SPLIT: + return { menuSetting: { split: value } } + + case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE: + return { menuSetting: { closeMixSidebarOnChange: value } } + + case HandlerEnum.MENU_FIXED: + return { menuSetting: { fixed: value } } + + case HandlerEnum.MENU_TRIGGER_MIX_SIDEBAR: + return { menuSetting: { mixSideTrigger: value } } + + case HandlerEnum.MENU_FIXED_MIX_SIDEBAR: + return { menuSetting: { mixSideFixed: value } } + + // ============transition================== + case HandlerEnum.OPEN_PAGE_LOADING: + appStore.setPageLoading(false) + return { transitionSetting: { openPageLoading: value } } + + case HandlerEnum.ROUTER_TRANSITION: + return { transitionSetting: { basicTransition: value } } + + case HandlerEnum.OPEN_ROUTE_TRANSITION: + return { transitionSetting: { enable: value } } + + case HandlerEnum.OPEN_PROGRESS: + return { transitionSetting: { openNProgress: value } } + // ============root================== + + case HandlerEnum.FULL_CONTENT: + return { fullContent: value } + + case HandlerEnum.CONTENT_MODE: + return { contentMode: value } + + case HandlerEnum.SHOW_BREADCRUMB: + return { showBreadCrumb: value } + + case HandlerEnum.SHOW_BREADCRUMB_ICON: + return { showBreadCrumbIcon: value } + + case HandlerEnum.GRAY_MODE: + updateGrayMode(value) + return { grayMode: value } + + case HandlerEnum.SHOW_FOOTER: + return { showFooter: value } + + case HandlerEnum.COLOR_WEAK: + updateColorWeak(value) + return { colorWeak: value } + + case HandlerEnum.SHOW_LOGO: + return { showLogo: value } + + // ============tabs================== + case HandlerEnum.TABS_SHOW_QUICK: + return { multiTabsSetting: { showQuick: value } } + + case HandlerEnum.TABS_SHOW: + return { multiTabsSetting: { show: value } } + + case HandlerEnum.TABS_SHOW_REDO: + return { multiTabsSetting: { showRedo: value } } + + case HandlerEnum.TABS_SHOW_FOLD: + return { multiTabsSetting: { showFold: value } } + + // ============header================== + case HandlerEnum.HEADER_THEME: + updateHeaderBgColor(value) + return { headerSetting: { bgColor: value } } + + case HandlerEnum.HEADER_SEARCH: + return { headerSetting: { showSearch: value } } + + case HandlerEnum.HEADER_FIXED: + return { headerSetting: { fixed: value } } + + case HandlerEnum.HEADER_SHOW: + return { headerSetting: { show: value } } + default: + return {} + } +} diff --git a/frontend/vben/src/layouts/default/setting/index.vue b/frontend/vben/src/layouts/default/setting/index.vue new file mode 100644 index 0000000..6be5298 --- /dev/null +++ b/frontend/vben/src/layouts/default/setting/index.vue @@ -0,0 +1,26 @@ + + diff --git a/frontend/vben/src/layouts/default/sider/DragBar.vue b/frontend/vben/src/layouts/default/sider/DragBar.vue new file mode 100644 index 0000000..ba079d4 --- /dev/null +++ b/frontend/vben/src/layouts/default/sider/DragBar.vue @@ -0,0 +1,66 @@ + + + diff --git a/frontend/vben/src/layouts/default/sider/LayoutSider.vue b/frontend/vben/src/layouts/default/sider/LayoutSider.vue new file mode 100644 index 0000000..e3ff63d --- /dev/null +++ b/frontend/vben/src/layouts/default/sider/LayoutSider.vue @@ -0,0 +1,185 @@ + + + diff --git a/frontend/vben/src/layouts/default/sider/MixSider.vue b/frontend/vben/src/layouts/default/sider/MixSider.vue new file mode 100644 index 0000000..4f2e880 --- /dev/null +++ b/frontend/vben/src/layouts/default/sider/MixSider.vue @@ -0,0 +1,590 @@ + + + diff --git a/frontend/vben/src/layouts/default/sider/index.vue b/frontend/vben/src/layouts/default/sider/index.vue new file mode 100644 index 0000000..fe69e6d --- /dev/null +++ b/frontend/vben/src/layouts/default/sider/index.vue @@ -0,0 +1,57 @@ + + + diff --git a/frontend/vben/src/layouts/default/sider/useLayoutSider.ts b/frontend/vben/src/layouts/default/sider/useLayoutSider.ts new file mode 100644 index 0000000..fe037e6 --- /dev/null +++ b/frontend/vben/src/layouts/default/sider/useLayoutSider.ts @@ -0,0 +1,143 @@ +import type { Ref } from 'vue' + +import { computed, unref, onMounted, nextTick } from 'vue' + +import { TriggerEnum } from '/@/enums/menuEnum' + +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting' +import { useDebounceFn } from '@vueuse/core' +import { useAppStore } from '/@/store/modules/app' + +/** + * Handle related operations of menu events + */ +export function useSiderEvent() { + const appStore = useAppStore() + const { getMiniWidthNumber } = useMenuSetting() + + const getCollapsedWidth = computed(() => { + return unref(getMiniWidthNumber) + }) + + function onBreakpointChange(broken: boolean) { + appStore.setProjectConfig({ + menuSetting: { + siderHidden: broken, + }, + }) + } + + return { getCollapsedWidth, onBreakpointChange } +} + +/** + * Handle related operations of menu folding + */ +export function useTrigger(getIsMobile: Ref) { + const { getTrigger, getSplit } = useMenuSetting() + + const getShowTrigger = computed(() => { + const trigger = unref(getTrigger) + + return ( + trigger !== TriggerEnum.NONE && + !unref(getIsMobile) && + (trigger === TriggerEnum.FOOTER || unref(getSplit)) + ) + }) + + const getTriggerAttr = computed(() => { + if (unref(getShowTrigger)) { + return {} + } + return { + trigger: null, + } + }) + + return { getTriggerAttr, getShowTrigger } +} + +/** + * Handle menu drag and drop related operations + * @param siderRef + * @param dragBarRef + */ +export function useDragLine(siderRef: Ref, dragBarRef: Ref, mix = false) { + const { getMiniWidthNumber, getCollapsed, setMenuSetting } = useMenuSetting() + + onMounted(() => { + nextTick(() => { + const exec = useDebounceFn(changeWrapWidth, 80) + exec() + }) + }) + + function getEl(elRef: Ref): any { + const el = unref(elRef) + if (!el) return null + if (Reflect.has(el, '$el')) { + return (unref(elRef) as ComponentRef)?.$el + } + return unref(elRef) + } + + function handleMouseMove(ele: HTMLElement, wrap: HTMLElement, clientX: number) { + document.onmousemove = function (innerE) { + let iT = (ele as any).left + (innerE.clientX - clientX) + innerE = innerE || window.event + const maxT = 800 + const minT = unref(getMiniWidthNumber) + iT < 0 && (iT = 0) + iT > maxT && (iT = maxT) + iT < minT && (iT = minT) + ele.style.left = wrap.style.width = iT + 'px' + return false + } + } + + // Drag and drop in the menu area-release the mouse + function removeMouseup(ele: any) { + const wrap = getEl(siderRef) + document.onmouseup = function () { + document.onmousemove = null + document.onmouseup = null + wrap.style.transition = 'width 0.2s' + const width = parseInt(wrap.style.width) + + if (!mix) { + const miniWidth = unref(getMiniWidthNumber) + if (!unref(getCollapsed)) { + width > miniWidth + 20 + ? setMenuSetting({ menuWidth: width }) + : setMenuSetting({ collapsed: true }) + } else { + width > miniWidth && setMenuSetting({ collapsed: false, menuWidth: width }) + } + } else { + setMenuSetting({ menuWidth: width }) + } + + ele.releaseCapture?.() + } + } + + function changeWrapWidth() { + const ele = getEl(dragBarRef) + if (!ele) return + const wrap = getEl(siderRef) + if (!wrap) return + + ele.onmousedown = (e: any) => { + wrap.style.transition = 'unset' + const clientX = e?.clientX + ele.left = ele.offsetLeft + handleMouseMove(ele, wrap, clientX) + removeMouseup(ele) + ele.setCapture?.() + return false + } + } + + return {} +} diff --git a/frontend/vben/src/layouts/default/tabs/components/FoldButton.vue b/frontend/vben/src/layouts/default/tabs/components/FoldButton.vue new file mode 100644 index 0000000..52ad0b3 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/components/FoldButton.vue @@ -0,0 +1,42 @@ + + diff --git a/frontend/vben/src/layouts/default/tabs/components/TabContent.vue b/frontend/vben/src/layouts/default/tabs/components/TabContent.vue new file mode 100644 index 0000000..fb802e7 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/components/TabContent.vue @@ -0,0 +1,76 @@ + + diff --git a/frontend/vben/src/layouts/default/tabs/components/TabRedo.vue b/frontend/vben/src/layouts/default/tabs/components/TabRedo.vue new file mode 100644 index 0000000..ebe0a59 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/components/TabRedo.vue @@ -0,0 +1,33 @@ + + diff --git a/frontend/vben/src/layouts/default/tabs/index.less b/frontend/vben/src/layouts/default/tabs/index.less new file mode 100644 index 0000000..e6cdeb3 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/index.less @@ -0,0 +1,207 @@ +@prefix-cls: ~'@{namespace}-multiple-tabs'; + +html[data-theme='dark'] { + .@{prefix-cls} { + .ant-tabs-tab { + border-bottom: 1px solid @border-color-base; + } + } +} + +html[data-theme='light'] { + .@{prefix-cls} { + .ant-tabs-tab:not(.ant-tabs-tab-active) { + border: 1px solid #d9d9d9 !important; + } + } +} + +.@{prefix-cls} { + z-index: 10; + height: @multiple-height + 2; + line-height: @multiple-height + 2; + background-color: @component-background; + border-bottom: 1px solid @border-color-base; + + .ant-tabs-small { + height: @multiple-height; + } + + .ant-tabs.ant-tabs-card { + .ant-tabs-nav { + padding-top: 2px; + height: @multiple-height; + margin: 0; + background-color: @component-background; + border: 0; + box-shadow: none; + + .ant-tabs-nav-container { + height: @multiple-height; + padding-top: 2px; + } + + .ant-tabs-tab { + height: calc(@multiple-height - 2px); + padding-right: 12px; + line-height: calc(@multiple-height - 2px); + color: @text-color-base; + background-color: @component-background; + transition: none; + + &:hover { + .ant-tabs-tab-remove { + opacity: 1; + } + } + + .ant-tabs-tab-remove { + width: 8px; + height: 28px; + font-size: 12px; + color: inherit; + opacity: 0; + transition: none; + margin-left: 2px; + margin-right: -4px; + + &:hover { + svg { + width: 0.8em; + } + } + } + + // > div { + // display: flex; + // justify-content: center; + // align-items: center; + // } + + svg { + fill: @text-color-base; + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + &:hover { + color: @primary-color; + } + } + + .ant-tabs-tab-active { + position: relative; + padding-left: 18px; + background: @primary-color; + border: 0; + transition: none; + + span { + color: @white !important; + } + + .ant-tabs-tab-remove { + opacity: 1; + } + + svg { + width: 0.7em; + fill: @white; + } + } + } + + .ant-tabs-nav > div:nth-child(1) { + padding: 0 6px; + + .ant-tabs-tab { + margin-right: 3px !important; + } + } + } + + .ant-tabs-tab:not(.ant-tabs-tab-active) { + .anticon-close { + font-size: 12px; + + svg { + width: 0.6em; + } + } + } + + .ant-dropdown-trigger { + display: inline-flex; + } + + &--hide-close { + .ant-tabs-tab-remove { + opacity: 0 !important; + } + } + + &-content { + &__extra-quick, + &__extra-redo, + &__extra-fold { + display: inline-block; + width: 36px; + height: @multiple-height; + line-height: @multiple-height; + color: @text-color-secondary; + text-align: center; + cursor: pointer; + border-left: 1px solid @border-color-base; + + &:hover { + color: @text-color-base; + } + + span[role='img'] { + transform: rotate(90deg); + } + } + + &__extra-redo { + span[role='img'] { + transform: rotate(0deg); + } + } + + &__info { + display: inline-block; + width: 100%; + height: @multiple-height - 2; + padding-left: 0; + margin-left: -10px; + font-size: 12px; + cursor: pointer; + user-select: none; + } + } +} + +.ant-tabs-dropdown-menu { + &-title-content { + display: flex; + align-items: center; + + .@{prefix-cls} { + &-content__info { + width: auto; + margin-left: 0; + line-height: 28px; + } + } + } + + &-item-remove { + margin-left: auto; + } +} + +.multiple-tabs__dropdown { + .ant-dropdown-content { + width: 172px; + } +} diff --git a/frontend/vben/src/layouts/default/tabs/index.vue b/frontend/vben/src/layouts/default/tabs/index.vue new file mode 100644 index 0000000..7025adb --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/index.vue @@ -0,0 +1,142 @@ + + + diff --git a/frontend/vben/src/layouts/default/tabs/types.ts b/frontend/vben/src/layouts/default/tabs/types.ts new file mode 100644 index 0000000..af60946 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/types.ts @@ -0,0 +1,25 @@ +import type { DropMenu } from '/@/components/Dropdown/index' +import type { RouteLocationNormalized } from 'vue-router' + +export enum TabContentEnum { + TAB_TYPE, + EXTRA_TYPE, +} + +export type { DropMenu } + +export interface TabContentProps { + tabItem: RouteLocationNormalized + type?: TabContentEnum + trigger?: ('click' | 'hover' | 'contextmenu')[] +} + +export enum MenuEventEnum { + REFRESH_PAGE, + CLOSE_CURRENT, + CLOSE_LEFT, + CLOSE_RIGHT, + CLOSE_OTHER, + CLOSE_ALL, + SCALE, +} diff --git a/frontend/vben/src/layouts/default/tabs/useMultipleTabs.ts b/frontend/vben/src/layouts/default/tabs/useMultipleTabs.ts new file mode 100644 index 0000000..bfd888c --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/useMultipleTabs.ts @@ -0,0 +1,80 @@ +import { toRaw, ref, nextTick } from 'vue' +import type { RouteLocationNormalized } from 'vue-router' +import { useDesign } from '/@/hooks/web/useDesign' +import { useSortable } from '/@/hooks/web/useSortable' +import { useMultipleTabStore } from '/@/store/modules/multipleTab' +import { isNullAndUnDef } from '/@/utils/is' +import projectSetting from '/@/settings/projectSetting' +import { useRouter } from 'vue-router' + +export function initAffixTabs(): string[] { + const affixList = ref([]) + + const tabStore = useMultipleTabStore() + const router = useRouter() + /** + * @description: Filter all fixed routes + */ + function filterAffixTabs(routes: RouteLocationNormalized[]) { + const tabs: RouteLocationNormalized[] = [] + routes && + routes.forEach((route) => { + if (route.meta && route.meta.affix) { + tabs.push(toRaw(route)) + } + }) + return tabs + } + + /** + * @description: Set fixed tabs + */ + function addAffixTabs(): void { + const affixTabs = filterAffixTabs(router.getRoutes() as unknown as RouteLocationNormalized[]) + affixList.value = affixTabs + for (const tab of affixTabs) { + tabStore.addTab({ + meta: tab.meta, + name: tab.name, + path: tab.path, + } as unknown as RouteLocationNormalized) + } + } + + let isAddAffix = false + + if (!isAddAffix) { + addAffixTabs() + isAddAffix = true + } + return affixList.value.map((item) => item.meta?.title).filter(Boolean) as string[] +} + +export function useTabsDrag(affixTextList: string[]) { + const tabStore = useMultipleTabStore() + const { multiTabsSetting } = projectSetting + const { prefixCls } = useDesign('multiple-tabs') + nextTick(() => { + if (!multiTabsSetting.canDrag) return + const el = document.querySelectorAll( + `.${prefixCls} .ant-tabs-nav-wrap > div`, + )?.[0] as HTMLElement + const { initSortable } = useSortable(el, { + filter: (e: ChangeEvent) => { + const text = e?.target?.innerText + if (!text) return false + return affixTextList.includes(text) + }, + onEnd: (evt) => { + const { oldIndex, newIndex } = evt + + if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) { + return + } + + tabStore.sortTabs(oldIndex, newIndex) + }, + }) + initSortable() + }) +} diff --git a/frontend/vben/src/layouts/default/tabs/useTabDropdown.ts b/frontend/vben/src/layouts/default/tabs/useTabDropdown.ts new file mode 100644 index 0000000..07e24f2 --- /dev/null +++ b/frontend/vben/src/layouts/default/tabs/useTabDropdown.ts @@ -0,0 +1,140 @@ +import type { TabContentProps } from './types' +import type { DropMenu } from '/@/components/Dropdown' +import type { ComputedRef } from 'vue' + +import { computed, unref, reactive } from 'vue' +import { MenuEventEnum } from './types' +import { useMultipleTabStore } from '/@/store/modules/multipleTab' +import { RouteLocationNormalized, useRouter } from 'vue-router' +import { useTabs } from '/@/hooks/web/useTabs' +import { useI18n } from '/@/hooks/web/useI18n' + +export function useTabDropdown(tabContentProps: TabContentProps, getIsTabs: ComputedRef) { + const state = reactive({ + current: null as Nullable, + currentIndex: 0, + }) + + const { t } = useI18n() + const tabStore = useMultipleTabStore() + const { currentRoute } = useRouter() + const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs() + + const getTargetTab = computed((): RouteLocationNormalized => { + return unref(getIsTabs) ? tabContentProps.tabItem : unref(currentRoute) + }) + + /** + * @description: drop-down list + */ + const getDropMenuList = computed(() => { + if (!unref(getTargetTab)) { + return + } + const { meta } = unref(getTargetTab) + const { path } = unref(currentRoute) + + const curItem = state.current + + const isCurItem = curItem ? curItem.path === path : false + + // Refresh button + const index = state.currentIndex + const refreshDisabled = !isCurItem + // Close left + const closeLeftDisabled = index === 0 || !isCurItem + + const disabled = tabStore.getTabList.length === 1 + + // Close right + const closeRightDisabled = + !isCurItem || (index === tabStore.getTabList.length - 1 && tabStore.getLastDragEndIndex >= 0) + const dropMenuList: DropMenu[] = [ + { + icon: 'ion:reload-sharp', + event: MenuEventEnum.REFRESH_PAGE, + text: t('layout.multipleTab.reload'), + disabled: refreshDisabled, + }, + { + icon: 'clarity:close-line', + event: MenuEventEnum.CLOSE_CURRENT, + text: t('layout.multipleTab.close'), + disabled: !!meta?.affix || disabled, + divider: true, + }, + { + icon: 'line-md:arrow-close-left', + event: MenuEventEnum.CLOSE_LEFT, + text: t('layout.multipleTab.closeLeft'), + disabled: closeLeftDisabled, + divider: false, + }, + { + icon: 'line-md:arrow-close-right', + event: MenuEventEnum.CLOSE_RIGHT, + text: t('layout.multipleTab.closeRight'), + disabled: closeRightDisabled, + divider: true, + }, + { + icon: 'dashicons:align-center', + event: MenuEventEnum.CLOSE_OTHER, + text: t('layout.multipleTab.closeOther'), + disabled: disabled || !isCurItem, + }, + { + icon: 'clarity:minus-line', + event: MenuEventEnum.CLOSE_ALL, + text: t('layout.multipleTab.closeAll'), + disabled: disabled, + }, + ] + + return dropMenuList + }) + + function handleContextMenu(tabItem: RouteLocationNormalized) { + return (e: Event) => { + if (!tabItem) { + return + } + e?.preventDefault() + const index = tabStore.getTabList.findIndex((tab) => tab.path === tabItem.path) + state.current = tabItem + state.currentIndex = index + } + } + + // Handle right click event + function handleMenuEvent(menu: DropMenu): void { + const { event } = menu + switch (event) { + case MenuEventEnum.REFRESH_PAGE: + // refresh page + refreshPage() + break + // Close current + case MenuEventEnum.CLOSE_CURRENT: + close(tabContentProps.tabItem) + break + // Close left + case MenuEventEnum.CLOSE_LEFT: + closeLeft() + break + // Close right + case MenuEventEnum.CLOSE_RIGHT: + closeRight() + break + // Close other + case MenuEventEnum.CLOSE_OTHER: + closeOther() + break + // Close all + case MenuEventEnum.CLOSE_ALL: + closeAll() + break + } + } + return { getDropMenuList, handleMenuEvent, handleContextMenu } +} diff --git a/frontend/vben/src/layouts/default/trigger/HeaderTrigger.vue b/frontend/vben/src/layouts/default/trigger/HeaderTrigger.vue new file mode 100644 index 0000000..ee96427 --- /dev/null +++ b/frontend/vben/src/layouts/default/trigger/HeaderTrigger.vue @@ -0,0 +1,25 @@ + + diff --git a/frontend/vben/src/layouts/default/trigger/SiderTrigger.vue b/frontend/vben/src/layouts/default/trigger/SiderTrigger.vue new file mode 100644 index 0000000..dffcee7 --- /dev/null +++ b/frontend/vben/src/layouts/default/trigger/SiderTrigger.vue @@ -0,0 +1,21 @@ + + diff --git a/frontend/vben/src/layouts/default/trigger/index.vue b/frontend/vben/src/layouts/default/trigger/index.vue new file mode 100644 index 0000000..c667eb7 --- /dev/null +++ b/frontend/vben/src/layouts/default/trigger/index.vue @@ -0,0 +1,22 @@ + + diff --git a/frontend/vben/src/layouts/page/index.vue b/frontend/vben/src/layouts/page/index.vue new file mode 100644 index 0000000..b1c4c49 --- /dev/null +++ b/frontend/vben/src/layouts/page/index.vue @@ -0,0 +1,67 @@ + + + diff --git a/frontend/vben/src/layouts/page/transition.ts b/frontend/vben/src/layouts/page/transition.ts new file mode 100644 index 0000000..5a3fedf --- /dev/null +++ b/frontend/vben/src/layouts/page/transition.ts @@ -0,0 +1,33 @@ +import type { FunctionalComponent } from 'vue' +import type { RouteLocation } from 'vue-router' + +export interface DefaultContext { + Component: FunctionalComponent & { type: Recordable } + route: RouteLocation +} + +export function getTransitionName({ + route, + openCache, + cacheTabs, + enableTransition, + def, +}: Pick & { + enableTransition: boolean + openCache: boolean + def: string + cacheTabs: string[] +}): string | undefined { + if (!enableTransition) { + return undefined + } + + const isInCache = cacheTabs.includes(route.name as string) + const transitionName = 'fade-slide' + let name: string | undefined = transitionName + + if (openCache) { + name = isInCache && route.meta.loaded ? transitionName : undefined + } + return name || (route.meta.transitionName as string) || def +} diff --git a/frontend/vben/src/locales/helper.ts b/frontend/vben/src/locales/helper.ts new file mode 100644 index 0000000..c09ade9 --- /dev/null +++ b/frontend/vben/src/locales/helper.ts @@ -0,0 +1,37 @@ +import type { LocaleType } from '/#/config' + +import { set } from 'lodash-es' + +export const loadLocalePool: LocaleType[] = [] + +export function setHtmlPageLang(locale: LocaleType) { + document.querySelector('html')?.setAttribute('lang', locale) +} + +export function setLoadLocalePool(cb: (loadLocalePool: LocaleType[]) => void) { + cb(loadLocalePool) +} + +export function genMessage(langs: Record>, prefix = 'lang') { + const obj: Recordable = {} + + Object.keys(langs).forEach((key) => { + const langFileModule = langs[key].default + let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, '') + const lastIndex = fileName.lastIndexOf('.') + fileName = fileName.substring(0, lastIndex) + const keyList = fileName.split('/') + const moduleName = keyList.shift() + const objKey = keyList.join('.') + + if (moduleName) { + if (objKey) { + set(obj, moduleName, obj[moduleName] || {}) + set(obj[moduleName], objKey, langFileModule) + } else { + set(obj, moduleName, langFileModule || {}) + } + } + }) + return obj +} diff --git a/frontend/vben/src/locales/lang/en.ts b/frontend/vben/src/locales/lang/en.ts new file mode 100644 index 0000000..239145d --- /dev/null +++ b/frontend/vben/src/locales/lang/en.ts @@ -0,0 +1,12 @@ +import { genMessage } from '../helper' +import antdLocale from 'ant-design-vue/es/locale/en_US' + +const modules = import.meta.globEager('./en/**/*.ts') +export default { + message: { + ...genMessage(modules, 'en'), + antdLocale, + }, + dateLocale: null, + dateLocaleName: 'en', +} diff --git a/frontend/vben/src/locales/lang/en/common.ts b/frontend/vben/src/locales/lang/en/common.ts new file mode 100644 index 0000000..b919e03 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/common.ts @@ -0,0 +1,20 @@ +export default { + okText: 'OK', + closeText: 'Close', + cancelText: 'Cancel', + loadingText: 'Loading...', + saveText: 'Save', + delText: 'Delete', + resetText: 'Reset', + searchText: 'Search', + queryText: 'Search', + + inputText: 'Please enter', + chooseText: 'Please choose', + + redo: 'Refresh', + back: 'Back', + + light: 'Light', + dark: 'Dark', +} diff --git a/frontend/vben/src/locales/lang/en/component.ts b/frontend/vben/src/locales/lang/en/component.ts new file mode 100644 index 0000000..3de9087 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/component.ts @@ -0,0 +1,129 @@ +export default { + app: { + searchNotData: 'No search results yet', + toSearch: 'to search', + toNavigate: 'to navigate', + }, + countdown: { + normalText: 'Get SMS code', + sendText: 'Reacquire in {0}s', + }, + cropper: { + selectImage: 'Select Image', + uploadSuccess: 'Uploaded success!', + modalTitle: 'Avatar upload', + okText: 'Confirm and upload', + btn_reset: 'Reset', + btn_rotate_left: 'Counterclockwise rotation', + btn_rotate_right: 'Clockwise rotation', + btn_scale_x: 'Flip horizontal', + btn_scale_y: 'Flip vertical', + btn_zoom_in: 'Zoom in', + btn_zoom_out: 'Zoom out', + preview: 'Preivew', + }, + drawer: { + loadingText: 'Loading...', + cancelText: 'Close', + okText: 'Confirm', + }, + excel: { + exportModalTitle: 'Export data', + fileType: 'File type', + fileName: 'File name', + }, + form: { + putAway: 'Put away', + unfold: 'Unfold', + maxTip: 'The number of characters should be less than {0}', + apiSelectNotFound: 'Wait for data loading to complete...', + }, + icon: { + placeholder: 'Click the select icon', + search: 'Search icon', + copy: 'Copy icon successfully!', + }, + menu: { + search: 'Menu search', + }, + modal: { + cancelText: 'Close', + okText: 'Confirm', + close: 'Close', + maximize: 'Maximize', + restore: 'Restore', + }, + table: { + settingDens: 'Density', + settingDensDefault: 'Default', + settingDensMiddle: 'Middle', + settingDensSmall: 'Compact', + settingColumn: 'Column settings', + settingColumnShow: 'Column display', + settingIndexColumnShow: 'Index Column', + settingSelectColumnShow: 'Selection Column', + settingFixedLeft: 'Fixed Left', + settingFixedRight: 'Fixed Right', + settingFullScreen: 'Full Screen', + index: 'Index', + total: 'total of {total}', + }, + time: { + before: ' ago', + after: ' after', + just: 'just now', + seconds: ' seconds', + minutes: ' minutes', + hours: ' hours', + days: ' days', + }, + tree: { + selectAll: 'Select All', + unSelectAll: 'Cancel Select', + expandAll: 'Expand All', + unExpandAll: 'Collapse all', + + checkStrictly: 'Hierarchical association', + checkUnStrictly: 'Hierarchical independence', + }, + upload: { + save: 'Save', + upload: 'Upload', + imgUpload: 'ImageUpload', + uploaded: 'Uploaded', + + operating: 'Operating', + del: 'Delete', + download: 'download', + saveWarn: 'Please wait for the file to upload and save!', + saveError: 'There is no file successfully uploaded and cannot be saved!', + + preview: 'Preview', + choose: 'Select the file', + + accept: 'Support {0} format', + acceptUpload: 'Only upload files in {0} format', + maxSize: 'A single file does not exceed {0}MB ', + maxSizeMultiple: 'Only upload files up to {0}MB!', + maxNumber: 'Only upload up to {0} files', + + legend: 'Legend', + fileName: 'File name', + fileSize: 'File size', + fileStatue: 'File status', + + startUpload: 'Start upload', + uploadSuccess: 'Upload successfully', + uploadError: 'Upload failed', + uploading: 'Uploading', + uploadWait: 'Please wait for the file upload to finish', + reUploadFailed: 'Re-upload failed files', + }, + verify: { + error: 'verification failed!', + time: 'The verification is successful and it takes {time} seconds!', + redoTip: 'Click the picture to refresh', + dragText: 'Hold down the slider and drag', + successText: 'Verified', + }, +} diff --git a/frontend/vben/src/locales/lang/en/layout.ts b/frontend/vben/src/locales/lang/en/layout.ts new file mode 100644 index 0000000..bc49ad5 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/layout.ts @@ -0,0 +1,106 @@ +export default { + footer: { onlinePreview: 'Preview', onlineDocument: 'Document' }, + header: { + // user dropdown + dropdownItemDoc: 'Document', + dropdownItemLoginOut: 'Login Out', + + tooltipErrorLog: 'Error log', + tooltipNotify: 'Notification', + + tooltipEntryFull: 'Full Screen', + tooltipExitFull: 'Exit Full Screen', + + home: 'Home', + }, + multipleTab: { + reload: 'Refresh current', + close: 'Close current', + closeLeft: 'Close Left', + closeRight: 'Close Right', + closeOther: 'Close Other', + closeAll: 'Close All', + }, + setting: { + // content mode + contentModeFull: 'Full', + contentModeFixed: 'Fixed width', + // topMenu align + topMenuAlignLeft: 'Left', + topMenuAlignRight: 'Center', + topMenuAlignCenter: 'Right', + // menu trigger + menuTriggerNone: 'Not Show', + menuTriggerBottom: 'Bottom', + menuTriggerTop: 'Top', + // menu type + menuTypeSidebar: 'Left menu mode', + menuTypeMixSidebar: 'Left menu mixed mode', + menuTypeMix: 'Top Menu Mix mode', + menuTypeTopMenu: 'Top menu mode', + + on: 'On', + off: 'Off', + minute: 'Minute', + + operatingTitle: 'Successful!', + operatingContent: + 'The copy is successful, please go to src/settings/projectSetting.ts to modify the configuration!', + resetSuccess: 'Successfully reset!', + + copyBtn: 'Copy', + clearBtn: 'Clear cache and to the login page', + + drawerTitle: 'Configuration', + + darkMode: 'Dark mode', + navMode: 'Navigation mode', + interfaceFunction: 'Interface function', + interfaceDisplay: 'Interface display', + animation: 'Animation', + splitMenu: 'Split menu', + closeMixSidebarOnChange: 'Switch page to close menu', + + sysTheme: 'System theme', + headerTheme: 'Header theme', + sidebarTheme: 'Menu theme', + + menuDrag: 'Drag Sidebar', + menuSearch: 'Menu search', + menuAccordion: 'Sidebar accordion', + menuCollapse: 'Collapse menu', + collapseMenuDisplayName: 'Collapse menu display name', + topMenuLayout: 'Top menu layout', + menuCollapseButton: 'Menu collapse button', + contentMode: 'Content area width', + expandedMenuWidth: 'Expanded menu width', + + breadcrumb: 'Breadcrumbs', + breadcrumbIcon: 'Breadcrumbs Icon', + tabs: 'Tabs', + tabDetail: 'Tab Detail', + tabsQuickBtn: 'Tabs quick button', + tabsRedoBtn: 'Tabs redo button', + tabsFoldBtn: 'Tabs flod button', + sidebar: 'Sidebar', + header: 'Header', + footer: 'Footer', + fullContent: 'Full content', + grayMode: 'Gray mode', + colorWeak: 'Color Weak Mode', + + progress: 'Progress', + switchLoading: 'Switch Loading', + switchAnimation: 'Switch animation', + animationType: 'Animation type', + + fixedHeader: 'Fixed header', + fixedSideBar: 'Fixed Sidebar', + + mixSidebarTrigger: 'Mixed menu Trigger', + triggerHover: 'Hover', + triggerClick: 'Click', + + mixSidebarFixed: 'Fixed expanded menu', + }, +} diff --git a/frontend/vben/src/locales/lang/en/routes/basic.ts b/frontend/vben/src/locales/lang/en/routes/basic.ts new file mode 100644 index 0000000..a347312 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/routes/basic.ts @@ -0,0 +1,4 @@ +export default { + login: 'Login', + errorLogList: 'Error Log', +} diff --git a/frontend/vben/src/locales/lang/en/routes/dashboard.ts b/frontend/vben/src/locales/lang/en/routes/dashboard.ts new file mode 100644 index 0000000..8107085 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/routes/dashboard.ts @@ -0,0 +1,6 @@ +export default { + dashboard: 'Dashboard', + about: 'About', + workbench: 'Workbench', + analysis: 'Analysis', +} diff --git a/frontend/vben/src/locales/lang/en/routes/demo.ts b/frontend/vben/src/locales/lang/en/routes/demo.ts new file mode 100644 index 0000000..e9c2476 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/routes/demo.ts @@ -0,0 +1,189 @@ +export default { + charts: { + baiduMap: 'Baidu map', + aMap: 'A map', + googleMap: 'Google map', + charts: 'Chart', + map: 'Map', + line: 'Line', + pie: 'Pie', + }, + comp: { + comp: 'Component', + basic: 'Basic', + transition: 'Animation', + + scroll: 'Scroll', + scrollBasic: 'Basic', + scrollAction: 'Scroll Function', + virtualScroll: 'Virtual Scroll', + + tree: 'Tree', + + treeBasic: 'Basic', + editTree: 'Searchable/toolbar', + actionTree: 'Function operation', + + modal: 'Modal', + drawer: 'Drawer', + desc: 'Desc', + + lazy: 'Lazy', + lazyBasic: 'Basic', + lazyTransition: 'Animation', + + verify: 'Verify', + verifyDrag: 'Drag ', + verifyRotate: 'Picture Restore', + + strength: 'Password strength', + upload: 'Upload', + + loading: 'Loading', + + time: 'Relative Time', + cropperImage: 'Cropper Image', + }, + editor: { + editor: 'Editor', + jsonEditor: 'Json editor', + markdown: 'Markdown editor', + + tinymce: 'Rich text', + tinymceBasic: 'Basic', + tinymceForm: 'embedded form', + }, + excel: { + excel: 'Excel', + customExport: 'Select export format', + jsonExport: 'JSON data export', + arrayExport: 'Array data export', + importExcel: 'Import', + }, + feat: { + feat: 'Page Function', + icon: 'Icon', + tabs: 'Tabs', + tabDetail: 'Tab Detail', + sessionTimeout: 'Session Timeout', + contextMenu: 'Context Menu', + download: 'Download', + imgPreview: 'Picture Preview', + copy: 'Clipboard', + msg: 'Message prompt', + watermark: 'Watermark', + ripple: 'Ripple', + fullScreen: 'Full Screen', + errorLog: 'Error Log', + tab: 'Tab with parameters', + tab1: 'Tab with parameter 1', + tab2: 'Tab with parameter 2', + menu: 'Menu with parameters', + menu1: 'Menu with parameters 1', + menu2: 'Menu with parameters 2', + + breadcrumb: 'Breadcrumbs', + breadcrumbFlat: 'Flat Mode', + breadcrumbFlatDetail: 'Flat mode details', + requestDemo: 'Retry request demo', + + breadcrumbChildren: 'Level mode', + breadcrumbChildrenDetail: 'Level mode detail', + }, + flow: { + name: 'Graphics editor', + flowChart: 'FlowChart', + }, + form: { + form: 'Form', + basic: 'Basic', + useForm: 'useForm', + refForm: 'RefForm', + advancedForm: 'Shrinkable', + ruleForm: 'Form validation', + dynamicForm: 'Dynamic', + customerForm: 'Custom', + appendForm: 'Append', + tabsForm: 'TabsForm', + }, + level: { level: 'MultiMenu' }, + page: { + page: 'Page', + + form: 'Form', + formBasic: 'Basic Form', + formStep: 'Step Form', + formHigh: 'Advanced Form', + + desc: 'Details', + descBasic: 'Basic Details', + descHigh: 'Advanced Details', + + result: 'Result', + resultSuccess: 'Success', + resultFail: 'Failed', + + account: 'Personal', + accountCenter: 'Personal Center', + accountSetting: 'Personal Settings', + + exception: 'Exception', + netWorkError: 'Network Error', + notData: 'No data', + + list: 'List page', + listCard: 'Card list', + basic: 'Basic list', + listBasic: 'Basic list', + listSearch: 'Search list', + }, + permission: { + permission: 'Permission', + + front: 'front-end', + frontPage: 'Page', + frontBtn: 'Button', + frontTestA: 'Test page A', + frontTestB: 'Test page B', + + back: 'background', + backPage: 'Page', + backBtn: 'Button', + }, + setup: { + page: 'Intro page', + }, + system: { + moduleName: 'System management', + + account: 'Account management', + account_detail: 'Account detail', + password: 'Change password', + + dept: 'Department management', + + menu: 'Menu management', + role: 'Role management', + }, + table: { + table: 'Table', + + basic: 'Basic', + treeTable: 'Tree', + fetchTable: 'Remote loading', + fixedColumn: 'Fixed column', + customerCell: 'Custom column', + formTable: 'Open search', + useTable: 'UseTable', + refTable: 'RefTable', + multipleHeader: 'MultiLevel header', + mergeHeader: 'Merge cells', + expandTable: 'Expandable table', + fixedHeight: 'Fixed height', + footerTable: 'Footer', + editCellTable: 'Editable cell', + editRowTable: 'Editable row', + authColumn: 'Auth column', + resizeParentHeightTable: 'resizeParentHeightTable', + }, +} diff --git a/frontend/vben/src/locales/lang/en/sys.ts b/frontend/vben/src/locales/lang/en/sys.ts new file mode 100644 index 0000000..5844b38 --- /dev/null +++ b/frontend/vben/src/locales/lang/en/sys.ts @@ -0,0 +1,96 @@ +export default { + api: { + operationFailed: 'Operation failed', + errorTip: 'Error Tip', + errorMessage: 'The operation failed, the system is abnormal!', + timeoutMessage: 'Login timed out, please log in again!', + apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!', + apiRequestFailed: 'The interface request failed, please try again later!', + networkException: 'network anomaly', + networkExceptionMsg: + 'Please check if your network connection is normal! The network is abnormal', + + errMsg401: 'The user does not have permission (token, user name, password error)!', + errMsg403: 'The user is authorized, but access is forbidden!', + errMsg404: 'Network request error, the resource was not found!', + errMsg405: 'Network request error, request method not allowed!', + errMsg408: 'Network request timed out!', + errMsg500: 'Server error, please contact the administrator!', + errMsg501: 'The network is not implemented!', + errMsg502: 'Network Error!', + errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!', + errMsg504: 'Network timeout!', + errMsg505: 'The http version does not support the request!', + }, + app: { + logoutTip: 'Reminder', + logoutMessage: 'Confirm to exit the system?', + menuLoading: 'Menu loading...', + }, + errorLog: { + tableTitle: 'Error log list', + tableColumnType: 'Type', + tableColumnDate: 'Time', + tableColumnFile: 'File', + tableColumnMsg: 'Error message', + tableColumnStackMsg: 'Stack info', + + tableActionDesc: 'Details', + + modalTitle: 'Error details', + + fireVueError: 'Fire vue error', + fireResourceError: 'Fire resource error', + fireAjaxError: 'Fire ajax error', + + enableMessage: 'Only effective when useErrorHandle=true in `/src/settings/projectSetting.ts`.', + }, + exception: { + backLogin: 'Back Login', + backHome: 'Back Home', + subTitle403: "Sorry, you don't have access to this page.", + subTitle404: 'Sorry, the page you visited does not exist.', + subTitle500: 'Sorry, the server is reporting an error.', + noDataTitle: 'No data on the current page.', + networkErrorTitle: 'Network Error', + networkErrorSubTitle: + 'Sorry,Your network connection has been disconnected, please check your network!', + }, + login: { + backSignIn: 'Back sign in', + mobileSignInFormTitle: 'Mobile sign in', + signInFormTitle: 'Sign in', + signUpFormTitle: 'Sign up', + forgetFormTitle: 'Reset password', + + signInTitle: 'Backstage management system', + signInDesc: 'Enter your personal details and get started!', + policy: 'I agree to the xxx Privacy Policy', + scanSign: `scanning the code to complete the login`, + + loginButton: 'Sign in', + registerButton: 'Sign up', + rememberMe: 'Remember me', + forgetPassword: 'Forget Password?', + otherSignIn: 'Sign in with', + + // notify + loginSuccessTitle: 'Login successful', + loginSuccessDesc: 'Welcome back', + + // placeholder + accountPlaceholder: 'Please input username', + passwordPlaceholder: 'Please input password', + smsPlaceholder: 'Please input sms code', + mobilePlaceholder: 'Please input mobile', + policyPlaceholder: 'Register after checking', + diffPwd: 'The two passwords are inconsistent', + + userName: 'Username', + password: 'Password', + confirmPassword: 'Confirm Password', + email: 'Email', + smsCode: 'SMS code', + mobile: 'Mobile', + }, +} diff --git a/frontend/vben/src/locales/lang/zh-CN/antdLocale/DatePicker.ts b/frontend/vben/src/locales/lang/zh-CN/antdLocale/DatePicker.ts new file mode 100644 index 0000000..3c43ec5 --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/antdLocale/DatePicker.ts @@ -0,0 +1,19 @@ +export default { + lang: { + shortWeekDays: ['一', '二', '三', '四', '五', '六', '日'], + shortMonths: [ + '1月', + '2月', + '3月', + '4月', + '5月', + '6月', + '7月', + '8月', + '9月', + '10月', + '11月', + '12月', + ], + }, +} diff --git a/frontend/vben/src/locales/lang/zh-CN/common.ts b/frontend/vben/src/locales/lang/zh-CN/common.ts new file mode 100644 index 0000000..9d34bce --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/common.ts @@ -0,0 +1,20 @@ +export default { + okText: '确认', + closeText: '关闭', + cancelText: '取消', + loadingText: '加载中...', + saveText: '保存', + delText: '删除', + resetText: '重置', + searchText: '搜索', + queryText: '查询', + + inputText: '请输入', + chooseText: '请选择', + + redo: '刷新', + back: '返回', + + light: '亮色主题', + dark: '黑暗主题', +} diff --git a/frontend/vben/src/locales/lang/zh-CN/component.ts b/frontend/vben/src/locales/lang/zh-CN/component.ts new file mode 100644 index 0000000..793f079 --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/component.ts @@ -0,0 +1,134 @@ +export default { + app: { + searchNotData: '暂无搜索结果', + toSearch: '确认', + toNavigate: '切换', + }, + countdown: { + normalText: '获取验证码', + sendText: '{0}秒后重新获取', + }, + cropper: { + selectImage: '选择图片', + uploadSuccess: '上传成功', + modalTitle: '头像上传', + okText: '确认并上传', + btn_reset: '重置', + btn_rotate_left: '逆时针旋转', + btn_rotate_right: '顺时针旋转', + btn_scale_x: '水平翻转', + btn_scale_y: '垂直翻转', + btn_zoom_in: '放大', + btn_zoom_out: '缩小', + preview: '预览', + }, + drawer: { + loadingText: '加载中...', + cancelText: '关闭', + okText: '确认', + }, + excel: { + exportModalTitle: '导出数据', + fileType: '文件类型', + fileName: '文件名', + }, + form: { + putAway: '收起', + unfold: '展开', + + maxTip: '字符数应小于{0}位', + + apiSelectNotFound: '请等待数据加载完成...', + }, + icon: { + placeholder: '点击选择图标', + search: '搜索图标', + copy: '复制图标成功!', + }, + menu: { + search: '菜单搜索', + }, + modal: { + cancelText: '关闭', + okText: '确认', + close: '关闭', + maximize: '最大化', + restore: '还原', + }, + table: { + settingDens: '密度', + settingDensDefault: '默认', + settingDensMiddle: '中等', + settingDensSmall: '紧凑', + settingColumn: '列设置', + settingColumnShow: '列展示', + settingIndexColumnShow: '序号列', + settingSelectColumnShow: '勾选列', + settingFixedLeft: '固定到左侧', + settingFixedRight: '固定到右侧', + settingFullScreen: '全屏', + + index: '序号', + + total: '共 {total} 条数据', + }, + time: { + before: '前', + after: '后', + just: '刚刚', + seconds: '秒', + minutes: '分钟', + hours: '小时', + days: '天', + }, + tree: { + selectAll: '选择全部', + unSelectAll: '取消选择', + expandAll: '展开全部', + unExpandAll: '折叠全部', + checkStrictly: '层级关联', + checkUnStrictly: '层级独立', + }, + upload: { + save: '保存', + upload: '上传', + imgUpload: '图片上传', + uploaded: '已上传', + + operating: '操作', + del: '删除', + download: '下载', + saveWarn: '请等待文件上传后,保存!', + saveError: '没有上传成功的文件,无法保存!', + + preview: '预览', + choose: '选择文件', + + accept: '支持{0}格式', + acceptUpload: '只能上传{0}格式文件', + maxSize: '单个文件不超过{0}MB', + maxSizeMultiple: '只能上传不超过{0}MB的文件!', + maxNumber: '最多只能上传{0}个文件', + + legend: '略缩图', + fileName: '文件名', + fileSize: '文件大小', + fileStatue: '状态', + + startUpload: '开始上传', + uploadSuccess: '上传成功', + uploadError: '上传失败', + uploading: '上传中', + uploadWait: '请等待文件上传结束后操作', + reUploadFailed: '重新上传失败文件', + }, + verify: { + error: '验证失败!', + time: '验证校验成功,耗时{time}秒!', + + redoTip: '点击图片可刷新', + + dragText: '请按住滑块拖动', + successText: '验证通过', + }, +} diff --git a/frontend/vben/src/locales/lang/zh-CN/layout.ts b/frontend/vben/src/locales/lang/zh-CN/layout.ts new file mode 100644 index 0000000..f5163b2 --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/layout.ts @@ -0,0 +1,106 @@ +export default { + footer: { onlinePreview: '在线预览', onlineDocument: '在线文档' }, + header: { + // user dropdown + dropdownItemDoc: '文档', + dropdownItemLoginOut: '退出系统', + + // tooltip + tooltipErrorLog: '错误日志', + tooltipNotify: '消息通知', + + tooltipEntryFull: '全屏', + tooltipExitFull: '退出全屏', + + home: '首页', + }, + multipleTab: { + reload: '重新加载', + close: '关闭标签页', + closeLeft: '关闭左侧标签页', + closeRight: '关闭右侧标签页', + closeOther: '关闭其它标签页', + closeAll: '关闭全部标签页', + }, + setting: { + // content mode + contentModeFull: '流式', + contentModeFixed: '定宽', + // topMenu align + topMenuAlignLeft: '居左', + topMenuAlignRight: '居中', + topMenuAlignCenter: '居右', + // menu trigger + menuTriggerNone: '不显示', + menuTriggerBottom: '底部', + menuTriggerTop: '顶部', + // menu type + menuTypeSidebar: '左侧菜单模式', + menuTypeMixSidebar: '左侧菜单混合模式', + menuTypeMix: '顶部菜单混合模式', + menuTypeTopMenu: '顶部菜单模式', + + on: '开', + off: '关', + minute: '分钟', + + operatingTitle: '操作成功', + operatingContent: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!', + resetSuccess: '重置成功!', + + copyBtn: '拷贝', + clearBtn: '清空缓存并返回登录页', + + drawerTitle: '项目配置', + + darkMode: '主题', + navMode: '导航栏模式', + interfaceFunction: '界面功能', + interfaceDisplay: '界面显示', + animation: '动画', + splitMenu: '分割菜单', + closeMixSidebarOnChange: '切换页面关闭菜单', + + sysTheme: '系统主题', + headerTheme: '顶栏主题', + sidebarTheme: '菜单主题', + + menuDrag: '侧边菜单拖拽', + menuSearch: '菜单搜索', + menuAccordion: '侧边菜单手风琴模式', + menuCollapse: '折叠菜单', + collapseMenuDisplayName: '折叠菜单显示名称', + topMenuLayout: '顶部菜单布局', + menuCollapseButton: '菜单折叠按钮', + contentMode: '内容区域宽度', + expandedMenuWidth: '菜单展开宽度', + + breadcrumb: '面包屑', + breadcrumbIcon: '面包屑图标', + tabs: '标签页', + tabDetail: '标签详情页', + tabsQuickBtn: '标签页快捷按钮', + tabsRedoBtn: '标签页刷新按钮', + tabsFoldBtn: '标签页折叠按钮', + sidebar: '左侧菜单', + header: '顶栏', + footer: '页脚', + fullContent: '全屏内容', + grayMode: '灰色模式', + colorWeak: '色弱模式', + + progress: '顶部进度条', + switchLoading: '切换loading', + switchAnimation: '切换动画', + animationType: '动画类型', + + fixedHeader: '固定header', + fixedSideBar: '固定Sidebar', + + mixSidebarTrigger: '混合菜单触发方式', + triggerHover: '悬停', + triggerClick: '点击', + + mixSidebarFixed: '固定展开菜单', + }, +} diff --git a/frontend/vben/src/locales/lang/zh-CN/routes/basic.ts b/frontend/vben/src/locales/lang/zh-CN/routes/basic.ts new file mode 100644 index 0000000..8027a14 --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/routes/basic.ts @@ -0,0 +1,4 @@ +export default { + login: '登录', + errorLogList: '错误日志列表', +} diff --git a/frontend/vben/src/locales/lang/zh-CN/routes/dashboard.ts b/frontend/vben/src/locales/lang/zh-CN/routes/dashboard.ts new file mode 100644 index 0000000..34eb004 --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/routes/dashboard.ts @@ -0,0 +1,6 @@ +export default { + dashboard: 'Dashboard', + about: '关于', + workbench: '工作台', + analysis: '分析页', +} diff --git a/frontend/vben/src/locales/lang/zh-CN/routes/demo.ts b/frontend/vben/src/locales/lang/zh-CN/routes/demo.ts new file mode 100644 index 0000000..85301cf --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/routes/demo.ts @@ -0,0 +1,181 @@ +export default { + charts: { + baiduMap: '百度地图', + aMap: '高德地图', + googleMap: '谷歌地图', + charts: '图表', + map: '地图', + line: '折线图', + pie: '饼图', + }, + comp: { + comp: '组件', + basic: '基础组件', + transition: '动画组件', + + scroll: '滚动组件', + scrollBasic: '基础滚动', + scrollAction: '滚动函数', + virtualScroll: '虚拟滚动', + + tree: 'Tree', + treeBasic: '基础树', + editTree: '可搜索/工具栏', + actionTree: '函数操作示例', + + modal: '弹窗扩展', + drawer: '抽屉扩展', + desc: '详情组件', + + lazy: '懒加载组件', + lazyBasic: '基础示例', + lazyTransition: '动画效果', + + verify: '验证组件', + verifyDrag: '拖拽校验', + verifyRotate: '图片还原', + + strength: '密码强度组件', + upload: '上传组件', + + loading: 'Loading', + + time: '相对时间', + cropperImage: '图片裁剪', + }, + editor: { + editor: '编辑器', + jsonEditor: 'Json编辑器', + markdown: 'markdown编辑器', + + tinymce: '富文本', + tinymceBasic: '基础使用', + tinymceForm: '嵌入form', + }, + excel: { + excel: 'Excel', + customExport: '选择导出格式', + jsonExport: 'JSON数据导出', + arrayExport: 'Array数据导出', + importExcel: '导入', + }, + feat: { + feat: '功能', + icon: '图标', + sessionTimeout: '登录过期', + tabs: '标签页操作', + tabDetail: '标签详情页', + contextMenu: '右键菜单', + download: '文件下载', + imgPreview: '图片预览', + copy: '剪切板', + msg: '消息提示', + watermark: '水印', + ripple: '水波纹', + fullScreen: '全屏', + errorLog: '错误日志', + tab: 'Tab带参', + tab1: 'Tab带参1', + tab2: 'Tab带参2', + menu: 'Menu带参', + menu1: 'Menu带参1', + menu2: 'Menu带参2', + breadcrumb: '面包屑导航', + breadcrumbFlat: '平级模式', + requestDemo: '测试请求重试', + breadcrumbFlatDetail: '平级详情', + breadcrumbChildren: '层级模式', + breadcrumbChildrenDetail: '层级详情', + }, + flow: { + name: '图形编辑器', + flowChart: '流程图', + }, + form: { + form: 'Form', + basic: '基础表单', + useForm: 'useForm', + refForm: 'RefForm', + advancedForm: '可收缩表单', + ruleForm: '表单验证', + dynamicForm: '动态表单', + customerForm: '自定义组件', + appendForm: '表单增删示例', + tabsForm: '标签页+多级field', + }, + level: { level: '多级菜单' }, + page: { + page: '页面', + + form: '表单页', + formBasic: '基础表单', + formStep: '分步表单', + formHigh: '高级表单', + + desc: '详情页', + descBasic: '基础详情页', + descHigh: '高级详情页', + + result: '结果页', + resultSuccess: '成功页', + resultFail: '失败页', + + account: '个人页', + accountCenter: '个人中心', + accountSetting: '个人设置', + + exception: '异常页', + netWorkError: '网络错误', + notData: '无数据', + + list: '列表页', + listCard: '卡片列表', + listBasic: '标准列表', + listSearch: '搜索列表', + }, + permission: { + permission: '权限管理', + + front: '基于前端权限', + frontPage: '页面权限', + frontBtn: '按钮权限', + frontTestA: '权限测试页A', + frontTestB: '权限测试页B', + + back: '基于后台权限', + backPage: '页面权限', + backBtn: '按钮权限', + }, + setup: { + page: '引导页', + }, + system: { + moduleName: '系统管理', + account: '账号管理', + account_detail: '账号详情', + password: '修改密码', + dept: '部门管理', + menu: '菜单管理', + role: '角色管理', + }, + table: { + table: 'Table', + basic: '基础表格', + treeTable: '树形表格', + fetchTable: '远程加载示例', + fixedColumn: '固定列', + customerCell: '自定义列', + formTable: '开启搜索区域', + useTable: 'UseTable', + refTable: 'RefTable', + multipleHeader: '多级表头', + mergeHeader: '合并单元格', + expandTable: '可展开表格', + fixedHeight: '定高/头部自定义', + footerTable: '表尾行合计', + editCellTable: '可编辑单元格', + editRowTable: '可编辑行', + authColumn: '权限列', + resizeParentHeightTable: '继承父元素高度', + }, +} diff --git a/frontend/vben/src/locales/lang/zh-CN/sys.ts b/frontend/vben/src/locales/lang/zh-CN/sys.ts new file mode 100644 index 0000000..b16defd --- /dev/null +++ b/frontend/vben/src/locales/lang/zh-CN/sys.ts @@ -0,0 +1,94 @@ +export default { + api: { + operationFailed: '操作失败', + errorTip: '错误提示', + errorMessage: '操作失败,系统异常!', + timeoutMessage: '登录超时,请重新登录!', + apiTimeoutMessage: '接口请求超时,请刷新页面重试!', + apiRequestFailed: '请求出错,请稍候重试', + networkException: '网络异常', + networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', + + errMsg401: '用户没有权限(令牌、用户名、密码错误)!', + errMsg403: '用户得到授权,但是访问是被禁止的。!', + errMsg404: '网络请求错误,未找到该资源!', + errMsg405: '网络请求错误,请求方法未允许!', + errMsg408: '网络请求超时!', + errMsg500: '服务器错误,请联系管理员!', + errMsg501: '网络未实现!', + errMsg502: '网络错误!', + errMsg503: '服务不可用,服务器暂时过载或维护!', + errMsg504: '网络超时!', + errMsg505: 'http版本不支持该请求!', + }, + app: { + Tip: '温馨提醒', + logoutMessage: '是否确认退出系统?', + menuLoading: '菜单加载中...', + }, + errorLog: { + tableTitle: '错误日志列表', + tableColumnType: '类型', + tableColumnDate: '时间', + tableColumnFile: '文件', + tableColumnMsg: '错误信息', + tableColumnStackMsg: 'stack信息', + + tableActionDesc: '详情', + + modalTitle: '错误详情', + + fireVueError: '点击触发vue错误', + fireResourceError: '点击触发资源加载错误', + fireAjaxError: '点击触发ajax错误', + + enableMessage: '只在`/src/settings/projectSetting.ts` 内的useErrorHandle=true时生效.', + }, + exception: { + backLogin: '返回登录', + backHome: '返回首页', + subTitle403: '抱歉,您无权访问此页面。', + subTitle404: '抱歉,您访问的页面不存在。', + subTitle500: '抱歉,服务器报告错误。', + noDataTitle: '当前页无数据', + networkErrorTitle: '网络错误', + networkErrorSubTitle: '抱歉,您的网络连接已断开,请检查您的网络!', + }, + login: { + backSignIn: '返回', + signInFormTitle: '登录', + mobileSignInFormTitle: '手机登录', + signUpFormTitle: '注册', + forgetFormTitle: '重置密码', + + signInTitle: '开箱即用的中后台管理系统', + signInDesc: '输入您的个人详细信息开始使用!', + policy: '我同意xxx隐私政策', + scanSign: `扫码后点击"确认",即可完成登录`, + + loginButton: '登录', + registerButton: '注册', + rememberMe: '记住我', + forgetPassword: '忘记密码?', + otherSignIn: '其他登录方式', + + // notify + loginSuccessTitle: '登录成功', + loginSuccessDesc: '欢迎回来', + + // placeholder + accountPlaceholder: '请输入账号', + passwordPlaceholder: '请输入密码', + smsPlaceholder: '请输入验证码', + mobilePlaceholder: '请输入手机号码', + policyPlaceholder: '勾选后才能注册', + diffPwd: '两次输入密码不一致', + + userName: '账号', + password: '密码', + confirmPassword: '确认密码', + email: '邮箱', + smsCode: '短信验证码', + mobile: '手机号码', + }, +} diff --git a/frontend/vben/src/locales/lang/zh_CN.ts b/frontend/vben/src/locales/lang/zh_CN.ts new file mode 100644 index 0000000..204c90b --- /dev/null +++ b/frontend/vben/src/locales/lang/zh_CN.ts @@ -0,0 +1,10 @@ +import { genMessage } from '../helper' +import antdLocale from 'ant-design-vue/es/locale/zh_CN' + +const modules = import.meta.globEager('./zh-CN/**/*.ts') +export default { + message: { + ...genMessage(modules, 'zh-CN'), + antdLocale, + }, +} diff --git a/frontend/vben/src/locales/setupI18n.ts b/frontend/vben/src/locales/setupI18n.ts new file mode 100644 index 0000000..889d36e --- /dev/null +++ b/frontend/vben/src/locales/setupI18n.ts @@ -0,0 +1,44 @@ +import type { App } from 'vue' +import type { I18n, I18nOptions } from 'vue-i18n' + +import { createI18n } from 'vue-i18n' +import { setHtmlPageLang, setLoadLocalePool } from './helper' +import { localeSetting } from '/@/settings/localeSetting' +import { useLocaleStoreWithOut } from '/@/store/modules/locale' + +const { fallback, availableLocales } = localeSetting + +export let i18n: ReturnType + +async function createI18nOptions(): Promise { + const localeStore = useLocaleStoreWithOut() + const locale = localeStore.getLocale + const defaultLocal = await import(`./lang/${locale}.ts`) + const message = defaultLocal.default?.message ?? {} + + setHtmlPageLang(locale) + setLoadLocalePool((loadLocalePool) => { + loadLocalePool.push(locale) + }) + + return { + legacy: false, + locale, + fallbackLocale: fallback, + messages: { + [locale]: message, + }, + availableLocales: availableLocales, + sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false. + silentTranslationWarn: true, // true - warning off + missingWarn: false, + silentFallbackWarn: true, + } +} + +// setup i18n instance with glob +export async function setupI18n(app: App) { + const options = await createI18nOptions() + i18n = createI18n(options) as I18n + app.use(i18n) +} diff --git a/frontend/vben/src/locales/useLocale.ts b/frontend/vben/src/locales/useLocale.ts new file mode 100644 index 0000000..0c6bdcb --- /dev/null +++ b/frontend/vben/src/locales/useLocale.ts @@ -0,0 +1,69 @@ +/** + * Multi-language related operations + */ +import type { LocaleType } from '/#/config' + +import { i18n } from './setupI18n' +import { useLocaleStoreWithOut } from '/@/store/modules/locale' +import { unref, computed } from 'vue' +import { loadLocalePool, setHtmlPageLang } from './helper' + +interface LangModule { + message: Recordable + dateLocale: Recordable + dateLocaleName: string +} + +function setI18nLanguage(locale: LocaleType) { + const localeStore = useLocaleStoreWithOut() + + if (i18n.mode === 'legacy') { + i18n.global.locale = locale + } else { + ;(i18n.global.locale as any).value = locale + } + localeStore.setLocaleInfo({ locale }) + setHtmlPageLang(locale) +} + +export function useLocale() { + const localeStore = useLocaleStoreWithOut() + const getLocale = computed(() => localeStore.getLocale) + const getShowLocalePicker = computed(() => localeStore.getShowPicker) + + const getAntdLocale = computed((): any => { + return i18n.global.getLocaleMessage(unref(getLocale))?.antdLocale ?? {} + }) + + // Switching the language will change the locale of useI18n + // And submit to configuration modification + async function changeLocale(locale: LocaleType) { + const globalI18n = i18n.global + const currentLocale = unref(globalI18n.locale) + if (currentLocale === locale) { + return locale + } + + if (loadLocalePool.includes(locale)) { + setI18nLanguage(locale) + return locale + } + const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule + if (!langModule) return + + const { message } = langModule + + globalI18n.setLocaleMessage(locale, message) + loadLocalePool.push(locale) + + setI18nLanguage(locale) + return locale + } + + return { + getLocale, + getShowLocalePicker, + changeLocale, + getAntdLocale, + } +} diff --git a/frontend/vben/src/logics/initAppConfig.ts b/frontend/vben/src/logics/initAppConfig.ts new file mode 100644 index 0000000..d78d774 --- /dev/null +++ b/frontend/vben/src/logics/initAppConfig.ts @@ -0,0 +1,84 @@ +/** + * Application configuration + */ +import type { ProjectConfig } from '/#/config' + +import { PROJ_CFG_KEY } from '/@/enums/cacheEnum' +import projectSetting from '/@/settings/projectSetting' + +import { updateHeaderBgColor, updateSidebarBgColor } from '/@/logics/theme/updateBackground' +import { updateColorWeak } from '/@/logics/theme/updateColorWeak' +import { updateGrayMode } from '/@/logics/theme/updateGrayMode' +import { updateDarkTheme } from '/@/logics/theme/dark' +import { changeTheme } from '/@/logics/theme' + +import { useAppStore } from '/@/store/modules/app' +import { useLocaleStore } from '/@/store/modules/locale' + +import { getCommonStoragePrefix, getStorageShortName } from '/@/utils/env' + +import { primaryColor } from '../../build/config/themeConfig' +import { Persistent } from '/@/utils/cache/persistent' +import { deepMerge } from '/@/utils' +import { ThemeEnum } from '/@/enums/appEnum' + +// Initial project configuration +export function initAppConfigStore() { + const localeStore = useLocaleStore() + const appStore = useAppStore() + let projCfg: ProjectConfig = Persistent.getLocal(PROJ_CFG_KEY) as ProjectConfig + projCfg = deepMerge(projectSetting, projCfg || {}) + const darkMode = appStore.getDarkMode + const { + colorWeak, + grayMode, + themeColor, + + headerSetting: { bgColor: headerBgColor } = {}, + menuSetting: { bgColor } = {}, + } = projCfg + try { + if (themeColor && themeColor !== primaryColor) { + changeTheme(themeColor) + } + + grayMode && updateGrayMode(grayMode) + colorWeak && updateColorWeak(colorWeak) + } catch (error) { + console.log(error) + } + appStore.setProjectConfig(projCfg) + + // init dark mode + updateDarkTheme(darkMode) + if (darkMode === ThemeEnum.DARK) { + updateHeaderBgColor() + updateSidebarBgColor() + } else { + headerBgColor && updateHeaderBgColor(headerBgColor) + bgColor && updateSidebarBgColor(bgColor) + } + // init store + localeStore.initLocale() + + setTimeout(() => { + clearObsoleteStorage() + }, 16) +} + +/** + * As the version continues to iterate, there will be more and more cache keys stored in localStorage. + * This method is used to delete useless keys + */ +export function clearObsoleteStorage() { + const commonPrefix = getCommonStoragePrefix() + const shortPrefix = getStorageShortName() + + ;[localStorage, sessionStorage].forEach((item: Storage) => { + Object.keys(item).forEach((key) => { + if (key && key.startsWith(commonPrefix) && !key.startsWith(shortPrefix)) { + item.removeItem(key) + } + }) + }) +} diff --git a/frontend/vben/src/logics/mitt/routeChange.ts b/frontend/vben/src/logics/mitt/routeChange.ts new file mode 100644 index 0000000..73e725b --- /dev/null +++ b/frontend/vben/src/logics/mitt/routeChange.ts @@ -0,0 +1,31 @@ +/** + * Used to monitor routing changes to change the status of menus and tabs. There is no need to monitor the route, because the route status change is affected by the page rendering time, which will be slow + */ + +import mitt from '/@/utils/mitt' +import type { RouteLocationNormalized } from 'vue-router' +import { getRawRoute } from '/@/utils' + +const emitter = mitt() + +const key = Symbol() + +let lastChangeTab: RouteLocationNormalized + +export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { + const r = getRawRoute(lastChangeRoute) + emitter.emit(key, r) + lastChangeTab = r +} + +export function listenerRouteChange( + callback: (route: RouteLocationNormalized) => void, + immediate = true, +) { + emitter.on(key, callback) + immediate && lastChangeTab && callback(lastChangeTab) +} + +export function removeTabChangeListener() { + emitter.clear() +} diff --git a/frontend/vben/src/logics/theme/dark.ts b/frontend/vben/src/logics/theme/dark.ts new file mode 100644 index 0000000..aae2cd1 --- /dev/null +++ b/frontend/vben/src/logics/theme/dark.ts @@ -0,0 +1,24 @@ +import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client' +import { addClass, hasClass, removeClass } from '/@/utils/domUtils' + +export async function updateDarkTheme(mode: string | null = 'light') { + const htmlRoot = document.getElementById('htmlRoot') + if (!htmlRoot) { + return + } + const hasDarkClass = hasClass(htmlRoot, 'dark') + if (mode === 'dark') { + if (import.meta.env.PROD && !darkCssIsReady) { + await loadDarkThemeCss() + } + htmlRoot.setAttribute('data-theme', 'dark') + if (!hasDarkClass) { + addClass(htmlRoot, 'dark') + } + } else { + htmlRoot.setAttribute('data-theme', 'light') + if (hasDarkClass) { + removeClass(htmlRoot, 'dark') + } + } +} diff --git a/frontend/vben/src/logics/theme/index.ts b/frontend/vben/src/logics/theme/index.ts new file mode 100644 index 0000000..e26010a --- /dev/null +++ b/frontend/vben/src/logics/theme/index.ts @@ -0,0 +1,17 @@ +import { getThemeColors, generateColors } from '../../../build/config/themeConfig' + +import { replaceStyleVariables } from 'vite-plugin-theme/es/client' +import { mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme/es/colorUtils' + +export async function changeTheme(color: string) { + const colors = generateColors({ + mixDarken, + mixLighten, + tinycolor, + color, + }) + + return await replaceStyleVariables({ + colorVariables: [...getThemeColors(color), ...colors], + }) +} diff --git a/frontend/vben/src/logics/theme/updateBackground.ts b/frontend/vben/src/logics/theme/updateBackground.ts new file mode 100644 index 0000000..4b6f5ef --- /dev/null +++ b/frontend/vben/src/logics/theme/updateBackground.ts @@ -0,0 +1,75 @@ +import { colorIsDark, lighten, darken } from '/@/utils/color' +import { useAppStore } from '/@/store/modules/app' +import { ThemeEnum } from '/@/enums/appEnum' +import { setCssVar } from './util' + +const HEADER_BG_COLOR_VAR = '--header-bg-color' +const HEADER_BG_HOVER_COLOR_VAR = '--header-bg-hover-color' +const HEADER_MENU_ACTIVE_BG_COLOR_VAR = '--header-active-menu-bg-color' + +const SIDER_DARK_BG_COLOR = '--sider-dark-bg-color' +const SIDER_DARK_DARKEN_BG_COLOR = '--sider-dark-darken-bg-color' +const SIDER_LIGHTEN_BG_COLOR = '--sider-dark-lighten-bg-color' + +/** + * Change the background color of the top header + * @param color + */ +export function updateHeaderBgColor(color?: string) { + const appStore = useAppStore() + const darkMode = appStore.getDarkMode === ThemeEnum.DARK + if (!color) { + if (darkMode) { + color = '#151515' + } else { + color = appStore.getHeaderSetting.bgColor + } + } + // bg color + setCssVar(HEADER_BG_COLOR_VAR, color) + + // hover color + const hoverColor = lighten(color!, 6) + setCssVar(HEADER_BG_HOVER_COLOR_VAR, hoverColor) + setCssVar(HEADER_MENU_ACTIVE_BG_COLOR_VAR, hoverColor) + + // Determine the depth of the color value and automatically switch the theme + const isDark = colorIsDark(color!) + + appStore.setProjectConfig({ + headerSetting: { + theme: isDark || darkMode ? ThemeEnum.DARK : ThemeEnum.LIGHT, + }, + }) +} + +/** + * Change the background color of the left menu + * @param color bg color + */ +export function updateSidebarBgColor(color?: string) { + const appStore = useAppStore() + + // if (!isHexColor(color)) return; + const darkMode = appStore.getDarkMode === ThemeEnum.DARK + if (!color) { + if (darkMode) { + color = '#212121' + } else { + color = appStore.getMenuSetting.bgColor + } + } + setCssVar(SIDER_DARK_BG_COLOR, color) + setCssVar(SIDER_DARK_DARKEN_BG_COLOR, darken(color!, 6)) + setCssVar(SIDER_LIGHTEN_BG_COLOR, lighten(color!, 5)) + + // only #ffffff is light + // Only when the background color is #fff, the theme of the menu will be changed to light + const isLight = ['#fff', '#ffffff'].includes(color!.toLowerCase()) + + appStore.setProjectConfig({ + menuSetting: { + theme: isLight && !darkMode ? ThemeEnum.LIGHT : ThemeEnum.DARK, + }, + }) +} diff --git a/frontend/vben/src/logics/theme/updateColorWeak.ts b/frontend/vben/src/logics/theme/updateColorWeak.ts new file mode 100644 index 0000000..031c9e3 --- /dev/null +++ b/frontend/vben/src/logics/theme/updateColorWeak.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util' + +/** + * Change the status of the project's color weakness mode + * @param colorWeak + */ +export function updateColorWeak(colorWeak: boolean) { + toggleClass(colorWeak, 'color-weak', document.documentElement) +} diff --git a/frontend/vben/src/logics/theme/updateGrayMode.ts b/frontend/vben/src/logics/theme/updateGrayMode.ts new file mode 100644 index 0000000..c548958 --- /dev/null +++ b/frontend/vben/src/logics/theme/updateGrayMode.ts @@ -0,0 +1,9 @@ +import { toggleClass } from './util' + +/** + * Change project gray mode status + * @param gray + */ +export function updateGrayMode(gray: boolean) { + toggleClass(gray, 'gray-mode', document.documentElement) +} diff --git a/frontend/vben/src/logics/theme/util.ts b/frontend/vben/src/logics/theme/util.ts new file mode 100644 index 0000000..43e3056 --- /dev/null +++ b/frontend/vben/src/logics/theme/util.ts @@ -0,0 +1,11 @@ +const docEle = document.documentElement +export function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { + const targetEl = target || document.body + let { className } = targetEl + className = className.replace(clsName, '') + targetEl.className = flag ? `${className} ${clsName} ` : className +} + +export function setCssVar(prop: string, val: any, dom = docEle) { + dom.style.setProperty(prop, val) +} diff --git a/frontend/vben/src/main.ts b/frontend/vben/src/main.ts new file mode 100644 index 0000000..fb275f8 --- /dev/null +++ b/frontend/vben/src/main.ts @@ -0,0 +1,64 @@ +import 'virtual:windi-base.css' +import 'virtual:windi-components.css' +import '/@/design/index.less' +import 'virtual:windi-utilities.css' +// Register icon sprite +import 'virtual:svg-icons-register' +import App from './App.vue' +import { createApp } from 'vue' +import { initAppConfigStore } from '/@/logics/initAppConfig' +import { router, setupRouter } from '/@/router' +import { setupRouterGuard } from '/@/router/guard' +import { setupStore } from '/@/store' +import { setupGlobDirectives } from '/@/directives' +import { setupI18n } from '/@/locales/setupI18n' +import { registerGlobComp } from '/@/components/registerGlobComp' + +import { isDevMode } from './utils/env' + +if (isDevMode()) { + import('ant-design-vue/es/style') +} + +async function bootstrap() { + const app = createApp(App) + + // Configure store + // 配置 store + setupStore(app) + + // Initialize internal system configuration + // 初始化内部系统配置 + initAppConfigStore() + + // Register global components + // 注册全局组件 + registerGlobComp(app) + + // Multilingual configuration + // 多语言配置 + // Asynchronous case: language files may be obtained from the server side + // 异步案例:语言文件可能从服务器端获取 + await setupI18n(app) + + // Configure routing + // 配置路由 + setupRouter(app) + + // router-guard + // 路由守卫 + setupRouterGuard(router) + + // Register global directive + // 注册全局指令 + setupGlobDirectives(app) + + // Configure global error handling + + // https://next.router.vuejs.org/api/#isready + // await router.isReady(); + + app.mount('#app') +} + +bootstrap() diff --git a/frontend/vben/src/router/constant.ts b/frontend/vben/src/router/constant.ts new file mode 100644 index 0000000..eebae6d --- /dev/null +++ b/frontend/vben/src/router/constant.ts @@ -0,0 +1,24 @@ +export const REDIRECT_NAME = 'Redirect' + +export const PARENT_LAYOUT_NAME = 'ParentLayout' + +export const PAGE_NOT_FOUND_NAME = 'PageNotFound' + +export const EXCEPTION_COMPONENT = () => import('/@/views/sys/exception/Exception.vue') + +/** + * @description: default layout + */ +export const LAYOUT = () => import('/@/layouts/default/index.vue') + +/** + * @description: parent-layout + */ +export const getParentLayout = (_name?: string) => { + return () => + new Promise((resolve) => { + resolve({ + name: PARENT_LAYOUT_NAME, + }) + }) +} diff --git a/frontend/vben/src/router/guard/index.ts b/frontend/vben/src/router/guard/index.ts new file mode 100644 index 0000000..67a920c --- /dev/null +++ b/frontend/vben/src/router/guard/index.ts @@ -0,0 +1,147 @@ +import type { Router, RouteLocationNormalized } from 'vue-router' +import { useAppStoreWithOut } from '/@/store/modules/app' +import { useUserStoreWithOut } from '/@/store/modules/user' +import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting' +import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel' +import { Modal, notification } from 'ant-design-vue' +import { warn } from '/@/utils/log' +import { unref } from 'vue' +import { setRouteChange } from '/@/logics/mitt/routeChange' +import { createPermissionGuard } from './permissionGuard' +import { createStateGuard } from './stateGuard' +import nProgress from 'nprogress' +import projectSetting from '/@/settings/projectSetting' +import { createParamMenuGuard } from './paramMenuGuard' + +// Don't change the order of creation +export function setupRouterGuard(router: Router) { + createPageGuard(router) + createPageLoadingGuard(router) + createHttpGuard(router) + createScrollGuard(router) + createMessageGuard(router) + createProgressGuard(router) + createPermissionGuard(router) + createParamMenuGuard(router) // must after createPermissionGuard (menu has been built.) + createStateGuard(router) +} + +/** + * Hooks for handling page state + */ +function createPageGuard(router: Router) { + const loadedPageMap = new Map() + + router.beforeEach(async (to) => { + // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing + to.meta.loaded = !!loadedPageMap.get(to.path) + // Notify routing changes + setRouteChange(to) + + return true + }) + + router.afterEach((to) => { + loadedPageMap.set(to.path, true) + }) +} + +// Used to handle page loading status +function createPageLoadingGuard(router: Router) { + const userStore = useUserStoreWithOut() + const appStore = useAppStoreWithOut() + const { getOpenPageLoading } = useTransitionSetting() + router.beforeEach(async (to) => { + if (!userStore.getToken) { + return true + } + if (to.meta.loaded) { + return true + } + + if (unref(getOpenPageLoading)) { + appStore.setPageLoadingAction(true) + return true + } + + return true + }) + router.afterEach(async () => { + if (unref(getOpenPageLoading)) { + // TODO Looking for a better way + // The timer simulates the loading time to prevent flashing too fast, + setTimeout(() => { + appStore.setPageLoading(false) + }, 220) + } + return true + }) +} + +/** + * The interface used to close the current page to complete the request when the route is switched + * @param router + */ +function createHttpGuard(router: Router) { + const { removeAllHttpPending } = projectSetting + let axiosCanceler: Nullable + if (removeAllHttpPending) { + axiosCanceler = new AxiosCanceler() + } + router.beforeEach(async () => { + // Switching the route will delete the previous request + axiosCanceler?.removeAllPending() + return true + }) +} + +// Routing switch back to the top +function createScrollGuard(router: Router) { + const isHash = (href: string) => { + return /^#/.test(href) + } + + const body = document.body + + router.afterEach(async (to) => { + // scroll top + isHash((to as RouteLocationNormalized & { href: string })?.href) && body.scrollTo(0, 0) + return true + }) +} + +/** + * Used to close the message instance when the route is switched + * @param router + */ +export function createMessageGuard(router: Router) { + const { closeMessageOnSwitch } = projectSetting + + router.beforeEach(async () => { + try { + if (closeMessageOnSwitch) { + Modal.destroyAll() + notification.destroy() + } + } catch (error) { + warn('message guard error:' + error) + } + return true + }) +} + +export function createProgressGuard(router: Router) { + const { getOpenNProgress } = useTransitionSetting() + router.beforeEach(async (to) => { + if (to.meta.loaded) { + return true + } + unref(getOpenNProgress) && nProgress.start() + return true + }) + + router.afterEach(async () => { + unref(getOpenNProgress) && nProgress.done() + return true + }) +} diff --git a/frontend/vben/src/router/guard/paramMenuGuard.ts b/frontend/vben/src/router/guard/paramMenuGuard.ts new file mode 100644 index 0000000..0618ce3 --- /dev/null +++ b/frontend/vben/src/router/guard/paramMenuGuard.ts @@ -0,0 +1,47 @@ +import type { Router } from 'vue-router' +import { configureDynamicParamsMenu } from '../helper/menuHelper' +import { Menu } from '../types' +import { PermissionModeEnum } from '/@/enums/appEnum' +import { useAppStoreWithOut } from '/@/store/modules/app' + +import { usePermissionStoreWithOut } from '/@/store/modules/permission' + +export function createParamMenuGuard(router: Router) { + const permissionStore = usePermissionStoreWithOut() + router.beforeEach(async (to, _, next) => { + // filter no name route + if (!to.name) { + next() + return + } + + // menu has been built. + if (!permissionStore.getIsDynamicAddedRoute) { + next() + return + } + + let menus: Menu[] = [] + if (isBackMode()) { + menus = permissionStore.getBackMenuList + } else if (isRouteMappingMode()) { + menus = permissionStore.getFrontMenuList + } + menus.forEach((item) => configureDynamicParamsMenu(item, to.params)) + + next() + }) +} + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut() + return appStore.getProjectConfig.permissionMode +} + +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK +} + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING +} diff --git a/frontend/vben/src/router/guard/permissionGuard.ts b/frontend/vben/src/router/guard/permissionGuard.ts new file mode 100644 index 0000000..a6dcdd9 --- /dev/null +++ b/frontend/vben/src/router/guard/permissionGuard.ts @@ -0,0 +1,118 @@ +import type { Router, RouteRecordRaw } from 'vue-router' + +import { usePermissionStoreWithOut } from '/@/store/modules/permission' + +import { PageEnum } from '/@/enums/pageEnum' +import { useUserStoreWithOut } from '/@/store/modules/user' + +import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic' + +import { RootRoute } from '/@/router/routes' + +const LOGIN_PATH = PageEnum.BASE_LOGIN + +const ROOT_PATH = RootRoute.path + +const whitePathList: PageEnum[] = [LOGIN_PATH] + +export function createPermissionGuard(router: Router) { + const userStore = useUserStoreWithOut() + const permissionStore = usePermissionStoreWithOut() + router.beforeEach(async (to, from, next) => { + if ( + from.path === ROOT_PATH && + to.path === PageEnum.BASE_HOME && + userStore.getUserInfo.homePath && + userStore.getUserInfo.homePath !== PageEnum.BASE_HOME + ) { + next(userStore.getUserInfo.homePath) + return + } + + const token = userStore.getToken + + // Whitelist can be directly entered + if (whitePathList.includes(to.path as PageEnum)) { + if (to.path === LOGIN_PATH && token) { + const isSessionTimeout = userStore.getSessionTimeout + try { + await userStore.afterLoginAction() + if (!isSessionTimeout) { + next((to.query?.redirect as string) || '/') + return + } + } catch {} + } + next() + return + } + + // token does not exist + if (!token) { + // You can access without permission. You need to set the routing meta.ignoreAuth to true + if (to.meta.ignoreAuth) { + next() + return + } + + // redirect login page + const redirectData: { path: string; replace: boolean; query?: Recordable } = { + path: LOGIN_PATH, + replace: true, + } + if (to.path) { + redirectData.query = { + ...redirectData.query, + redirect: to.path, + } + } + next(redirectData) + return + } + + // Jump to the 404 page after processing the login + if ( + from.path === LOGIN_PATH && + to.name === PAGE_NOT_FOUND_ROUTE.name && + to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME) + ) { + next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME) + return + } + + // get userinfo while last fetch time is empty + if (userStore.getLastUpdateTime === 0) { + try { + await userStore.getUserInfoAction() + } catch (err) { + next() + return + } + } + + if (permissionStore.getIsDynamicAddedRoute) { + next() + return + } + + const routes = await permissionStore.buildRoutesAction() + + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) + }) + + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw) + + permissionStore.setDynamicAddedRoute(true) + + if (to.name === PAGE_NOT_FOUND_ROUTE.name) { + // 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容 + next({ path: to.fullPath, replace: true, query: to.query }) + } else { + const redirectPath = (from.query.redirect || to.path) as string + const redirect = decodeURIComponent(redirectPath) + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } + next(nextData) + } + }) +} diff --git a/frontend/vben/src/router/guard/stateGuard.ts b/frontend/vben/src/router/guard/stateGuard.ts new file mode 100644 index 0000000..4680142 --- /dev/null +++ b/frontend/vben/src/router/guard/stateGuard.ts @@ -0,0 +1,24 @@ +import type { Router } from 'vue-router' +import { useAppStore } from '/@/store/modules/app' +import { useMultipleTabStore } from '/@/store/modules/multipleTab' +import { useUserStore } from '/@/store/modules/user' +import { usePermissionStore } from '/@/store/modules/permission' +import { PageEnum } from '/@/enums/pageEnum' +import { removeTabChangeListener } from '/@/logics/mitt/routeChange' + +export function createStateGuard(router: Router) { + router.afterEach((to) => { + // Just enter the login page and clear the authentication information + if (to.path === PageEnum.BASE_LOGIN) { + const tabStore = useMultipleTabStore() + const userStore = useUserStore() + const appStore = useAppStore() + const permissionStore = usePermissionStore() + appStore.resetAllState() + permissionStore.resetState() + tabStore.resetState() + userStore.resetState() + removeTabChangeListener() + } + }) +} diff --git a/frontend/vben/src/router/helper/menuHelper.ts b/frontend/vben/src/router/helper/menuHelper.ts new file mode 100644 index 0000000..3670929 --- /dev/null +++ b/frontend/vben/src/router/helper/menuHelper.ts @@ -0,0 +1,106 @@ +import { AppRouteModule } from '/@/router/types' +import type { MenuModule, Menu, AppRouteRecordRaw } from '/@/router/types' +import { findPath, treeMap } from '/@/utils/helper/treeHelper' +import { cloneDeep } from 'lodash-es' +import { isUrl } from '/@/utils/is' +import { RouteParams } from 'vue-router' +import { toRaw } from 'vue' + +export function getAllParentPath(treeData: T[], path: string) { + const menuList = findPath(treeData, (n) => n.path === path) as Menu[] + return (menuList || []).map((item) => item.path) +} + +// 路径处理 +function joinParentPath(menus: Menu[], parentPath = '') { + for (let index = 0; index < menus.length; index++) { + const menu = menus[index] + // https://next.router.vuejs.org/guide/essentials/nested-routes.html + // Note that nested paths that start with / will be treated as a root path. + // 请注意,以 / 开头的嵌套路径将被视为根路径。 + // This allows you to leverage the component nesting without having to use a nested URL. + // 这允许你利用组件嵌套,而无需使用嵌套 URL。 + if (!(menu.path.startsWith('/') || isUrl(menu.path))) { + // path doesn't start with /, nor is it a url, join parent path + // 路径不以 / 开头,也不是 url,加入父路径 + menu.path = `${parentPath}/${menu.path}` + } + if (menu?.children?.length) { + joinParentPath(menu.children, menu.meta?.hidePathForChildren ? parentPath : menu.path) + } + } +} + +// Parsing the menu module +export function transformMenuModule(menuModule: MenuModule): Menu { + const { menu } = menuModule + + const menuList = [menu] + + joinParentPath(menuList) + return menuList[0] +} + +// 将路由转换成菜单 +export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) { + // 借助 lodash 深拷贝 + const cloneRouteModList = cloneDeep(routeModList) + const routeList: AppRouteRecordRaw[] = [] + + // 对路由项进行修改 + cloneRouteModList.forEach((item) => { + if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') { + item.path = item.redirect + } + + if (item.meta?.single) { + const realItem = item?.children?.[0] + realItem && routeList.push(realItem) + } else { + routeList.push(item) + } + }) + // 提取树指定结构 + const list = treeMap(routeList, { + conversion: (node: AppRouteRecordRaw) => { + const { meta: { title, hideMenu = false } = {} } = node + + return { + ...(node.meta || {}), + meta: node.meta, + name: title, + hideMenu, + path: node.path, + ...(node.redirect ? { redirect: node.redirect } : {}), + } + }, + }) + // 路径处理 + joinParentPath(list) + return cloneDeep(list) +} + +/** + * config menu with given params + */ +const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g + +export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) { + const { path, paramPath } = toRaw(menu) + let realPath = paramPath ? paramPath : path + const matchArr = realPath.match(menuParamRegex) + + matchArr?.forEach((it) => { + const realIt = it.substr(1) + if (params[realIt]) { + realPath = realPath.replace(`:${realIt}`, params[realIt] as string) + } + }) + // save original param path. + if (!paramPath && matchArr && matchArr.length > 0) { + menu.paramPath = path + } + menu.path = realPath + // children + menu.children?.forEach((item) => configureDynamicParamsMenu(item, params)) +} diff --git a/frontend/vben/src/router/helper/routeHelper.ts b/frontend/vben/src/router/helper/routeHelper.ts new file mode 100644 index 0000000..52e001f --- /dev/null +++ b/frontend/vben/src/router/helper/routeHelper.ts @@ -0,0 +1,172 @@ +import type { AppRouteModule, AppRouteRecordRaw } from '/@/router/types' +import type { Router, RouteRecordNormalized } from 'vue-router' + +import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '/@/router/constant' +import { cloneDeep, omit } from 'lodash-es' +import { warn } from '/@/utils/log' +import { createRouter, createWebHashHistory } from 'vue-router' + +export type LayoutMapKey = 'LAYOUT' +const LayoutMap = new Map Promise>() + +LayoutMap.set('LAYOUT', LAYOUT) + +let dynamicViewsModules: Record Promise> + +// Dynamic introduction +function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { + dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}') + if (!routes) return + routes.forEach((item) => { + const { component, name } = item + const { children } = item + if (component) { + const layoutFound = LayoutMap.get(component.toUpperCase()) + if (layoutFound) { + item.component = layoutFound + } else { + item.component = dynamicImport(dynamicViewsModules, component as string) + } + } else if (name) { + item.component = getParentLayout() + } + children && asyncImportRoute(children) + }) +} + +function dynamicImport( + dynamicViewsModules: Record Promise>, + component: string, +) { + const keys = Object.keys(dynamicViewsModules) + const matchKeys = keys.filter((key) => { + const k = key.replace('../../views', '') + const startFlag = component.startsWith('/') + const endFlag = component.endsWith('.vue') || component.endsWith('.tsx') + const startIndex = startFlag ? 0 : 1 + const lastIndex = endFlag ? k.length : k.lastIndexOf('.') + return k.substring(startIndex, lastIndex) === component + }) + if (matchKeys?.length === 1) { + const matchKey = matchKeys[0] + return dynamicViewsModules[matchKey] + } else if (matchKeys?.length > 1) { + warn( + 'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure', + ) + return + } else { + warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!') + return EXCEPTION_COMPONENT + } +} + +// Turn background objects into routing objects +// 将背景对象变成路由对象 +export function transformObjToRoute(routeList: AppRouteModule[]): T[] { + routeList.forEach((route) => { + const component = route.component as string + if (component) { + if (component.toUpperCase() === 'LAYOUT') { + route.component = LayoutMap.get(component.toUpperCase()) + } else { + route.children = [cloneDeep(route)] + route.component = LAYOUT + route.name = `${route.name}Parent` + route.path = '' + const meta = route.meta || {} + meta.single = true + meta.affix = false + route.meta = meta + } + } else { + warn('请正确配置路由:' + route?.name + '的component属性') + } + route.children && asyncImportRoute(route.children) + }) + return routeList as unknown as T[] +} + +/** + * Convert multi-level routing to level 2 routing + * 将多级路由转换为 2 级路由 + */ +export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) { + const modules: AppRouteModule[] = cloneDeep(routeModules) + + for (let index = 0; index < modules.length; index++) { + const routeModule = modules[index] + // 判断级别是否 多级 路由 + if (!isMultipleRoute(routeModule)) { + // 声明终止当前循环, 即跳过此次循环,进行下一轮 + continue + } + // 路由等级提升 + promoteRouteLevel(routeModule) + } + return modules +} + +// Routing level upgrade +// 路由等级提升 +function promoteRouteLevel(routeModule: AppRouteModule) { + // Use vue-router to splice menus + // 使用vue-router拼接菜单 + // createRouter 创建一个可以被 Vue 应用程序使用的路由实例 + let router: Router | null = createRouter({ + routes: [routeModule as unknown as RouteRecordNormalized], + history: createWebHashHistory(), + }) + // getRoutes: 获取所有 路由记录的完整列表。 + const routes = router.getRoutes() + // 将所有子路由添加到二级路由 + addToChildren(routes, routeModule.children || [], routeModule) + router = null + + // omit lodash的函数 对传入的item对象的children进行删除 + routeModule.children = routeModule.children?.map((item) => omit(item, 'children')) +} + +// Add all sub-routes to the secondary route +// 将所有子路由添加到二级路由 +function addToChildren( + routes: RouteRecordNormalized[], + children: AppRouteRecordRaw[], + routeModule: AppRouteModule, +) { + for (let index = 0; index < children.length; index++) { + const child = children[index] + const route = routes.find((item) => item.name === child.name) + if (!route) { + continue + } + routeModule.children = routeModule.children || [] + if (!routeModule.children.find((item) => item.name === route.name)) { + routeModule.children?.push(route as unknown as AppRouteModule) + } + if (child.children?.length) { + addToChildren(routes, child.children, routeModule) + } + } +} + +// Determine whether the level exceeds 2 levels +// 判断级别是否超过2级 +function isMultipleRoute(routeModule: AppRouteModule) { + // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性 + if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) { + return false + } + + const children = routeModule.children + + let flag = false + for (let index = 0; index < children.length; index++) { + const child = children[index] + if (child.children?.length) { + flag = true + break + } + } + return flag +} diff --git a/frontend/vben/src/router/index.ts b/frontend/vben/src/router/index.ts new file mode 100644 index 0000000..0c0203a --- /dev/null +++ b/frontend/vben/src/router/index.ts @@ -0,0 +1,42 @@ +import type { RouteRecordRaw } from 'vue-router' +import type { App } from 'vue' + +import { createRouter, createWebHashHistory } from 'vue-router' +import { basicRoutes } from './routes' + +// 白名单应该包含基本静态路由 +const WHITE_NAME_LIST: string[] = [] +const getRouteNames = (array: any[]) => + array.forEach((item) => { + WHITE_NAME_LIST.push(item.name) + getRouteNames(item.children || []) + }) +getRouteNames(basicRoutes) + +// app router +// 创建一个可以被 Vue 应用程序使用的路由实例 +export const router = createRouter({ + // 创建一个 hash 历史记录。 + history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH), + // 应该添加到路由的初始路由列表。 + routes: basicRoutes as unknown as RouteRecordRaw[], + // 是否应该禁止尾部斜杠。默认为假 + strict: true, + scrollBehavior: () => ({ left: 0, top: 0 }), +}) + +// reset router +export function resetRouter() { + router.getRoutes().forEach((route) => { + const { name } = route + if (name && !WHITE_NAME_LIST.includes(name as string)) { + router.hasRoute(name) && router.removeRoute(name) + } + }) +} + +// config router +// 配置路由器 +export function setupRouter(app: App) { + app.use(router) +} diff --git a/frontend/vben/src/router/menus/index.ts b/frontend/vben/src/router/menus/index.ts new file mode 100644 index 0000000..d313252 --- /dev/null +++ b/frontend/vben/src/router/menus/index.ts @@ -0,0 +1,126 @@ +import type { Menu, MenuModule } from '/@/router/types' +import type { RouteRecordNormalized } from 'vue-router' + +import { useAppStoreWithOut } from '/@/store/modules/app' +import { usePermissionStore } from '/@/store/modules/permission' +import { transformMenuModule, getAllParentPath } from '/@/router/helper/menuHelper' +import { filter } from '/@/utils/helper/treeHelper' +import { isUrl } from '/@/utils/is' +import { router } from '/@/router' +import { PermissionModeEnum } from '/@/enums/appEnum' +import { pathToRegexp } from 'path-to-regexp' + +const modules = import.meta.globEager('./modules/**/*.ts') + +const menuModules: MenuModule[] = [] + +Object.keys(modules).forEach((key) => { + const mod = modules[key].default || {} + const modList = Array.isArray(mod) ? [...mod] : [mod] + menuModules.push(...modList) +}) + +// =========================== +// ==========Helper=========== +// =========================== + +const getPermissionMode = () => { + const appStore = useAppStoreWithOut() + return appStore.getProjectConfig.permissionMode +} +const isBackMode = () => { + return getPermissionMode() === PermissionModeEnum.BACK +} + +const isRouteMappingMode = () => { + return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING +} + +const isRoleMode = () => { + return getPermissionMode() === PermissionModeEnum.ROLE +} + +const staticMenus: Menu[] = [] +;(() => { + menuModules.sort((a, b) => { + return (a.orderNo || 0) - (b.orderNo || 0) + }) + + for (const menu of menuModules) { + staticMenus.push(transformMenuModule(menu)) + } +})() + +async function getAsyncMenus() { + const permissionStore = usePermissionStore() + if (isBackMode()) { + return permissionStore.getBackMenuList.filter((item) => !item.meta?.hideMenu && !item.hideMenu) + } + if (isRouteMappingMode()) { + return permissionStore.getFrontMenuList.filter((item) => !item.hideMenu) + } + return staticMenus +} + +export const getMenus = async (): Promise => { + const menus = await getAsyncMenus() + if (isRoleMode()) { + const routes = router.getRoutes() + return filter(menus, basicFilter(routes)) + } + return menus +} + +export async function getCurrentParentPath(currentPath: string) { + const menus = await getAsyncMenus() + const allParentPath = await getAllParentPath(menus, currentPath) + return allParentPath?.[0] +} + +// Get the level 1 menu, delete children +export async function getShallowMenus(): Promise { + const menus = await getAsyncMenus() + const shallowMenuList = menus.map((item) => ({ ...item, children: undefined })) + if (isRoleMode()) { + const routes = router.getRoutes() + return shallowMenuList.filter(basicFilter(routes)) + } + return shallowMenuList +} + +// Get the children of the menu +export async function getChildrenMenus(parentPath: string) { + const menus = await getMenus() + const parent = menus.find((item) => item.path === parentPath) + if (!parent || !parent.children || !!parent?.meta?.hideChildrenInMenu) { + return [] as Menu[] + } + if (isRoleMode()) { + const routes = router.getRoutes() + return filter(parent.children, basicFilter(routes)) + } + return parent.children +} + +function basicFilter(routes: RouteRecordNormalized[]) { + return (menu: Menu) => { + const matchRoute = routes.find((route) => { + if (isUrl(menu.path)) return true + + if (route.meta?.carryParam) { + return pathToRegexp(route.path).test(menu.path) + } + const isSame = route.path === menu.path + if (!isSame) return false + + if (route.meta?.ignoreAuth) return true + + return isSame || pathToRegexp(route.path).test(menu.path) + }) + + if (!matchRoute) return false + menu.icon = (menu.icon || matchRoute.meta.icon) as string + menu.meta = matchRoute.meta + return true + } +} diff --git a/frontend/vben/src/router/routes/basic.ts b/frontend/vben/src/router/routes/basic.ts new file mode 100644 index 0000000..e35d1cb --- /dev/null +++ b/frontend/vben/src/router/routes/basic.ts @@ -0,0 +1,48 @@ +import type { AppRouteRecordRaw } from '/@/router/types' +import { REDIRECT_NAME, LAYOUT, EXCEPTION_COMPONENT, PAGE_NOT_FOUND_NAME } from '/@/router/constant' + +// 404 on a page +export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME, + component: LAYOUT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/:path(.*)*', + name: PAGE_NOT_FOUND_NAME, + component: EXCEPTION_COMPONENT, + meta: { + title: 'ErrorPage', + hideBreadcrumb: true, + hideMenu: true, + }, + }, + ], +} + +export const REDIRECT_ROUTE: AppRouteRecordRaw = { + path: '/redirect', + component: LAYOUT, + name: 'RedirectTo', + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + hideMenu: true, + }, + children: [ + { + path: '/redirect/:path(.*)', + name: REDIRECT_NAME, + component: () => import('/@/views/sys/redirect/index.vue'), + meta: { + title: REDIRECT_NAME, + hideBreadcrumb: true, + }, + }, + ], +} diff --git a/frontend/vben/src/router/routes/index.ts b/frontend/vben/src/router/routes/index.ts new file mode 100644 index 0000000..a4b025b --- /dev/null +++ b/frontend/vben/src/router/routes/index.ts @@ -0,0 +1,42 @@ +import type { AppRouteRecordRaw, AppRouteModule } from '/@/router/types' + +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic' + +import { PageEnum } from '/@/enums/pageEnum' +import { t } from '/@/hooks/web/useI18n' + +// import.meta.globEager() 直接引入所有的模块 Vite 独有的功能 +const modules = import.meta.globEager('./modules/**/*.ts') +const routeModuleList: AppRouteModule[] = [] + +// 加入到路由集合中 +Object.keys(modules).forEach((key) => { + const mod = modules[key].default || {} + const modList = Array.isArray(mod) ? [...mod] : [mod] + routeModuleList.push(...modList) +}) + +export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList] + +// 根路由 +export const RootRoute: AppRouteRecordRaw = { + path: '/', + name: 'Root', + redirect: PageEnum.BASE_HOME, + meta: { + title: 'Root', + }, +} + +export const LoginRoute: AppRouteRecordRaw = { + path: '/login', + name: 'Login', + component: () => import('/@/views/sys/login/Login.vue'), + meta: { + title: t('routes.basic.login'), + }, +} + +// Basic routing without permission +// 未经许可的基本路由 +export const basicRoutes = [LoginRoute, RootRoute, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE] diff --git a/frontend/vben/src/router/routes/modules/about.ts b/frontend/vben/src/router/routes/modules/about.ts new file mode 100644 index 0000000..b304abd --- /dev/null +++ b/frontend/vben/src/router/routes/modules/about.ts @@ -0,0 +1,31 @@ +import type { AppRouteModule } from '/@/router/types' + +import { LAYOUT } from '/@/router/constant' +import { t } from '/@/hooks/web/useI18n' + +const about: AppRouteModule = { + path: '/about', + name: 'About', + component: LAYOUT, + redirect: '/about/index', + meta: { + hideChildrenInMenu: true, + icon: 'simple-icons:about-dot-me', + title: t('routes.dashboard.about'), + orderNo: 100000, + }, + children: [ + { + path: 'index', + name: 'AboutPage', + component: () => import('/@/views/sys/about/index.vue'), + meta: { + title: t('routes.dashboard.about'), + icon: 'simple-icons:about-dot-me', + hideMenu: true, + }, + }, + ], +} + +export default about diff --git a/frontend/vben/src/router/routes/modules/dashboard.ts b/frontend/vben/src/router/routes/modules/dashboard.ts new file mode 100644 index 0000000..ac4b0d3 --- /dev/null +++ b/frontend/vben/src/router/routes/modules/dashboard.ts @@ -0,0 +1,37 @@ +import type { AppRouteModule } from '/@/router/types' + +import { LAYOUT } from '/@/router/constant' +import { t } from '/@/hooks/web/useI18n' + +const dashboard: AppRouteModule = { + path: '/dashboard', + name: 'Dashboard', + component: LAYOUT, + redirect: '/dashboard/analysis', + meta: { + orderNo: 10, + icon: 'ion:grid-outline', + title: t('routes.dashboard.dashboard'), + }, + children: [ + { + path: 'analysis', + name: 'Analysis', + component: () => import('/@/views/dashboard/analysis/index.vue'), + meta: { + // affix: true, + title: t('routes.dashboard.analysis'), + }, + }, + { + path: 'workbench', + name: 'Workbench', + component: () => import('/@/views/dashboard/workbench/index.vue'), + meta: { + title: t('routes.dashboard.workbench'), + }, + }, + ], +} + +export default dashboard diff --git a/frontend/vben/src/router/routes/modules/setup.ts b/frontend/vben/src/router/routes/modules/setup.ts new file mode 100644 index 0000000..62757d7 --- /dev/null +++ b/frontend/vben/src/router/routes/modules/setup.ts @@ -0,0 +1,31 @@ +import type { AppRouteModule } from '/@/router/types' + +import { LAYOUT } from '/@/router/constant' +import { t } from '/@/hooks/web/useI18n' + +const setup: AppRouteModule = { + path: '/setup', + name: 'SetupDemo', + component: LAYOUT, + redirect: '/setup/index', + meta: { + orderNo: 90000, + hideChildrenInMenu: true, + icon: 'whh:paintroll', + title: t('routes.demo.setup.page'), + }, + children: [ + { + path: 'index', + name: 'SetupDemoPage', + component: () => import('/@/views/setup/index.vue'), + meta: { + title: t('routes.demo.setup.page'), + icon: 'whh:paintroll', + hideMenu: true, + }, + }, + ], +} + +export default setup diff --git a/frontend/vben/src/router/types.ts b/frontend/vben/src/router/types.ts new file mode 100644 index 0000000..6756b97 --- /dev/null +++ b/frontend/vben/src/router/types.ts @@ -0,0 +1,58 @@ +import type { RouteRecordRaw, RouteMeta } from 'vue-router' +import { RoleEnum } from '/@/enums/roleEnum' +import { defineComponent } from 'vue' + +export type Component = + | ReturnType + | (() => Promise) + | (() => Promise) + +// @ts-ignore +export interface AppRouteRecordRaw extends Omit { + name: string + meta: RouteMeta + component?: Component | string + components?: Component + children?: AppRouteRecordRaw[] + props?: Recordable + fullPath?: string +} + +export interface MenuTag { + type?: 'primary' | 'error' | 'warn' | 'success' + content?: string + dot?: boolean +} + +export interface Menu { + name: string + + icon?: string + + path: string + + // path contains param, auto assignment. + paramPath?: string + + disabled?: boolean + + children?: Menu[] + + orderNo?: number + + roles?: RoleEnum[] + + meta?: Partial + + tag?: MenuTag + + hideMenu?: boolean +} + +export interface MenuModule { + orderNo?: number + menu: Menu +} + +// export type AppRouteModule = RouteModule | AppRouteRecordRaw; +export type AppRouteModule = AppRouteRecordRaw diff --git a/frontend/vben/src/settings/componentSetting.ts b/frontend/vben/src/settings/componentSetting.ts new file mode 100644 index 0000000..2cf29e5 --- /dev/null +++ b/frontend/vben/src/settings/componentSetting.ts @@ -0,0 +1,51 @@ +// Used to configure the general configuration of some components without modifying the components + +import type { SorterResult } from '../components/Table' + +export default { + // basic-table setting + table: { + // Form interface request general configuration + // support xxx.xxx.xxx + fetchSetting: { + // The field name of the current page passed to the background + pageField: 'page', + // The number field name of each page displayed in the background + sizeField: 'pageSize', + // Field name of the form data returned by the interface + listField: 'items', + // Total number of tables returned by the interface field name + totalField: 'total', + }, + // Number of pages that can be selected + pageSizeOptions: ['10', '50', '80', '100'], + // Default display quantity on one page + defaultPageSize: 10, + // Default Size + defaultSize: 'middle', + // Custom general sort function + defaultSortFn: (sortInfo: SorterResult) => { + const { field, order } = sortInfo + if (field && order) { + return { + // The sort field passed to the backend you + field, + // Sorting method passed to the background asc/desc + order, + } + } else { + return {} + } + }, + // Custom general filter function + defaultFilterFn: (data: Partial>) => { + return data + }, + }, + // scrollbar setting + scrollbar: { + // Whether to use native scroll bar + // After opening, the menu, modal, drawer will change the pop-up scroll bar to native + native: false, + }, +} diff --git a/frontend/vben/src/settings/designSetting.ts b/frontend/vben/src/settings/designSetting.ts new file mode 100644 index 0000000..1c17464 --- /dev/null +++ b/frontend/vben/src/settings/designSetting.ts @@ -0,0 +1,48 @@ +import { ThemeEnum } from '../enums/appEnum' + +export const prefixCls = 'vben' + +export const darkMode = ThemeEnum.LIGHT + +// app theme preset color +export const APP_PRESET_COLOR_LIST: string[] = [ + '#0960bd', + '#0084f4', + '#009688', + '#536dfe', + '#ff5c93', + '#ee4f12', + '#0096c7', + '#9c27b0', + '#ff9800', +] + +// header preset color +export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ + '#ffffff', + '#151515', + '#009688', + '#5172DC', + '#018ffb', + '#409eff', + '#e74c3c', + '#24292e', + '#394664', + '#001529', + '#383f45', +] + +// sider preset color +export const SIDE_BAR_BG_COLOR_LIST: string[] = [ + '#001529', + '#212121', + '#273352', + '#ffffff', + '#191b24', + '#191a23', + '#304156', + '#001628', + '#28333E', + '#344058', + '#383f45', +] diff --git a/frontend/vben/src/settings/encryptionSetting.ts b/frontend/vben/src/settings/encryptionSetting.ts new file mode 100644 index 0000000..3c97305 --- /dev/null +++ b/frontend/vben/src/settings/encryptionSetting.ts @@ -0,0 +1,13 @@ +import { isDevMode } from '/@/utils/env' + +// System default cache time, in seconds +export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7 + +// aes encryption key +export const cacheCipher = { + key: '_11111000001111@', + iv: '@11111000001111_', +} + +// Whether the system cache is encrypted using aes +export const enableStorageEncryption = !isDevMode() diff --git a/frontend/vben/src/settings/localeSetting.ts b/frontend/vben/src/settings/localeSetting.ts new file mode 100644 index 0000000..7d5fea9 --- /dev/null +++ b/frontend/vben/src/settings/localeSetting.ts @@ -0,0 +1,29 @@ +import type { DropMenu } from '../components/Dropdown' +import type { LocaleSetting, LocaleType } from '/#/config' + +export const LOCALE: { [key: string]: LocaleType } = { + ZH_CN: 'zh_CN', + EN_US: 'en', +} + +export const localeSetting: LocaleSetting = { + showPicker: true, + // Locale + locale: LOCALE.ZH_CN, + // Default locale + fallback: LOCALE.ZH_CN, + // available Locales + availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US], +} + +// locale list +export const localeList: DropMenu[] = [ + { + text: '简体中文', + event: LOCALE.ZH_CN, + }, + { + text: 'English', + event: LOCALE.EN_US, + }, +] diff --git a/frontend/vben/src/settings/projectSetting.ts b/frontend/vben/src/settings/projectSetting.ts new file mode 100644 index 0000000..768d4f0 --- /dev/null +++ b/frontend/vben/src/settings/projectSetting.ts @@ -0,0 +1,177 @@ +import type { ProjectConfig } from '/#/config' +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum' +import { CacheTypeEnum } from '/@/enums/cacheEnum' +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '/@/enums/appEnum' +import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST } from './designSetting' +import { primaryColor } from '../../build/config/themeConfig' + +// ! You need to clear the browser cache after the change +const setting: ProjectConfig = { + // Whether to show the configuration button + showSettingButton: true, + + // Whether to show the theme switch button + showDarkModeToggle: true, + + // `Settings` button position + settingButtonPosition: SettingButtonPositionEnum.AUTO, + + // Permission mode + permissionMode: PermissionModeEnum.ROUTE_MAPPING, + + // Permission-related cache is stored in sessionStorage or localStorage + permissionCacheType: CacheTypeEnum.LOCAL, + + // Session timeout processing + sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP, + + // color + themeColor: primaryColor, + + // Website gray mode, open for possible mourning dates + grayMode: false, + + // Color Weakness Mode + colorWeak: false, + + // Whether to cancel the menu, the top, the multi-tab page display, for possible embedded in other systems + fullContent: false, + + // content mode + contentMode: ContentEnum.FULL, + + // Whether to display the logo + showLogo: true, + + // Whether to show footer + showFooter: false, + + // Header configuration + headerSetting: { + // header bg color + bgColor: HEADER_PRESET_BG_COLOR_LIST[0], + // Fixed at the top + fixed: true, + // Whether to show top + show: true, + // theme + theme: ThemeEnum.LIGHT, + // Whether to show the full screen button + showFullScreen: true, + // Whether to show the document button + showDoc: true, + // Whether to show the notification button + showNotice: true, + // Whether to display the menu search + showSearch: true, + }, + + // Menu configuration + menuSetting: { + // sidebar menu bg color + bgColor: SIDE_BAR_BG_COLOR_LIST[0], + // Whether to fix the left menu + fixed: true, + // Menu collapse + collapsed: false, + // When sider hide because of the responsive layout + siderHidden: false, + // Whether to display the menu name when folding the menu + collapsedShowTitle: false, + // Whether it can be dragged + // Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu + canDrag: false, + // Whether to show no dom + show: true, + // Whether to show dom + hidden: false, + // Menu width + menuWidth: 210, + // Menu mode + mode: MenuModeEnum.INLINE, + // Menu type + type: MenuTypeEnum.SIDEBAR, + // Menu theme + theme: ThemeEnum.DARK, + // Split menu + split: false, + // Top menu layout + topMenuAlign: 'center', + // Fold trigger position + trigger: TriggerEnum.HEADER, + // Turn on accordion mode, only show a menu + accordion: true, + // Switch page to close menu + closeMixSidebarOnChange: false, + // Module opening method ‘click’ |'hover' + mixSideTrigger: MixSidebarTriggerEnum.CLICK, + // Fixed expanded menu + mixSideFixed: false, + }, + + // Multi-label + multiTabsSetting: { + cache: false, + // Turn on + show: true, + // Is it possible to drag and drop sorting tabs + canDrag: true, + // Turn on quick actions + showQuick: true, + // Whether to show the refresh button + showRedo: true, + // Whether to show the collapse button + showFold: true, + }, + + // Transition Setting + transitionSetting: { + // Whether to open the page switching animation + // The disabled state will also disable pageLoading + enable: true, + + // Route basic switching animation + basicTransition: RouterTransitionEnum.FADE_SIDE, + + // Whether to open page switching loading + // Only open when enable=true + openPageLoading: true, + + // Whether to open the top progress bar + openNProgress: false, + }, + + // Whether to enable KeepAlive cache is best to close during development, otherwise the cache needs to be cleared every time + openKeepAlive: true, + + // Whether to show breadcrumbs + showBreadCrumb: true, + + // Whether to show the breadcrumb icon + showBreadCrumbIcon: false, + + // Use error-handler-plugin + useErrorHandle: false, + + // Whether to open back to top + useOpenBackTop: true, + + // Is it possible to embed iframe pages + canEmbedIFramePage: true, + + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: true, + + // Whether to cancel the http request that has been sent but not responded when switching the interface. + // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface + removeAllHttpPending: false, +} + +export default setting diff --git a/frontend/vben/src/settings/siteSetting.ts b/frontend/vben/src/settings/siteSetting.ts new file mode 100644 index 0000000..5f465d3 --- /dev/null +++ b/frontend/vben/src/settings/siteSetting.ts @@ -0,0 +1,8 @@ +// github repo url +export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin' + +// vue-vben-admin-next-doc +export const DOC_URL = 'https://vvbin.cn/doc-next/' + +// site url +export const SITE_URL = 'https://vvbin.cn/next/' diff --git a/frontend/vben/src/store/index.ts b/frontend/vben/src/store/index.ts new file mode 100644 index 0000000..4d393cb --- /dev/null +++ b/frontend/vben/src/store/index.ts @@ -0,0 +1,10 @@ +import type { App } from 'vue' +import { createPinia } from 'pinia' + +const store = createPinia() + +export function setupStore(app: App) { + app.use(store) +} + +export { store } diff --git a/frontend/vben/src/store/modules/app.ts b/frontend/vben/src/store/modules/app.ts new file mode 100644 index 0000000..0d73999 --- /dev/null +++ b/frontend/vben/src/store/modules/app.ts @@ -0,0 +1,108 @@ +import type { + ProjectConfig, + HeaderSetting, + MenuSetting, + TransitionSetting, + MultiTabsSetting, +} from '/#/config' +import type { BeforeMiniState } from '/#/store' + +import { defineStore } from 'pinia' +import { store } from '/@/store' + +import { ThemeEnum } from '/@/enums/appEnum' +import { APP_DARK_MODE_KEY_, PROJ_CFG_KEY } from '/@/enums/cacheEnum' +import { Persistent } from '/@/utils/cache/persistent' +import { darkMode } from '/@/settings/designSetting' +import { resetRouter } from '/@/router' +import { deepMerge } from '/@/utils' + +interface AppState { + darkMode?: ThemeEnum + // Page loading status + pageLoading: boolean + // project config + projectConfig: ProjectConfig | null + // When the window shrinks, remember some states, and restore these states when the window is restored + beforeMiniInfo: BeforeMiniState +} +let timeId: TimeoutHandle +export const useAppStore = defineStore({ + id: 'app', + state: (): AppState => ({ + darkMode: undefined, + pageLoading: false, + projectConfig: Persistent.getLocal(PROJ_CFG_KEY), + beforeMiniInfo: {}, + }), + getters: { + getPageLoading(): boolean { + return this.pageLoading + }, + getDarkMode(): 'light' | 'dark' | string { + return this.darkMode || localStorage.getItem(APP_DARK_MODE_KEY_) || darkMode + }, + + getBeforeMiniInfo(): BeforeMiniState { + return this.beforeMiniInfo + }, + + getProjectConfig(): ProjectConfig { + return this.projectConfig || ({} as ProjectConfig) + }, + + getHeaderSetting(): HeaderSetting { + return this.getProjectConfig.headerSetting + }, + getMenuSetting(): MenuSetting { + return this.getProjectConfig.menuSetting + }, + getTransitionSetting(): TransitionSetting { + return this.getProjectConfig.transitionSetting + }, + getMultiTabsSetting(): MultiTabsSetting { + return this.getProjectConfig.multiTabsSetting + }, + }, + actions: { + setPageLoading(loading: boolean): void { + this.pageLoading = loading + }, + + setDarkMode(mode: ThemeEnum): void { + this.darkMode = mode + localStorage.setItem(APP_DARK_MODE_KEY_, mode) + }, + + setBeforeMiniInfo(state: BeforeMiniState): void { + this.beforeMiniInfo = state + }, + + setProjectConfig(config: DeepPartial): void { + this.projectConfig = deepMerge(this.projectConfig || {}, config) + Persistent.setLocal(PROJ_CFG_KEY, this.projectConfig) + }, + + async resetAllState() { + resetRouter() + Persistent.clearAll() + }, + async setPageLoadingAction(loading: boolean): Promise { + if (loading) { + clearTimeout(timeId) + // Prevent flicker + timeId = setTimeout(() => { + this.setPageLoading(loading) + }, 50) + } else { + this.setPageLoading(loading) + clearTimeout(timeId) + } + }, + }, +}) + +// Need to be used outside the setup +export function useAppStoreWithOut() { + return useAppStore(store) +} diff --git a/frontend/vben/src/store/modules/locale.ts b/frontend/vben/src/store/modules/locale.ts new file mode 100644 index 0000000..afd7b32 --- /dev/null +++ b/frontend/vben/src/store/modules/locale.ts @@ -0,0 +1,55 @@ +import type { LocaleSetting, LocaleType } from '/#/config' + +import { defineStore } from 'pinia' +import { store } from '/@/store' + +import { LOCALE_KEY } from '/@/enums/cacheEnum' +import { createLocalStorage } from '/@/utils/cache' +import { localeSetting } from '/@/settings/localeSetting' + +const ls = createLocalStorage() + +const lsLocaleSetting = (ls.get(LOCALE_KEY) || localeSetting) as LocaleSetting + +interface LocaleState { + localInfo: LocaleSetting +} + +export const useLocaleStore = defineStore({ + id: 'app-locale', + state: (): LocaleState => ({ + localInfo: lsLocaleSetting, + }), + getters: { + getShowPicker(): boolean { + return !!this.localInfo?.showPicker + }, + getLocale(): LocaleType { + return this.localInfo?.locale ?? 'zh_CN' + }, + }, + actions: { + /** + * Set up multilingual information and cache + * @param info multilingual info + */ + setLocaleInfo(info: Partial) { + this.localInfo = { ...this.localInfo, ...info } + ls.set(LOCALE_KEY, this.localInfo) + }, + /** + * Initialize multilingual information and load the existing configuration from the local cache + */ + initLocale() { + this.setLocaleInfo({ + ...localeSetting, + ...this.localInfo, + }) + }, + }, +}) + +// Need to be used outside the setup +export function useLocaleStoreWithOut() { + return useLocaleStore(store) +} diff --git a/frontend/vben/src/store/modules/multipleTab.ts b/frontend/vben/src/store/modules/multipleTab.ts new file mode 100644 index 0000000..2f64011 --- /dev/null +++ b/frontend/vben/src/store/modules/multipleTab.ts @@ -0,0 +1,359 @@ +import type { RouteLocationNormalized, RouteLocationRaw, Router } from 'vue-router' + +import { toRaw, unref } from 'vue' +import { defineStore } from 'pinia' +import { store } from '/@/store' + +import { useGo, useRedo } from '/@/hooks/web/usePage' +import { Persistent } from '/@/utils/cache/persistent' + +import { PageEnum } from '/@/enums/pageEnum' +import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic' +import { getRawRoute } from '/@/utils' +import { MULTIPLE_TABS_KEY } from '/@/enums/cacheEnum' + +import projectSetting from '/@/settings/projectSetting' +import { useUserStore } from '/@/store/modules/user' + +export interface MultipleTabState { + cacheTabList: Set + tabList: RouteLocationNormalized[] + lastDragEndIndex: number +} + +function handleGotoPage(router: Router) { + const go = useGo(router) + go(unref(router.currentRoute).path, true) +} + +const getToTarget = (tabItem: RouteLocationNormalized) => { + const { params, path, query } = tabItem + return { + params: params || {}, + path, + query: query || {}, + } +} + +const cacheTab = projectSetting.multiTabsSetting.cache + +export const useMultipleTabStore = defineStore({ + id: 'app-multiple-tab', + state: (): MultipleTabState => ({ + // Tabs that need to be cached + cacheTabList: new Set(), + // multiple tab list + tabList: cacheTab ? Persistent.getLocal(MULTIPLE_TABS_KEY) || [] : [], + // Index of the last moved tab + lastDragEndIndex: 0, + }), + getters: { + getTabList(): RouteLocationNormalized[] { + return this.tabList + }, + getCachedTabList(): string[] { + return Array.from(this.cacheTabList) + }, + getLastDragEndIndex(): number { + return this.lastDragEndIndex + }, + }, + actions: { + /** + * Update the cache according to the currently opened tabs + */ + async updateCacheTab() { + const cacheMap: Set = new Set() + + for (const tab of this.tabList) { + const item = getRawRoute(tab) + // Ignore the cache + const needCache = !item.meta?.ignoreKeepAlive + if (!needCache) { + continue + } + const name = item.name as string + cacheMap.add(name) + } + this.cacheTabList = cacheMap + }, + + /** + * Refresh tabs + */ + async refreshPage(router: Router) { + const { currentRoute } = router + const route = unref(currentRoute) + const name = route.name + + const findTab = this.getCachedTabList.find((item) => item === name) + if (findTab) { + this.cacheTabList.delete(findTab) + } + const redo = useRedo(router) + await redo() + }, + clearCacheTabs(): void { + this.cacheTabList = new Set() + }, + resetState(): void { + this.tabList = [] + this.clearCacheTabs() + }, + goToPage(router: Router) { + const go = useGo(router) + const len = this.tabList.length + const { path } = unref(router.currentRoute) + + let toPath: PageEnum | string = PageEnum.BASE_HOME + + if (len > 0) { + const page = this.tabList[len - 1] + const p = page.fullPath || page.path + if (p) { + toPath = p + } + } + // Jump to the current page and report an error + path !== toPath && go(toPath as PageEnum, true) + }, + + async addTab(route: RouteLocationNormalized) { + const { path, name, fullPath, params, query, meta } = getRawRoute(route) + // 404 The page does not need to add a tab + if ( + path === PageEnum.ERROR_PAGE || + path === PageEnum.BASE_LOGIN || + !name || + [REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string) + ) { + return + } + + let updateIndex = -1 + // Existing pages, do not add tabs repeatedly + const tabHasExits = this.tabList.some((tab, index) => { + updateIndex = index + return (tab.fullPath || tab.path) === (fullPath || path) + }) + + // If the tab already exists, perform the update operation + if (tabHasExits) { + const curTab = toRaw(this.tabList)[updateIndex] + if (!curTab) { + return + } + curTab.params = params || curTab.params + curTab.query = query || curTab.query + curTab.fullPath = fullPath || curTab.fullPath + this.tabList.splice(updateIndex, 1, curTab) + } else { + // Add tab + // 获取动态路由打开数,超过 0 即代表需要控制打开数 + const dynamicLevel = meta?.dynamicLevel ?? -1 + if (dynamicLevel > 0) { + // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 + // 首先获取到真实的路由,使用配置方式减少计算开销. + // const realName: string = path.match(/(\S*)\//)![1]; + const realPath = meta?.realPath ?? '' + // 获取到已经打开的动态路由数, 判断是否大于某一个值 + if ( + this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= dynamicLevel + ) { + // 关闭第一个 + const index = this.tabList.findIndex((item) => item.meta.realPath === realPath) + index !== -1 && this.tabList.splice(index, 1) + } + } + this.tabList.push(route) + } + this.updateCacheTab() + cacheTab && Persistent.setLocal(MULTIPLE_TABS_KEY, this.tabList) + }, + + async closeTab(tab: RouteLocationNormalized, router: Router) { + const close = (route: RouteLocationNormalized) => { + const { fullPath, meta: { affix } = {} } = route + if (affix) { + return + } + const index = this.tabList.findIndex((item) => item.fullPath === fullPath) + index !== -1 && this.tabList.splice(index, 1) + } + + const { currentRoute, replace } = router + + const { path } = unref(currentRoute) + if (path !== tab.path) { + // Closed is not the activation tab + close(tab) + return + } + + // Closed is activated atb + let toTarget: RouteLocationRaw = {} + + const index = this.tabList.findIndex((item) => item.path === path) + + // If the current is the leftmost tab + if (index === 0) { + // There is only one tab, then jump to the homepage, otherwise jump to the right tab + if (this.tabList.length === 1) { + const userStore = useUserStore() + toTarget = userStore.getUserInfo.homePath || PageEnum.BASE_HOME + } else { + // Jump to the right tab + const page = this.tabList[index + 1] + toTarget = getToTarget(page) + } + } else { + // Close the current tab + const page = this.tabList[index - 1] + toTarget = getToTarget(page) + } + close(currentRoute.value) + await replace(toTarget) + }, + + // Close according to key + async closeTabByKey(key: string, router: Router) { + const index = this.tabList.findIndex((item) => (item.fullPath || item.path) === key) + if (index !== -1) { + await this.closeTab(this.tabList[index], router) + const { currentRoute, replace } = router + // 检查当前路由是否存在于tabList中 + const isActivated = this.tabList.findIndex((item) => { + return item.fullPath === currentRoute.value.fullPath + }) + // 如果当前路由不存在于TabList中,尝试切换到其它路由 + if (isActivated === -1) { + let pageIndex + if (index > 0) { + pageIndex = index - 1 + } else if (index < this.tabList.length - 1) { + pageIndex = index + 1 + } else { + pageIndex = -1 + } + if (pageIndex >= 0) { + const page = this.tabList[index - 1] + const toTarget = getToTarget(page) + await replace(toTarget) + } + } + } + }, + + // Sort the tabs + async sortTabs(oldIndex: number, newIndex: number) { + const currentTab = this.tabList[oldIndex] + this.tabList.splice(oldIndex, 1) + this.tabList.splice(newIndex, 0, currentTab) + this.lastDragEndIndex = this.lastDragEndIndex + 1 + }, + + // Close the tab on the right and jump + async closeLeftTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.path === route.path) + + if (index > 0) { + const leftTabs = this.tabList.slice(0, index) + const pathList: string[] = [] + for (const item of leftTabs) { + const affix = item?.meta?.affix ?? false + if (!affix) { + pathList.push(item.fullPath) + } + } + this.bulkCloseTabs(pathList) + } + this.updateCacheTab() + handleGotoPage(router) + }, + + // Close the tab on the left and jump + async closeRightTabs(route: RouteLocationNormalized, router: Router) { + const index = this.tabList.findIndex((item) => item.fullPath === route.fullPath) + + if (index >= 0 && index < this.tabList.length - 1) { + const rightTabs = this.tabList.slice(index + 1, this.tabList.length) + + const pathList: string[] = [] + for (const item of rightTabs) { + const affix = item?.meta?.affix ?? false + if (!affix) { + pathList.push(item.fullPath) + } + } + this.bulkCloseTabs(pathList) + } + this.updateCacheTab() + handleGotoPage(router) + }, + + async closeAllTab(router: Router) { + this.tabList = this.tabList.filter((item) => item?.meta?.affix ?? false) + this.clearCacheTabs() + this.goToPage(router) + }, + + /** + * Close other tabs + */ + async closeOtherTabs(route: RouteLocationNormalized, router: Router) { + const closePathList = this.tabList.map((item) => item.fullPath) + + const pathList: string[] = [] + + for (const path of closePathList) { + if (path !== route.fullPath) { + const closeItem = this.tabList.find((item) => item.path === path) + if (!closeItem) { + continue + } + const affix = closeItem?.meta?.affix ?? false + if (!affix) { + pathList.push(closeItem.fullPath) + } + } + } + this.bulkCloseTabs(pathList) + this.updateCacheTab() + handleGotoPage(router) + }, + + /** + * Close tabs in bulk + */ + async bulkCloseTabs(pathList: string[]) { + this.tabList = this.tabList.filter((item) => !pathList.includes(item.fullPath)) + }, + + /** + * Set tab's title + */ + async setTabTitle(title: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route) + if (findTab) { + findTab.meta.title = title + await this.updateCacheTab() + } + }, + /** + * replace tab's path + * **/ + async updateTabPath(fullPath: string, route: RouteLocationNormalized) { + const findTab = this.getTabList.find((item) => item === route) + if (findTab) { + findTab.fullPath = fullPath + findTab.path = fullPath + await this.updateCacheTab() + } + }, + }, +}) + +// Need to be used outside the setup +export function useMultipleTabWithOutStore() { + return useMultipleTabStore(store) +} diff --git a/frontend/vben/src/store/modules/permission.ts b/frontend/vben/src/store/modules/permission.ts new file mode 100644 index 0000000..9542522 --- /dev/null +++ b/frontend/vben/src/store/modules/permission.ts @@ -0,0 +1,259 @@ +import type { AppRouteRecordRaw, Menu } from '/@/router/types' + +import { defineStore } from 'pinia' +import { store } from '/@/store' +import { useI18n } from '/@/hooks/web/useI18n' +import { useUserStore } from './user' +import { useAppStoreWithOut } from './app' +import { toRaw } from 'vue' +import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper' +import { transformRouteToMenu } from '/@/router/helper/menuHelper' + +import projectSetting from '/@/settings/projectSetting' + +import { PermissionModeEnum } from '/@/enums/appEnum' + +import { asyncRoutes } from '/@/router/routes' +import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic' + +import { filter } from '/@/utils/helper/treeHelper' + +import { getMenuList } from '/@/api/sys/menu' +import { getPermCode } from '/@/api/sys/user' + +import { useMessage } from '/@/hooks/web/useMessage' +import { PageEnum } from '/@/enums/pageEnum' + +interface PermissionState { + // Permission code list + // 权限代码列表 + permCodeList: string[] | number[] + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: boolean + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: number + // Backstage menu list + // 后台菜单列表 + backMenuList: Menu[] + // 菜单列表 + frontMenuList: Menu[] +} + +export const usePermissionStore = defineStore({ + id: 'app-permission', + state: (): PermissionState => ({ + // 权限代码列表 + permCodeList: [], + // Whether the route has been dynamically added + // 路由是否动态添加 + isDynamicAddedRoute: false, + // To trigger a menu update + // 触发菜单更新 + lastBuildMenuTime: 0, + // Backstage menu list + // 后台菜单列表 + backMenuList: [], + // menu List + // 菜单列表 + frontMenuList: [], + }), + getters: { + getPermCodeList(): string[] | number[] { + return this.permCodeList + }, + getBackMenuList(): Menu[] { + return this.backMenuList + }, + getFrontMenuList(): Menu[] { + return this.frontMenuList + }, + getLastBuildMenuTime(): number { + return this.lastBuildMenuTime + }, + getIsDynamicAddedRoute(): boolean { + return this.isDynamicAddedRoute + }, + }, + actions: { + setPermCodeList(codeList: string[]) { + this.permCodeList = codeList + }, + + setBackMenuList(list: Menu[]) { + this.backMenuList = list + list?.length > 0 && this.setLastBuildMenuTime() + }, + + setFrontMenuList(list: Menu[]) { + this.frontMenuList = list + }, + + setLastBuildMenuTime() { + this.lastBuildMenuTime = new Date().getTime() + }, + + setDynamicAddedRoute(added: boolean) { + this.isDynamicAddedRoute = added + }, + resetState(): void { + this.isDynamicAddedRoute = false + this.permCodeList = [] + this.backMenuList = [] + this.lastBuildMenuTime = 0 + }, + async changePermissionCode() { + const codeList = await getPermCode() + this.setPermCodeList(codeList) + }, + + // 构建路由 + async buildRoutesAction(): Promise { + const { t } = useI18n() + const userStore = useUserStore() + const appStore = useAppStoreWithOut() + + let routes: AppRouteRecordRaw[] = [] + const roleList = toRaw(userStore.getRoleList) || [] + const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig + + // 路由过滤器 在 函数filter 作为回调传入遍历使用 + const routeFilter = (route: AppRouteRecordRaw) => { + const { meta } = route + // 抽出角色 + const { roles } = meta || {} + if (!roles) return true + // 进行角色权限判断 + return roleList.some((role) => roles.includes(role)) + } + + const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { + const { meta } = route + // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现 + const { ignoreRoute } = meta || {} + // arr.filter 返回 true 表示该元素通过测试 + return !ignoreRoute + } + + /** + * @description 根据设置的首页path,修正routes中的affix标记(固定首页) + * */ + const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { + if (!routes || routes.length === 0) return + let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME + + function patcher(routes: AppRouteRecordRaw[], parentPath = '') { + if (parentPath) parentPath = parentPath + '/' + routes.forEach((route: AppRouteRecordRaw) => { + const { path, children, redirect } = route + const currentPath = path.startsWith('/') ? path : parentPath + path + if (currentPath === homePath) { + if (redirect) { + homePath = route.redirect! as string + } else { + route.meta = Object.assign({}, route.meta, { affix: true }) + throw new Error('end') + } + } + children && children.length > 0 && patcher(children, currentPath) + }) + } + + try { + patcher(routes) + } catch (e) { + // 已处理完毕跳出循环 + } + return + } + + switch (permissionMode) { + // 角色权限 + case PermissionModeEnum.ROLE: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter) + // 对一级路由根据角色权限过滤 + routes = routes.filter(routeFilter) + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes) + break + + // 路由映射, 默认进入该case + case PermissionModeEnum.ROUTE_MAPPING: + // 对非一级路由进行过滤 + routes = filter(asyncRoutes, routeFilter) + // 对一级路由再次根据角色权限过滤 + routes = routes.filter(routeFilter) + // 将路由转换成菜单 + const menuList = transformRouteToMenu(routes, true) + // 移除掉 ignoreRoute: true 的路由 非一级路由 + routes = filter(routes, routeRemoveIgnoreFilter) + // 移除掉 ignoreRoute: true 的路由 一级路由; + routes = routes.filter(routeRemoveIgnoreFilter) + // 对菜单进行排序 + menuList.sort((a, b) => { + return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0) + }) + + // 设置菜单列表 + this.setFrontMenuList(menuList) + + // Convert multi-level routing to level 2 routing + // 将多级路由转换为 2 级路由 + routes = flatMultiLevelRoutes(routes) + break + + // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below + // 如果确定不需要做后台动态权限,请在下方评论整个判断 + case PermissionModeEnum.BACK: + const { createMessage } = useMessage() + + createMessage.loading({ + content: t('sys.app.menuLoading'), + duration: 1, + }) + + // !Simulate to obtain permission codes from the background, + // 模拟从后台获取权限码, + // this function may only need to be executed once, and the actual project can be put at the right time by itself + // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间 + let routeList: AppRouteRecordRaw[] = [] + try { + await this.changePermissionCode() + routeList = (await getMenuList()) as AppRouteRecordRaw[] + } catch (error) { + console.error(error) + } + + // Dynamically introduce components + // 动态引入组件 + routeList = transformObjToRoute(routeList) + + // Background routing to menu structure + // 后台路由到菜单结构 + const backMenuList = transformRouteToMenu(routeList) + this.setBackMenuList(backMenuList) + + // remove meta.ignoreRoute item + // 删除 meta.ignoreRoute 项 + routeList = filter(routeList, routeRemoveIgnoreFilter) + routeList = routeList.filter(routeRemoveIgnoreFilter) + + routeList = flatMultiLevelRoutes(routeList) + routes = [PAGE_NOT_FOUND_ROUTE, ...routeList] + break + } + + patchHomeAffix(routes) + return routes + }, + }, +}) + +// Need to be used outside the setup +// 需要在设置之外使用 +export function usePermissionStoreWithOut() { + return usePermissionStore(store) +} diff --git a/frontend/vben/src/store/modules/user.ts b/frontend/vben/src/store/modules/user.ts new file mode 100644 index 0000000..49dc38e --- /dev/null +++ b/frontend/vben/src/store/modules/user.ts @@ -0,0 +1,177 @@ +import type { UserInfo } from '/#/store' +import type { ErrorMessageMode } from '/#/axios' +import { defineStore } from 'pinia' +import { store } from '/@/store' +import { RoleEnum } from '/@/enums/roleEnum' +import { PageEnum } from '/@/enums/pageEnum' +import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum' +import { getAuthCache, setAuthCache } from '/@/utils/auth' +import { GetUserInfoModel, LoginParams } from '/@/api/sys/model/userModel' +import { doLogout, getUserInfo, loginApi } from '/@/api/sys/user' +import { useI18n } from '/@/hooks/web/useI18n' +import { useMessage } from '/@/hooks/web/useMessage' +import { router } from '/@/router' +import { usePermissionStore } from '/@/store/modules/permission' +import { RouteRecordRaw } from 'vue-router' +import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic' +import { isArray } from '/@/utils/is' +import { h } from 'vue' + +interface UserState { + userInfo: Nullable + token?: string + roleList: RoleEnum[] + sessionTimeout?: boolean + lastUpdateTime: number +} + +export const useUserStore = defineStore({ + id: 'app-user', + state: (): UserState => ({ + // user info + userInfo: null, + // token + token: undefined, + // roleList + roleList: [], + // Whether the login expired + sessionTimeout: false, + // Last fetch time + lastUpdateTime: 0, + }), + getters: { + getUserInfo(): UserInfo { + return this.userInfo || getAuthCache(USER_INFO_KEY) || {} + }, + getToken(): string { + return this.token || getAuthCache(TOKEN_KEY) + }, + getRoleList(): RoleEnum[] { + return this.roleList.length > 0 ? this.roleList : getAuthCache(ROLES_KEY) + }, + getSessionTimeout(): boolean { + return !!this.sessionTimeout + }, + getLastUpdateTime(): number { + return this.lastUpdateTime + }, + }, + actions: { + setToken(info: string | undefined) { + this.token = info ? info : '' // for null or undefined value + setAuthCache(TOKEN_KEY, info) + }, + setRoleList(roleList: RoleEnum[]) { + this.roleList = roleList + setAuthCache(ROLES_KEY, roleList) + }, + setUserInfo(info: UserInfo | null) { + this.userInfo = info + this.lastUpdateTime = new Date().getTime() + setAuthCache(USER_INFO_KEY, info) + }, + setSessionTimeout(flag: boolean) { + this.sessionTimeout = flag + }, + resetState() { + this.userInfo = null + this.token = '' + this.roleList = [] + this.sessionTimeout = false + }, + /** + * @description: login + */ + async login( + params: LoginParams & { + goHome?: boolean + mode?: ErrorMessageMode + }, + ): Promise { + try { + const { goHome = true, mode, ...loginParams } = params + const data = await loginApi(loginParams, mode) + const { token } = data + + // save token + this.setToken(token) + return this.afterLoginAction(goHome) + } catch (error) { + return Promise.reject(error) + } + }, + async afterLoginAction(goHome?: boolean): Promise { + if (!this.getToken) return null + // get user info + const userInfo = await this.getUserInfoAction() + + const sessionTimeout = this.sessionTimeout + if (sessionTimeout) { + this.setSessionTimeout(false) + } else { + const permissionStore = usePermissionStore() + if (!permissionStore.isDynamicAddedRoute) { + const routes = await permissionStore.buildRoutesAction() + routes.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) + }) + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw) + permissionStore.setDynamicAddedRoute(true) + } + goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME)) + } + return userInfo + }, + async getUserInfoAction(): Promise { + if (!this.getToken) return null + const userInfo = await getUserInfo() + const { roles = [] } = userInfo + if (isArray(roles)) { + const roleList = roles.map((item) => item.value) as RoleEnum[] + this.setRoleList(roleList) + } else { + userInfo.roles = [] + this.setRoleList([]) + } + this.setUserInfo(userInfo) + return userInfo + }, + /** + * @description: logout + */ + async logout(goLogin = false) { + if (this.getToken) { + try { + await doLogout() + } catch { + console.log('注销Token失败') + } + } + this.setToken(undefined) + this.setSessionTimeout(false) + this.setUserInfo(null) + goLogin && router.push(PageEnum.BASE_LOGIN) + }, + + /** + * @description: Confirm before logging out + */ + confirmLoginOut() { + const { createConfirm } = useMessage() + const { t } = useI18n() + createConfirm({ + iconType: 'warning', + title: () => h('span', t('sys.app.Tip')), + content: () => h('span', t('sys.app.logoutMessage')), + onOk: async () => { + await this.logout(true) + }, + }) + }, + }, +}) + +// Need to be used outside the setup +export function useUserStoreWithOut() { + return useUserStore(store) +} diff --git a/frontend/vben/src/utils/auth/index.ts b/frontend/vben/src/utils/auth/index.ts new file mode 100644 index 0000000..02ada37 --- /dev/null +++ b/frontend/vben/src/utils/auth/index.ts @@ -0,0 +1,26 @@ +import { Persistent, BasicKeys } from '/@/utils/cache/persistent' +import { CacheTypeEnum } from '/@/enums/cacheEnum' +import projectSetting from '/@/settings/projectSetting' +import { TOKEN_KEY } from '/@/enums/cacheEnum' + +const { permissionCacheType } = projectSetting +const isLocal = permissionCacheType === CacheTypeEnum.LOCAL + +export function getToken() { + return getAuthCache(TOKEN_KEY) +} + +export function getAuthCache(key: BasicKeys) { + const fn = isLocal ? Persistent.getLocal : Persistent.getSession + return fn(key) as T +} + +export function setAuthCache(key: BasicKeys, value) { + const fn = isLocal ? Persistent.setLocal : Persistent.setSession + return fn(key, value, true) +} + +export function clearAuthCache(immediate = true) { + const fn = isLocal ? Persistent.clearLocal : Persistent.clearSession + return fn(immediate) +} diff --git a/frontend/vben/src/utils/bem.ts b/frontend/vben/src/utils/bem.ts new file mode 100644 index 0000000..3a39b6a --- /dev/null +++ b/frontend/vben/src/utils/bem.ts @@ -0,0 +1,52 @@ +import { prefixCls } from '/@/settings/designSetting' + +type Mod = string | { [key: string]: any } +type Mods = Mod | Mod[] + +export type BEM = ReturnType + +function genBem(name: string, mods?: Mods): string { + if (!mods) { + return '' + } + + if (typeof mods === 'string') { + return ` ${name}--${mods}` + } + + if (Array.isArray(mods)) { + return mods.reduce((ret, item) => ret + genBem(name, item), '') + } + + return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? genBem(name, key) : ''), '') +} + +/** + * bem helper + * b() // 'button' + * b('text') // 'button__text' + * b({ disabled }) // 'button button--disabled' + * b('text', { disabled }) // 'button__text button__text--disabled' + * b(['disabled', 'primary']) // 'button button--disabled button--primary' + */ +export function buildBEM(name: string) { + return (el?: Mods, mods?: Mods): Mods => { + if (el && typeof el !== 'string') { + mods = el + el = '' + } + + el = el ? `${name}__${el}` : name + + return `${el}${genBem(el, mods)}` + } +} + +export function createBEM(name: string) { + return [buildBEM(`${prefixCls}-${name}`)] +} + +export function createNamespace(name: string) { + const prefixedName = `${prefixCls}-${name}` + return [prefixedName, buildBEM(prefixedName)] as const +} diff --git a/frontend/vben/src/utils/cache/index.ts b/frontend/vben/src/utils/cache/index.ts new file mode 100644 index 0000000..8502912 --- /dev/null +++ b/frontend/vben/src/utils/cache/index.ts @@ -0,0 +1,32 @@ +import { getStorageShortName } from '/@/utils/env' +import { createStorage as create, CreateStorageParams } from './storageCache' +import { enableStorageEncryption } from '/@/settings/encryptionSetting' +import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting' + +export type Options = Partial + +const createOptions = (storage: Storage, options: Options = {}): Options => { + return { + // No encryption in debug mode + hasEncrypt: enableStorageEncryption, + storage, + prefixKey: getStorageShortName(), + ...options, + } +} + +export const WebStorage = create(createOptions(sessionStorage)) + +export const createStorage = (storage: Storage = sessionStorage, options: Options = {}) => { + return create(createOptions(storage, options)) +} + +export const createSessionStorage = (options: Options = {}) => { + return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME }) +} + +export const createLocalStorage = (options: Options = {}) => { + return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME }) +} + +export default WebStorage diff --git a/frontend/vben/src/utils/cache/memory.ts b/frontend/vben/src/utils/cache/memory.ts new file mode 100644 index 0000000..0eb84ad --- /dev/null +++ b/frontend/vben/src/utils/cache/memory.ts @@ -0,0 +1,107 @@ +export interface Cache { + value?: V + timeoutId?: ReturnType + time?: number + alive?: number +} + +const NOT_ALIVE = 0 + +export class Memory { + private cache: { [key in keyof T]?: Cache } = {} + private alive: number + + constructor(alive = NOT_ALIVE) { + // Unit second + this.alive = alive * 1000 + } + + get getCache() { + return this.cache + } + + setCache(cache) { + this.cache = cache + } + + // get(key: K) { + // const item = this.getItem(key); + // const time = item?.time; + // if (!isNullOrUnDef(time) && time < new Date().getTime()) { + // this.remove(key); + // } + // return item?.value ?? undefined; + // } + + get(key: K) { + return this.cache[key] + } + + set(key: K, value: V, expires?: number) { + let item = this.get(key) + + if (!expires || (expires as number) <= 0) { + expires = this.alive + } + if (item) { + if (item.timeoutId) { + clearTimeout(item.timeoutId) + item.timeoutId = undefined + } + item.value = value + } else { + item = { value, alive: expires } + this.cache[key] = item + } + + if (!expires) { + return value + } + const now = new Date().getTime() + /** + * Prevent overflow of the setTimeout Maximum delay value + * Maximum delay value 2,147,483,647 ms + * https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value + */ + item.time = expires > now ? expires : now + expires + item.timeoutId = setTimeout( + () => { + this.remove(key) + }, + expires > now ? expires - now : expires, + ) + + return value + } + + remove(key: K) { + const item = this.get(key) + Reflect.deleteProperty(this.cache, key) + if (item) { + clearTimeout(item.timeoutId!) + return item.value + } + } + + resetCache(cache: { [K in keyof T]: Cache }) { + Object.keys(cache).forEach((key) => { + const k = key as any as keyof T + const item = cache[k] + if (item && item.time) { + const now = new Date().getTime() + const expire = item.time + if (expire > now) { + this.set(k, item.value, expire) + } + } + }) + } + + clear() { + Object.keys(this.cache).forEach((key) => { + const item = this.cache[key] + item.timeoutId && clearTimeout(item.timeoutId) + }) + this.cache = {} + } +} diff --git a/frontend/vben/src/utils/cache/persistent.ts b/frontend/vben/src/utils/cache/persistent.ts new file mode 100644 index 0000000..8462cf1 --- /dev/null +++ b/frontend/vben/src/utils/cache/persistent.ts @@ -0,0 +1,125 @@ +import type { UserInfo } from '/#/store' +import type { ProjectConfig } from '/#/config' +import type { RouteLocationNormalized } from 'vue-router' + +import { createLocalStorage, createSessionStorage } from '/@/utils/cache' +import { Memory } from './memory' +import { + TOKEN_KEY, + USER_INFO_KEY, + ROLES_KEY, + PROJ_CFG_KEY, + APP_LOCAL_CACHE_KEY, + APP_SESSION_CACHE_KEY, + MULTIPLE_TABS_KEY, +} from '/@/enums/cacheEnum' +import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting' +import { toRaw } from 'vue' +import { pick, omit } from 'lodash-es' + +interface BasicStore { + [TOKEN_KEY]: string | number | null | undefined + [USER_INFO_KEY]: UserInfo + [ROLES_KEY]: string[] + [PROJ_CFG_KEY]: ProjectConfig + [MULTIPLE_TABS_KEY]: RouteLocationNormalized[] +} + +type LocalStore = BasicStore + +type SessionStore = BasicStore + +export type BasicKeys = keyof BasicStore +type LocalKeys = keyof LocalStore +type SessionKeys = keyof SessionStore + +const ls = createLocalStorage() +const ss = createSessionStorage() + +const localMemory = new Memory(DEFAULT_CACHE_TIME) +const sessionMemory = new Memory(DEFAULT_CACHE_TIME) + +function initPersistentMemory() { + const localCache = ls.get(APP_LOCAL_CACHE_KEY) + const sessionCache = ss.get(APP_SESSION_CACHE_KEY) + localCache && localMemory.resetCache(localCache) + sessionCache && sessionMemory.resetCache(sessionCache) +} + +export class Persistent { + static getLocal(key: LocalKeys) { + return localMemory.get(key)?.value as Nullable + } + + static setLocal(key: LocalKeys, value: LocalStore[LocalKeys], immediate = false): void { + localMemory.set(key, toRaw(value)) + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache) + } + + static removeLocal(key: LocalKeys, immediate = false): void { + localMemory.remove(key) + immediate && ls.set(APP_LOCAL_CACHE_KEY, localMemory.getCache) + } + + static clearLocal(immediate = false): void { + localMemory.clear() + immediate && ls.clear() + } + + static getSession(key: SessionKeys) { + return sessionMemory.get(key)?.value as Nullable + } + + static setSession(key: SessionKeys, value: SessionStore[SessionKeys], immediate = false): void { + sessionMemory.set(key, toRaw(value)) + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache) + } + + static removeSession(key: SessionKeys, immediate = false): void { + sessionMemory.remove(key) + immediate && ss.set(APP_SESSION_CACHE_KEY, sessionMemory.getCache) + } + static clearSession(immediate = false): void { + sessionMemory.clear() + immediate && ss.clear() + } + + static clearAll(immediate = false) { + sessionMemory.clear() + localMemory.clear() + if (immediate) { + ls.clear() + ss.clear() + } + } +} + +window.addEventListener('beforeunload', function () { + // TOKEN_KEY 在登录或注销时已经写入到storage了,此处为了解决同时打开多个窗口时token不同步的问题 + ss.set(APP_SESSION_CACHE_KEY, { + ...omit(sessionMemory.getCache), + ...pick(ss.get(APP_SESSION_CACHE_KEY), [TOKEN_KEY, USER_INFO_KEY]), + }) +}) + +function storageChange(e: any) { + const { key, newValue, oldValue } = e + + if (!key) { + Persistent.clearAll() + return + } + + if (!!newValue && !!oldValue) { + if (APP_LOCAL_CACHE_KEY === key) { + Persistent.clearLocal() + } + if (APP_SESSION_CACHE_KEY === key) { + Persistent.clearSession() + } + } +} + +window.addEventListener('storage', storageChange) + +initPersistentMemory() diff --git a/frontend/vben/src/utils/cache/storageCache.ts b/frontend/vben/src/utils/cache/storageCache.ts new file mode 100644 index 0000000..5fd4fb9 --- /dev/null +++ b/frontend/vben/src/utils/cache/storageCache.ts @@ -0,0 +1,109 @@ +import { cacheCipher } from '/@/settings/encryptionSetting' +import type { EncryptionParams } from '/@/utils/cipher' +import { AesEncryption } from '/@/utils/cipher' +import { isNullOrUnDef } from '/@/utils/is' + +export interface CreateStorageParams extends EncryptionParams { + prefixKey: string + storage: Storage + hasEncrypt: boolean + timeout?: Nullable +} +export const createStorage = ({ + prefixKey = '', + storage = sessionStorage, + key = cacheCipher.key, + iv = cacheCipher.iv, + timeout = null, + hasEncrypt = true, +}: Partial = {}) => { + if (hasEncrypt && [key.length, iv.length].some((item) => item !== 16)) { + throw new Error('When hasEncrypt is true, the key or iv must be 16 bits!') + } + + const encryption = new AesEncryption({ key, iv }) + + /** + * Cache class + * Construction parameters can be passed into sessionStorage, localStorage, + * @class Cache + * @example + */ + const WebStorage = class WebStorage { + private storage: Storage + private prefixKey?: string + private encryption: AesEncryption + private hasEncrypt: boolean + /** + * + * @param {*} storage + */ + constructor() { + this.storage = storage + this.prefixKey = prefixKey + this.encryption = encryption + this.hasEncrypt = hasEncrypt + } + + private getKey(key: string) { + return `${this.prefixKey}${key}`.toUpperCase() + } + + /** + * Set cache + * @param {string} key + * @param {*} value + * @param {*} expire Expiration time in seconds + * @memberof Cache + */ + set(key: string, value: any, expire: number | null = timeout) { + const stringData = JSON.stringify({ + value, + time: Date.now(), + expire: !isNullOrUnDef(expire) ? new Date().getTime() + expire * 1000 : null, + }) + const stringifyValue = this.hasEncrypt ? this.encryption.encryptByAES(stringData) : stringData + this.storage.setItem(this.getKey(key), stringifyValue) + } + + /** + * Read cache + * @param {string} key + * @param {*} def + * @memberof Cache + */ + get(key: string, def: any = null): any { + const val = this.storage.getItem(this.getKey(key)) + if (!val) return def + + try { + const decVal = this.hasEncrypt ? this.encryption.decryptByAES(val) : val + const data = JSON.parse(decVal) + const { value, expire } = data + if (isNullOrUnDef(expire) || expire >= new Date().getTime()) { + return value + } + this.remove(key) + } catch (e) { + return def + } + } + + /** + * Delete cache based on key + * @param {string} key + * @memberof Cache + */ + remove(key: string) { + this.storage.removeItem(this.getKey(key)) + } + + /** + * Delete all caches of this instance + */ + clear(): void { + this.storage.clear() + } + } + return new WebStorage() +} diff --git a/frontend/vben/src/utils/cipher.ts b/frontend/vben/src/utils/cipher.ts new file mode 100644 index 0000000..15169c0 --- /dev/null +++ b/frontend/vben/src/utils/cipher.ts @@ -0,0 +1,55 @@ +import { encrypt, decrypt } from 'crypto-js/aes' +import { parse } from 'crypto-js/enc-utf8' +import pkcs7 from 'crypto-js/pad-pkcs7' +import ECB from 'crypto-js/mode-ecb' +import md5 from 'crypto-js/md5' +import UTF8 from 'crypto-js/enc-utf8' +import Base64 from 'crypto-js/enc-base64' + +export interface EncryptionParams { + key: string + iv: string +} + +export class AesEncryption { + private key + private iv + + constructor(opt: Partial = {}) { + const { key, iv } = opt + if (key) { + this.key = parse(key) + } + if (iv) { + this.iv = parse(iv) + } + } + + get getOptions() { + return { + mode: ECB, + padding: pkcs7, + iv: this.iv, + } + } + + encryptByAES(cipherText: string) { + return encrypt(cipherText, this.key, this.getOptions).toString() + } + + decryptByAES(cipherText: string) { + return decrypt(cipherText, this.key, this.getOptions).toString(UTF8) + } +} + +export function encryptByBase64(cipherText: string) { + return UTF8.parse(cipherText).toString(Base64) +} + +export function decodeByBase64(cipherText: string) { + return Base64.parse(cipherText).toString(UTF8) +} + +export function encryptByMd5(password: string) { + return md5(password).toString() +} diff --git a/frontend/vben/src/utils/color.ts b/frontend/vben/src/utils/color.ts new file mode 100644 index 0000000..afe312d --- /dev/null +++ b/frontend/vben/src/utils/color.ts @@ -0,0 +1,151 @@ +/** + * 判断是否 十六进制颜色值. + * 输入形式可为 #fff000 #f00 + * + * @param String color 十六进制颜色值 + * @return Boolean + */ +export function isHexColor(color: string) { + const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/ + return reg.test(color) +} + +/** + * RGB 颜色值转换为 十六进制颜色值. + * r, g, 和 b 需要在 [0, 255] 范围内 + * + * @return String 类似#ff00ff + * @param r + * @param g + * @param b + */ +export function rgbToHex(r: number, g: number, b: number) { + // tslint:disable-next-line:no-bitwise + const hex = ((r << 16) | (g << 8) | b).toString(16) + return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex +} + +/** + * Transform a HEX color to its RGB representation + * @param {string} hex The color to transform + * @returns The RGB representation of the passed color + */ +export function hexToRGB(hex: string) { + let sHex = hex.toLowerCase() + if (isHexColor(hex)) { + if (sHex.length === 4) { + let sColorNew = '#' + for (let i = 1; i < 4; i += 1) { + sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)) + } + sHex = sColorNew + } + const sColorChange: number[] = [] + for (let i = 1; i < 7; i += 2) { + sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))) + } + return 'RGB(' + sColorChange.join(',') + ')' + } + return sHex +} + +export function colorIsDark(color: string) { + if (!isHexColor(color)) return + const [r, g, b] = hexToRGB(color) + .replace(/(?:\(|\)|rgb|RGB)*/g, '') + .split(',') + .map((item) => Number(item)) + return r * 0.299 + g * 0.578 + b * 0.114 < 192 +} + +/** + * Darkens a HEX color given the passed percentage + * @param {string} color The color to process + * @param {number} amount The amount to change the color by + * @returns {string} The HEX representation of the processed color + */ +export function darken(color: string, amount: number) { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount, + )}${subtractLight(color.substring(4, 6), amount)}` +} + +/** + * Lightens a 6 char HEX color according to the passed percentage + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed color represented as HEX + */ +export function lighten(color: string, amount: number) { + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = Math.trunc((255 * amount) / 100) + return `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount, + )}${addLight(color.substring(4, 6), amount)}` +} + +/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ +/** + * Sums the passed percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +function addLight(color: string, amount: number) { + const cc = parseInt(color, 16) + amount + const c = cc > 255 ? 255 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} + +/** + * Calculates luminance of an rgb color + * @param {number} r red + * @param {number} g green + * @param {number} b blue + */ +function luminanace(r: number, g: number, b: number) { + const a = [r, g, b].map((v) => { + v /= 255 + return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4) + }) + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722 +} + +/** + * Calculates contrast between two rgb colors + * @param {string} rgb1 rgb color 1 + * @param {string} rgb2 rgb color 2 + */ +function contrast(rgb1: string[], rgb2: number[]) { + return ( + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ) +} + +/** + * Determines what the best text color is (black or white) based con the contrast with the background + * @param hexColor - Last selected color by the user + */ +export function calculateBestTextColor(hexColor: string) { + const rgbColor = hexToRGB(hexColor.substring(1)) + const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]) + + return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF' +} + +/** + * Subtracts the indicated percentage to the R, G or B of a HEX color + * @param {string} color The color to change + * @param {number} amount The amount to change the color by + * @returns {string} The processed part of the color + */ +function subtractLight(color: string, amount: number) { + const cc = parseInt(color, 16) - amount + const c = cc < 0 ? 0 : cc + return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}` +} diff --git a/frontend/vben/src/utils/dateUtil.ts b/frontend/vben/src/utils/dateUtil.ts new file mode 100644 index 0000000..458c982 --- /dev/null +++ b/frontend/vben/src/utils/dateUtil.ts @@ -0,0 +1,23 @@ +/** + * Independent time operation tool to facilitate subsequent switch to dayjs + */ +import dayjs from 'dayjs' + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' +const DATE_FORMAT = 'YYYY-MM-DD' + +export function formatToDateTime( + date: dayjs.Dayjs | undefined = undefined, + format = DATE_TIME_FORMAT, +): string { + return dayjs(date).format(format) +} + +export function formatToDate( + date: dayjs.Dayjs | undefined = undefined, + format = DATE_FORMAT, +): string { + return dayjs(date).format(format) +} + +export const dateUtil = dayjs diff --git a/frontend/vben/src/utils/domUtils.ts b/frontend/vben/src/utils/domUtils.ts new file mode 100644 index 0000000..9b1f53f --- /dev/null +++ b/frontend/vben/src/utils/domUtils.ts @@ -0,0 +1,180 @@ +import type { FunctionArgs } from '@vueuse/core' +import { upperFirst } from 'lodash-es' + +export interface ViewportOffsetResult { + left: number + top: number + right: number + bottom: number + rightIncludeBody: number + bottomIncludeBody: number +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0 + } + return element.getBoundingClientRect() +} + +function trim(string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false + if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.') + if (el.classList) { + return el.classList.contains(cls) + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return + let curClass = el.className + const classes = (cls || '').split(' ') + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.add(clsName) + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName + } + } + if (!el.classList) { + el.className = curClass + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return + const classes = cls.split(' ') + let curClass = ' ' + el.className + ' ' + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.remove(clsName) + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' ') + } + } + if (!el.classList) { + el.className = trim(curClass) + } +} +/** + * Get the left and top offset of the current element + * left: the distance between the leftmost element and the left side of the document + * top: the distance from the top of the element to the top of the document + * right: the distance from the far right of the element to the right of the document + * bottom: the distance from the bottom of the element to the bottom of the document + * rightIncludeBody: the distance between the leftmost element and the right side of the document + * bottomIncludeBody: the distance from the bottom of the element to the bottom of the document + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement + + const docScrollLeft = doc.scrollLeft + const docScrollTop = doc.scrollTop + const docClientLeft = doc.clientLeft + const docClientTop = doc.clientTop + + const pageXOffset = window.pageXOffset + const pageYOffset = window.pageYOffset + + const box = getBoundingClientRect(element) + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0) + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0) + const offsetLeft = retLeft + pageXOffset + const offsetTop = rectTop + pageYOffset + + const left = offsetLeft - scrollLeft + const top = offsetTop - scrollTop + + const clientWidth = window.document.documentElement.clientWidth + const clientHeight = window.document.documentElement.clientHeight + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top, + } +} + +export function hackCss(attr: string, value: string) { + const prefix: string[] = ['webkit', 'Moz', 'ms', 'OT'] + + const styleObj: any = {} + prefix.forEach((item) => { + styleObj[`${item}${upperFirst(attr)}`] = value + }) + return { + ...styleObj, + [attr]: value, + } +} + +/* istanbul ignore next */ +export function on( + element: Element | HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject, +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export function off( + element: Element | HTMLElement | Document | Window, + event: string, + handler: Fn, +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export function once(el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + fn.apply(this, args) + } + off(el, event, listener) + } + on(el, event, listener) +} + +export function useRafThrottle(fn: T): T { + let locked = false + // @ts-ignore + return function (...args: any[]) { + if (locked) return + locked = true + window.requestAnimationFrame(() => { + // @ts-ignore + fn.apply(this, args) + locked = false + }) + } +} diff --git a/frontend/vben/src/utils/env.ts b/frontend/vben/src/utils/env.ts new file mode 100644 index 0000000..3f16939 --- /dev/null +++ b/frontend/vben/src/utils/env.ts @@ -0,0 +1,83 @@ +import type { GlobEnvConfig } from '/#/config' + +import { warn } from '/@/utils/log' +import pkg from '../../package.json' +import { getConfigFileName } from '../../build/getConfigFileName' + +export function getCommonStoragePrefix() { + const { VITE_GLOB_APP_SHORT_NAME } = getAppEnvConfig() + return `${VITE_GLOB_APP_SHORT_NAME}__${getEnv()}`.toUpperCase() +} + +// Generate cache key according to version +export function getStorageShortName() { + return `${getCommonStoragePrefix()}${`__${pkg.version}`}__`.toUpperCase() +} + +export function getAppEnvConfig() { + const ENV_NAME = getConfigFileName(import.meta.env) + + const ENV = (import.meta.env.DEV + ? // Get the global configuration (the configuration will be extracted independently when packaging) + (import.meta.env as unknown as GlobEnvConfig) + : window[ENV_NAME as any]) as unknown as GlobEnvConfig + + const { + VITE_GLOB_APP_TITLE, + VITE_GLOB_API_URL, + VITE_GLOB_APP_SHORT_NAME, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + } = ENV + + if (!/^[a-zA-Z\_]*$/.test(VITE_GLOB_APP_SHORT_NAME)) { + warn( + `VITE_GLOB_APP_SHORT_NAME Variables can only be characters/underscores, please modify in the environment variables and re-running.`, + ) + } + + return { + VITE_GLOB_APP_TITLE, + VITE_GLOB_API_URL, + VITE_GLOB_APP_SHORT_NAME, + VITE_GLOB_API_URL_PREFIX, + VITE_GLOB_UPLOAD_URL, + } +} + +/** + * @description: Development mode + */ +export const devMode = 'development' + +/** + * @description: Production mode + */ +export const prodMode = 'production' + +/** + * @description: Get environment variables + * @returns: + * @example: + */ +export function getEnv(): string { + return import.meta.env.MODE +} + +/** + * @description: Is it a development mode + * @returns: + * @example: + */ +export function isDevMode(): boolean { + return import.meta.env.DEV +} + +/** + * @description: Is it a production mode + * @returns: + * @example: + */ +export function isProdMode(): boolean { + return import.meta.env.PROD +} diff --git a/frontend/vben/src/utils/event/index.ts b/frontend/vben/src/utils/event/index.ts new file mode 100644 index 0000000..3b56534 --- /dev/null +++ b/frontend/vben/src/utils/event/index.ts @@ -0,0 +1,42 @@ +import ResizeObserver from 'resize-observer-polyfill' + +const isServer = typeof window === 'undefined' + +/* istanbul ignore next */ +function resizeHandler(entries: any[]) { + for (const entry of entries) { + const listeners = entry.target.__resizeListeners__ || [] + if (listeners.length) { + listeners.forEach((fn: () => any) => { + fn() + }) + } + } +} + +/* istanbul ignore next */ +export function addResizeListener(element: any, fn: () => any) { + if (isServer) return + if (!element.__resizeListeners__) { + element.__resizeListeners__ = [] + element.__ro__ = new ResizeObserver(resizeHandler) + element.__ro__.observe(element) + } + element.__resizeListeners__.push(fn) +} + +/* istanbul ignore next */ +export function removeResizeListener(element: any, fn: () => any) { + if (!element || !element.__resizeListeners__) return + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1) + if (!element.__resizeListeners__.length) { + element.__ro__.disconnect() + } +} + +export function triggerWindowResize() { + const event = document.createEvent('HTMLEvents') + event.initEvent('resize', true, true) + ;(event as any).eventType = 'message' + window.dispatchEvent(event) +} diff --git a/frontend/vben/src/utils/factory/createAsyncComponent.tsx b/frontend/vben/src/utils/factory/createAsyncComponent.tsx new file mode 100644 index 0000000..668678e --- /dev/null +++ b/frontend/vben/src/utils/factory/createAsyncComponent.tsx @@ -0,0 +1,63 @@ +import { + defineAsyncComponent, + // FunctionalComponent, CSSProperties +} from 'vue' +import { Spin } from 'ant-design-vue' +import { noop } from '/@/utils' + +// const Loading: FunctionalComponent<{ size: 'small' | 'default' | 'large' }> = (props) => { +// const style: CSSProperties = { +// position: 'absolute', +// display: 'flex', +// justifyContent: 'center', +// alignItems: 'center', +// }; +// return ( +//
+// +//
+// ); +// }; + +interface Options { + size?: 'default' | 'small' | 'large' + delay?: number + timeout?: number + loading?: boolean + retry?: boolean +} + +export function createAsyncComponent(loader: Fn, options: Options = {}) { + const { size = 'small', delay = 100, timeout = 30000, loading = false, retry = true } = options + return defineAsyncComponent({ + loader, + loadingComponent: loading ? : undefined, + // The error component will be displayed if a timeout is + // provided and exceeded. Default: Infinity. + // TODO + timeout, + // errorComponent + // Defining if component is suspensible. Default: true. + // suspensible: false, + delay, + /** + * + * @param {*} error Error message object + * @param {*} retry A function that indicating whether the async component should retry when the loader promise rejects + * @param {*} fail End of failure + * @param {*} attempts Maximum allowed retries number + */ + onError: !retry + ? noop + : (error, retry, fail, attempts) => { + if (error.message.match(/fetch/) && attempts <= 3) { + // retry on fetch errors, 3 max attempts + retry() + } else { + // Note that retry/fail are like resolve/reject of a promise: + // one of them must be called for the error handling to continue. + fail() + } + }, + }) +} diff --git a/frontend/vben/src/utils/file/base64Conver.ts b/frontend/vben/src/utils/file/base64Conver.ts new file mode 100644 index 0000000..b94225d --- /dev/null +++ b/frontend/vben/src/utils/file/base64Conver.ts @@ -0,0 +1,41 @@ +/** + * @description: base64 to blob + */ +export function dataURLtoBlob(base64Buf: string): Blob { + const arr = base64Buf.split(',') + const typeItem = arr[0] + const mime = typeItem.match(/:(.*?);/)![1] + const bstr = window.atob(arr[1]) + let n = bstr.length + const u8arr = new Uint8Array(n) + while (n--) { + u8arr[n] = bstr.charCodeAt(n) + } + return new Blob([u8arr], { type: mime }) +} + +/** + * img url to base64 + * @param url + */ +export function urlToBase64(url: string, mineType?: string): Promise { + return new Promise((resolve, reject) => { + let canvas = document.createElement('CANVAS') as Nullable + const ctx = canvas!.getContext('2d') + + const img = new Image() + img.crossOrigin = '' + img.onload = function () { + if (!canvas || !ctx) { + return reject() + } + canvas.height = img.height + canvas.width = img.width + ctx.drawImage(img, 0, 0) + const dataURL = canvas.toDataURL(mineType || 'image/png') + canvas = null + resolve(dataURL) + } + img.src = url + }) +} diff --git a/frontend/vben/src/utils/file/download.ts b/frontend/vben/src/utils/file/download.ts new file mode 100644 index 0000000..d068042 --- /dev/null +++ b/frontend/vben/src/utils/file/download.ts @@ -0,0 +1,96 @@ +import { openWindow } from '..' +import { dataURLtoBlob, urlToBase64 } from './base64Conver' + +/** + * Download online pictures + * @param url + * @param filename + * @param mime + * @param bom + */ +export function downloadByOnlineUrl(url: string, filename: string, mime?: string, bom?: BlobPart) { + urlToBase64(url).then((base64) => { + downloadByBase64(base64, filename, mime, bom) + }) +} + +/** + * Download pictures based on base64 + * @param buf + * @param filename + * @param mime + * @param bom + */ +export function downloadByBase64(buf: string, filename: string, mime?: string, bom?: BlobPart) { + const base64Buf = dataURLtoBlob(buf) + downloadByData(base64Buf, filename, mime, bom) +} + +/** + * Download according to the background interface file stream + * @param {*} data + * @param {*} filename + * @param {*} mime + * @param {*} bom + */ +export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) { + const blobData = typeof bom !== 'undefined' ? [bom, data] : [data] + const blob = new Blob(blobData, { type: mime || 'application/octet-stream' }) + + const blobURL = window.URL.createObjectURL(blob) + const tempLink = document.createElement('a') + tempLink.style.display = 'none' + tempLink.href = blobURL + tempLink.setAttribute('download', filename) + if (typeof tempLink.download === 'undefined') { + tempLink.setAttribute('target', '_blank') + } + document.body.appendChild(tempLink) + tempLink.click() + document.body.removeChild(tempLink) + window.URL.revokeObjectURL(blobURL) +} + +/** + * Download file according to file address + * @param {*} sUrl + */ +export function downloadByUrl({ + url, + target = '_blank', + fileName, +}: { + url: string + target?: TargetContext + fileName?: string +}): boolean { + const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1 + const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1 + + if (/(iP)/g.test(window.navigator.userAgent)) { + console.error('Your browser does not support download!') + return false + } + if (isChrome || isSafari) { + const link = document.createElement('a') + link.href = url + link.target = target + + if (link.download !== undefined) { + link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length) + } + + if (document.createEvent) { + const e = document.createEvent('MouseEvents') + e.initEvent('click', true, true) + link.dispatchEvent(e) + return true + } + } + if (url.indexOf('?') === -1) { + url += '?download' + } + + openWindow(url, { target }) + return true +} diff --git a/frontend/vben/src/utils/helper/treeHelper.ts b/frontend/vben/src/utils/helper/treeHelper.ts new file mode 100644 index 0000000..d028191 --- /dev/null +++ b/frontend/vben/src/utils/helper/treeHelper.ts @@ -0,0 +1,216 @@ +interface TreeHelperConfig { + id: string + children: string + pid: string +} + +// 默认配置 +const DEFAULT_CONFIG: TreeHelperConfig = { + id: 'id', + children: 'children', + pid: 'pid', +} + +// 获取配置。 Object.assign 从一个或多个源对象复制到目标对象 +const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config) + +// tree from list +// 列表中的树 +export function listToTree(list: any[], config: Partial = {}): T[] { + const conf = getConfig(config) as TreeHelperConfig + const nodeMap = new Map() + const result: T[] = [] + const { id, children, pid } = conf + + for (const node of list) { + node[children] = node[children] || [] + nodeMap.set(node[id], node) + } + for (const node of list) { + const parent = nodeMap.get(node[pid]) + ;(parent ? parent[children] : result).push(node) + } + return result +} + +export function treeToList(tree: any, config: Partial = {}): T { + config = getConfig(config) + const { children } = config + const result: any = [...tree] + for (let i = 0; i < result.length; i++) { + if (!result[i][children!]) continue + result.splice(i + 1, 0, ...result[i][children!]) + } + return result +} + +export function findNode( + tree: any, + func: Fn, + config: Partial = {}, +): T | null { + config = getConfig(config) + const { children } = config + const list = [...tree] + for (const node of list) { + if (func(node)) return node + node[children!] && list.push(...node[children!]) + } + return null +} + +export function findNodeAll( + tree: any, + func: Fn, + config: Partial = {}, +): T[] { + config = getConfig(config) + const { children } = config + const list = [...tree] + const result: T[] = [] + for (const node of list) { + func(node) && result.push(node) + node[children!] && list.push(...node[children!]) + } + return result +} + +export function findPath( + tree: any, + func: Fn, + config: Partial = {}, +): T | T[] | null { + config = getConfig(config) + const path: T[] = [] + const list = [...tree] + const visitedSet = new Set() + const { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + if (func(node)) { + return path + } + } + } + return null +} + +export function findPathAll(tree: any, func: Fn, config: Partial = {}) { + config = getConfig(config) + const path: any[] = [] + const list = [...tree] + const result: any[] = [] + const visitedSet = new Set(), + { children } = config + while (list.length) { + const node = list[0] + if (visitedSet.has(node)) { + path.pop() + list.shift() + } else { + visitedSet.add(node) + node[children!] && list.unshift(...node[children!]) + path.push(node) + func(node) && result.push([...path]) + } + } + return result +} + +export function filter( + tree: T[], + func: (n: T) => boolean, + // Partial 将 T 中的所有属性设为可选 + config: Partial = {}, +): T[] { + // 获取配置 + config = getConfig(config) + const children = config.children as string + + function listFilter(list: T[]) { + return list + .map((node: any) => ({ ...node })) + .filter((node) => { + // 递归调用 对含有children项 进行再次调用自身函数 listFilter + node[children] = node[children] && listFilter(node[children]) + // 执行传入的回调 func 进行过滤 + return func(node) || (node[children] && node[children].length) + }) + } + + return listFilter(tree) +} + +export function forEach( + tree: T[], + func: (n: T) => any, + config: Partial = {}, +): void { + config = getConfig(config) + const list: any[] = [...tree] + const { children } = config + for (let i = 0; i < list.length; i++) { + //func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿 + if (func(list[i])) { + return + } + children && list[i][children] && list.splice(i + 1, 0, ...list[i][children]) + } +} + +/** + * @description: Extract tree specified structure + * @description: 提取树指定结构 + */ +export function treeMap(treeData: T[], opt: { children?: string; conversion: Fn }): T[] { + return treeData.map((item) => treeMapEach(item, opt)) +} + +/** + * @description: Extract tree specified structure + * @description: 提取树指定结构 + */ +export function treeMapEach( + data: any, + { children = 'children', conversion }: { children?: string; conversion: Fn }, +) { + const haveChildren = Array.isArray(data[children]) && data[children].length > 0 + const conversionData = conversion(data) || {} + if (haveChildren) { + return { + ...conversionData, + [children]: data[children].map((i: number) => + treeMapEach(i, { + children, + conversion, + }), + ), + } + } else { + return { + ...conversionData, + } + } +} + +/** + * 递归遍历树结构 + * @param treeDatas 树 + * @param callBack 回调 + * @param parentNode 父节点 + */ +export function eachTree(treeDatas: any[], callBack: Fn, parentNode = {}) { + treeDatas.forEach((element) => { + const newNode = callBack(element, parentNode) || element + if (element.children) { + eachTree(element.children, callBack, newNode) + } + }) +} diff --git a/frontend/vben/src/utils/helper/tsxHelper.tsx b/frontend/vben/src/utils/helper/tsxHelper.tsx new file mode 100644 index 0000000..913a8b8 --- /dev/null +++ b/frontend/vben/src/utils/helper/tsxHelper.tsx @@ -0,0 +1,35 @@ +import { Slots } from 'vue' +import { isFunction } from '/@/utils/is' + +/** + * @description: Get slot to prevent empty error + */ +export function getSlot(slots: Slots, slot = 'default', data?: any) { + if (!slots || !Reflect.has(slots, slot)) { + return null + } + if (!isFunction(slots[slot])) { + console.error(`${slot} is not a function!`) + return null + } + const slotFn = slots[slot] + if (!slotFn) return null + return slotFn(data) +} + +/** + * extends slots + * @param slots + * @param excludeKeys + */ +export function extendSlots(slots: Slots, excludeKeys: string[] = []) { + const slotKeys = Object.keys(slots) + const ret: any = {} + slotKeys.map((key) => { + if (excludeKeys.includes(key)) { + return null + } + ret[key] = (data?: any) => getSlot(slots, key, data) + }) + return ret +} diff --git a/frontend/vben/src/utils/http/axios/Axios.ts b/frontend/vben/src/utils/http/axios/Axios.ts new file mode 100644 index 0000000..b56eecd --- /dev/null +++ b/frontend/vben/src/utils/http/axios/Axios.ts @@ -0,0 +1,237 @@ +import type { AxiosRequestConfig, AxiosInstance, AxiosResponse, AxiosError } from 'axios' +import type { RequestOptions, Result, UploadFileParams } from '/#/axios' +import type { CreateAxiosOptions } from './axiosTransform' +import axios from 'axios' +import qs from 'qs' +import { AxiosCanceler } from './axiosCancel' +import { isFunction } from '/@/utils/is' +import { cloneDeep } from 'lodash-es' +import { ContentTypeEnum } from '/@/enums/httpEnum' +import { RequestEnum } from '/@/enums/httpEnum' + +export * from './axiosTransform' + +/** + * @description: axios module + */ +export class VAxios { + private axiosInstance: AxiosInstance + private readonly options: CreateAxiosOptions + + constructor(options: CreateAxiosOptions) { + this.options = options + this.axiosInstance = axios.create(options) + this.setupInterceptors() + } + + /** + * @description: Create axios instance + */ + private createAxios(config: CreateAxiosOptions): void { + this.axiosInstance = axios.create(config) + } + + private getTransform() { + const { transform } = this.options + return transform + } + + getAxios(): AxiosInstance { + return this.axiosInstance + } + + /** + * @description: Reconfigure axios + */ + configAxios(config: CreateAxiosOptions) { + if (!this.axiosInstance) { + return + } + this.createAxios(config) + } + + /** + * @description: Set general header + */ + setHeader(headers: any): void { + if (!this.axiosInstance) { + return + } + Object.assign(this.axiosInstance.defaults.headers, headers) + } + + /** + * @description: Interceptor configuration 拦截器配置 + */ + private setupInterceptors() { + const transform = this.getTransform() + if (!transform) { + return + } + const { + requestInterceptors, + requestInterceptorsCatch, + responseInterceptors, + responseInterceptorsCatch, + } = transform + + const axiosCanceler = new AxiosCanceler() + + // Request interceptor configuration processing + this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => { + // If cancel repeat request is turned on, then cancel repeat request is prohibited + // @ts-ignore + const { ignoreCancelToken } = config.requestOptions + const ignoreCancel = + ignoreCancelToken !== undefined + ? ignoreCancelToken + : this.options.requestOptions?.ignoreCancelToken + + !ignoreCancel && axiosCanceler.addPending(config) + if (requestInterceptors && isFunction(requestInterceptors)) { + config = requestInterceptors(config, this.options) + } + return config + }, undefined) + + // Request interceptor error capture + requestInterceptorsCatch && + isFunction(requestInterceptorsCatch) && + this.axiosInstance.interceptors.request.use(undefined, requestInterceptorsCatch) + + // Response result interceptor processing + this.axiosInstance.interceptors.response.use((res: AxiosResponse) => { + res && axiosCanceler.removePending(res.config) + if (responseInterceptors && isFunction(responseInterceptors)) { + res = responseInterceptors(res) + } + return res + }, undefined) + + // Response result interceptor error capture + responseInterceptorsCatch && + isFunction(responseInterceptorsCatch) && + this.axiosInstance.interceptors.response.use(undefined, (error) => { + // @ts-ignore + return responseInterceptorsCatch(this.axiosInstance, error) + }) + } + + /** + * @description: File Upload + */ + uploadFile(config: AxiosRequestConfig, params: UploadFileParams) { + const formData = new window.FormData() + const customFilename = params.name || 'file' + + if (params.filename) { + formData.append(customFilename, params.file, params.filename) + } else { + formData.append(customFilename, params.file) + } + + if (params.data) { + Object.keys(params.data).forEach((key) => { + const value = params.data![key] + if (Array.isArray(value)) { + value.forEach((item) => { + formData.append(`${key}[]`, item) + }) + return + } + + formData.append(key, params.data![key]) + }) + } + + return this.axiosInstance.request({ + ...config, + method: 'POST', + data: formData, + headers: { + 'Content-type': ContentTypeEnum.FORM_DATA, + // @ts-ignore + ignoreCancelToken: true, + }, + }) + } + + // support form-data + supportFormData(config: AxiosRequestConfig) { + const headers = config.headers || this.options.headers + const contentType = headers?.['Content-Type'] || headers?.['content-type'] + + if ( + contentType !== ContentTypeEnum.FORM_URLENCODED || + !Reflect.has(config, 'data') || + config.method?.toUpperCase() === RequestEnum.GET + ) { + return config + } + + return { + ...config, + data: qs.stringify(config.data, { arrayFormat: 'brackets' }), + } + } + + get(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'GET' }, options) + } + + post(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'POST' }, options) + } + + put(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'PUT' }, options) + } + + delete(config: AxiosRequestConfig, options?: RequestOptions): Promise { + return this.request({ ...config, method: 'DELETE' }, options) + } + + request(config: AxiosRequestConfig, options?: RequestOptions): Promise { + let conf: CreateAxiosOptions = cloneDeep(config) + const transform = this.getTransform() + + const { requestOptions } = this.options + + const opt: RequestOptions = Object.assign({}, requestOptions, options) + + const { beforeRequestHook, requestCatchHook, transformResponseHook } = transform || {} + if (beforeRequestHook && isFunction(beforeRequestHook)) { + conf = beforeRequestHook(conf, opt) + } + conf.requestOptions = opt + + conf = this.supportFormData(conf) + + return new Promise((resolve, reject) => { + this.axiosInstance + .request>(conf) + .then((res: AxiosResponse) => { + if (transformResponseHook && isFunction(transformResponseHook)) { + try { + const ret = transformResponseHook(res, opt) + resolve(ret) + } catch (err) { + reject(err || new Error('request error!')) + } + return + } + resolve(res as unknown as Promise) + }) + .catch((e: Error | AxiosError) => { + if (requestCatchHook && isFunction(requestCatchHook)) { + reject(requestCatchHook(e, opt)) + return + } + if (axios.isAxiosError(e)) { + // rewrite error message from axios in here + } + reject(e) + }) + }) + } +} diff --git a/frontend/vben/src/utils/http/axios/axiosCancel.ts b/frontend/vben/src/utils/http/axios/axiosCancel.ts new file mode 100644 index 0000000..f2dc289 --- /dev/null +++ b/frontend/vben/src/utils/http/axios/axiosCancel.ts @@ -0,0 +1,60 @@ +import type { AxiosRequestConfig, Canceler } from 'axios' +import axios from 'axios' +import { isFunction } from '/@/utils/is' + +// Used to store the identification and cancellation function of each request +let pendingMap = new Map() + +export const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&') + +export class AxiosCanceler { + /** + * Add request + * @param {Object} config + */ + addPending(config: AxiosRequestConfig) { + this.removePending(config) + const url = getPendingUrl(config) + config.cancelToken = + config.cancelToken || + new axios.CancelToken((cancel) => { + if (!pendingMap.has(url)) { + // If there is no current request in pending, add it + pendingMap.set(url, cancel) + } + }) + } + + /** + * @description: Clear all pending + */ + removeAllPending() { + pendingMap.forEach((cancel) => { + cancel && isFunction(cancel) && cancel() + }) + pendingMap.clear() + } + + /** + * Removal request + * @param {Object} config + */ + removePending(config: AxiosRequestConfig) { + const url = getPendingUrl(config) + + if (pendingMap.has(url)) { + // If there is a current request identifier in pending, + // the current request needs to be cancelled and removed + const cancel = pendingMap.get(url) + cancel && cancel(url) + pendingMap.delete(url) + } + } + + /** + * @description: reset + */ + reset(): void { + pendingMap = new Map() + } +} diff --git a/frontend/vben/src/utils/http/axios/axiosRetry.ts b/frontend/vben/src/utils/http/axios/axiosRetry.ts new file mode 100644 index 0000000..2f685cb --- /dev/null +++ b/frontend/vben/src/utils/http/axios/axiosRetry.ts @@ -0,0 +1,28 @@ +import { AxiosError, AxiosInstance } from 'axios' +/** + * 请求重试机制 + */ + +export class AxiosRetry { + /** + * 重试 + */ + retry(AxiosInstance: AxiosInstance, error: AxiosError) { + // @ts-ignore + const { config } = error.response + const { waitTime, count } = config?.requestOptions?.retryRequest + config.__retryCount = config.__retryCount || 0 + if (config.__retryCount >= count) { + return Promise.reject(error) + } + config.__retryCount += 1 + return this.delay(waitTime).then(() => AxiosInstance(config)) + } + + /** + * 延迟 + */ + private delay(waitTime: number) { + return new Promise((resolve) => setTimeout(resolve, waitTime)) + } +} diff --git a/frontend/vben/src/utils/http/axios/axiosTransform.ts b/frontend/vben/src/utils/http/axios/axiosTransform.ts new file mode 100644 index 0000000..703f81e --- /dev/null +++ b/frontend/vben/src/utils/http/axios/axiosTransform.ts @@ -0,0 +1,52 @@ +/** + * Data processing class, can be configured according to the project + */ +import type { AxiosRequestConfig, AxiosResponse } from 'axios' +import type { RequestOptions, Result } from '/#/axios' + +export interface CreateAxiosOptions extends AxiosRequestConfig { + authenticationScheme?: string + transform?: AxiosTransform + requestOptions?: RequestOptions +} + +export abstract class AxiosTransform { + /** + * @description: Process configuration before request + * @description: Process configuration before request + */ + beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig + + /** + * @description: 处理响应数据 + */ + transformResponseHook?: (res: AxiosResponse, options: RequestOptions) => any + + /** + * @description: 请求失败处理 + */ + requestCatchHook?: (e: Error, options: RequestOptions) => Promise + + /** + * @description: 请求之前的拦截器 + */ + requestInterceptors?: ( + config: AxiosRequestConfig, + options: CreateAxiosOptions, + ) => AxiosRequestConfig + + /** + * @description: 请求之后的拦截器 + */ + responseInterceptors?: (res: AxiosResponse) => AxiosResponse + + /** + * @description: 请求之前的拦截器错误处理 + */ + requestInterceptorsCatch?: (error: Error) => void + + /** + * @description: 请求之后的拦截器错误处理 + */ + responseInterceptorsCatch?: (axiosInstance: AxiosResponse, error: Error) => void +} diff --git a/frontend/vben/src/utils/http/axios/checkStatus.ts b/frontend/vben/src/utils/http/axios/checkStatus.ts new file mode 100644 index 0000000..4872d88 --- /dev/null +++ b/frontend/vben/src/utils/http/axios/checkStatus.ts @@ -0,0 +1,80 @@ +import type { ErrorMessageMode } from '/#/axios' +import { useMessage } from '/@/hooks/web/useMessage' +import { useI18n } from '/@/hooks/web/useI18n' +// import router from '/@/router'; +// import { PageEnum } from '/@/enums/pageEnum'; +import { useUserStoreWithOut } from '/@/store/modules/user' +import projectSetting from '/@/settings/projectSetting' +import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum' + +const { createMessage, createErrorModal } = useMessage() +const error = createMessage.error! +const stp = projectSetting.sessionTimeoutProcessing + +export function checkStatus( + status: number, + msg: string, + errorMessageMode: ErrorMessageMode = 'message', +): void { + const { t } = useI18n() + const userStore = useUserStoreWithOut() + let errMessage = '' + + switch (status) { + case 400: + errMessage = `${msg}` + break + // 401: Not logged in + // Jump to the login page if not logged in, and carry the path of the current page + // Return to the current page after successful login. This step needs to be operated on the login page. + case 401: + userStore.setToken(undefined) + errMessage = msg || t('sys.api.errMsg401') + if (stp === SessionTimeoutProcessingEnum.PAGE_COVERAGE) { + userStore.setSessionTimeout(true) + } else { + userStore.logout(true) + } + break + case 403: + errMessage = t('sys.api.errMsg403') + break + // 404请求不存在 + case 404: + errMessage = t('sys.api.errMsg404') + break + case 405: + errMessage = t('sys.api.errMsg405') + break + case 408: + errMessage = t('sys.api.errMsg408') + break + case 500: + errMessage = t('sys.api.errMsg500') + break + case 501: + errMessage = t('sys.api.errMsg501') + break + case 502: + errMessage = t('sys.api.errMsg502') + break + case 503: + errMessage = t('sys.api.errMsg503') + break + case 504: + errMessage = t('sys.api.errMsg504') + break + case 505: + errMessage = t('sys.api.errMsg505') + break + default: + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }) + } else if (errorMessageMode === 'message') { + error({ content: errMessage, key: `global_error_message_status_${status}` }) + } + } +} diff --git a/frontend/vben/src/utils/http/axios/helper.ts b/frontend/vben/src/utils/http/axios/helper.ts new file mode 100644 index 0000000..bf53d90 --- /dev/null +++ b/frontend/vben/src/utils/http/axios/helper.ts @@ -0,0 +1,48 @@ +import { isObject, isString } from '/@/utils/is' + +const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' + +export function joinTimestamp( + join: boolean, + restful: T, +): T extends true ? string : object + +export function joinTimestamp(join: boolean, restful = false): string | object { + if (!join) { + return restful ? '' : {} + } + const now = new Date().getTime() + if (restful) { + return `?_t=${now}` + } + return { _t: now } +} + +/** + * @description: Format request parameter time + */ +export function formatRequestDate(params: Recordable) { + if (Object.prototype.toString.call(params) !== '[object Object]') { + return + } + + for (const key in params) { + const format = params[key]?.format ?? null + if (format && typeof format === 'function') { + params[key] = params[key].format(DATE_TIME_FORMAT) + } + if (isString(key)) { + const value = params[key] + if (value) { + try { + params[key] = isString(value) ? value.trim() : value + } catch (error: any) { + throw new Error(error) + } + } + } + if (isObject(params[key])) { + formatRequestDate(params[key]) + } + } +} diff --git a/frontend/vben/src/utils/http/axios/index.ts b/frontend/vben/src/utils/http/axios/index.ts new file mode 100644 index 0000000..0334a6d --- /dev/null +++ b/frontend/vben/src/utils/http/axios/index.ts @@ -0,0 +1,267 @@ +// axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 +// The axios configuration can be changed according to the project, just change the file, other files can be left unchanged + +import type { AxiosResponse } from 'axios' +import { clone } from 'lodash-es' +import type { RequestOptions, Result } from '/#/axios' +import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform' +import { VAxios } from './Axios' +import { checkStatus } from './checkStatus' +import { useGlobSetting } from '/@/hooks/setting' +import { useMessage } from '/@/hooks/web/useMessage' +import { RequestEnum, ResultEnum, ContentTypeEnum } from '/@/enums/httpEnum' +import { isString } from '/@/utils/is' +import { getToken } from '/@/utils/auth' +import { setObjToUrlParams, deepMerge } from '/@/utils' +import { useI18n } from '/@/hooks/web/useI18n' +import { joinTimestamp, formatRequestDate } from './helper' +import { useUserStoreWithOut } from '/@/store/modules/user' +import { AxiosRetry } from '/@/utils/http/axios/axiosRetry' + +const globSetting = useGlobSetting() +const urlPrefix = globSetting.urlPrefix +const { createMessage, createErrorModal } = useMessage() + +/** + * @description: 数据处理,方便区分多种处理方式 + */ +const transform: AxiosTransform = { + /** + * @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误 + */ + transformResponseHook: (res: AxiosResponse, options: RequestOptions) => { + const { t } = useI18n() + const { isTransformResponse, isReturnNativeResponse } = options + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + if (isReturnNativeResponse) { + return res + } + // 不进行任何处理,直接返回 + // 用于页面代码可能需要直接获取code,data,message这些信息时开启 + if (!isTransformResponse) { + return res.data + } + // 错误的时候返回 + + const { data } = res + if (!data) { + // return '[HTTP] Request has no return value'; + throw new Error(t('sys.api.apiRequestFailed')) + } + // 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 + const { code, result, message } = data + + // 这里逻辑可以根据项目进行修改 + const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS + if (hasSuccess) { + return result + } + + // 在此处根据自己项目的实际情况对不同的code执行不同的操作 + // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 + let timeoutMsg = '' + switch (code) { + case ResultEnum.TIMEOUT: + timeoutMsg = t('sys.api.timeoutMessage') + const userStore = useUserStoreWithOut() + userStore.setToken(undefined) + userStore.logout(true) + break + default: + if (message) { + timeoutMsg = message + } + } + + // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 + // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示 + if (options.errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg }) + } else if (options.errorMessageMode === 'message') { + createMessage.error(timeoutMsg) + } + + throw new Error(timeoutMsg || t('sys.api.apiRequestFailed')) + }, + + // 请求之前处理config + beforeRequestHook: (config, options) => { + const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options + + if (joinPrefix) { + config.url = `${urlPrefix}${config.url}` + } + + if (apiUrl && isString(apiUrl)) { + config.url = `${apiUrl}${config.url}` + } + const params = config.params || {} + const data = config.data || false + formatDate && data && !isString(data) && formatRequestDate(data) + if (config.method?.toUpperCase() === RequestEnum.GET) { + if (!isString(params)) { + // 给 get 请求加上时间戳参数,避免从缓存中拿数据。 + config.params = Object.assign(params || {}, joinTimestamp(joinTime, false)) + } else { + // 兼容restful风格 + config.url = config.url + params + `${joinTimestamp(joinTime, true)}` + config.params = undefined + } + } else { + if (!isString(params)) { + formatDate && formatRequestDate(params) + if ( + Reflect.has(config, 'data') && + config.data && + (Object.keys(config.data).length > 0 || config.data instanceof FormData) + ) { + config.data = data + config.params = params + } else { + // 非GET请求如果没有提供data,则将params视为data + config.data = params + config.params = undefined + } + if (joinParamsToUrl) { + config.url = setObjToUrlParams( + config.url as string, + Object.assign({}, config.params, config.data), + ) + } + } else { + // 兼容restful风格 + config.url = config.url + params + config.params = undefined + } + } + return config + }, + + /** + * @description: 请求拦截器处理 + */ + requestInterceptors: (config, options) => { + // 请求之前处理config + const token = getToken() + if (token && (config as Recordable)?.requestOptions?.withToken !== false) { + // jwt token + ;(config as Recordable).headers.Authorization = options.authenticationScheme + ? `${options.authenticationScheme} ${token}` + : token + } + return config + }, + + /** + * @description: 响应拦截器处理 + */ + responseInterceptors: (res: AxiosResponse) => { + return res + }, + + /** + * @description: 响应错误处理 + */ + responseInterceptorsCatch: (axiosInstance: AxiosResponse, error: any) => { + const { t } = useI18n() + const { response, code, message, config } = error || {} + const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none' + const msg: string = response?.data?.error?.message ?? '' + const err: string = error?.toString?.() ?? '' + let errMessage = '' + + try { + if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { + errMessage = t('sys.api.apiTimeoutMessage') + } + if (err?.includes('Network Error')) { + errMessage = t('sys.api.networkExceptionMsg') + } + + if (errMessage) { + if (errorMessageMode === 'modal') { + createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }) + } else if (errorMessageMode === 'message') { + createMessage.error(errMessage) + } + return Promise.reject(error) + } + } catch (error) { + throw new Error(error as unknown as string) + } + + checkStatus(error?.response?.status, msg, errorMessageMode) + + // 添加自动重试机制 保险起见 只针对GET请求 + const retryRequest = new AxiosRetry() + const { isOpenRetry } = config.requestOptions.retryRequest + config.method?.toUpperCase() === RequestEnum.GET && + isOpenRetry && + // @ts-ignore + retryRequest.retry(axiosInstance, error) + return Promise.reject(error) + }, +} + +function createAxios(opt?: Partial) { + return new VAxios( + // 深度合并 + deepMerge( + { + // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes + // authentication schemes,e.g: Bearer + // authenticationScheme: 'Bearer', + authenticationScheme: '', + timeout: 10 * 1000, + // 基础接口地址 + // baseURL: globSetting.apiUrl, + + headers: { 'Content-Type': ContentTypeEnum.JSON }, + // 如果是form-data格式 + // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED }, + // 数据处理方式 + transform: clone(transform), + // 配置项,下面的选项都可以在独立的接口请求中覆盖 + requestOptions: { + // 默认将prefix 添加到url + joinPrefix: true, + // 是否返回原生响应头 比如:需要获取响应头时使用该属性 + isReturnNativeResponse: false, + // 需要对返回数据进行处理 + isTransformResponse: true, + // post请求的时候添加参数到url + joinParamsToUrl: false, + // 格式化提交参数时间 + formatDate: true, + // 消息提示类型 + errorMessageMode: 'message', + // 接口地址 + apiUrl: globSetting.apiUrl, + // 接口拼接地址 + urlPrefix: urlPrefix, + // 是否加入时间戳 + joinTime: true, + // 忽略重复请求 + ignoreCancelToken: true, + // 是否携带token + withToken: true, + retryRequest: { + isOpenRetry: true, + count: 5, + waitTime: 100, + }, + }, + }, + opt || {}, + ), + ) +} +export const defHttp = createAxios() + +// other api url +// export const otherHttp = createAxios({ +// requestOptions: { +// apiUrl: 'xxx', +// urlPrefix: 'xxx', +// }, +// }); diff --git a/frontend/vben/src/utils/index.ts b/frontend/vben/src/utils/index.ts new file mode 100644 index 0000000..a887d17 --- /dev/null +++ b/frontend/vben/src/utils/index.ts @@ -0,0 +1,92 @@ +import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router' +import type { App, Plugin } from 'vue' + +import { unref } from 'vue' +import { isObject } from '/@/utils/is' + +export const noop = () => {} + +/** + * @description: Set ui mount node + */ +export function getPopupContainer(node?: HTMLElement): HTMLElement { + return (node?.parentNode as HTMLElement) ?? document.body +} + +/** + * Add the object as a parameter to the URL + * @param baseUrl url + * @param obj + * @returns {string} + * eg: + * let obj = {a: '3', b: '4'} + * setObjToUrlParams('www.baidu.com', obj) + * ==>www.baidu.com?a=3&b=4 + */ +export function setObjToUrlParams(baseUrl: string, obj: any): string { + let parameters = '' + for (const key in obj) { + parameters += key + '=' + encodeURIComponent(obj[key]) + '&' + } + parameters = parameters.replace(/&$/, '') + return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters +} + +// 深度合并 +export function deepMerge(src: any = {}, target: any = {}): T { + let key: string + for (key in target) { + src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]) + } + return src +} + +export function openWindow( + url: string, + opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }, +) { + const { target = '__blank', noopener = true, noreferrer = true } = opt || {} + const feature: string[] = [] + + noopener && feature.push('noopener=yes') + noreferrer && feature.push('noreferrer=yes') + + window.open(url, target, feature.join(',')) +} + +// dynamic use hook props +export function getDynamicProps(props: T): Partial { + const ret: Recordable = {} + + Object.keys(props).map((key) => { + ret[key] = unref((props as Recordable)[key]) + }) + + return ret as Partial +} + +export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized { + if (!route) return route + const { matched, ...opt } = route + return { + ...opt, + matched: (matched + ? matched.map((item) => ({ + meta: item.meta, + name: item.name, + path: item.path, + })) + : undefined) as RouteRecordNormalized[], + } +} + +export const withInstall = (component: T, alias?: string) => { + const comp = component as any + comp.install = (app: App) => { + app.component(comp.name || comp.displayName, component) + if (alias) { + app.config.globalProperties[alias] = component + } + } + return component as T & Plugin +} diff --git a/frontend/vben/src/utils/is.ts b/frontend/vben/src/utils/is.ts new file mode 100644 index 0000000..fe55760 --- /dev/null +++ b/frontend/vben/src/utils/is.ts @@ -0,0 +1,99 @@ +const toString = Object.prototype.toString + +export function is(val: unknown, type: string) { + return toString.call(val) === `[object ${type}]` +} + +export function isDef(val?: T): val is T { + return typeof val !== 'undefined' +} + +export function isUnDef(val?: T): val is T { + return !isDef(val) +} + +export function isObject(val: any): val is Record { + return val !== null && is(val, 'Object') +} + +export function isEmpty(val: T): val is T { + if (isArray(val) || isString(val)) { + return val.length === 0 + } + + if (val instanceof Map || val instanceof Set) { + return val.size === 0 + } + + if (isObject(val)) { + return Object.keys(val).length === 0 + } + + return false +} + +export function isDate(val: unknown): val is Date { + return is(val, 'Date') +} + +export function isNull(val: unknown): val is null { + return val === null +} + +export function isNullAndUnDef(val: unknown): val is null | undefined { + return isUnDef(val) && isNull(val) +} + +export function isNullOrUnDef(val: unknown): val is null | undefined { + return isUnDef(val) || isNull(val) +} + +export function isNumber(val: unknown): val is number { + return is(val, 'Number') +} + +export function isPromise(val: unknown): val is Promise { + return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) +} + +export function isString(val: unknown): val is string { + return is(val, 'String') +} + +export function isFunction(val: unknown): val is Function { + return typeof val === 'function' +} + +export function isBoolean(val: unknown): val is boolean { + return is(val, 'Boolean') +} + +export function isRegExp(val: unknown): val is RegExp { + return is(val, 'RegExp') +} + +export function isArray(val: any): val is Array { + return val && Array.isArray(val) +} + +export function isWindow(val: any): val is Window { + return typeof window !== 'undefined' && is(val, 'Window') +} + +export function isElement(val: unknown): val is Element { + return isObject(val) && !!val.tagName +} + +export function isMap(val: unknown): val is Map { + return is(val, 'Map') +} + +export const isServer = typeof window === 'undefined' + +export const isClient = !isServer + +export function isUrl(path: string): boolean { + const reg = + /^(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?(\/#\/)?(?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/ + return reg.test(path) +} diff --git a/frontend/vben/src/utils/lib/echarts.ts b/frontend/vben/src/utils/lib/echarts.ts new file mode 100644 index 0000000..a50314f --- /dev/null +++ b/frontend/vben/src/utils/lib/echarts.ts @@ -0,0 +1,57 @@ +import * as echarts from 'echarts/core' + +import { + BarChart, + LineChart, + PieChart, + MapChart, + PictorialBarChart, + RadarChart, + ScatterChart, +} from 'echarts/charts' + +import { + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + LegendComponent, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, +} from 'echarts/components' + +import { SVGRenderer } from 'echarts/renderers' + +echarts.use([ + LegendComponent, + TitleComponent, + TooltipComponent, + GridComponent, + PolarComponent, + AriaComponent, + ParallelComponent, + BarChart, + LineChart, + PieChart, + MapChart, + RadarChart, + SVGRenderer, + PictorialBarChart, + RadarComponent, + ToolboxComponent, + DataZoomComponent, + VisualMapComponent, + TimelineComponent, + CalendarComponent, + GraphicComponent, + ScatterChart, +]) + +export default echarts diff --git a/frontend/vben/src/utils/log.ts b/frontend/vben/src/utils/log.ts new file mode 100644 index 0000000..6f0d9d4 --- /dev/null +++ b/frontend/vben/src/utils/log.ts @@ -0,0 +1,9 @@ +const projectName = import.meta.env.VITE_GLOB_APP_TITLE + +export function warn(message: string) { + console.warn(`[${projectName} warn]:${message}`) +} + +export function error(message: string) { + throw new Error(`[${projectName} error]:${message}`) +} diff --git a/frontend/vben/src/utils/mitt.ts b/frontend/vben/src/utils/mitt.ts new file mode 100644 index 0000000..d550c68 --- /dev/null +++ b/frontend/vben/src/utils/mitt.ts @@ -0,0 +1,101 @@ +/** + * copy to https://github.com/developit/mitt + * Expand clear method + */ + +export type EventType = string | symbol + +// An event handler can take an optional event argument +// and should not return a value +export type Handler = (event?: T) => void +export type WildcardHandler = (type: EventType, event?: any) => void + +// An array of all currently registered event handlers for a type +export type EventHandlerList = Array +export type WildCardEventHandlerList = Array + +// A map of event types and their corresponding event handlers. +export type EventHandlerMap = Map + +export interface Emitter { + all: EventHandlerMap + + on(type: EventType, handler: Handler): void + on(type: '*', handler: WildcardHandler): void + + off(type: EventType, handler: Handler): void + off(type: '*', handler: WildcardHandler): void + + emit(type: EventType, event?: T): void + emit(type: '*', event?: any): void + clear(): void +} + +/** + * Mitt: Tiny (~200b) functional event emitter / pubsub. + * @name mitt + * @returns {Mitt} + */ +export default function mitt(all?: EventHandlerMap): Emitter { + all = all || new Map() + + return { + /** + * A Map of event names to registered handler functions. + */ + all, + + /** + * Register an event handler for the given type. + * @param {string|symbol} type Type of event to listen for, or `"*"` for all events + * @param {Function} handler Function to call in response to given event + * @memberOf mitt + */ + on(type: EventType, handler: Handler) { + const handlers = all?.get(type) + const added = handlers && handlers.push(handler) + if (!added) { + all?.set(type, [handler]) + } + }, + + /** + * Remove an event handler for the given type. + * @param {string|symbol} type Type of event to unregister `handler` from, or `"*"` + * @param {Function} handler Handler function to remove + * @memberOf mitt + */ + off(type: EventType, handler: Handler) { + const handlers = all?.get(type) + if (handlers) { + handlers.splice(handlers.indexOf(handler) >>> 0, 1) + } + }, + + /** + * Invoke all handlers for the given type. + * If present, `"*"` handlers are invoked after type-matched handlers. + * + * Note: Manually firing "*" handlers is not supported. + * + * @param {string|symbol} type The event type to invoke + * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler + * @memberOf mitt + */ + emit(type: EventType, evt: T) { + ;((all?.get(type) || []) as EventHandlerList).slice().map((handler) => { + handler(evt) + }) + ;((all?.get('*') || []) as WildCardEventHandlerList).slice().map((handler) => { + handler(type, evt) + }) + }, + + /** + * Clear all + */ + clear() { + this.all.clear() + }, + } +} diff --git a/frontend/vben/src/utils/propTypes.ts b/frontend/vben/src/utils/propTypes.ts new file mode 100644 index 0000000..d06bf16 --- /dev/null +++ b/frontend/vben/src/utils/propTypes.ts @@ -0,0 +1,34 @@ +import { CSSProperties, VNodeChild } from 'vue' +import { createTypes, VueTypeValidableDef, VueTypesInterface } from 'vue-types' + +export type VueNode = VNodeChild | JSX.Element + +type PropTypes = VueTypesInterface & { + readonly style: VueTypeValidableDef + readonly VNodeChild: VueTypeValidableDef + // readonly trueBool: VueTypeValidableDef; +} + +const propTypes = createTypes({ + func: undefined, + bool: undefined, + string: undefined, + number: undefined, + object: undefined, + integer: undefined, +}) as PropTypes + +propTypes.extend([ + { + name: 'style', + getter: true, + type: [String, Object], + default: undefined, + }, + { + name: 'VNodeChild', + getter: true, + type: undefined, + }, +]) +export { propTypes } diff --git a/frontend/vben/src/utils/props.ts b/frontend/vben/src/utils/props.ts new file mode 100644 index 0000000..9f5e8ac --- /dev/null +++ b/frontend/vben/src/utils/props.ts @@ -0,0 +1,185 @@ +// copy from element-plus + +import { warn } from 'vue' +import { isObject } from '@vue/shared' +import { fromPairs } from 'lodash-es' +import type { ExtractPropTypes, PropType } from '@vue/runtime-core' +import type { Mutable } from './types' + +const wrapperKey = Symbol() +export type PropWrapper = { [wrapperKey]: T } + +export const propKey = Symbol() + +type ResolveProp = ExtractPropTypes<{ + key: { type: T; required: true } +}>['key'] +type ResolvePropType = ResolveProp extends { type: infer V } ? V : ResolveProp +type ResolvePropTypeWithReadonly = Readonly extends Readonly> + ? ResolvePropType + : ResolvePropType + +type IfUnknown = [unknown] extends [T] ? V : T + +export type BuildPropOption, R, V, C> = { + type?: T + values?: readonly V[] + required?: R + default?: R extends true + ? never + : D extends Record | Array + ? () => D + : (() => D) | D + validator?: ((val: any) => val is C) | ((val: any) => boolean) +} + +type _BuildPropType = + | (T extends PropWrapper + ? T[typeof wrapperKey] + : [V] extends [never] + ? ResolvePropTypeWithReadonly + : never) + | V + | C +export type BuildPropType = _BuildPropType< + IfUnknown, + IfUnknown, + IfUnknown +> + +type _BuildPropDefault = [T] extends [ + // eslint-disable-next-line @typescript-eslint/ban-types + Record | Array | Function, +] + ? D + : D extends () => T + ? ReturnType + : D + +export type BuildPropDefault = R extends true + ? { readonly default?: undefined } + : { + readonly default: Exclude extends never + ? undefined + : Exclude<_BuildPropDefault, undefined> + } +export type BuildPropReturn = { + readonly type: PropType> + readonly required: IfUnknown + readonly validator: ((val: unknown) => boolean) | undefined + [propKey]: true +} & BuildPropDefault, IfUnknown, IfUnknown> + +/** + * @description Build prop. It can better optimize prop types + * @description 生成 prop,能更好地优化类型 + * @example + // limited options + // the type will be PropType<'light' | 'dark'> + buildProp({ + type: String, + values: ['light', 'dark'], + } as const) + * @example + // limited options and other types + // the type will be PropType<'small' | 'medium' | number> + buildProp({ + type: [String, Number], + values: ['small', 'medium'], + validator: (val: unknown): val is number => typeof val === 'number', + } as const) + @link see more: https://github.com/element-plus/element-plus/pull/3341 + */ +export function buildProp< + T = never, + D extends BuildPropType = never, + R extends boolean = false, + V = never, + C = never, +>(option: BuildPropOption, key?: string): BuildPropReturn { + // filter native prop type and nested prop, e.g `null`, `undefined` (from `buildProps`) + if (!isObject(option) || !!option[propKey]) return option as any + + const { values, required, default: defaultValue, type, validator } = option + + const _validator = + values || validator + ? (val: unknown) => { + let valid = false + let allowedValues: unknown[] = [] + + if (values) { + allowedValues = [...values, defaultValue] + valid ||= allowedValues.includes(val) + } + if (validator) valid ||= validator(val) + + if (!valid && allowedValues.length > 0) { + const allowValuesText = [...new Set(allowedValues)] + .map((value) => JSON.stringify(value)) + .join(', ') + warn( + `Invalid prop: validation failed${ + key ? ` for prop "${key}"` : '' + }. Expected one of [${allowValuesText}], got value ${JSON.stringify(val)}.`, + ) + } + return valid + } + : undefined + + return { + type: + typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) + ? type[wrapperKey] + : type, + required: !!required, + default: defaultValue, + validator: _validator, + [propKey]: true, + } as unknown as BuildPropReturn +} + +type NativePropType = [((...args: any) => any) | { new (...args: any): any } | undefined | null] + +export const buildProps = < + O extends { + [K in keyof O]: O[K] extends BuildPropReturn + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption + ? D extends BuildPropType + ? BuildPropOption + : never + : never + }, +>( + props: O, +) => + fromPairs( + Object.entries(props).map(([key, option]) => [key, buildProp(option as any, key)]), + ) as unknown as { + [K in keyof O]: O[K] extends { [propKey]: boolean } + ? O[K] + : [O[K]] extends NativePropType + ? O[K] + : O[K] extends BuildPropOption< + infer T, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + infer _D, + infer R, + infer V, + infer C + > + ? BuildPropReturn + : never + } + +export const definePropType = (val: any) => ({ [wrapperKey]: val } as PropWrapper) + +export const keyOf = (arr: T) => Object.keys(arr) as Array +export const mutable = >(val: T) => + val as Mutable + +export const componentSize = ['large', 'medium', 'small', 'mini'] as const diff --git a/frontend/vben/src/utils/types.ts b/frontend/vben/src/utils/types.ts new file mode 100644 index 0000000..aa85196 --- /dev/null +++ b/frontend/vben/src/utils/types.ts @@ -0,0 +1,42 @@ +// copy from element-plus + +import type { CSSProperties, Plugin } from 'vue' + +type OptionalKeys> = { + [K in keyof T]: T extends Record ? never : K +}[keyof T] + +type RequiredKeys> = Exclude> + +type MonoArgEmitter = (evt: K, arg?: T[K]) => void + +type BiArgEmitter = (evt: K, arg: T[K]) => void + +export type EventEmitter> = MonoArgEmitter> & + BiArgEmitter> + +export type AnyFunction = (...args: any[]) => T + +export type PartialReturnType unknown> = Partial> + +export type SFCWithInstall = T & Plugin + +export type Nullable = T | null + +export type RefElement = Nullable + +export type CustomizedHTMLElement = HTMLElement & T + +export type Indexable = { + [key: string]: T +} + +export type Hash = Indexable + +export type TimeoutHandle = ReturnType + +export type ComponentSize = 'large' | 'medium' | 'small' | 'mini' + +export type StyleValue = string | CSSProperties | Array + +export type Mutable = { -readonly [P in keyof T]: T[P] } diff --git a/frontend/vben/src/utils/uuid.ts b/frontend/vben/src/utils/uuid.ts new file mode 100644 index 0000000..4e10122 --- /dev/null +++ b/frontend/vben/src/utils/uuid.ts @@ -0,0 +1,28 @@ +const hexList: string[] = [] +for (let i = 0; i <= 15; i++) { + hexList[i] = i.toString(16) +} + +export function buildUUID(): string { + let uuid = '' + for (let i = 1; i <= 36; i++) { + if (i === 9 || i === 14 || i === 19 || i === 24) { + uuid += '-' + } else if (i === 15) { + uuid += 4 + } else if (i === 20) { + uuid += hexList[(Math.random() * 4) | 8] + } else { + uuid += hexList[(Math.random() * 16) | 0] + } + } + return uuid.replace(/-/g, '') +} + +let unique = 0 +export function buildShortUUID(prefix = ''): string { + const time = Date.now() + const random = Math.floor(Math.random() * 1000000000) + unique++ + return prefix + '_' + random + unique + String(time) +} diff --git a/frontend/vben/src/views/dashboard/analysis/components/GrowCard.vue b/frontend/vben/src/views/dashboard/analysis/components/GrowCard.vue new file mode 100644 index 0000000..6d5ede4 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/GrowCard.vue @@ -0,0 +1,14 @@ + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/SalesProductPie.vue b/frontend/vben/src/views/dashboard/analysis/components/SalesProductPie.vue new file mode 100644 index 0000000..5e90f17 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/SalesProductPie.vue @@ -0,0 +1,64 @@ + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/SiteAnalysis.vue b/frontend/vben/src/views/dashboard/analysis/components/SiteAnalysis.vue new file mode 100644 index 0000000..4ba132c --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/SiteAnalysis.vue @@ -0,0 +1,38 @@ + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysis.vue b/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysis.vue new file mode 100644 index 0000000..a238e13 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysis.vue @@ -0,0 +1,89 @@ + + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysisBar.vue b/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysisBar.vue new file mode 100644 index 0000000..ef9f2b8 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/VisitAnalysisBar.vue @@ -0,0 +1,47 @@ + + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/VisitRadar.vue b/frontend/vben/src/views/dashboard/analysis/components/VisitRadar.vue new file mode 100644 index 0000000..7cb92fe --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/VisitRadar.vue @@ -0,0 +1,94 @@ + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/VisitSource.vue b/frontend/vben/src/views/dashboard/analysis/components/VisitSource.vue new file mode 100644 index 0000000..65bb84f --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/VisitSource.vue @@ -0,0 +1,81 @@ + + diff --git a/frontend/vben/src/views/dashboard/analysis/components/props.ts b/frontend/vben/src/views/dashboard/analysis/components/props.ts new file mode 100644 index 0000000..a91a779 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/components/props.ts @@ -0,0 +1,16 @@ +import { PropType } from 'vue' + +export interface BasicProps { + width: string + height: string +} +export const basicProps = { + width: { + type: String as PropType, + default: '100%', + }, + height: { + type: String as PropType, + default: '280px', + }, +} diff --git a/frontend/vben/src/views/dashboard/analysis/data.ts b/frontend/vben/src/views/dashboard/analysis/data.ts new file mode 100644 index 0000000..9667391 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/data.ts @@ -0,0 +1,8 @@ +export interface GrowCardItem { + icon: string + title: string + value: number + total: number + color: string + action: string +} diff --git a/frontend/vben/src/views/dashboard/analysis/index.vue b/frontend/vben/src/views/dashboard/analysis/index.vue new file mode 100644 index 0000000..a2eecf8 --- /dev/null +++ b/frontend/vben/src/views/dashboard/analysis/index.vue @@ -0,0 +1,25 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/DynamicInfo.vue b/frontend/vben/src/views/dashboard/workbench/components/DynamicInfo.vue new file mode 100644 index 0000000..697398d --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/DynamicInfo.vue @@ -0,0 +1,31 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/ProjectCard.vue b/frontend/vben/src/views/dashboard/workbench/components/ProjectCard.vue new file mode 100644 index 0000000..45a1ad5 --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/ProjectCard.vue @@ -0,0 +1,32 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/QuickNav.vue b/frontend/vben/src/views/dashboard/workbench/components/QuickNav.vue new file mode 100644 index 0000000..3fb22b8 --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/QuickNav.vue @@ -0,0 +1,17 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/SaleRadar.vue b/frontend/vben/src/views/dashboard/workbench/components/SaleRadar.vue new file mode 100644 index 0000000..793c60f --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/SaleRadar.vue @@ -0,0 +1,94 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/WorkbenchHeader.vue b/frontend/vben/src/views/dashboard/workbench/components/WorkbenchHeader.vue new file mode 100644 index 0000000..0ebb377 --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/WorkbenchHeader.vue @@ -0,0 +1,33 @@ + + diff --git a/frontend/vben/src/views/dashboard/workbench/components/data.ts b/frontend/vben/src/views/dashboard/workbench/components/data.ts new file mode 100644 index 0000000..a47c68d --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/components/data.ts @@ -0,0 +1,156 @@ +interface GroupItem { + title: string + icon: string + color: string + desc: string + date: string + group: string +} + +interface NavItem { + title: string + icon: string + color: string +} + +interface DynamicInfoItem { + avatar: string + name: string + date: string + desc: string +} + +export const navItems: NavItem[] = [ + { + title: '首页', + icon: 'ion:home-outline', + color: '#1fdaca', + }, + { + title: '仪表盘', + icon: 'ion:grid-outline', + color: '#bf0c2c', + }, + { + title: '组件', + icon: 'ion:layers-outline', + color: '#e18525', + }, + { + title: '系统管理', + icon: 'ion:settings-outline', + color: '#3fb27f', + }, + { + title: '权限管理', + icon: 'ion:key-outline', + color: '#4daf1bc9', + }, + { + title: '图表', + icon: 'ion:bar-chart-outline', + color: '#00d8ff', + }, +] + +export const dynamicInfoItems: DynamicInfoItem[] = [ + { + avatar: 'dynamic-avatar-1|svg', + name: '威廉', + date: '刚刚', + desc: `在
开源组 创建了项目 Vue`, + }, + { + avatar: 'dynamic-avatar-2|svg', + name: '艾文', + date: '1个小时前', + desc: `关注了 威廉 `, + }, + { + avatar: 'dynamic-avatar-3|svg', + name: '克里斯', + date: '1天前', + desc: `发布了 个人动态 `, + }, + { + avatar: 'dynamic-avatar-4|svg', + name: 'Vben', + date: '2天前', + desc: `发表文章 如何编写一个Vite插件 `, + }, + { + avatar: 'dynamic-avatar-5|svg', + name: '皮特', + date: '3天前', + desc: `回复了 杰克 的问题 如何进行项目优化?`, + }, + { + avatar: 'dynamic-avatar-6|svg', + name: '杰克', + date: '1周前', + desc: `关闭了问题 如何运行项目 `, + }, + { + avatar: 'dynamic-avatar-1|svg', + name: '威廉', + date: '1周前', + desc: `发布了 个人动态 `, + }, + { + avatar: 'dynamic-avatar-1|svg', + name: '威廉', + date: '2021-04-01 20:00', + desc: `推送了代码到 Github`, + }, +] + +export const groupItems: GroupItem[] = [ + { + title: 'Github', + icon: 'carbon:logo-github', + color: '', + desc: '不要等待机会,而要创造机会。', + group: '开源组', + date: '2021-04-01', + }, + { + title: 'Vue', + icon: 'ion:logo-vue', + color: '#3fb27f', + desc: '现在的你决定将来的你。', + group: '算法组', + date: '2021-04-01', + }, + { + title: 'Html5', + icon: 'ion:logo-html5', + color: '#e18525', + desc: '没有什么才能比努力更重要。', + group: '上班摸鱼', + date: '2021-04-01', + }, + { + title: 'Angular', + icon: 'ion:logo-angular', + color: '#bf0c2c', + desc: '热情和欲望可以突破一切难关。', + group: 'UI', + date: '2021-04-01', + }, + { + title: 'React', + icon: 'bx:bxl-react', + color: '#00d8ff', + desc: '健康的身体是实目标的基石。', + group: '技术牛', + date: '2021-04-01', + }, + { + title: 'Js', + icon: 'ion:logo-javascript', + color: '#4daf1bc9', + desc: '路是走出来的,而不是空想出来的。', + group: '架构组', + date: '2021-04-01', + }, +] diff --git a/frontend/vben/src/views/dashboard/workbench/index.vue b/frontend/vben/src/views/dashboard/workbench/index.vue new file mode 100644 index 0000000..74ba025 --- /dev/null +++ b/frontend/vben/src/views/dashboard/workbench/index.vue @@ -0,0 +1,36 @@ + + diff --git a/frontend/vben/src/views/setup/index.vue b/frontend/vben/src/views/setup/index.vue new file mode 100644 index 0000000..fb83f55 --- /dev/null +++ b/frontend/vben/src/views/setup/index.vue @@ -0,0 +1,43 @@ + + diff --git a/frontend/vben/src/views/sys/about/index.vue b/frontend/vben/src/views/sys/about/index.vue new file mode 100644 index 0000000..a72d6bc --- /dev/null +++ b/frontend/vben/src/views/sys/about/index.vue @@ -0,0 +1,98 @@ + + diff --git a/frontend/vben/src/views/sys/exception/Exception.vue b/frontend/vben/src/views/sys/exception/Exception.vue new file mode 100644 index 0000000..06d9694 --- /dev/null +++ b/frontend/vben/src/views/sys/exception/Exception.vue @@ -0,0 +1,148 @@ + + diff --git a/frontend/vben/src/views/sys/exception/index.ts b/frontend/vben/src/views/sys/exception/index.ts new file mode 100644 index 0000000..86b6f81 --- /dev/null +++ b/frontend/vben/src/views/sys/exception/index.ts @@ -0,0 +1 @@ +export { default as Exception } from './Exception.vue' diff --git a/frontend/vben/src/views/sys/login/ForgetPasswordForm.vue b/frontend/vben/src/views/sys/login/ForgetPasswordForm.vue new file mode 100644 index 0000000..291f62b --- /dev/null +++ b/frontend/vben/src/views/sys/login/ForgetPasswordForm.vue @@ -0,0 +1,64 @@ + + diff --git a/frontend/vben/src/views/sys/login/Login.vue b/frontend/vben/src/views/sys/login/Login.vue new file mode 100644 index 0000000..8364e13 --- /dev/null +++ b/frontend/vben/src/views/sys/login/Login.vue @@ -0,0 +1,215 @@ + + + diff --git a/frontend/vben/src/views/sys/login/LoginForm.vue b/frontend/vben/src/views/sys/login/LoginForm.vue new file mode 100644 index 0000000..5c62fec --- /dev/null +++ b/frontend/vben/src/views/sys/login/LoginForm.vue @@ -0,0 +1,137 @@ + + diff --git a/frontend/vben/src/views/sys/login/LoginFormTitle.vue b/frontend/vben/src/views/sys/login/LoginFormTitle.vue new file mode 100644 index 0000000..9b2ecb7 --- /dev/null +++ b/frontend/vben/src/views/sys/login/LoginFormTitle.vue @@ -0,0 +1,24 @@ + + diff --git a/frontend/vben/src/views/sys/login/MobileForm.vue b/frontend/vben/src/views/sys/login/MobileForm.vue new file mode 100644 index 0000000..4db2451 --- /dev/null +++ b/frontend/vben/src/views/sys/login/MobileForm.vue @@ -0,0 +1,63 @@ + + diff --git a/frontend/vben/src/views/sys/login/RegisterForm.vue b/frontend/vben/src/views/sys/login/RegisterForm.vue new file mode 100644 index 0000000..7542dcf --- /dev/null +++ b/frontend/vben/src/views/sys/login/RegisterForm.vue @@ -0,0 +1,104 @@ + + diff --git a/frontend/vben/src/views/sys/login/SessionTimeoutLogin.vue b/frontend/vben/src/views/sys/login/SessionTimeoutLogin.vue new file mode 100644 index 0000000..16ee772 --- /dev/null +++ b/frontend/vben/src/views/sys/login/SessionTimeoutLogin.vue @@ -0,0 +1,53 @@ + + + diff --git a/frontend/vben/src/views/sys/login/useLogin.ts b/frontend/vben/src/views/sys/login/useLogin.ts new file mode 100644 index 0000000..cdb9d36 --- /dev/null +++ b/frontend/vben/src/views/sys/login/useLogin.ts @@ -0,0 +1,118 @@ +import type { ValidationRule } from 'ant-design-vue/lib/form/Form' +import type { RuleObject } from 'ant-design-vue/lib/form/interface' +import { ref, computed, unref, Ref } from 'vue' +import { useI18n } from '/@/hooks/web/useI18n' + +export enum LoginStateEnum { + LOGIN, + REGISTER, + RESET_PASSWORD, + MOBILE, + QR_CODE, +} + +const currentState = ref(LoginStateEnum.LOGIN) + +export function useLoginState() { + function setLoginState(state: LoginStateEnum) { + currentState.value = state + } + + const getLoginState = computed(() => currentState.value) + + function handleBackLogin() { + setLoginState(LoginStateEnum.LOGIN) + } + + return { setLoginState, getLoginState, handleBackLogin } +} + +export function useFormValid(formRef: Ref) { + async function validForm() { + const form = unref(formRef) + if (!form) return + const data = await form.validate() + return data as T + } + + return { validForm } +} + +export function useFormRules(formData?: Recordable) { + const { t } = useI18n() + + const getAccountFormRule = computed(() => createRule(t('sys.login.accountPlaceholder'))) + const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))) + const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))) + const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder'))) + + const validatePolicy = async (_: RuleObject, value: boolean) => { + return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve() + } + + const validateConfirmPassword = (password: string) => { + return async (_: RuleObject, value: string) => { + if (!value) { + return Promise.reject(t('sys.login.passwordPlaceholder')) + } + if (value !== password) { + return Promise.reject(t('sys.login.diffPwd')) + } + return Promise.resolve() + } + } + + const getFormRules = computed((): { [k: string]: ValidationRule | ValidationRule[] } => { + const accountFormRule = unref(getAccountFormRule) + const passwordFormRule = unref(getPasswordFormRule) + const smsFormRule = unref(getSmsFormRule) + const mobileFormRule = unref(getMobileFormRule) + + const mobileRule = { + sms: smsFormRule, + mobile: mobileFormRule, + } + switch (unref(currentState)) { + // register form rules + case LoginStateEnum.REGISTER: + return { + account: accountFormRule, + password: passwordFormRule, + confirmPassword: [ + { validator: validateConfirmPassword(formData?.password), trigger: 'change' }, + ], + policy: [{ validator: validatePolicy, trigger: 'change' }], + ...mobileRule, + } + + // reset password form rules + case LoginStateEnum.RESET_PASSWORD: + return { + account: accountFormRule, + ...mobileRule, + } + + // mobile form rules + case LoginStateEnum.MOBILE: + return mobileRule + + // login form rules + default: + return { + account: accountFormRule, + password: passwordFormRule, + } + } + }) + return { getFormRules } +} + +function createRule(message: string) { + return [ + { + required: true, + message, + trigger: 'change', + }, + ] +} diff --git a/frontend/vben/src/views/sys/redirect/index.vue b/frontend/vben/src/views/sys/redirect/index.vue new file mode 100644 index 0000000..42ba7c1 --- /dev/null +++ b/frontend/vben/src/views/sys/redirect/index.vue @@ -0,0 +1,30 @@ + + diff --git a/frontend/vben/stylelint.config.js b/frontend/vben/stylelint.config.js new file mode 100644 index 0000000..4b3501d --- /dev/null +++ b/frontend/vben/stylelint.config.js @@ -0,0 +1,100 @@ +module.exports = { + root: true, + plugins: ['stylelint-order'], + extends: ['stylelint-config-standard', 'stylelint-config-prettier'], + customSyntax: 'postcss-html', + rules: { + 'function-no-unknown': null, + 'selector-class-pattern': null, + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['global'], + }, + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep'], + }, + ], + 'at-rule-no-unknown': [ + true, + { + ignoreAtRules: [ + 'tailwind', + 'apply', + 'variants', + 'responsive', + 'screen', + 'function', + 'if', + 'each', + 'include', + 'mixin', + ], + }, + ], + 'no-empty-source': null, + 'string-quotes': null, + 'named-grid-areas-no-invalid': null, + 'unicode-bom': 'never', + 'no-descending-specificity': null, + 'font-family-no-missing-generic-family-keyword': null, + 'declaration-colon-space-after': 'always-single-line', + 'declaration-colon-space-before': 'never', + // 'declaration-block-trailing-semicolon': 'always', + 'rule-empty-line-before': [ + 'always', + { + ignore: ['after-comment', 'first-nested'], + }, + ], + 'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], + 'order/order': [ + [ + 'dollar-variables', + 'custom-properties', + 'at-rules', + 'declarations', + { + type: 'at-rule', + name: 'supports', + }, + { + type: 'at-rule', + name: 'media', + }, + 'rules', + ], + { severity: 'warning' }, + ], + }, + ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'], + overrides: [ + { + files: ['*.vue', '**/*.vue', '*.html', '**/*.html'], + extends: ['stylelint-config-recommended'], + rules: { + 'keyframes-name-pattern': null, + 'selector-pseudo-class-no-unknown': [ + true, + { + ignorePseudoClasses: ['deep', 'global'], + }, + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'], + }, + ], + }, + }, + { + files: ['*.less', '**/*.less'], + customSyntax: 'postcss-less', + extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'], + }, + ], +}; diff --git a/frontend/vben/tsconfig.json b/frontend/vben/tsconfig.json new file mode 100644 index 0000000..76e91f2 --- /dev/null +++ b/frontend/vben/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "noLib": false, + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true, + "strictFunctionTypes": false, + "jsx": "preserve", + "baseUrl": ".", + "allowJs": true, + "sourceMap": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "experimentalDecorators": true, + "lib": ["dom", "esnext"], + "noImplicitAny": false, + "skipLibCheck": true, + "types": ["vite/client"], + "removeComments": true, + "paths": { + "/@/*": ["src/*"], + "/#/*": ["types/*"] + } + }, + "include": [ + "tests/**/*.ts", + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue", + "types/**/*.d.ts", + "types/**/*.ts", + "build/**/*.ts", + "build/**/*.d.ts", + "mock/**/*.ts", + "vite.config.ts" + ], + "exclude": ["node_modules", "tests/server/**/*.ts", "dist", "**/*.js"] +} diff --git a/frontend/vben/types/axios.d.ts b/frontend/vben/types/axios.d.ts new file mode 100644 index 0000000..70db541 --- /dev/null +++ b/frontend/vben/types/axios.d.ts @@ -0,0 +1,53 @@ +export type ErrorMessageMode = 'none' | 'modal' | 'message' | undefined + +export interface RequestOptions { + // Splicing request parameters to url + joinParamsToUrl?: boolean + // Format request parameter time + formatDate?: boolean + // Whether to process the request result + isTransformResponse?: boolean + // Whether to return native response headers + // For example: use this attribute when you need to get the response headers + isReturnNativeResponse?: boolean + // Whether to join url + joinPrefix?: boolean + // Interface address, use the default apiUrl if you leave it blank + apiUrl?: string + // 请求拼接路径 + urlPrefix?: string + // Error message prompt type + errorMessageMode?: ErrorMessageMode + // Whether to add a timestamp + joinTime?: boolean + ignoreCancelToken?: boolean + // Whether to send token in header + withToken?: boolean + // 请求重试机制 + retryRequest?: RetryRequest +} + +export interface RetryRequest { + isOpenRetry: boolean + count: number + waitTime: number +} +export interface Result { + code: number + type: 'success' | 'error' | 'warning' + message: string + result: T +} + +// multipart/form-data: upload file +export interface UploadFileParams { + // Other parameters + data?: Recordable + // File parameter interface field name + name?: string + // file name + file: File | Blob + // file name + filename?: string + [key: string]: any +} diff --git a/frontend/vben/types/config.d.ts b/frontend/vben/types/config.d.ts new file mode 100644 index 0000000..d7a4278 --- /dev/null +++ b/frontend/vben/types/config.d.ts @@ -0,0 +1,158 @@ +import { MenuTypeEnum, MenuModeEnum, TriggerEnum, MixSidebarTriggerEnum } from '/@/enums/menuEnum' +import { + ContentEnum, + PermissionModeEnum, + ThemeEnum, + RouterTransitionEnum, + SettingButtonPositionEnum, + SessionTimeoutProcessingEnum, +} from '/@/enums/appEnum' + +import { CacheTypeEnum } from '/@/enums/cacheEnum' + +export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko' + +export interface MenuSetting { + bgColor: string + fixed: boolean + collapsed: boolean + siderHidden: boolean + canDrag: boolean + show: boolean + hidden: boolean + split: boolean + menuWidth: number + mode: MenuModeEnum + type: MenuTypeEnum + theme: ThemeEnum + topMenuAlign: 'start' | 'center' | 'end' + trigger: TriggerEnum + accordion: boolean + closeMixSidebarOnChange: boolean + collapsedShowTitle: boolean + mixSideTrigger: MixSidebarTriggerEnum + mixSideFixed: boolean +} + +export interface MultiTabsSetting { + cache: boolean + show: boolean + showQuick: boolean + canDrag: boolean + showRedo: boolean + showFold: boolean +} + +export interface HeaderSetting { + bgColor: string + fixed: boolean + show: boolean + theme: ThemeEnum + // Turn on full screen + showFullScreen: boolean + // Show document button + showDoc: boolean + // Show message center button + showNotice: boolean + showSearch: boolean +} + +export interface LocaleSetting { + showPicker: boolean + // Current language + locale: LocaleType + // default language + fallback: LocaleType + // available Locales + availableLocales: LocaleType[] +} + +export interface TransitionSetting { + // Whether to open the page switching animation + enable: boolean + // Route basic switching animation + basicTransition: RouterTransitionEnum + // Whether to open page switching loading + openPageLoading: boolean + // Whether to open the top progress bar + openNProgress: boolean +} + +export interface ProjectConfig { + // Storage location of permission related information + permissionCacheType: CacheTypeEnum + // Whether to show the configuration button + showSettingButton: boolean + // Whether to show the theme switch button + showDarkModeToggle: boolean + // Configure where the button is displayed + settingButtonPosition: SettingButtonPositionEnum + // Permission mode + permissionMode: PermissionModeEnum + // Session timeout processing + sessionTimeoutProcessing: SessionTimeoutProcessingEnum + // Website gray mode, open for possible mourning dates + grayMode: boolean + // Whether to turn on the color weak mode + colorWeak: boolean + // Theme color + themeColor: string + + // The main interface is displayed in full screen, the menu is not displayed, and the top + fullContent: boolean + // content width + contentMode: ContentEnum + // Whether to display the logo + showLogo: boolean + // Whether to show the global footer + showFooter: boolean + // menuType: MenuTypeEnum; + headerSetting: HeaderSetting + // menuSetting + menuSetting: MenuSetting + // Multi-tab settings + multiTabsSetting: MultiTabsSetting + // Animation configuration + transitionSetting: TransitionSetting + // pageLayout whether to enable keep-alive + openKeepAlive: boolean + // Show breadcrumbs + showBreadCrumb: boolean + // Show breadcrumb icon + showBreadCrumbIcon: boolean + // Use error-handler-plugin + useErrorHandle: boolean + // Whether to open back to top + useOpenBackTop: boolean + // Is it possible to embed iframe pages + canEmbedIFramePage: boolean + // Whether to delete unclosed messages and notify when switching the interface + closeMessageOnSwitch: boolean + // Whether to cancel the http request that has been sent but not responded when switching the interface. + removeAllHttpPending: boolean +} + +export interface GlobConfig { + // Site title + title: string + // Service interface url + apiUrl: string + // Upload url + uploadUrl?: string + // Service interface url prefix + urlPrefix?: string + // Project abbreviation + shortName: string +} +export interface GlobEnvConfig { + // Site title + VITE_GLOB_APP_TITLE: string + // Service interface url + VITE_GLOB_API_URL: string + // Service interface url prefix + VITE_GLOB_API_URL_PREFIX?: string + // Project abbreviation + VITE_GLOB_APP_SHORT_NAME: string + // Upload url + VITE_GLOB_UPLOAD_URL?: string +} diff --git a/frontend/vben/types/global.d.ts b/frontend/vben/types/global.d.ts new file mode 100644 index 0000000..4067869 --- /dev/null +++ b/frontend/vben/types/global.d.ts @@ -0,0 +1,101 @@ +import type { + ComponentRenderProxy, + VNode, + VNodeChild, + ComponentPublicInstance, + FunctionalComponent, + PropType as VuePropType, +} from 'vue' + +declare global { + const __APP_INFO__: { + pkg: { + name: string + version: string + dependencies: Recordable + devDependencies: Recordable + } + lastBuildTime: string + } + // declare interface Window { + // // Global vue app instance + // __APP__: App; + // } + + // vue + declare type PropType = VuePropType + declare type VueNode = VNodeChild | JSX.Element + + export type Writable = { + -readonly [P in keyof T]: T[P] + } + + declare type Nullable = T | null + declare type NonNullable = T extends null | undefined ? never : T + declare type Recordable = Record + declare type ReadonlyRecordable = { + readonly [key: string]: T + } + declare type Indexable = { + [key: string]: T + } + declare type DeepPartial = { + [P in keyof T]?: DeepPartial + } + declare type TimeoutHandle = ReturnType + declare type IntervalHandle = ReturnType + + declare interface ChangeEvent extends Event { + target: HTMLInputElement + } + + declare interface WheelEvent { + path?: EventTarget[] + } + interface ImportMetaEnv extends ViteEnv { + __: unknown + } + + declare interface ViteEnv { + VITE_PORT: number + VITE_USE_MOCK: boolean + VITE_USE_PWA: boolean + VITE_PUBLIC_PATH: string + VITE_PROXY: [string, string][] + VITE_GLOB_APP_TITLE: string + VITE_GLOB_APP_SHORT_NAME: string + VITE_USE_CDN: boolean + VITE_DROP_CONSOLE: boolean + VITE_BUILD_COMPRESS: 'gzip' | 'brotli' | 'none' + VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean + VITE_LEGACY: boolean + VITE_USE_IMAGEMIN: boolean + VITE_GENERATE_UI: string + } + + declare function parseInt(s: string | number, radix?: number): number + + declare function parseFloat(string: string | number): number + + namespace JSX { + // tslint:disable no-empty-interface + type Element = VNode + // tslint:disable no-empty-interface + type ElementClass = ComponentRenderProxy + interface ElementAttributesProperty { + $props: any + } + interface IntrinsicElements { + [elem: string]: any + } + interface IntrinsicAttributes { + [elem: string]: any + } + } +} + +declare module 'vue' { + export type JSXComponent = + | { new (): ComponentPublicInstance } + | FunctionalComponent +} diff --git a/frontend/vben/types/index.d.ts b/frontend/vben/types/index.d.ts new file mode 100644 index 0000000..d721cba --- /dev/null +++ b/frontend/vben/types/index.d.ts @@ -0,0 +1,27 @@ +declare interface Fn { + (...arg: T[]): R +} + +declare interface PromiseFn { + (...arg: T[]): Promise +} + +declare type RefType = T | null + +declare type LabelValueOptions = { + label: string + value: any + [key: string]: string | number | boolean +}[] + +declare type EmitType = (event: string, ...args: any[]) => void + +declare type TargetContext = '_self' | '_blank' + +declare interface ComponentElRef { + $el: T +} + +declare type ComponentRef = ComponentElRef | null + +declare type ElRef = Nullable diff --git a/frontend/vben/types/module.d.ts b/frontend/vben/types/module.d.ts new file mode 100644 index 0000000..1c5a0c4 --- /dev/null +++ b/frontend/vben/types/module.d.ts @@ -0,0 +1,16 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue' + const Component: DefineComponent<{}, {}, any> + export default Component +} + +declare module 'ant-design-vue/es/locale/*' { + import { Locale } from 'ant-design-vue/types/locale-provider' + const locale: Locale & ReadonlyRecordable + export default locale as Locale & ReadonlyRecordable +} + +declare module 'virtual:*' { + const result: any + export default result +} diff --git a/frontend/vben/types/store.d.ts b/frontend/vben/types/store.d.ts new file mode 100644 index 0000000..8c1a602 --- /dev/null +++ b/frontend/vben/types/store.d.ts @@ -0,0 +1,40 @@ +import { ErrorTypeEnum } from '/@/enums/exceptionEnum' +import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum' +import { RoleInfo } from '/@/api/sys/model/userModel' + +// Error-log information +export interface ErrorLogInfo { + // Type of error + type: ErrorTypeEnum + // Error file + file: string + // Error name + name?: string + // Error message + message: string + // Error stack + stack?: string + // Error detail + detail: string + // Error url + url: string + // Error time + time?: string +} + +export interface UserInfo { + userId: string | number + username: string + realName: string + avatar: string + desc?: string + homePath?: string + roles: RoleInfo[] +} + +export interface BeforeMiniState { + menuCollapsed?: boolean + menuSplit?: boolean + menuMode?: MenuModeEnum + menuType?: MenuTypeEnum +} diff --git a/frontend/vben/types/utils.d.ts b/frontend/vben/types/utils.d.ts new file mode 100644 index 0000000..e306d02 --- /dev/null +++ b/frontend/vben/types/utils.d.ts @@ -0,0 +1,5 @@ +import type { ComputedRef, Ref } from 'vue' + +export type DynamicProps = { + [P in keyof T]: Ref | T[P] | ComputedRef +} diff --git a/frontend/vben/types/vue-router.d.ts b/frontend/vben/types/vue-router.d.ts new file mode 100644 index 0000000..569fba0 --- /dev/null +++ b/frontend/vben/types/vue-router.d.ts @@ -0,0 +1,45 @@ +export {} + +declare module 'vue-router' { + interface RouteMeta extends Record { + orderNo?: number + // title + title: string + // dynamic router level. + dynamicLevel?: number + // dynamic router real route path (For performance). + realPath?: string + // Whether to ignore permissions + ignoreAuth?: boolean + // role info + roles?: RoleEnum[] + // Whether not to cache + ignoreKeepAlive?: boolean + // Is it fixed on tab + affix?: boolean + // icon on tab + icon?: string + frameSrc?: string + // current page transition + transitionName?: string + // Whether the route has been dynamically added + hideBreadcrumb?: boolean + // Hide submenu + hideChildrenInMenu?: boolean + // Carrying parameters + carryParam?: boolean + // Used internally to mark single-level menus + single?: boolean + // Currently active menu + currentActiveMenu?: string + // Never show in tab + hideTab?: boolean + // Never show in menu + hideMenu?: boolean + isLink?: boolean + // only build for Menu + ignoreRoute?: boolean + // Hide path for children + hidePathForChildren?: boolean + } +} diff --git a/frontend/vben/vite.config.ts b/frontend/vben/vite.config.ts new file mode 100644 index 0000000..bd1302b --- /dev/null +++ b/frontend/vben/vite.config.ts @@ -0,0 +1,115 @@ +import type { UserConfig, ConfigEnv } from 'vite' +import pkg from './package.json' +import dayjs from 'dayjs' +import { loadEnv } from 'vite' +import { resolve } from 'path' +import { generateModifyVars } from './build/generate/generateModifyVars' +import { createProxy } from './build/vite/proxy' +import { wrapperEnv } from './build/utils' +import { createVitePlugins } from './build/vite/plugin' +import { OUTPUT_DIR } from './build/constant' + +function pathResolve(dir: string) { + return resolve(process.cwd(), '.', dir) +} + +const { dependencies, devDependencies, name, version } = pkg +const __APP_INFO__ = { + pkg: { dependencies, devDependencies, name, version }, + lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), +} + +export default ({ command, mode }: ConfigEnv): UserConfig => { + const root = process.cwd() + + const env = loadEnv(mode, root) + + // The boolean type read by loadEnv is a string. This function can be converted to boolean type + const viteEnv = wrapperEnv(env) + + const { VITE_PORT, VITE_PUBLIC_PATH, VITE_PROXY, VITE_DROP_CONSOLE } = viteEnv + + const isBuild = command === 'build' + + return { + base: VITE_PUBLIC_PATH, + root, + resolve: { + alias: [ + { + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // /@/xxxx => src/xxxx + { + find: /\/@\//, + replacement: pathResolve('src') + '/', + }, + // /#/xxxx => types/xxxx + { + find: /\/#\//, + replacement: pathResolve('types') + '/', + }, + ], + }, + server: { + https: true, + // Listening on all local IPs + host: true, + port: VITE_PORT, + // Load proxy configuration from .env + proxy: createProxy(VITE_PROXY), + }, + esbuild: { + pure: VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [], + }, + build: { + target: 'es2015', + cssTarget: 'chrome80', + outDir: OUTPUT_DIR, + // minify: 'terser', + /** + * 当 minify=“minify:'terser'” 解开注释 + * Uncomment when minify="minify:'terser'" + */ + // terserOptions: { + // compress: { + // keep_infinity: true, + // drop_console: VITE_DROP_CONSOLE, + // }, + // }, + // Turning off brotliSize display can slightly reduce packaging time + brotliSize: false, + chunkSizeWarningLimit: 2000, + }, + define: { + // setting vue-i18-next + // Suppress warning + __INTLIFY_PROD_DEVTOOLS__: false, + __APP_INFO__: JSON.stringify(__APP_INFO__), + }, + + css: { + preprocessorOptions: { + less: { + modifyVars: generateModifyVars(), + javascriptEnabled: true, + }, + }, + }, + + // The vite plugin used by the project. The quantity is large, so it is separately extracted and managed + plugins: createVitePlugins(viteEnv, isBuild), + + optimizeDeps: { + // @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly + include: [ + '@vue/runtime-core', + '@vue/shared', + '@iconify/iconify', + 'ant-design-vue/es/locale/zh_CN', + 'ant-design-vue/es/locale/en_US', + ], + }, + } +} diff --git a/frontend/vben/windi.config.ts b/frontend/vben/windi.config.ts new file mode 100644 index 0000000..0f3d1f2 --- /dev/null +++ b/frontend/vben/windi.config.ts @@ -0,0 +1,74 @@ +import { defineConfig } from 'vite-plugin-windicss'; +import { primaryColor } from './build/config/themeConfig'; + +export default defineConfig({ + darkMode: 'class', + plugins: [createEnterPlugin()], + theme: { + extend: { + zIndex: { + '-1': '-1', + }, + colors: { + primary: primaryColor, + }, + screens: { + sm: '576px', + md: '768px', + lg: '992px', + xl: '1200px', + '2xl': '1600px', + }, + }, + }, +}); + +/** + * Used for animation when the element is displayed. + * @param maxOutput The larger the maxOutput output, the larger the generated css volume. + */ +function createEnterPlugin(maxOutput = 6) { + const createCss = (index: number, d = 'x') => { + const upd = d.toUpperCase(); + return { + [`*> .enter-${d}:nth-child(${index})`]: { + transform: `translate${upd}(50px)`, + }, + [`*> .-enter-${d}:nth-child(${index})`]: { + transform: `translate${upd}(-50px)`, + }, + [`* > .enter-${d}:nth-child(${index}),* > .-enter-${d}:nth-child(${index})`]: { + 'z-index': `${10 - index}`, + opacity: '0', + animation: `enter-${d}-animation 0.4s ease-in-out 0.3s`, + 'animation-fill-mode': 'forwards', + 'animation-delay': `${(index * 1) / 10}s`, + }, + }; + }; + const handler = ({ addBase }) => { + const addRawCss = {}; + for (let index = 1; index < maxOutput; index++) { + Object.assign(addRawCss, { + ...createCss(index, 'x'), + ...createCss(index, 'y'), + }); + } + addBase({ + ...addRawCss, + [`@keyframes enter-x-animation`]: { + to: { + opacity: '1', + transform: 'translateX(0)', + }, + }, + [`@keyframes enter-y-animation`]: { + to: { + opacity: '1', + transform: 'translateY(0)', + }, + }, + }); + }; + return { handler }; +} diff --git a/frontend/vben/yarn.lock b/frontend/vben/yarn.lock new file mode 100644 index 0000000..2694214 --- /dev/null +++ b/frontend/vben/yarn.lock @@ -0,0 +1,9754 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + "integrity" "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==" + "resolved" "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@ant-design/colors@^6.0.0": + "integrity" "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==" + "resolved" "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "@ctrl/tinycolor" "^3.4.0" + +"@ant-design/icons-svg@^4.2.1": + "integrity" "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==" + "resolved" "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz" + "version" "4.2.1" + +"@ant-design/icons-vue@^6.1.0": + "integrity" "sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==" + "resolved" "https://registry.npmmirror.com/@ant-design/icons-vue/-/icons-vue-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "@ant-design/colors" "^6.0.0" + "@ant-design/icons-svg" "^4.2.1" + +"@antfu/utils@^0.5.2": + "integrity" "sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==" + "resolved" "https://registry.npmmirror.com/@antfu/utils/-/utils-0.5.2.tgz" + "version" "0.5.2" + +"@apideck/better-ajv-errors@^0.3.1": + "integrity" "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==" + "resolved" "https://registry.npmmirror.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz" + "version" "0.3.6" + dependencies: + "json-schema" "^0.4.0" + "jsonpointer" "^5.0.0" + "leven" "^3.1.0" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6": + "integrity" "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==" + "resolved" "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.18.6": + "integrity" "sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ==" + "resolved" "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.18.6.tgz" + "version" "7.18.6" + +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.17.9", "@babel/core@^7.4.0-0": + "integrity" "sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ==" + "resolved" "https://registry.npmmirror.com/@babel/core/-/core-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helpers" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.2" + "json5" "^2.2.1" + "semver" "^6.3.0" + +"@babel/generator@^7.18.6": + "integrity" "sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A==" + "resolved" "https://registry.npmmirror.com/@babel/generator/-/generator-7.18.7.tgz" + "version" "7.18.7" + dependencies: + "@babel/types" "^7.18.7" + "@jridgewell/gen-mapping" "^0.3.2" + "jsesc" "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + "integrity" "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==" + "resolved" "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + "integrity" "sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.18.6": + "integrity" "sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg==" + "resolved" "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "browserslist" "^4.20.2" + "semver" "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6": + "integrity" "sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6": + "integrity" "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==" + "resolved" "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "regexpu-core" "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.3.1": + "integrity" "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==" + "resolved" "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" + "semver" "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.6": + "integrity" "sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q==" + "resolved" "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz" + "version" "7.18.6" + +"@babel/helper-explode-assignable-expression@^7.18.6": + "integrity" "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==" + "resolved" "https://registry.npmmirror.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.6": + "integrity" "sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-hoist-variables@^7.18.6": + "integrity" "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==" + "resolved" "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.6": + "integrity" "sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng==" + "resolved" "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.18.6": + "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" + "resolved" "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.6": + "integrity" "sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-optimise-call-expression@^7.18.6": + "integrity" "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==" + "resolved" "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + "integrity" "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==" + "resolved" "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz" + "version" "7.18.6" + +"@babel/helper-remap-async-to-generator@^7.18.6": + "integrity" "sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ==" + "resolved" "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-wrap-function" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-replace-supers@^7.18.6": + "integrity" "sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g==" + "resolved" "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-simple-access@^7.18.6": + "integrity" "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==" + "resolved" "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.6": + "integrity" "sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-split-export-declaration@^7.18.6": + "integrity" "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==" + "resolved" "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + "integrity" "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" + "resolved" "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz" + "version" "7.18.6" + +"@babel/helper-validator-option@^7.18.6": + "integrity" "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" + "version" "7.18.6" + +"@babel/helper-wrap-function@^7.18.6": + "integrity" "sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw==" + "resolved" "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-function-name" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helpers@^7.18.6": + "integrity" "sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ==" + "resolved" "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/highlight@^7.18.6": + "integrity" "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==" + "resolved" "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + "chalk" "^2.0.0" + "js-tokens" "^4.0.0" + +"@babel/parser@^7.16.4", "@babel/parser@^7.18.6": + "integrity" "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==" + "resolved" "https://registry.npmmirror.com/@babel/parser/-/parser-7.18.6.tgz" + "version" "7.18.6" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + "integrity" "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.6": + "integrity" "sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" + +"@babel/plugin-proposal-async-generator-functions@^7.18.6": + "integrity" "sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.18.6": + "integrity" "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-class-static-block@^7.18.6": + "integrity" "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + "integrity" "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-namespace-from@^7.18.6": + "integrity" "sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.18.6": + "integrity" "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.18.6": + "integrity" "sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + "integrity" "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.18.6": + "integrity" "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.18.6": + "integrity" "sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.18.6" + +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + "integrity" "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.18.6": + "integrity" "sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.18.6": + "integrity" "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + "integrity" "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + "integrity" "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-async-generators@^7.8.4": + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.18.6": + "integrity" "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-import-meta@^7.10.4": + "integrity" "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + "version" "7.10.4" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.0.0": + "integrity" "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.18.6": + "integrity" "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.18.6": + "integrity" "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.18.6": + "integrity" "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + "integrity" "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.18.6": + "integrity" "sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-classes@^7.18.6": + "integrity" "sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "globals" "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.18.6": + "integrity" "sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-destructuring@^7.18.6": + "integrity" "sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + "integrity" "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-duplicate-keys@^7.18.6": + "integrity" "sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + "integrity" "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.18.6": + "integrity" "sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.18.6": + "integrity" "sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-literals@^7.18.6": + "integrity" "sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-member-expression-literals@^7.18.6": + "integrity" "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-amd@^7.18.6": + "integrity" "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.18.6": + "integrity" "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.18.6": + "integrity" "sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "babel-plugin-dynamic-import-node" "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.18.6": + "integrity" "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6": + "integrity" "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-new-target@^7.18.6": + "integrity" "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.18.6": + "integrity" "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.18.6": + "integrity" "sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-property-literals@^7.18.6": + "integrity" "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-regenerator@^7.18.6": + "integrity" "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "regenerator-transform" "^0.15.0" + +"@babel/plugin-transform-reserved-words@^7.18.6": + "integrity" "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-shorthand-properties@^7.18.6": + "integrity" "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.18.6": + "integrity" "sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + "integrity" "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.6": + "integrity" "sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-typeof-symbol@^7.18.6": + "integrity" "sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-typescript@^7.16.8": + "integrity" "sha512-ijHNhzIrLj5lQCnI6aaNVRtGVuUZhOXFLRVFs7lLrkXTHip4FKty5oAuQdk4tywG0/WjXmjTfQCWmuzrvFer1w==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-typescript" "^7.18.6" + +"@babel/plugin-transform-unicode-escapes@^7.18.6": + "integrity" "sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + "integrity" "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==" + "resolved" "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.11.0": + "integrity" "sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw==" + "resolved" "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-async-generator-functions" "^7.18.6" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.6" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.6" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.18.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.18.6" + "@babel/plugin-transform-classes" "^7.18.6" + "@babel/plugin-transform-computed-properties" "^7.18.6" + "@babel/plugin-transform-destructuring" "^7.18.6" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.6" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.6" + "@babel/plugin-transform-function-name" "^7.18.6" + "@babel/plugin-transform-literals" "^7.18.6" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.18.6" + "@babel/plugin-transform-modules-commonjs" "^7.18.6" + "@babel/plugin-transform-modules-systemjs" "^7.18.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.18.6" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.18.6" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.6" + "@babel/plugin-transform-typeof-symbol" "^7.18.6" + "@babel/plugin-transform-unicode-escapes" "^7.18.6" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.18.6" + "babel-plugin-polyfill-corejs2" "^0.3.1" + "babel-plugin-polyfill-corejs3" "^0.5.2" + "babel-plugin-polyfill-regenerator" "^0.3.1" + "core-js-compat" "^3.22.1" + "semver" "^6.3.0" + +"@babel/preset-modules@^0.1.5": + "integrity" "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==" + "resolved" "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + "version" "0.1.5" + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + "esutils" "^2.0.2" + +"@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.8.4": + "integrity" "sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==" + "resolved" "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "regenerator-runtime" "^0.13.4" + +"@babel/standalone@^7.17.11": + "integrity" "sha512-AIOn3ON0KhYqAbvmkT11vi/YAlhrPn6RSPQb8Hl3PUZoE1yFwut5fQ9/oJ4Dvf2SGmO41pF7xmwP2W1RT0uJCA==" + "resolved" "https://registry.npmmirror.com/@babel/standalone/-/standalone-7.18.7.tgz" + "version" "7.18.7" + +"@babel/template@^7.0.0", "@babel/template@^7.18.6": + "integrity" "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==" + "resolved" "https://registry.npmmirror.com/@babel/template/-/template-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.18.6": + "integrity" "sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw==" + "resolved" "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.18.6.tgz" + "version" "7.18.6" + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + "debug" "^4.1.0" + "globals" "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.7", "@babel/types@^7.4.4": + "integrity" "sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ==" + "resolved" "https://registry.npmmirror.com/@babel/types/-/types-7.18.7.tgz" + "version" "7.18.7" + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + "to-fast-properties" "^2.0.0" + +"@commitlint/cli@^16.2.3": + "integrity" "sha512-P+kvONlfsuTMnxSwWE1H+ZcPMY3STFaHb2kAacsqoIkNx66O0T7sTpBxpxkMrFPyhkJiLJnJWMhk4bbvYD3BMA==" + "resolved" "https://registry.npmmirror.com/@commitlint/cli/-/cli-16.3.0.tgz" + "version" "16.3.0" + dependencies: + "@commitlint/format" "^16.2.1" + "@commitlint/lint" "^16.2.4" + "@commitlint/load" "^16.3.0" + "@commitlint/read" "^16.2.1" + "@commitlint/types" "^16.2.1" + "lodash" "^4.17.19" + "resolve-from" "5.0.0" + "resolve-global" "1.0.0" + "yargs" "^17.0.0" + +"@commitlint/config-conventional@^16.2.1": + "integrity" "sha512-av2UQJa3CuE5P0dzxj/o/B9XVALqYzEViHrMXtDrW9iuflrqCStWBAioijppj9URyz6ONpohJKAtSdgAOE0gkA==" + "resolved" "https://registry.npmmirror.com/@commitlint/config-conventional/-/config-conventional-16.2.4.tgz" + "version" "16.2.4" + dependencies: + "conventional-changelog-conventionalcommits" "^4.3.1" + +"@commitlint/config-validator@^16.2.1": + "integrity" "sha512-hogSe0WGg7CKmp4IfNbdNES3Rq3UEI4XRPB8JL4EPgo/ORq5nrGTVzxJh78omibNuB8Ho4501Czb1Er1MoDWpw==" + "resolved" "https://registry.npmmirror.com/@commitlint/config-validator/-/config-validator-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/types" "^16.2.1" + "ajv" "^6.12.6" + +"@commitlint/ensure@^16.2.1": + "integrity" "sha512-/h+lBTgf1r5fhbDNHOViLuej38i3rZqTQnBTk+xEg+ehOwQDXUuissQ5GsYXXqI5uGy+261ew++sT4EA3uBJ+A==" + "resolved" "https://registry.npmmirror.com/@commitlint/ensure/-/ensure-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/types" "^16.2.1" + "lodash" "^4.17.19" + +"@commitlint/execute-rule@^16.2.1": + "integrity" "sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g==" + "resolved" "https://registry.npmmirror.com/@commitlint/execute-rule/-/execute-rule-16.2.1.tgz" + "version" "16.2.1" + +"@commitlint/format@^16.2.1": + "integrity" "sha512-Yyio9bdHWmNDRlEJrxHKglamIk3d6hC0NkEUW6Ti6ipEh2g0BAhy8Od6t4vLhdZRa1I2n+gY13foy+tUgk0i1Q==" + "resolved" "https://registry.npmmirror.com/@commitlint/format/-/format-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/types" "^16.2.1" + "chalk" "^4.0.0" + +"@commitlint/is-ignored@^16.2.4": + "integrity" "sha512-Lxdq9aOAYCOOOjKi58ulbwK/oBiiKz+7Sq0+/SpFIEFwhHkIVugvDvWjh2VRBXmRC/x5lNcjDcYEwS/uYUvlYQ==" + "resolved" "https://registry.npmmirror.com/@commitlint/is-ignored/-/is-ignored-16.2.4.tgz" + "version" "16.2.4" + dependencies: + "@commitlint/types" "^16.2.1" + "semver" "7.3.7" + +"@commitlint/lint@^16.2.4": + "integrity" "sha512-AUDuwOxb2eGqsXbTMON3imUGkc1jRdtXrbbohiLSCSk3jFVXgJLTMaEcr39pR00N8nE9uZ+V2sYaiILByZVmxQ==" + "resolved" "https://registry.npmmirror.com/@commitlint/lint/-/lint-16.2.4.tgz" + "version" "16.2.4" + dependencies: + "@commitlint/is-ignored" "^16.2.4" + "@commitlint/parse" "^16.2.1" + "@commitlint/rules" "^16.2.4" + "@commitlint/types" "^16.2.1" + +"@commitlint/load@^16.3.0": + "integrity" "sha512-3tykjV/iwbkv2FU9DG+NZ/JqmP0Nm3b7aDwgCNQhhKV5P74JAuByULkafnhn+zsFGypG1qMtI5u+BZoa9APm0A==" + "resolved" "https://registry.npmmirror.com/@commitlint/load/-/load-16.3.0.tgz" + "version" "16.3.0" + dependencies: + "@commitlint/config-validator" "^16.2.1" + "@commitlint/execute-rule" "^16.2.1" + "@commitlint/resolve-extends" "^16.2.1" + "@commitlint/types" "^16.2.1" + "@types/node" ">=12" + "chalk" "^4.0.0" + "cosmiconfig" "^7.0.0" + "cosmiconfig-typescript-loader" "^2.0.0" + "lodash" "^4.17.19" + "resolve-from" "^5.0.0" + "typescript" "^4.4.3" + +"@commitlint/message@^16.2.1": + "integrity" "sha512-2eWX/47rftViYg7a3axYDdrgwKv32mxbycBJT6OQY/MJM7SUfYNYYvbMFOQFaA4xIVZt7t2Alyqslbl6blVwWw==" + "resolved" "https://registry.npmmirror.com/@commitlint/message/-/message-16.2.1.tgz" + "version" "16.2.1" + +"@commitlint/parse@^16.2.1": + "integrity" "sha512-2NP2dDQNL378VZYioLrgGVZhWdnJO4nAxQl5LXwYb08nEcN+cgxHN1dJV8OLJ5uxlGJtDeR8UZZ1mnQ1gSAD/g==" + "resolved" "https://registry.npmmirror.com/@commitlint/parse/-/parse-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/types" "^16.2.1" + "conventional-changelog-angular" "^5.0.11" + "conventional-commits-parser" "^3.2.2" + +"@commitlint/read@^16.2.1": + "integrity" "sha512-tViXGuaxLTrw2r7PiYMQOFA2fueZxnnt0lkOWqKyxT+n2XdEMGYcI9ID5ndJKXnfPGPppD0w/IItKsIXlZ+alw==" + "resolved" "https://registry.npmmirror.com/@commitlint/read/-/read-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/top-level" "^16.2.1" + "@commitlint/types" "^16.2.1" + "fs-extra" "^10.0.0" + "git-raw-commits" "^2.0.0" + +"@commitlint/resolve-extends@^16.2.1": + "integrity" "sha512-NbbCMPKTFf2J805kwfP9EO+vV+XvnaHRcBy6ud5dF35dxMsvdJqke54W3XazXF1ZAxC4a3LBy4i/GNVBAthsEg==" + "resolved" "https://registry.npmmirror.com/@commitlint/resolve-extends/-/resolve-extends-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "@commitlint/config-validator" "^16.2.1" + "@commitlint/types" "^16.2.1" + "import-fresh" "^3.0.0" + "lodash" "^4.17.19" + "resolve-from" "^5.0.0" + "resolve-global" "^1.0.0" + +"@commitlint/rules@^16.2.4": + "integrity" "sha512-rK5rNBIN2ZQNQK+I6trRPK3dWa0MtaTN4xnwOma1qxa4d5wQMQJtScwTZjTJeallFxhOgbNOgr48AMHkdounVg==" + "resolved" "https://registry.npmmirror.com/@commitlint/rules/-/rules-16.2.4.tgz" + "version" "16.2.4" + dependencies: + "@commitlint/ensure" "^16.2.1" + "@commitlint/message" "^16.2.1" + "@commitlint/to-lines" "^16.2.1" + "@commitlint/types" "^16.2.1" + "execa" "^5.0.0" + +"@commitlint/to-lines@^16.2.1": + "integrity" "sha512-9/VjpYj5j1QeY3eiog1zQWY6axsdWAc0AonUUfyZ7B0MVcRI0R56YsHAfzF6uK/g/WwPZaoe4Lb1QCyDVnpVaQ==" + "resolved" "https://registry.npmmirror.com/@commitlint/to-lines/-/to-lines-16.2.1.tgz" + "version" "16.2.1" + +"@commitlint/top-level@^16.2.1": + "integrity" "sha512-lS6GSieHW9y6ePL73ied71Z9bOKyK+Ib9hTkRsB8oZFAyQZcyRwq2w6nIa6Fngir1QW51oKzzaXfJL94qwImyw==" + "resolved" "https://registry.npmmirror.com/@commitlint/top-level/-/top-level-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "find-up" "^5.0.0" + +"@commitlint/types@^16.2.1": + "integrity" "sha512-7/z7pA7BM0i8XvMSBynO7xsB3mVQPUZbVn6zMIlp/a091XJ3qAXRXc+HwLYhiIdzzS5fuxxNIHZMGHVD4HJxdA==" + "resolved" "https://registry.npmmirror.com/@commitlint/types/-/types-16.2.1.tgz" + "version" "16.2.1" + dependencies: + "chalk" "^4.0.0" + +"@cspotcode/source-map-support@^0.8.0": + "integrity" "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==" + "resolved" "https://registry.npmmirror.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + "version" "0.8.1" + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@csstools/selector-specificity@^2.0.1": + "integrity" "sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA==" + "resolved" "https://registry.npmmirror.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz" + "version" "2.0.1" + +"@ctrl/tinycolor@^3.4.0": + "integrity" "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" + "resolved" "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz" + "version" "3.4.1" + +"@eslint/eslintrc@^1.3.0": + "integrity" "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==" + "resolved" "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "ajv" "^6.12.4" + "debug" "^4.3.2" + "espree" "^9.3.2" + "globals" "^13.15.0" + "ignore" "^5.2.0" + "import-fresh" "^3.2.1" + "js-yaml" "^4.1.0" + "minimatch" "^3.1.2" + "strip-json-comments" "^3.1.1" + +"@humanwhocodes/config-array@^0.9.2": + "integrity" "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==" + "resolved" "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz" + "version" "0.9.5" + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + "debug" "^4.1.1" + "minimatch" "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + "integrity" "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "resolved" "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + "version" "1.2.1" + +"@hutson/parse-repository-url@^3.0.0": + "integrity" "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==" + "resolved" "https://registry.npmmirror.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz" + "version" "3.0.2" + +"@iconify/iconify@^2.2.1", "@iconify/iconify@>=2.0.0-rc.6": + "integrity" "sha512-WJzw+3iicrF/tbjbxxRinSgy5FHdJoz/egTqwi3xCDkNRJPq482RX1iyaWrjNuY2vMNSPkQMuqHvZDXgA+WnwQ==" + "resolved" "https://registry.npmmirror.com/@iconify/iconify/-/iconify-2.2.1.tgz" + "version" "2.2.1" + +"@iconify/iconify@2.1.2": + "integrity" "sha512-QcUzFeEWkE/mW+BVtEGmcWATClcCOIJFiYUD/PiCWuTcdEA297o8D4oN6Ra44WrNOHu1wqNW4J0ioaDIiqaFOQ==" + "resolved" "https://registry.npmmirror.com/@iconify/iconify/-/iconify-2.1.2.tgz" + "version" "2.1.2" + dependencies: + "cross-fetch" "^3.1.5" + +"@iconify/json@^2.1.30": + "integrity" "sha512-mRybH87M9TWNkXRbp4cncV3ZRt6JaQRnvMMFE+gokSA7xTOomxLCNBFn2lkBA1B4/0rQ9h/UffkS6XVd0gMYjQ==" + "resolved" "https://registry.npmmirror.com/@iconify/json/-/json-2.1.73.tgz" + "version" "2.1.73" + dependencies: + "@iconify/types" "*" + "pathe" "^0.3.0" + +"@iconify/types@*": + "integrity" "sha512-Jh0llaK2LRXQoYsorIH8maClebsnzTcve+7U3rQUSnC11X4jtPnFuyatqFLvMxZ8MLG8dB4zfHsbPfuvxluONw==" + "resolved" "https://registry.npmmirror.com/@iconify/types/-/types-1.1.0.tgz" + "version" "1.1.0" + +"@intlify/core-base@9.1.10": + "integrity" "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==" + "resolved" "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/devtools-if" "9.1.10" + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + +"@intlify/devtools-if@9.1.10": + "integrity" "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==" + "resolved" "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/shared" "9.1.10" + +"@intlify/message-compiler@9.1.10": + "integrity" "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==" + "resolved" "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + "source-map" "0.6.1" + +"@intlify/message-resolver@9.1.10": + "integrity" "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w==" + "resolved" "https://registry.npmmirror.com/@intlify/message-resolver/-/message-resolver-9.1.10.tgz" + "version" "9.1.10" + +"@intlify/runtime@9.1.10": + "integrity" "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==" + "resolved" "https://registry.npmmirror.com/@intlify/runtime/-/runtime-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/message-compiler" "9.1.10" + "@intlify/message-resolver" "9.1.10" + "@intlify/shared" "9.1.10" + +"@intlify/shared@9.1.10": + "integrity" "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==" + "resolved" "https://registry.npmmirror.com/@intlify/shared/-/shared-9.1.10.tgz" + "version" "9.1.10" + +"@intlify/vue-devtools@9.1.10": + "integrity" "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==" + "resolved" "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/message-resolver" "9.1.10" + "@intlify/runtime" "9.1.10" + "@intlify/shared" "9.1.10" + +"@jridgewell/gen-mapping@^0.1.0": + "integrity" "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==" + "resolved" "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0": + "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" + "resolved" "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + "version" "0.3.2" + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/gen-mapping@^0.3.2": + "integrity" "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==" + "resolved" "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + "version" "0.3.2" + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "resolved" "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + "version" "3.1.0" + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "resolved" "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz" + "version" "1.1.2" + +"@jridgewell/source-map@^0.3.2": + "integrity" "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==" + "resolved" "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.2.tgz" + "version" "0.3.2" + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "resolved" "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + "version" "1.4.14" + +"@jridgewell/trace-mapping@^0.3.9": + "integrity" "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==" + "resolved" "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz" + "version" "0.3.14" + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@0.3.9": + "integrity" "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==" + "resolved" "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + "version" "0.3.9" + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@logicflow/core@^1.1.13", "@logicflow/core@^1.1.21": + "integrity" "sha512-LfFnHV009HhozPSWyFlLwsIsEXniFtjJKHGxQVxzRDwKqsgBOUBwyCTbDgejTIc4fw0zaINYhG5YRFSPGsDzWQ==" + "resolved" "https://registry.npmmirror.com/@logicflow/core/-/core-1.1.21.tgz" + "version" "1.1.21" + dependencies: + "@types/mousetrap" "^1.6.4" + "mousetrap" "^1.6.5" + "preact" "^10.4.8" + +"@logicflow/extension@^1.1.13": + "integrity" "sha512-jUrChV89BC7QsyejGt3tIWX9/EGI/Rh+LFsht0OZDafgabk4D99D3J8Glg1UC/unh9dOUNDoD3Hs3xaO8gDBzg==" + "resolved" "https://registry.npmmirror.com/@logicflow/extension/-/extension-1.1.21.tgz" + "version" "1.1.21" + dependencies: + "@logicflow/core" "^1.1.21" + "ids" "^1.0.0" + "preact" "^10.4.8" + +"@nodelib/fs.scandir@2.1.5": + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" + dependencies: + "@nodelib/fs.stat" "2.0.5" + "run-parallel" "^1.1.9" + +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" + +"@nodelib/fs.walk@^1.2.3": + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" + dependencies: + "@nodelib/fs.scandir" "2.1.5" + "fastq" "^1.6.0" + +"@octokit/auth-token@^2.4.4": + "integrity" "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==" + "resolved" "https://registry.npmmirror.com/@octokit/auth-token/-/auth-token-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/core@^3.5.1", "@octokit/core@>=2", "@octokit/core@>=3": + "integrity" "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==" + "resolved" "https://registry.npmmirror.com/@octokit/core/-/core-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.6.3" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + "before-after-hook" "^2.2.0" + "universal-user-agent" "^6.0.0" + +"@octokit/endpoint@^6.0.1": + "integrity" "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==" + "resolved" "https://registry.npmmirror.com/@octokit/endpoint/-/endpoint-6.0.12.tgz" + "version" "6.0.12" + dependencies: + "@octokit/types" "^6.0.3" + "is-plain-object" "^5.0.0" + "universal-user-agent" "^6.0.0" + +"@octokit/graphql@^4.5.8": + "integrity" "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==" + "resolved" "https://registry.npmmirror.com/@octokit/graphql/-/graphql-4.8.0.tgz" + "version" "4.8.0" + dependencies: + "@octokit/request" "^5.6.0" + "@octokit/types" "^6.0.3" + "universal-user-agent" "^6.0.0" + +"@octokit/openapi-types@^12.7.0": + "integrity" "sha512-ydcKLs2KKcxlhpdWLzJxEBDEk/U5MUeqtqkXlrtAUXXFPs6vLl1PEGghFC/BbpleosB7iXs0Z4P2DGe7ZT5ZNg==" + "resolved" "https://registry.npmmirror.com/@octokit/openapi-types/-/openapi-types-12.8.0.tgz" + "version" "12.8.0" + +"@octokit/plugin-paginate-rest@^2.16.8": + "integrity" "sha512-NVNTK63yoTFp07GqISWK+uDfGH1CAPhQXS7LzsJBvaK5W+UlvG549pLZC55FK0FqANVl6q/9ra3SR5c97xF/sw==" + "resolved" "https://registry.npmmirror.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.1.tgz" + "version" "2.21.1" + dependencies: + "@octokit/types" "^6.38.2" + +"@octokit/plugin-request-log@^1.0.4": + "integrity" "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==" + "resolved" "https://registry.npmmirror.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz" + "version" "1.0.4" + +"@octokit/plugin-rest-endpoint-methods@^5.12.0": + "integrity" "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==" + "resolved" "https://registry.npmmirror.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz" + "version" "5.16.2" + dependencies: + "@octokit/types" "^6.39.0" + "deprecation" "^2.3.1" + +"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": + "integrity" "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==" + "resolved" "https://registry.npmmirror.com/@octokit/request-error/-/request-error-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "@octokit/types" "^6.0.3" + "deprecation" "^2.0.0" + "once" "^1.4.0" + +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + "integrity" "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==" + "resolved" "https://registry.npmmirror.com/@octokit/request/-/request-5.6.3.tgz" + "version" "5.6.3" + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.16.1" + "is-plain-object" "^5.0.0" + "node-fetch" "^2.6.7" + "universal-user-agent" "^6.0.0" + +"@octokit/rest@^18.12.0": + "integrity" "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==" + "resolved" "https://registry.npmmirror.com/@octokit/rest/-/rest-18.12.0.tgz" + "version" "18.12.0" + dependencies: + "@octokit/core" "^3.5.1" + "@octokit/plugin-paginate-rest" "^2.16.8" + "@octokit/plugin-request-log" "^1.0.4" + "@octokit/plugin-rest-endpoint-methods" "^5.12.0" + +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.38.2", "@octokit/types@^6.39.0": + "integrity" "sha512-Mq4N9sOAYCitTsBtDdRVrBE80lIrMBhL9Jbrw0d+j96BAzlq4V+GLHFJbHokEsVvO/9tQupQdoFdgVYhD2C8UQ==" + "resolved" "https://registry.npmmirror.com/@octokit/types/-/types-6.39.0.tgz" + "version" "6.39.0" + dependencies: + "@octokit/openapi-types" "^12.7.0" + +"@purge-icons/core@^0.8.0": + "integrity" "sha512-8L6hP1U9XQO5B7kvquVJ5N7jzFvO0LZLXhBCjUQzzJzi42i6MAUanVKROApqbBuh21o9tmPwvNUg0xPe/uftRA==" + "resolved" "https://registry.npmmirror.com/@purge-icons/core/-/core-0.8.0.tgz" + "version" "0.8.0" + dependencies: + "@iconify/iconify" "2.1.2" + "axios" "^0.26.0" + "debug" "^4.3.3" + "fast-glob" "^3.2.11" + "fs-extra" "^10.0.1" + +"@purge-icons/generated@^0.8.1": + "integrity" "sha512-rIExGA33EGKEToqtc8WfpboaR7or1XRp+KV1Y5v/P0Rq7G5Me95DmP3ow/MpG7ql+XZ9xPzyS2naGRx5358+6Q==" + "resolved" "https://registry.npmmirror.com/@purge-icons/generated/-/generated-0.8.1.tgz" + "version" "0.8.1" + dependencies: + "@iconify/iconify" ">=2.0.0-rc.6" + +"@rollup/plugin-babel@^5.2.0": + "integrity" "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==" + "resolved" "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@rollup/pluginutils" "^3.1.0" + +"@rollup/plugin-node-resolve@^11.2.1": + "integrity" "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==" + "resolved" "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz" + "version" "11.2.1" + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + "builtin-modules" "^3.1.0" + "deepmerge" "^4.2.2" + "is-module" "^1.0.0" + "resolve" "^1.19.0" + +"@rollup/plugin-node-resolve@^13.0.4": + "integrity" "sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==" + "resolved" "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz" + "version" "13.3.0" + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + "deepmerge" "^4.2.2" + "is-builtin-module" "^3.1.0" + "is-module" "^1.0.0" + "resolve" "^1.19.0" + +"@rollup/plugin-replace@^2.4.1": + "integrity" "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==" + "resolved" "https://registry.npmmirror.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "@rollup/pluginutils" "^3.1.0" + "magic-string" "^0.25.7" + +"@rollup/pluginutils@^3.1.0": + "integrity" "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==" + "resolved" "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "@types/estree" "0.0.39" + "estree-walker" "^1.0.1" + "picomatch" "^2.2.2" + +"@rollup/pluginutils@^4.1.2", "@rollup/pluginutils@^4.2.0": + "integrity" "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==" + "resolved" "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "estree-walker" "^2.0.1" + "picomatch" "^2.2.2" + +"@simonwep/pickr@~1.8.0": + "integrity" "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==" + "resolved" "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz" + "version" "1.8.2" + dependencies: + "core-js" "^3.15.1" + "nanopop" "^2.1.0" + +"@sindresorhus/is@^0.7.0": + "integrity" "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + "resolved" "https://registry.npmmirror.com/@sindresorhus/is/-/is-0.7.0.tgz" + "version" "0.7.0" + +"@surma/rollup-plugin-off-main-thread@^2.2.3": + "integrity" "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==" + "resolved" "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz" + "version" "2.2.3" + dependencies: + "ejs" "^3.1.6" + "json5" "^2.2.0" + "magic-string" "^0.25.0" + "string.prototype.matchall" "^4.0.6" + +"@trysound/sax@0.2.0": + "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "resolved" "https://registry.npmmirror.com/@trysound/sax/-/sax-0.2.0.tgz" + "version" "0.2.0" + +"@tsconfig/node10@^1.0.7": + "integrity" "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + "resolved" "https://registry.npmmirror.com/@tsconfig/node10/-/node10-1.0.9.tgz" + "version" "1.0.9" + +"@tsconfig/node12@^1.0.7": + "integrity" "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "resolved" "https://registry.npmmirror.com/@tsconfig/node12/-/node12-1.0.11.tgz" + "version" "1.0.11" + +"@tsconfig/node14@^1.0.0": + "integrity" "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "resolved" "https://registry.npmmirror.com/@tsconfig/node14/-/node14-1.0.3.tgz" + "version" "1.0.3" + +"@tsconfig/node16@^1.0.2": + "integrity" "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "resolved" "https://registry.npmmirror.com/@tsconfig/node16/-/node16-1.0.3.tgz" + "version" "1.0.3" + +"@types/codemirror@^5.60.5": + "integrity" "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==" + "resolved" "https://registry.npmmirror.com/@types/codemirror/-/codemirror-5.60.5.tgz" + "version" "5.60.5" + dependencies: + "@types/tern" "*" + +"@types/crypto-js@^4.1.1": + "integrity" "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" + "resolved" "https://registry.npmmirror.com/@types/crypto-js/-/crypto-js-4.1.1.tgz" + "version" "4.1.1" + +"@types/estree@*": + "integrity" "sha512-BZWrtCU0bMVAIliIV+HJO1f1PR41M7NKjfxrFJwwhKI1KwhwOxYw1SXg9ao+CIMt774nFuGiG6eU+udtbEI9oQ==" + "resolved" "https://registry.npmmirror.com/@types/estree/-/estree-0.0.52.tgz" + "version" "0.0.52" + +"@types/estree@0.0.39": + "integrity" "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + "resolved" "https://registry.npmmirror.com/@types/estree/-/estree-0.0.39.tgz" + "version" "0.0.39" + +"@types/fs-extra@^9.0.13": + "integrity" "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==" + "resolved" "https://registry.npmmirror.com/@types/fs-extra/-/fs-extra-9.0.13.tgz" + "version" "9.0.13" + dependencies: + "@types/node" "*" + +"@types/glob@^7.1.1": + "integrity" "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==" + "resolved" "https://registry.npmmirror.com/@types/glob/-/glob-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/imagemin-gifsicle@^7.0.1": + "integrity" "sha512-kUz6sUh0P95JOS0RGEaaemWUrASuw+dLsWIveK2UZJx74id/B9epgblMkCk/r5MjUWbZ83wFvacG5Rb/f97gyA==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-gifsicle/-/imagemin-gifsicle-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "@types/imagemin" "*" + +"@types/imagemin-jpegtran@^5.0.1": + "integrity" "sha512-Ps8kbm+DUFte/Eln/tUdEvpMWHKFCsQKlV8n+RN50zqWqL/7QhfLxR0ymitP9wa90P6+rkbJlintBNPkVR+B/Q==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-jpegtran/-/imagemin-jpegtran-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "@types/imagemin" "*" + +"@types/imagemin-mozjpeg@^8.0.1": + "integrity" "sha512-kMQWEoKxxhlnH4POI3qfW9DjXlQfi80ux3l2b3j5R3eudSCoUIzKQLkfMjNJ6eMYnMWBcB+rfQOWqIzdIwFGKw==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.1.tgz" + "version" "8.0.1" + dependencies: + "@types/imagemin" "*" + +"@types/imagemin-optipng@^5.2.1": + "integrity" "sha512-XCM/3q+HUL7v4zOqMI+dJ5dTxT+MUukY9KU49DSnYb/4yWtSMHJyADP+WHSMVzTR63J2ZvfUOzSilzBNEQW78g==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz" + "version" "5.2.1" + dependencies: + "@types/imagemin" "*" + +"@types/imagemin-svgo@^10.0.0": + "integrity" "sha512-F3Tcm0iElDp9o1QnulC7EFR6KrYaXs0ARFnAmaYwPsPQ1AMcrjy45NI7cfGJ9yfuBDep/GU/tqj4EUD62DOWgg==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-svgo/-/imagemin-svgo-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "@types/imagemin" "*" + "@types/svgo" "*" + +"@types/imagemin-webp@^7.0.0": + "integrity" "sha512-Lb1tjy2vEU7qYwM5iFB9o5k0J3mIpulw6Yftset5LLLugPu7+C16rLYRP1WEwr4QM8AeJZRjC2BGBLd9lGvRhQ==" + "resolved" "https://registry.npmmirror.com/@types/imagemin-webp/-/imagemin-webp-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "@types/imagemin" "*" + +"@types/imagemin@*", "@types/imagemin@^7.0.1": + "integrity" "sha512-xEn5+M3lDBtI3JxLy6eU3ksoVurygnlG7OYhTqJfGGP4PcvYnfn+IABCmMve7ziM/SneHDm5xgJFKC8hCYPicw==" + "resolved" "https://registry.npmmirror.com/@types/imagemin/-/imagemin-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "@types/node" "*" + +"@types/inquirer@^8.2.1": + "integrity" "sha512-wKW3SKIUMmltbykg4I5JzCVzUhkuD9trD6efAmYgN2MrSntY0SMRQzEnD3mkyJ/rv9NLbTC7g3hKKE86YwEDLw==" + "resolved" "https://registry.npmmirror.com/@types/inquirer/-/inquirer-8.2.1.tgz" + "version" "8.2.1" + dependencies: + "@types/through" "*" + "rxjs" "^7.2.0" + +"@types/intro.js@^3.0.2": + "integrity" "sha512-kow8REgIIG42atN9vAaIdpEqVzj6WzV9m0PII8oce+an4Lc3eyfQF32/FbabbGmfWuF7TceTdd+gh74kOrXkPw==" + "resolved" "https://registry.npmmirror.com/@types/intro.js/-/intro.js-3.0.2.tgz" + "version" "3.0.2" + +"@types/json-schema@^7.0.9": + "integrity" "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + "resolved" "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz" + "version" "7.0.11" + +"@types/lodash-es@^4.17.6": + "integrity" "sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==" + "resolved" "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.6.tgz" + "version" "4.17.6" + dependencies: + "@types/lodash" "*" + +"@types/lodash@*": + "integrity" "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + "resolved" "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.182.tgz" + "version" "4.14.182" + +"@types/minimatch@*": + "integrity" "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" + "resolved" "https://registry.npmmirror.com/@types/minimatch/-/minimatch-3.0.5.tgz" + "version" "3.0.5" + +"@types/minimist@^1.2.0": + "integrity" "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" + "resolved" "https://registry.npmmirror.com/@types/minimist/-/minimist-1.2.2.tgz" + "version" "1.2.2" + +"@types/mockjs@^1.0.4", "@types/mockjs@^1.0.6": + "integrity" "sha512-Yu5YlqbYZyqsd6LjO4e8ONJDN9pTSnciHDcRP4teNOh/au2b8helFhgRx+3w8xsTFEnwr9jtfTVJbAx+eYmlHA==" + "resolved" "https://registry.npmmirror.com/@types/mockjs/-/mockjs-1.0.6.tgz" + "version" "1.0.6" + +"@types/mousetrap@^1.6.4": + "integrity" "sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg==" + "resolved" "https://registry.npmmirror.com/@types/mousetrap/-/mousetrap-1.6.9.tgz" + "version" "1.6.9" + +"@types/node@*", "@types/node@^17.0.25", "@types/node@>=12": + "integrity" "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "resolved" "https://registry.npmmirror.com/@types/node/-/node-17.0.45.tgz" + "version" "17.0.45" + +"@types/node@^14.17.1": + "integrity" "sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q==" + "resolved" "https://registry.npmmirror.com/@types/node/-/node-14.18.21.tgz" + "version" "14.18.21" + +"@types/normalize-package-data@^2.4.0": + "integrity" "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" + "resolved" "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" + "version" "2.4.1" + +"@types/nprogress@^0.2.0": + "integrity" "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==" + "resolved" "https://registry.npmmirror.com/@types/nprogress/-/nprogress-0.2.0.tgz" + "version" "0.2.0" + +"@types/parse-json@^4.0.0": + "integrity" "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "resolved" "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" + +"@types/qs@^6.9.7": + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmmirror.com/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" + +"@types/resolve@1.17.1": + "integrity" "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==" + "resolved" "https://registry.npmmirror.com/@types/resolve/-/resolve-1.17.1.tgz" + "version" "1.17.1" + dependencies: + "@types/node" "*" + +"@types/showdown@^1.9.4": + "integrity" "sha512-50ehC3IAijfkvoNqmQ+VL73S7orOxmAK8ljQAFBv8o7G66lAZyxQj1L3BAv2dD86myLXI+sgKP1kcxAaxW356w==" + "resolved" "https://registry.npmmirror.com/@types/showdown/-/showdown-1.9.4.tgz" + "version" "1.9.4" + +"@types/sortablejs@^1.10.7": + "integrity" "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==" + "resolved" "https://registry.npmmirror.com/@types/sortablejs/-/sortablejs-1.13.0.tgz" + "version" "1.13.0" + +"@types/svgo@*", "@types/svgo@^2.6.1": + "integrity" "sha512-5sP0Xgo0dXppY0tbYF6TevB/1+tzFLuu71XXxC/zGvQAn9PW7y+DwtDO81g0ZUPye00K6tPwtsLDOpARa0mFcA==" + "resolved" "https://registry.npmmirror.com/@types/svgo/-/svgo-2.6.3.tgz" + "version" "2.6.3" + dependencies: + "@types/node" "*" + +"@types/tern@*": + "integrity" "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==" + "resolved" "https://registry.npmmirror.com/@types/tern/-/tern-0.23.4.tgz" + "version" "0.23.4" + dependencies: + "@types/estree" "*" + +"@types/through@*": + "integrity" "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==" + "resolved" "https://registry.npmmirror.com/@types/through/-/through-0.0.30.tgz" + "version" "0.0.30" + dependencies: + "@types/node" "*" + +"@types/tinycolor2@^1.4.2": + "integrity" "sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==" + "resolved" "https://registry.npmmirror.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz" + "version" "1.4.3" + +"@types/trusted-types@^2.0.2": + "integrity" "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + "resolved" "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.2.tgz" + "version" "2.0.2" + +"@types/web-bluetooth@^0.0.14": + "integrity" "sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==" + "resolved" "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz" + "version" "0.0.14" + +"@typescript-eslint/eslint-plugin@^5.20.0": + "integrity" "sha512-lftkqRoBvc28VFXEoRgyZuztyVUQ04JvUnATSPtIRFAccbXTWL6DEtXGYMcbg998kXw1NLUJm7rTQ9eUt+q6Ig==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/type-utils" "5.30.5" + "@typescript-eslint/utils" "5.30.5" + "debug" "^4.3.4" + "functional-red-black-tree" "^1.0.1" + "ignore" "^5.2.0" + "regexpp" "^3.2.0" + "semver" "^7.3.7" + "tsutils" "^3.21.0" + +"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.20.0": + "integrity" "sha512-zj251pcPXI8GO9NDKWWmygP6+UjwWmrdf9qMW/L/uQJBM/0XbU2inxe5io/234y/RCvwpKEYjZ6c1YrXERkK4Q==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/typescript-estree" "5.30.5" + "debug" "^4.3.4" + +"@typescript-eslint/scope-manager@5.30.5": + "integrity" "sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/visitor-keys" "5.30.5" + +"@typescript-eslint/type-utils@5.30.5": + "integrity" "sha512-k9+ejlv1GgwN1nN7XjVtyCgE0BTzhzT1YsQF0rv4Vfj2U9xnslBgMYYvcEYAFVdvhuEscELJsB7lDkN7WusErw==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/utils" "5.30.5" + "debug" "^4.3.4" + "tsutils" "^3.21.0" + +"@typescript-eslint/types@5.30.5": + "integrity" "sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.30.5.tgz" + "version" "5.30.5" + +"@typescript-eslint/typescript-estree@5.30.5": + "integrity" "sha512-qGTc7QZC801kbYjAr4AgdOfnokpwStqyhSbiQvqGBLixniAKyH+ib2qXIVo4P9NgGzwyfD9I0nlJN7D91E1VpQ==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/visitor-keys" "5.30.5" + "debug" "^4.3.4" + "globby" "^11.1.0" + "is-glob" "^4.0.3" + "semver" "^7.3.7" + "tsutils" "^3.21.0" + +"@typescript-eslint/utils@5.30.5": + "integrity" "sha512-o4SSUH9IkuA7AYIfAvatldovurqTAHrfzPApOZvdUq01hHojZojCFXx06D/aFpKCgWbMPRdJBWAC3sWp3itwTA==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.30.5" + "@typescript-eslint/types" "5.30.5" + "@typescript-eslint/typescript-estree" "5.30.5" + "eslint-scope" "^5.1.1" + "eslint-utils" "^3.0.0" + +"@typescript-eslint/visitor-keys@5.30.5": + "integrity" "sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA==" + "resolved" "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz" + "version" "5.30.5" + dependencies: + "@typescript-eslint/types" "5.30.5" + "eslint-visitor-keys" "^3.3.0" + +"@vitejs/plugin-legacy@^1.8.1": + "integrity" "sha512-NCOKU+pU+cxLMR9P9RTolEuOK+h+zYBXlknj+zGcKSj/NXBZYgA1GAH1FnO4zijoWRiTaiOm2ha9LQrELE7XHg==" + "resolved" "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-1.8.2.tgz" + "version" "1.8.2" + dependencies: + "@babel/standalone" "^7.17.11" + "core-js" "^3.22.3" + "magic-string" "^0.26.1" + "regenerator-runtime" "^0.13.9" + "systemjs" "^6.12.1" + +"@vitejs/plugin-vue-jsx@^1.3.10": + "integrity" "sha512-Cf5zznh4yNMiEMBfTOztaDVDmK1XXfgxClzOSUVUc8WAmHzogrCUeM8B05ABzuGtg0D1amfng+mUmSIOFGP3Pw==" + "resolved" "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-1.3.10.tgz" + "version" "1.3.10" + dependencies: + "@babel/core" "^7.17.9" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-transform-typescript" "^7.16.8" + "@rollup/pluginutils" "^4.2.0" + "@vue/babel-plugin-jsx" "^1.1.1" + "hash-sum" "^2.0.0" + +"@vitejs/plugin-vue@^2.3.1": + "integrity" "sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==" + "resolved" "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz" + "version" "2.3.3" + +"@volar/code-gen@0.33.9": + "integrity" "sha512-HI+XemEjvOv9uSjqaNXIL1brSTaBy9vRTcXqz9787nL5VKktI8aU1Zk4w9yJR88eTqw7mlPIdMaib7Ps/QPq8Q==" + "resolved" "https://registry.npmmirror.com/@volar/code-gen/-/code-gen-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/source-map" "0.33.9" + +"@volar/pug-language-service@0.33.9": + "integrity" "sha512-3oOV0HmoqkCyPAiHXSMoDzbLrSEQQv3d1dY/Lfo4H8hGoS8kUYJ958328TuLFc90yzsSmYnuvIux5AUok138pg==" + "resolved" "https://registry.npmmirror.com/@volar/pug-language-service/-/pug-language-service-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/code-gen" "0.33.9" + "@volar/shared" "0.33.9" + "@volar/source-map" "0.33.9" + "@volar/transforms" "0.33.9" + "pug-lexer" "^5.0.1" + "pug-parser" "^6.0.0" + "vscode-languageserver-textdocument" "^1.0.3" + "vscode-languageserver-types" "^3.17.0-next.6" + +"@volar/shared@0.33.9": + "integrity" "sha512-YqEBYT1SjyO+/W73lyKZlftumimsrYGvd98pHrIyvgc6HNhFnCcthRbyHskstjU6P8Bgj90mRl+7Sb29J+Z5ng==" + "resolved" "https://registry.npmmirror.com/@volar/shared/-/shared-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "upath" "^2.0.1" + "vscode-jsonrpc" "^8.0.0-next.5" + "vscode-uri" "^3.0.3" + +"@volar/source-map@0.33.9": + "integrity" "sha512-SE7dfumZ8pLsbj4DtiSDTg2/d/JT45nF51rUnuz1UNSBPEeXBexlzvz5EQ2AyrX0FjAAd2ijrRtirTk1a0SFhQ==" + "resolved" "https://registry.npmmirror.com/@volar/source-map/-/source-map-0.33.9.tgz" + "version" "0.33.9" + +"@volar/transforms@0.33.9": + "integrity" "sha512-qdc2d0ZW/G6jCx1pBmoMjMJTY245pZJjpPL/OCT3zgbDLGvLvqhowXxQYQd2YiNXqxJvbadEKviH5LiZL3sU9g==" + "resolved" "https://registry.npmmirror.com/@volar/transforms/-/transforms-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/shared" "0.33.9" + "vscode-languageserver-types" "^3.17.0-next.6" + +"@volar/vue-code-gen@0.33.9": + "integrity" "sha512-qRCXcBhm1kUlI06sW5zolavn8gqZdSC2eIWw7jgbW68K/cGlTyXHGGZgJPM9P22cF9pcrjV1ByehO18ke2u+aA==" + "resolved" "https://registry.npmmirror.com/@volar/vue-code-gen/-/vue-code-gen-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/code-gen" "0.33.9" + "@volar/source-map" "0.33.9" + "@vue/compiler-core" "^3.2.27" + "@vue/compiler-dom" "^3.2.27" + "@vue/shared" "^3.2.27" + +"@volar/vue-typescript@0.33.9": + "integrity" "sha512-UUViaQfzAV7z49TB+IsGCT6ls7zdEUib2N0L4k8U9nZbd2BQA4kcR9nyS/8oDOU5fK3ErP+pPlC+XzGGamKhcw==" + "resolved" "https://registry.npmmirror.com/@volar/vue-typescript/-/vue-typescript-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/code-gen" "0.33.9" + "@volar/pug-language-service" "0.33.9" + "@volar/source-map" "0.33.9" + "@volar/vue-code-gen" "0.33.9" + "@vue/compiler-sfc" "^3.2.27" + "@vue/reactivity" "^3.2.27" + +"@vue/babel-helper-vue-transform-on@^1.0.2": + "integrity" "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==" + "resolved" "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz" + "version" "1.0.2" + +"@vue/babel-plugin-jsx@^1.1.1": + "integrity" "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==" + "resolved" "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + "@vue/babel-helper-vue-transform-on" "^1.0.2" + "camelcase" "^6.0.0" + "html-tags" "^3.1.0" + "svg-tags" "^1.0.0" + +"@vue/compiler-core@^3.2.27", "@vue/compiler-core@3.2.37": + "integrity" "sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==" + "resolved" "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@babel/parser" "^7.16.4" + "@vue/shared" "3.2.37" + "estree-walker" "^2.0.2" + "source-map" "^0.6.1" + +"@vue/compiler-dom@^3.2.27", "@vue/compiler-dom@3.2.37": + "integrity" "sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==" + "resolved" "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/compiler-sfc@^3.2.27", "@vue/compiler-sfc@^3.2.29", "@vue/compiler-sfc@^3.2.33", "@vue/compiler-sfc@3.2.37": + "integrity" "sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==" + "resolved" "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-ssr" "3.2.37" + "@vue/reactivity-transform" "3.2.37" + "@vue/shared" "3.2.37" + "estree-walker" "^2.0.2" + "magic-string" "^0.25.7" + "postcss" "^8.1.10" + "source-map" "^0.6.1" + +"@vue/compiler-ssr@3.2.37": + "integrity" "sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==" + "resolved" "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/compiler-dom" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/devtools-api@^6.0.0-beta.7", "@vue/devtools-api@^6.1.0", "@vue/devtools-api@^6.1.4": + "integrity" "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==" + "resolved" "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.2.0.tgz" + "version" "6.2.0" + +"@vue/reactivity-transform@3.2.37": + "integrity" "sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==" + "resolved" "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@babel/parser" "^7.16.4" + "@vue/compiler-core" "3.2.37" + "@vue/shared" "3.2.37" + "estree-walker" "^2.0.2" + "magic-string" "^0.25.7" + +"@vue/reactivity@^3.2.27", "@vue/reactivity@3.2.37": + "integrity" "sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==" + "resolved" "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/shared" "3.2.37" + +"@vue/runtime-core@^3.2.33", "@vue/runtime-core@3.2.37": + "integrity" "sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==" + "resolved" "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/reactivity" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/runtime-dom@3.2.37": + "integrity" "sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==" + "resolved" "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/runtime-core" "3.2.37" + "@vue/shared" "3.2.37" + "csstype" "^2.6.8" + +"@vue/server-renderer@3.2.37": + "integrity" "sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==" + "resolved" "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/compiler-ssr" "3.2.37" + "@vue/shared" "3.2.37" + +"@vue/shared@^3.2.27", "@vue/shared@^3.2.33", "@vue/shared@3.2.37": + "integrity" "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" + "resolved" "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz" + "version" "3.2.37" + +"@vue/test-utils@^2.0.0-rc.21": + "integrity" "sha512-E2P4oXSaWDqTZNbmKZFVLrNN/siVN78YkEqs7pHryWerrlZR9bBFLWdJwRoguX45Ru6HxIflzKl4vQvwRMwm5g==" + "resolved" "https://registry.npmmirror.com/@vue/test-utils/-/test-utils-2.0.2.tgz" + "version" "2.0.2" + +"@vueuse/core@^8.3.0": + "integrity" "sha512-eKWehF6gsiLYxnYM/1xgDu16bKED7AWvkk56JIFNQes8OKgktr3Jc1wUy8UWIulrnwCXICUu9YUo+Wkq4r2JNw==" + "resolved" "https://registry.npmmirror.com/@vueuse/core/-/core-8.9.0.tgz" + "version" "8.9.0" + dependencies: + "@types/web-bluetooth" "^0.0.14" + "@vueuse/metadata" "8.9.0" + "@vueuse/shared" "8.9.0" + "vue-demi" "*" + +"@vueuse/metadata@8.9.0": + "integrity" "sha512-pjkIbQgJPRUrxK5/iXVKQFGC+OhJ+Vd6fhBsdwgj+NNJEHUotRliYymwdvhnEke/o+kkulT0xMvoK19nyPoiMw==" + "resolved" "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-8.9.0.tgz" + "version" "8.9.0" + +"@vueuse/shared@^8.3.0", "@vueuse/shared@8.9.0": + "integrity" "sha512-Pmu3Fopk/JJjN8b90uQuFrVCc/RPcSA/0zDFRTyn3YIhoB5ESna/1Sac5WZxK+n82g/ERXHHQTetGI9yxEdPfA==" + "resolved" "https://registry.npmmirror.com/@vueuse/shared/-/shared-8.9.0.tgz" + "version" "8.9.0" + dependencies: + "vue-demi" "*" + +"@windicss/config@1.8.6": + "integrity" "sha512-WVS41qUJtd44g2iWzTAE8tpgk8gD0yAr1RwwaWi7FAECKm3LVNMLOoToum9R/QKFE2n64EUVJpIvSUNby8rlhg==" + "resolved" "https://registry.npmmirror.com/@windicss/config/-/config-1.8.6.tgz" + "version" "1.8.6" + dependencies: + "debug" "^4.3.4" + "jiti" "^1.14.0" + "windicss" "^3.5.6" + +"@windicss/plugin-utils@1.8.6": + "integrity" "sha512-YY6EcUsgkosaQkIseFiIoHfU1H5boOAs/l74QWLI6ryNeHLMq2e04QVsFz+Rt+U8b8PRNxXPC8ADbxE05X7I7g==" + "resolved" "https://registry.npmmirror.com/@windicss/plugin-utils/-/plugin-utils-1.8.6.tgz" + "version" "1.8.6" + dependencies: + "@antfu/utils" "^0.5.2" + "@windicss/config" "1.8.6" + "debug" "^4.3.4" + "fast-glob" "^3.2.11" + "magic-string" "^0.26.2" + "micromatch" "^4.0.5" + "windicss" "^3.5.6" + +"@zxcvbn-ts/core@^2.0.1": + "integrity" "sha512-i3viYattwORK5liqS/d9WaIWSLki75oKVog5Elg9Ls9d8L6zKLwpAkj6PT/P4LZqJHIVRPnKjgajpP6SLerr6Q==" + "resolved" "https://registry.npmmirror.com/@zxcvbn-ts/core/-/core-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "fastest-levenshtein" "1.0.12" + +"acorn-jsx@^5.3.2": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn-walk@^8.1.1": + "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + "resolved" "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.2.0.tgz" + "version" "8.2.0" + +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^8.4.1", "acorn@^8.5.0", "acorn@^8.7.1": + "integrity" "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "resolved" "https://registry.npmmirror.com/acorn/-/acorn-8.7.1.tgz" + "version" "8.7.1" + +"acorn@^7.1.1": + "integrity" "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "resolved" "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz" + "version" "7.4.1" + +"add-stream@^1.0.0": + "integrity" "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==" + "resolved" "https://registry.npmmirror.com/add-stream/-/add-stream-1.0.0.tgz" + "version" "1.0.0" + +"adler-32@~1.3.0": + "integrity" "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==" + "resolved" "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz" + "version" "1.3.1" + +"aggregate-error@^3.0.0": + "integrity" "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==" + "resolved" "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "clean-stack" "^2.0.0" + "indent-string" "^4.0.0" + +"ajv@^6.10.0", "ajv@^6.12.4", "ajv@^6.12.6": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + dependencies: + "fast-deep-equal" "^3.1.1" + "fast-json-stable-stringify" "^2.0.0" + "json-schema-traverse" "^0.4.1" + "uri-js" "^4.2.2" + +"ajv@^8.0.1": + "integrity" "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==" + "resolved" "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz" + "version" "8.11.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"ajv@^8.6.0", "ajv@>=8": + "integrity" "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==" + "resolved" "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz" + "version" "8.11.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"ansi-escapes@^4.2.1", "ansi-escapes@^4.3.0": + "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==" + "resolved" "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + "version" "4.3.2" + dependencies: + "type-fest" "^0.21.3" + +"ansi-regex@^2.0.0": + "integrity" "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + "resolved" "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz" + "version" "2.1.1" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-regex@^6.0.1": + "integrity" "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + "resolved" "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz" + "version" "6.0.1" + +"ansi-styles@^2.2.1": + "integrity" "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + "resolved" "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz" + "version" "2.2.1" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"ansi-styles@^6.0.0": + "integrity" "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==" + "resolved" "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.1.0.tgz" + "version" "6.1.0" + +"ant-design-vue@^3.2.0": + "integrity" "sha512-fnZJpAf4tYAPGBALD9dv8VBmeqfJ+xPt87DfgY1/JI6x3hn6Gfge7voF1GkS0yVT0zLyzc2aTWkDVFWKB5iupA==" + "resolved" "https://registry.npmmirror.com/ant-design-vue/-/ant-design-vue-3.2.9.tgz" + "version" "3.2.9" + dependencies: + "@ant-design/colors" "^6.0.0" + "@ant-design/icons-vue" "^6.1.0" + "@babel/runtime" "^7.10.5" + "@ctrl/tinycolor" "^3.4.0" + "@simonwep/pickr" "~1.8.0" + "array-tree-filter" "^2.1.0" + "async-validator" "^4.0.0" + "dayjs" "^1.10.5" + "dom-align" "^1.12.1" + "dom-scroll-into-view" "^2.0.0" + "lodash" "^4.17.21" + "lodash-es" "^4.17.15" + "resize-observer-polyfill" "^1.5.1" + "scroll-into-view-if-needed" "^2.2.25" + "shallow-equal" "^1.0.0" + "vue-types" "^3.0.0" + "warning" "^4.0.0" + +"anymatch@~3.1.2": + "integrity" "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==" + "resolved" "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"arch@^2.1.0": + "integrity" "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==" + "resolved" "https://registry.npmmirror.com/arch/-/arch-2.2.0.tgz" + "version" "2.2.0" + +"archive-type@^4.0.0": + "integrity" "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==" + "resolved" "https://registry.npmmirror.com/archive-type/-/archive-type-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "file-type" "^4.2.0" + +"arg@^4.1.0": + "integrity" "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "resolved" "https://registry.npmmirror.com/arg/-/arg-4.1.3.tgz" + "version" "4.1.3" + +"argparse@^2.0.1": + "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "resolved" "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz" + "version" "2.0.1" + +"arr-diff@^4.0.0": + "integrity" "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + "resolved" "https://registry.npmmirror.com/arr-diff/-/arr-diff-4.0.0.tgz" + "version" "4.0.0" + +"arr-flatten@^1.1.0": + "integrity" "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "resolved" "https://registry.npmmirror.com/arr-flatten/-/arr-flatten-1.1.0.tgz" + "version" "1.1.0" + +"arr-union@^3.1.0": + "integrity" "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" + "resolved" "https://registry.npmmirror.com/arr-union/-/arr-union-3.1.0.tgz" + "version" "3.1.0" + +"array-find-index@^1.0.1": + "integrity" "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==" + "resolved" "https://registry.npmmirror.com/array-find-index/-/array-find-index-1.0.2.tgz" + "version" "1.0.2" + +"array-ify@^1.0.0": + "integrity" "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==" + "resolved" "https://registry.npmmirror.com/array-ify/-/array-ify-1.0.0.tgz" + "version" "1.0.0" + +"array-tree-filter@^2.1.0": + "integrity" "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + "resolved" "https://registry.npmmirror.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz" + "version" "2.1.0" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"array-unique@^0.3.2": + "integrity" "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + "resolved" "https://registry.npmmirror.com/array-unique/-/array-unique-0.3.2.tgz" + "version" "0.3.2" + +"arrify@^1.0.1": + "integrity" "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==" + "resolved" "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz" + "version" "1.0.1" + +"assign-symbols@^1.0.0": + "integrity" "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" + "resolved" "https://registry.npmmirror.com/assign-symbols/-/assign-symbols-1.0.0.tgz" + "version" "1.0.0" + +"astral-regex@^2.0.0": + "integrity" "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "resolved" "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz" + "version" "2.0.0" + +"async-validator@^4.0.0": + "integrity" "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + "resolved" "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz" + "version" "4.2.5" + +"async@^3.2.3": + "integrity" "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "resolved" "https://registry.npmmirror.com/async/-/async-3.2.4.tgz" + "version" "3.2.4" + +"at-least-node@^1.0.0": + "integrity" "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "resolved" "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz" + "version" "1.0.0" + +"atob@^2.1.2": + "integrity" "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "resolved" "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz" + "version" "2.1.2" + +"autoprefixer@^10.4.4": + "integrity" "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==" + "resolved" "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.7.tgz" + "version" "10.4.7" + dependencies: + "browserslist" "^4.20.3" + "caniuse-lite" "^1.0.30001335" + "fraction.js" "^4.2.0" + "normalize-range" "^0.1.2" + "picocolors" "^1.0.0" + "postcss-value-parser" "^4.2.0" + +"axios@^0.21.4": + "integrity" "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==" + "resolved" "https://registry.npmmirror.com/axios/-/axios-0.21.4.tgz" + "version" "0.21.4" + dependencies: + "follow-redirects" "^1.14.0" + +"axios@^0.26.0", "axios@^0.26.1": + "integrity" "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==" + "resolved" "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz" + "version" "0.26.1" + dependencies: + "follow-redirects" "^1.14.8" + +"babel-plugin-dynamic-import-node@^2.3.3": + "integrity" "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==" + "resolved" "https://registry.npmmirror.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + "version" "2.3.3" + dependencies: + "object.assign" "^4.1.0" + +"babel-plugin-polyfill-corejs2@^0.3.1": + "integrity" "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==" + "resolved" "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + "semver" "^6.1.1" + +"babel-plugin-polyfill-corejs3@^0.5.2": + "integrity" "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==" + "resolved" "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + "core-js-compat" "^3.21.0" + +"babel-plugin-polyfill-regenerator@^0.3.1": + "integrity" "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==" + "resolved" "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"balanced-match@^2.0.0": + "integrity" "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==" + "resolved" "https://registry.npmmirror.com/balanced-match/-/balanced-match-2.0.0.tgz" + "version" "2.0.0" + +"base@^0.11.1": + "integrity" "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==" + "resolved" "https://registry.npmmirror.com/base/-/base-0.11.2.tgz" + "version" "0.11.2" + dependencies: + "cache-base" "^1.0.1" + "class-utils" "^0.3.5" + "component-emitter" "^1.2.1" + "define-property" "^1.0.0" + "isobject" "^3.0.1" + "mixin-deep" "^1.2.0" + "pascalcase" "^0.1.1" + +"base64-js@^1.3.1": + "integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "resolved" "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz" + "version" "1.5.1" + +"before-after-hook@^2.2.0": + "integrity" "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + "resolved" "https://registry.npmmirror.com/before-after-hook/-/before-after-hook-2.2.2.tgz" + "version" "2.2.2" + +"big.js@^5.2.2": + "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "resolved" "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz" + "version" "5.2.2" + +"bin-build@^3.0.0": + "integrity" "sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==" + "resolved" "https://registry.npmmirror.com/bin-build/-/bin-build-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "decompress" "^4.0.0" + "download" "^6.2.2" + "execa" "^0.7.0" + "p-map-series" "^1.0.0" + "tempfile" "^2.0.0" + +"bin-check@^4.1.0": + "integrity" "sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==" + "resolved" "https://registry.npmmirror.com/bin-check/-/bin-check-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "execa" "^0.7.0" + "executable" "^4.1.0" + +"bin-version-check@^4.0.0": + "integrity" "sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==" + "resolved" "https://registry.npmmirror.com/bin-version-check/-/bin-version-check-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "bin-version" "^3.0.0" + "semver" "^5.6.0" + "semver-truncate" "^1.1.2" + +"bin-version@^3.0.0": + "integrity" "sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==" + "resolved" "https://registry.npmmirror.com/bin-version/-/bin-version-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "execa" "^1.0.0" + "find-versions" "^3.0.0" + +"bin-wrapper@^4.0.0": + "integrity" "sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==" + "resolved" "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "bin-check" "^4.1.0" + "bin-version-check" "^4.0.0" + "download" "^7.1.0" + "import-lazy" "^3.1.0" + "os-filter-obj" "^2.0.0" + "pify" "^4.0.1" + +"bin-wrapper@^4.0.1": + "integrity" "sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==" + "resolved" "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "bin-check" "^4.1.0" + "bin-version-check" "^4.0.0" + "download" "^7.1.0" + "import-lazy" "^3.1.0" + "os-filter-obj" "^2.0.0" + "pify" "^4.0.1" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"bl@^1.0.0": + "integrity" "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==" + "resolved" "https://registry.npmmirror.com/bl/-/bl-1.2.3.tgz" + "version" "1.2.3" + dependencies: + "readable-stream" "^2.3.5" + "safe-buffer" "^5.1.1" + +"bl@^4.1.0": + "integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==" + "resolved" "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "buffer" "^5.5.0" + "inherits" "^2.0.4" + "readable-stream" "^3.4.0" + +"bluebird@^3.5.0": + "integrity" "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "resolved" "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz" + "version" "3.7.2" + +"boolbase@^1.0.0": + "integrity" "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "resolved" "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz" + "version" "1.0.0" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"brace-expansion@^2.0.1": + "integrity" "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==" + "resolved" "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "balanced-match" "^1.0.0" + +"braces@^2.2.2": + "integrity" "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==" + "resolved" "https://registry.npmmirror.com/braces/-/braces-2.3.2.tgz" + "version" "2.3.2" + dependencies: + "arr-flatten" "^1.1.0" + "array-unique" "^0.3.2" + "extend-shallow" "^2.0.1" + "fill-range" "^4.0.0" + "isobject" "^3.0.1" + "repeat-element" "^1.1.2" + "snapdragon" "^0.8.1" + "snapdragon-node" "^2.0.1" + "split-string" "^3.0.2" + "to-regex" "^3.0.1" + +"braces@^3.0.2", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"browserslist@^4.20.2", "browserslist@^4.20.3", "browserslist@^4.21.0", "browserslist@>= 4.21.0": + "integrity" "sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ==" + "resolved" "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.1.tgz" + "version" "4.21.1" + dependencies: + "caniuse-lite" "^1.0.30001359" + "electron-to-chromium" "^1.4.172" + "node-releases" "^2.0.5" + "update-browserslist-db" "^1.0.4" + +"buffer-alloc-unsafe@^1.1.0": + "integrity" "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + "resolved" "https://registry.npmmirror.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz" + "version" "1.1.0" + +"buffer-alloc@^1.2.0": + "integrity" "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==" + "resolved" "https://registry.npmmirror.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "buffer-alloc-unsafe" "^1.1.0" + "buffer-fill" "^1.0.0" + +"buffer-crc32@~0.2.3": + "integrity" "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + "resolved" "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz" + "version" "0.2.13" + +"buffer-fill@^1.0.0": + "integrity" "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + "resolved" "https://registry.npmmirror.com/buffer-fill/-/buffer-fill-1.0.0.tgz" + "version" "1.0.0" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"buffer@^5.2.1", "buffer@^5.5.0": + "integrity" "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==" + "resolved" "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz" + "version" "5.7.1" + dependencies: + "base64-js" "^1.3.1" + "ieee754" "^1.1.13" + +"builtin-modules@^3.0.0", "builtin-modules@^3.1.0": + "integrity" "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + "resolved" "https://registry.npmmirror.com/builtin-modules/-/builtin-modules-3.3.0.tgz" + "version" "3.3.0" + +"builtins@^4.0.0": + "integrity" "sha512-1bPRZQtmKaO6h7qV1YHXNtr6nCK28k0Zo95KM4dXfILcZZwoHJBN1m3lfLv9LPkcOZlrSr+J1bzMaZFO98Yq0w==" + "resolved" "https://registry.npmmirror.com/builtins/-/builtins-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "semver" "^7.0.0" + +"cache-base@^1.0.1": + "integrity" "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==" + "resolved" "https://registry.npmmirror.com/cache-base/-/cache-base-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "collection-visit" "^1.0.0" + "component-emitter" "^1.2.1" + "get-value" "^2.0.6" + "has-value" "^1.0.0" + "isobject" "^3.0.1" + "set-value" "^2.0.0" + "to-object-path" "^0.3.0" + "union-value" "^1.0.0" + "unset-value" "^1.0.0" + +"cacheable-request@^2.1.1": + "integrity" "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==" + "resolved" "https://registry.npmmirror.com/cacheable-request/-/cacheable-request-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "clone-response" "1.0.2" + "get-stream" "3.0.0" + "http-cache-semantics" "3.8.1" + "keyv" "3.0.0" + "lowercase-keys" "1.0.0" + "normalize-url" "2.0.1" + "responselike" "1.0.2" + +"call-bind@^1.0.0", "call-bind@^1.0.2": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camel-case@^4.1.2": + "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" + "resolved" "https://registry.npmmirror.com/camel-case/-/camel-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "pascal-case" "^3.1.2" + "tslib" "^2.0.3" + +"camelcase-keys@^2.0.0": + "integrity" "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==" + "resolved" "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "camelcase" "^2.0.0" + "map-obj" "^1.0.0" + +"camelcase-keys@^6.2.2": + "integrity" "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==" + "resolved" "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz" + "version" "6.2.2" + dependencies: + "camelcase" "^5.3.1" + "map-obj" "^4.0.0" + "quick-lru" "^4.0.1" + +"camelcase@^2.0.0": + "integrity" "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==" + "resolved" "https://registry.npmmirror.com/camelcase/-/camelcase-2.1.1.tgz" + "version" "2.1.1" + +"camelcase@^5.3.1": + "integrity" "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "resolved" "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz" + "version" "5.3.1" + +"camelcase@^6.0.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-lite@^1.0.30001335", "caniuse-lite@^1.0.30001359": + "integrity" "sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz" + "version" "1.0.30001460" + +"capital-case@^1.0.4": + "integrity" "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==" + "resolved" "https://registry.npmmirror.com/capital-case/-/capital-case-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + "upper-case-first" "^2.0.2" + +"caw@^2.0.0", "caw@^2.0.1": + "integrity" "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==" + "resolved" "https://registry.npmmirror.com/caw/-/caw-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "get-proxy" "^2.0.0" + "isurl" "^1.0.0-alpha5" + "tunnel-agent" "^0.6.0" + "url-to-options" "^1.0.1" + +"cfb@~1.2.1": + "integrity" "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==" + "resolved" "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz" + "version" "1.2.2" + dependencies: + "adler-32" "~1.3.0" + "crc-32" "~1.2.0" + +"chalk@^1.0.0": + "integrity" "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==" + "resolved" "https://registry.npmmirror.com/chalk/-/chalk-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "ansi-styles" "^2.2.1" + "escape-string-regexp" "^1.0.2" + "has-ansi" "^2.0.0" + "strip-ansi" "^3.0.0" + "supports-color" "^2.0.0" + +"chalk@^1.1.3": + "integrity" "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==" + "resolved" "https://registry.npmmirror.com/chalk/-/chalk-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "ansi-styles" "^2.2.1" + "escape-string-regexp" "^1.0.2" + "has-ansi" "^2.0.0" + "strip-ansi" "^3.0.0" + "supports-color" "^2.0.0" + +"chalk@^2.0.0": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^2.4.1": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.0.0", "chalk@^4.0.2", "chalk@^4.1.0", "chalk@^4.1.1", "chalk@^4.1.2": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"change-case@^4.1.2": + "integrity" "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==" + "resolved" "https://registry.npmmirror.com/change-case/-/change-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "camel-case" "^4.1.2" + "capital-case" "^1.0.4" + "constant-case" "^3.0.4" + "dot-case" "^3.0.4" + "header-case" "^2.0.4" + "no-case" "^3.0.4" + "param-case" "^3.0.4" + "pascal-case" "^3.1.2" + "path-case" "^3.0.4" + "sentence-case" "^3.0.4" + "snake-case" "^3.0.4" + "tslib" "^2.0.3" + +"character-parser@^2.2.0": + "integrity" "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==" + "resolved" "https://registry.npmmirror.com/character-parser/-/character-parser-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-regex" "^1.0.3" + +"chardet@^0.7.0": + "integrity" "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + "resolved" "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz" + "version" "0.7.0" + +"chokidar@^3.5.2": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + dependencies: + "anymatch" "~3.1.2" + "braces" "~3.0.2" + "glob-parent" "~5.1.2" + "is-binary-path" "~2.1.0" + "is-glob" "~4.0.1" + "normalize-path" "~3.0.0" + "readdirp" "~3.6.0" + optionalDependencies: + "fsevents" "~2.3.2" + +"class-utils@^0.3.5": + "integrity" "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==" + "resolved" "https://registry.npmmirror.com/class-utils/-/class-utils-0.3.6.tgz" + "version" "0.3.6" + dependencies: + "arr-union" "^3.1.0" + "define-property" "^0.2.5" + "isobject" "^3.0.0" + "static-extend" "^0.1.1" + +"clean-css@^5.1.2", "clean-css@^5.2.2": + "integrity" "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==" + "resolved" "https://registry.npmmirror.com/clean-css/-/clean-css-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "source-map" "~0.6.0" + +"clean-stack@^2.0.0": + "integrity" "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + "resolved" "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz" + "version" "2.2.0" + +"cli-cursor@^3.1.0": + "integrity" "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==" + "resolved" "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "restore-cursor" "^3.1.0" + +"cli-spinners@^2.5.0": + "integrity" "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + "resolved" "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.6.1.tgz" + "version" "2.6.1" + +"cli-truncate@^2.1.0": + "integrity" "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==" + "resolved" "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "slice-ansi" "^3.0.0" + "string-width" "^4.2.0" + +"cli-truncate@^3.1.0": + "integrity" "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==" + "resolved" "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "slice-ansi" "^5.0.0" + "string-width" "^5.0.0" + +"cli-width@^3.0.0": + "integrity" "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + "resolved" "https://registry.npmmirror.com/cli-width/-/cli-width-3.0.0.tgz" + "version" "3.0.0" + +"cliui@^7.0.2": + "integrity" "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==" + "resolved" "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz" + "version" "7.0.4" + dependencies: + "string-width" "^4.2.0" + "strip-ansi" "^6.0.0" + "wrap-ansi" "^7.0.0" + +"clone-regexp@^2.1.0": + "integrity" "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==" + "resolved" "https://registry.npmmirror.com/clone-regexp/-/clone-regexp-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-regexp" "^2.0.0" + +"clone-response@1.0.2": + "integrity" "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==" + "resolved" "https://registry.npmmirror.com/clone-response/-/clone-response-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "mimic-response" "^1.0.0" + +"clone@^1.0.2": + "integrity" "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + "resolved" "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz" + "version" "1.0.4" + +"clone@^2.1.1": + "integrity" "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + "resolved" "https://registry.npmmirror.com/clone/-/clone-2.1.2.tgz" + "version" "2.1.2" + +"codemirror@^5.65.3": + "integrity" "sha512-zNihMSMoDxK9Gqv9oEyDT8oM51rcRrQ+IEo2zyS48gJByBq5Fj8XuNEguMra+MuIOuh6lkpnLUJeL70DoTt6yw==" + "resolved" "https://registry.npmmirror.com/codemirror/-/codemirror-5.65.6.tgz" + "version" "5.65.6" + +"codepage@~1.15.0": + "integrity" "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==" + "resolved" "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz" + "version" "1.15.0" + +"collection-visit@^1.0.0": + "integrity" "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==" + "resolved" "https://registry.npmmirror.com/collection-visit/-/collection-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "map-visit" "^1.0.0" + "object-visit" "^1.0.0" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "resolved" "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colord@^2.9.2": + "integrity" "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==" + "resolved" "https://registry.npmmirror.com/colord/-/colord-2.9.2.tgz" + "version" "2.9.2" + +"colorette@^2.0.16": + "integrity" "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + "resolved" "https://registry.npmmirror.com/colorette/-/colorette-2.0.19.tgz" + "version" "2.0.19" + +"commander@*", "commander@^8.3.0": + "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "resolved" "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz" + "version" "8.3.0" + +"commander@^2.20.0": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^2.8.1": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^7.2.0": + "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "resolved" "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz" + "version" "7.2.0" + +"commander@^9.0.0": + "integrity" "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==" + "resolved" "https://registry.npmmirror.com/commander/-/commander-9.3.0.tgz" + "version" "9.3.0" + +"common-tags@^1.8.0": + "integrity" "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + "resolved" "https://registry.npmmirror.com/common-tags/-/common-tags-1.8.2.tgz" + "version" "1.8.2" + +"compare-func@^2.0.0": + "integrity" "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==" + "resolved" "https://registry.npmmirror.com/compare-func/-/compare-func-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "array-ify" "^1.0.0" + "dot-prop" "^5.1.0" + +"component-emitter@^1.2.1": + "integrity" "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "resolved" "https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.0.tgz" + "version" "1.3.0" + +"compute-scroll-into-view@^1.0.17": + "integrity" "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + "resolved" "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz" + "version" "1.0.17" + +"concat-map@0.0.1": + "integrity" "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "resolved" "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"config-chain@^1.1.11": + "integrity" "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==" + "resolved" "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz" + "version" "1.1.13" + dependencies: + "ini" "^1.3.4" + "proto-list" "~1.2.1" + +"connect-history-api-fallback@^1.6.0": + "integrity" "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" + "resolved" "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz" + "version" "1.6.0" + +"connect@^3.7.0": + "integrity" "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==" + "resolved" "https://registry.npmmirror.com/connect/-/connect-3.7.0.tgz" + "version" "3.7.0" + dependencies: + "debug" "2.6.9" + "finalhandler" "1.1.2" + "parseurl" "~1.3.3" + "utils-merge" "1.0.1" + +"consola@^2.15.3": + "integrity" "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + "resolved" "https://registry.npmmirror.com/consola/-/consola-2.15.3.tgz" + "version" "2.15.3" + +"console-stream@^0.1.1": + "integrity" "sha512-QC/8l9e6ofi6nqZ5PawlDgzmMw3OxIXtvolBzap/F4UDBJlDaZRSNbL/lb41C29FcbSJncBFlJFj2WJoNyZRfQ==" + "resolved" "https://registry.npmmirror.com/console-stream/-/console-stream-0.1.1.tgz" + "version" "0.1.1" + +"console@^0.7.2": + "integrity" "sha512-+JSDwGunA4MTEgAV/4VBKwUHonP8CzJ/6GIuwPi6acKFqFfHUdSGCm89ZxZ5FfGWdZfkdgAroy5bJ5FSeN/t4g==" + "resolved" "https://registry.npmmirror.com/console/-/console-0.7.2.tgz" + "version" "0.7.2" + +"constant-case@^3.0.4": + "integrity" "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==" + "resolved" "https://registry.npmmirror.com/constant-case/-/constant-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + "upper-case" "^2.0.2" + +"content-disposition@^0.5.2": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"conventional-changelog-angular@^5.0.11", "conventional-changelog-angular@^5.0.12": + "integrity" "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz" + "version" "5.0.13" + dependencies: + "compare-func" "^2.0.0" + "q" "^1.5.1" + +"conventional-changelog-atom@^2.0.8": + "integrity" "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz" + "version" "2.0.8" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-cli@^2.2.2": + "integrity" "sha512-8grMV5Jo8S0kP3yoMeJxV2P5R6VJOqK72IiSV9t/4H5r/HiRqEBQ83bYGuz4Yzfdj4bjaAEhZN/FFbsFXr5bOA==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-cli/-/conventional-changelog-cli-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "add-stream" "^1.0.0" + "conventional-changelog" "^3.1.24" + "lodash" "^4.17.15" + "meow" "^8.0.0" + "tempfile" "^3.0.0" + +"conventional-changelog-codemirror@^2.0.8": + "integrity" "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz" + "version" "2.0.8" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-conventionalcommits@^4.3.1", "conventional-changelog-conventionalcommits@^4.5.0": + "integrity" "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz" + "version" "4.6.3" + dependencies: + "compare-func" "^2.0.0" + "lodash" "^4.17.15" + "q" "^1.5.1" + +"conventional-changelog-core@^4.2.1": + "integrity" "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz" + "version" "4.2.4" + dependencies: + "add-stream" "^1.0.0" + "conventional-changelog-writer" "^5.0.0" + "conventional-commits-parser" "^3.2.0" + "dateformat" "^3.0.0" + "get-pkg-repo" "^4.0.0" + "git-raw-commits" "^2.0.8" + "git-remote-origin-url" "^2.0.0" + "git-semver-tags" "^4.1.1" + "lodash" "^4.17.15" + "normalize-package-data" "^3.0.0" + "q" "^1.5.1" + "read-pkg" "^3.0.0" + "read-pkg-up" "^3.0.0" + "through2" "^4.0.0" + +"conventional-changelog-ember@^2.0.9": + "integrity" "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz" + "version" "2.0.9" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-eslint@^3.0.9": + "integrity" "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz" + "version" "3.0.9" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-express@^2.0.6": + "integrity" "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz" + "version" "2.0.6" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-jquery@^3.0.11": + "integrity" "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz" + "version" "3.0.11" + dependencies: + "q" "^1.5.1" + +"conventional-changelog-jshint@^2.0.9": + "integrity" "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz" + "version" "2.0.9" + dependencies: + "compare-func" "^2.0.0" + "q" "^1.5.1" + +"conventional-changelog-preset-loader@^2.3.4": + "integrity" "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz" + "version" "2.3.4" + +"conventional-changelog-writer@^5.0.0": + "integrity" "sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ==" + "resolved" "https://registry.npmmirror.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "conventional-commits-filter" "^2.0.7" + "dateformat" "^3.0.0" + "handlebars" "^4.7.7" + "json-stringify-safe" "^5.0.1" + "lodash" "^4.17.15" + "meow" "^8.0.0" + "semver" "^6.0.0" + "split" "^1.0.0" + "through2" "^4.0.0" + +"conventional-changelog@^3.1.24": + "integrity" "sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ==" + "resolved" "https://registry.npmmirror.com/conventional-changelog/-/conventional-changelog-3.1.25.tgz" + "version" "3.1.25" + dependencies: + "conventional-changelog-angular" "^5.0.12" + "conventional-changelog-atom" "^2.0.8" + "conventional-changelog-codemirror" "^2.0.8" + "conventional-changelog-conventionalcommits" "^4.5.0" + "conventional-changelog-core" "^4.2.1" + "conventional-changelog-ember" "^2.0.9" + "conventional-changelog-eslint" "^3.0.9" + "conventional-changelog-express" "^2.0.6" + "conventional-changelog-jquery" "^3.0.11" + "conventional-changelog-jshint" "^2.0.9" + "conventional-changelog-preset-loader" "^2.3.4" + +"conventional-commits-filter@^2.0.7": + "integrity" "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==" + "resolved" "https://registry.npmmirror.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "lodash.ismatch" "^4.4.0" + "modify-values" "^1.0.0" + +"conventional-commits-parser@^3.2.0", "conventional-commits-parser@^3.2.2": + "integrity" "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==" + "resolved" "https://registry.npmmirror.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz" + "version" "3.2.4" + dependencies: + "is-text-path" "^1.0.1" + "JSONStream" "^1.0.4" + "lodash" "^4.17.15" + "meow" "^8.0.0" + "split2" "^3.0.0" + "through2" "^4.0.0" + +"convert-source-map@^1.7.0": + "integrity" "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==" + "resolved" "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.8.0.tgz" + "version" "1.8.0" + dependencies: + "safe-buffer" "~5.1.1" + +"copy-anything@^2.0.1": + "integrity" "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==" + "resolved" "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz" + "version" "2.0.6" + dependencies: + "is-what" "^3.14.1" + +"copy-descriptor@^0.1.0": + "integrity" "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==" + "resolved" "https://registry.npmmirror.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz" + "version" "0.1.1" + +"core-js-compat@^3.21.0", "core-js-compat@^3.22.1": + "integrity" "sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw==" + "resolved" "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.23.3.tgz" + "version" "3.23.3" + dependencies: + "browserslist" "^4.21.0" + "semver" "7.0.0" + +"core-js@^3.15.1", "core-js@^3.22.3": + "integrity" "sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q==" + "resolved" "https://registry.npmmirror.com/core-js/-/core-js-3.23.3.tgz" + "version" "3.23.3" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"cors@^2.8.5": + "integrity" "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==" + "resolved" "https://registry.npmmirror.com/cors/-/cors-2.8.5.tgz" + "version" "2.8.5" + dependencies: + "object-assign" "^4" + "vary" "^1" + +"cosmiconfig-typescript-loader@^2.0.0": + "integrity" "sha512-KmE+bMjWMXJbkWCeY4FJX/npHuZPNr9XF9q9CIQ/bpFwi1qHfCmSiKarrCcRa0LO4fWjk93pVoeRtJAkTGcYNw==" + "resolved" "https://registry.npmmirror.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "cosmiconfig" "^7" + "ts-node" "^10.8.1" + +"cosmiconfig@^7", "cosmiconfig@^7.0.0", "cosmiconfig@^7.0.1": + "integrity" "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==" + "resolved" "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "@types/parse-json" "^4.0.0" + "import-fresh" "^3.2.1" + "parse-json" "^5.0.0" + "path-type" "^4.0.0" + "yaml" "^1.10.0" + +"crc-32@~1.2.0", "crc-32@~1.2.1": + "integrity" "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" + "resolved" "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz" + "version" "1.2.2" + +"create-require@^1.1.0": + "integrity" "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "resolved" "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz" + "version" "1.1.1" + +"cropperjs@^1.5.12": + "integrity" "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==" + "resolved" "https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.12.tgz" + "version" "1.5.12" + +"cross-env@^7.0.3": + "integrity" "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==" + "resolved" "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "cross-spawn" "^7.0.1" + +"cross-fetch@^3.1.5": + "integrity" "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==" + "resolved" "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.5.tgz" + "version" "3.1.5" + dependencies: + "node-fetch" "2.6.7" + +"cross-spawn@^5.0.1": + "integrity" "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==" + "resolved" "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "lru-cache" "^4.0.1" + "shebang-command" "^1.2.0" + "which" "^1.2.9" + +"cross-spawn@^6.0.0": + "integrity" "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==" + "resolved" "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz" + "version" "6.0.5" + dependencies: + "nice-try" "^1.0.4" + "path-key" "^2.0.1" + "semver" "^5.5.0" + "shebang-command" "^1.2.0" + "which" "^1.2.9" + +"cross-spawn@^6.0.5": + "integrity" "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==" + "resolved" "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz" + "version" "6.0.5" + dependencies: + "nice-try" "^1.0.4" + "path-key" "^2.0.1" + "semver" "^5.5.0" + "shebang-command" "^1.2.0" + "which" "^1.2.9" + +"cross-spawn@^7.0.0", "cross-spawn@^7.0.1", "cross-spawn@^7.0.2", "cross-spawn@^7.0.3": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"crypto-js@^4.1.1": + "integrity" "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + "resolved" "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.1.1.tgz" + "version" "4.1.1" + +"crypto-random-string@^2.0.0": + "integrity" "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + "resolved" "https://registry.npmmirror.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + "version" "2.0.0" + +"css-functions-list@^3.1.0": + "integrity" "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==" + "resolved" "https://registry.npmmirror.com/css-functions-list/-/css-functions-list-3.1.0.tgz" + "version" "3.1.0" + +"css-select@^4.1.3", "css-select@^4.2.1": + "integrity" "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==" + "resolved" "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^6.0.1" + "domhandler" "^4.3.1" + "domutils" "^2.8.0" + "nth-check" "^2.0.1" + +"css-tree@^1.1.2", "css-tree@^1.1.3": + "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" + "resolved" "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "mdn-data" "2.0.14" + "source-map" "^0.6.1" + +"css-what@^6.0.1": + "integrity" "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + "resolved" "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz" + "version" "6.1.0" + +"cssesc@^3.0.0": + "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "resolved" "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz" + "version" "3.0.0" + +"csso@^4.2.0": + "integrity" "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==" + "resolved" "https://registry.npmmirror.com/csso/-/csso-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "css-tree" "^1.1.2" + +"csstype@^2.6.8": + "integrity" "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + "resolved" "https://registry.npmmirror.com/csstype/-/csstype-2.6.20.tgz" + "version" "2.6.20" + +"currently-unhandled@^0.4.1": + "integrity" "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==" + "resolved" "https://registry.npmmirror.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz" + "version" "0.4.1" + dependencies: + "array-find-index" "^1.0.1" + +"cwebp-bin@^5.0.0": + "integrity" "sha512-BsPKStaNr98zfxwejWWLIGELbPERULJoD2v5ijvpeutSAGsegX7gmABgnkRK7MUucCPROXXfaPqkLAwI509JzA==" + "resolved" "https://registry.npmmirror.com/cwebp-bin/-/cwebp-bin-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.1" + "logalot" "^2.1.0" + +"cz-git@^1.3.11": + "integrity" "sha512-AToFbLeqhPU/fNM6gH8dX4c5pIIFzHTUhS1FkDaNjsCylrjYPYAMyRUczn4eeAcxtqy1bctIQDOEOwPRTnUs5A==" + "resolved" "https://registry.npmjs.org/cz-git/-/cz-git-1.5.3.tgz" + "version" "1.5.3" + +"czg@^1.3.11": + "integrity" "sha512-prQB6tiJdRhw59Ec5t8lZPmhwL2ZmUIwmjF7+V9mB/2mMu1Tj9IcdNn/6/+nb6v/CSIT6kAIGpLb+hC2l5UuqA==" + "resolved" "https://registry.npmjs.org/czg/-/czg-1.5.3.tgz" + "version" "1.5.3" + +"dargs@^7.0.0": + "integrity" "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==" + "resolved" "https://registry.npmmirror.com/dargs/-/dargs-7.0.0.tgz" + "version" "7.0.0" + +"dateformat@^3.0.0": + "integrity" "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" + "resolved" "https://registry.npmmirror.com/dateformat/-/dateformat-3.0.3.tgz" + "version" "3.0.3" + +"dayjs@^1.10.5", "dayjs@^1.11.1": + "integrity" "sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==" + "resolved" "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz" + "version" "1.11.3" + +"debug@^2.2.0": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^2.3.3": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.2.6": + "integrity" "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" + "resolved" "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz" + "version" "3.2.7" + dependencies: + "ms" "^2.1.1" + +"debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.2", "debug@^4.3.3", "debug@^4.3.4": + "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" + "resolved" "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz" + "version" "4.3.4" + dependencies: + "ms" "2.1.2" + +"debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"decamelize-keys@^1.1.0": + "integrity" "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==" + "resolved" "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "decamelize" "^1.1.0" + "map-obj" "^1.0.0" + +"decamelize@^1.1.0", "decamelize@^1.1.2", "decamelize@^1.2.0": + "integrity" "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + "resolved" "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz" + "version" "1.2.0" + +"decode-uri-component@^0.2.0": + "integrity" "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" + "resolved" "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz" + "version" "0.2.2" + +"decompress-response@^3.2.0", "decompress-response@^3.3.0": + "integrity" "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==" + "resolved" "https://registry.npmmirror.com/decompress-response/-/decompress-response-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "mimic-response" "^1.0.0" + +"decompress-tar@^4.0.0", "decompress-tar@^4.1.0", "decompress-tar@^4.1.1": + "integrity" "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==" + "resolved" "https://registry.npmmirror.com/decompress-tar/-/decompress-tar-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "file-type" "^5.2.0" + "is-stream" "^1.1.0" + "tar-stream" "^1.5.2" + +"decompress-tarbz2@^4.0.0": + "integrity" "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==" + "resolved" "https://registry.npmmirror.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "decompress-tar" "^4.1.0" + "file-type" "^6.1.0" + "is-stream" "^1.1.0" + "seek-bzip" "^1.0.5" + "unbzip2-stream" "^1.0.9" + +"decompress-targz@^4.0.0": + "integrity" "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==" + "resolved" "https://registry.npmmirror.com/decompress-targz/-/decompress-targz-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "decompress-tar" "^4.1.1" + "file-type" "^5.2.0" + "is-stream" "^1.1.0" + +"decompress-unzip@^4.0.1": + "integrity" "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==" + "resolved" "https://registry.npmmirror.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "file-type" "^3.8.0" + "get-stream" "^2.2.0" + "pify" "^2.3.0" + "yauzl" "^2.4.2" + +"decompress@^4.0.0", "decompress@^4.2.0": + "integrity" "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==" + "resolved" "https://registry.npmmirror.com/decompress/-/decompress-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "decompress-tar" "^4.0.0" + "decompress-tarbz2" "^4.0.0" + "decompress-targz" "^4.0.0" + "decompress-unzip" "^4.0.1" + "graceful-fs" "^4.1.10" + "make-dir" "^1.0.0" + "pify" "^2.3.0" + "strip-dirs" "^2.0.0" + +"deep-is@^0.1.3": + "integrity" "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "resolved" "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz" + "version" "0.1.4" + +"deepmerge@^4.2.2": + "integrity" "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "resolved" "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.2.2.tgz" + "version" "4.2.2" + +"defaults@^1.0.3": + "integrity" "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==" + "resolved" "https://registry.npmmirror.com/defaults/-/defaults-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "clone" "^1.0.2" + +"define-lazy-prop@^2.0.0": + "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "resolved" "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + "version" "2.0.0" + +"define-properties@^1.1.3", "define-properties@^1.1.4": + "integrity" "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==" + "resolved" "https://registry.npmmirror.com/define-properties/-/define-properties-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "has-property-descriptors" "^1.0.0" + "object-keys" "^1.1.1" + +"define-property@^0.2.5": + "integrity" "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==" + "resolved" "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz" + "version" "0.2.5" + dependencies: + "is-descriptor" "^0.1.0" + +"define-property@^1.0.0": + "integrity" "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==" + "resolved" "https://registry.npmmirror.com/define-property/-/define-property-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-descriptor" "^1.0.0" + +"define-property@^2.0.2": + "integrity" "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==" + "resolved" "https://registry.npmmirror.com/define-property/-/define-property-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "is-descriptor" "^1.0.2" + "isobject" "^3.0.1" + +"deprecation@^2.0.0", "deprecation@^2.3.1": + "integrity" "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + "resolved" "https://registry.npmmirror.com/deprecation/-/deprecation-2.3.1.tgz" + "version" "2.3.1" + +"diff-match-patch@^1.0.5": + "integrity" "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + "resolved" "https://registry.npmmirror.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz" + "version" "1.0.5" + +"diff@^4.0.1": + "integrity" "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "resolved" "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz" + "version" "4.0.2" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"doctrine@^3.0.0": + "integrity" "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==" + "resolved" "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "esutils" "^2.0.2" + +"dom-align@^1.12.1": + "integrity" "sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==" + "resolved" "https://registry.npmmirror.com/dom-align/-/dom-align-1.12.3.tgz" + "version" "1.12.3" + +"dom-scroll-into-view@^2.0.0": + "integrity" "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==" + "resolved" "https://registry.npmmirror.com/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz" + "version" "2.0.1" + +"dom-serializer@^1.0.1": + "integrity" "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==" + "resolved" "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@0": + "integrity" "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==" + "resolved" "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-0.2.2.tgz" + "version" "0.2.2" + dependencies: + "domelementtype" "^2.0.1" + "entities" "^2.0.0" + +"domelementtype@^1.3.1", "domelementtype@1": + "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "resolved" "https://registry.npmmirror.com/domelementtype/-/domelementtype-1.3.1.tgz" + "version" "1.3.1" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0": + "integrity" "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + "resolved" "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz" + "version" "2.3.0" + +"domhandler@^2.3.0": + "integrity" "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==" + "resolved" "https://registry.npmmirror.com/domhandler/-/domhandler-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "domelementtype" "1" + +"domhandler@^4.2.0", "domhandler@^4.2.2", "domhandler@^4.3.1": + "integrity" "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==" + "resolved" "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz" + "version" "4.3.1" + dependencies: + "domelementtype" "^2.2.0" + +"domutils@^1.5.1": + "integrity" "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==" + "resolved" "https://registry.npmmirror.com/domutils/-/domutils-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"dot-case@^3.0.4": + "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" + "resolved" "https://registry.npmmirror.com/dot-case/-/dot-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"dot-prop@^5.1.0": + "integrity" "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==" + "resolved" "https://registry.npmmirror.com/dot-prop/-/dot-prop-5.3.0.tgz" + "version" "5.3.0" + dependencies: + "is-obj" "^2.0.0" + +"dotenv-expand@^8.0.2": + "integrity" "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==" + "resolved" "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-8.0.3.tgz" + "version" "8.0.3" + +"dotenv@^16.0.0": + "integrity" "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" + "resolved" "https://registry.npmmirror.com/dotenv/-/dotenv-16.0.1.tgz" + "version" "16.0.1" + +"download@^6.2.2": + "integrity" "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==" + "resolved" "https://registry.npmmirror.com/download/-/download-6.2.5.tgz" + "version" "6.2.5" + dependencies: + "caw" "^2.0.0" + "content-disposition" "^0.5.2" + "decompress" "^4.0.0" + "ext-name" "^5.0.0" + "file-type" "5.2.0" + "filenamify" "^2.0.0" + "get-stream" "^3.0.0" + "got" "^7.0.0" + "make-dir" "^1.0.0" + "p-event" "^1.0.0" + "pify" "^3.0.0" + +"download@^7.1.0": + "integrity" "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==" + "resolved" "https://registry.npmjs.org/download/-/download-7.1.0.tgz" + "version" "7.1.0" + dependencies: + "archive-type" "^4.0.0" + "caw" "^2.0.1" + "content-disposition" "^0.5.2" + "decompress" "^4.2.0" + "ext-name" "^5.0.0" + "file-type" "^8.1.0" + "filenamify" "^2.0.0" + "get-stream" "^3.0.0" + "got" "^8.3.1" + "make-dir" "^1.2.0" + "p-event" "^2.1.0" + "pify" "^3.0.0" + +"duplexer3@^0.1.4": + "integrity" "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==" + "resolved" "https://registry.npmmirror.com/duplexer3/-/duplexer3-0.1.4.tgz" + "version" "0.1.4" + +"eastasianwidth@^0.2.0": + "integrity" "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "resolved" "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz" + "version" "0.2.0" + +"echarts@^5.3.2": + "integrity" "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==" + "resolved" "https://registry.npmmirror.com/echarts/-/echarts-5.3.3.tgz" + "version" "5.3.3" + dependencies: + "tslib" "2.3.0" + "zrender" "5.3.2" + +"ee-first@1.1.1": + "integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "resolved" "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"ejs@^3.1.6": + "integrity" "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==" + "resolved" "https://registry.npmmirror.com/ejs/-/ejs-3.1.8.tgz" + "version" "3.1.8" + dependencies: + "jake" "^10.8.5" + +"electron-to-chromium@^1.4.172": + "integrity" "sha512-OpEjTADzGoXABjqobGhpy0D2YsTncAax7IkER68ycc4adaq0dqEG9//9aenKPy7BGA90bqQdLac0dPp6uMkcSg==" + "resolved" "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.182.tgz" + "version" "1.4.182" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"emoji-regex@^9.2.2": + "integrity" "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "resolved" "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz" + "version" "9.2.2" + +"emojis-list@^3.0.0": + "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "resolved" "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz" + "version" "3.0.0" + +"encodeurl@~1.0.2": + "integrity" "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "resolved" "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"end-of-stream@^1.0.0", "end-of-stream@^1.1.0": + "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" + "resolved" "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz" + "version" "1.4.4" + dependencies: + "once" "^1.4.0" + +"entities@^1.1.1": + "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "resolved" "https://registry.npmmirror.com/entities/-/entities-1.1.2.tgz" + "version" "1.1.2" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^3.0.1": + "integrity" "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + "resolved" "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz" + "version" "3.0.1" + +"errno@^0.1.1": + "integrity" "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==" + "resolved" "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz" + "version" "0.1.8" + dependencies: + "prr" "~1.0.1" + +"error-ex@^1.2.0", "error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-abstract@^1.19.0", "es-abstract@^1.19.1", "es-abstract@^1.19.5": + "integrity" "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==" + "resolved" "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.20.1.tgz" + "version" "1.20.1" + dependencies: + "call-bind" "^1.0.2" + "es-to-primitive" "^1.2.1" + "function-bind" "^1.1.1" + "function.prototype.name" "^1.1.5" + "get-intrinsic" "^1.1.1" + "get-symbol-description" "^1.0.0" + "has" "^1.0.3" + "has-property-descriptors" "^1.0.0" + "has-symbols" "^1.0.3" + "internal-slot" "^1.0.3" + "is-callable" "^1.2.4" + "is-negative-zero" "^2.0.2" + "is-regex" "^1.1.4" + "is-shared-array-buffer" "^1.0.2" + "is-string" "^1.0.7" + "is-weakref" "^1.0.2" + "object-inspect" "^1.12.0" + "object-keys" "^1.1.1" + "object.assign" "^4.1.2" + "regexp.prototype.flags" "^1.4.3" + "string.prototype.trimend" "^1.0.5" + "string.prototype.trimstart" "^1.0.5" + "unbox-primitive" "^1.0.2" + +"es-module-lexer@^0.9.3": + "integrity" "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + "resolved" "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz" + "version" "0.9.3" + +"es-to-primitive@^1.2.1": + "integrity" "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==" + "resolved" "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "is-callable" "^1.1.4" + "is-date-object" "^1.0.1" + "is-symbol" "^1.0.2" + +"esbuild-darwin-64@0.14.48": + "integrity" "sha512-gGQZa4+hab2Va/Zww94YbshLuWteyKGD3+EsVon8EWTWhnHFRm5N9NbALNbwi/7hQ/hM1Zm4FuHg+k6BLsl5UA==" + "resolved" "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.48.tgz" + "version" "0.14.48" + +"esbuild-node-loader@^0.6.5": + "integrity" "sha512-uPP+dllWm38cFvDysdocutN3lfe5pTIbddAHp1ENyLzpHYqE2r+3Wo+pfg9X3p8DFWwzIisft5YkeBIthIcixw==" + "resolved" "https://registry.npmmirror.com/esbuild-node-loader/-/esbuild-node-loader-0.6.5.tgz" + "version" "0.6.5" + dependencies: + "esbuild" ">=0.13.12" + +"esbuild-plugin-alias@^0.1.2": + "integrity" "sha512-WsX0OJy8IGOsGZV+4oHEU5B6XQUpxOsZN1iSoYf9COTDbY7WXcOwd1oCLYNWUIWCExyGXSghIGq2k7sXBldxwQ==" + "resolved" "https://registry.npmmirror.com/esbuild-plugin-alias/-/esbuild-plugin-alias-0.1.2.tgz" + "version" "0.1.2" + +"esbuild-register@^3.3.2": + "integrity" "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==" + "resolved" "https://registry.npmmirror.com/esbuild-register/-/esbuild-register-3.3.3.tgz" + "version" "3.3.3" + +"esbuild@^0.11.23": + "integrity" "sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==" + "resolved" "https://registry.npmmirror.com/esbuild/-/esbuild-0.11.23.tgz" + "version" "0.11.23" + +"esbuild@^0.14.14", "esbuild@^0.14.27", "esbuild@>=0.12 <1", "esbuild@>=0.13.0", "esbuild@>=0.13.12": + "integrity" "sha512-w6N1Yn5MtqK2U1/WZTX9ZqUVb8IOLZkZ5AdHkT6x3cHDMVsYWC7WPdiLmx19w3i4Rwzy5LqsEMtVihG3e4rFzA==" + "resolved" "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.48.tgz" + "version" "0.14.48" + optionalDependencies: + "esbuild-android-64" "0.14.48" + "esbuild-android-arm64" "0.14.48" + "esbuild-darwin-64" "0.14.48" + "esbuild-darwin-arm64" "0.14.48" + "esbuild-freebsd-64" "0.14.48" + "esbuild-freebsd-arm64" "0.14.48" + "esbuild-linux-32" "0.14.48" + "esbuild-linux-64" "0.14.48" + "esbuild-linux-arm" "0.14.48" + "esbuild-linux-arm64" "0.14.48" + "esbuild-linux-mips64le" "0.14.48" + "esbuild-linux-ppc64le" "0.14.48" + "esbuild-linux-riscv64" "0.14.48" + "esbuild-linux-s390x" "0.14.48" + "esbuild-netbsd-64" "0.14.48" + "esbuild-openbsd-64" "0.14.48" + "esbuild-sunos-64" "0.14.48" + "esbuild-windows-32" "0.14.48" + "esbuild-windows-64" "0.14.48" + "esbuild-windows-arm64" "0.14.48" + +"esbuild@0.11.3": + "integrity" "sha512-BzVRHcCtFepjS9WcqRjqoIxLqgpK21a8J4Zi4msSGxDxiXVO1IbcqT1KjhdDDnJxKfe7bvzZrvMEX+bVO0Elcw==" + "resolved" "https://registry.npmmirror.com/esbuild/-/esbuild-0.11.3.tgz" + "version" "0.11.3" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-html@~1.0.3": + "integrity" "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "resolved" "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.2": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"escape-string-regexp@1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"eslint-config-prettier@^8.5.0": + "integrity" "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==" + "resolved" "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz" + "version" "8.5.0" + +"eslint-plugin-prettier@^4.0.0": + "integrity" "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==" + "resolved" "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "prettier-linter-helpers" "^1.0.0" + +"eslint-plugin-vue@^8.6.0": + "integrity" "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==" + "resolved" "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz" + "version" "8.7.1" + dependencies: + "eslint-utils" "^3.0.0" + "natural-compare" "^1.4.0" + "nth-check" "^2.0.1" + "postcss-selector-parser" "^6.0.9" + "semver" "^7.3.5" + "vue-eslint-parser" "^8.0.1" + +"eslint-scope@^5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"eslint-scope@^7.0.0": + "integrity" "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==" + "resolved" "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz" + "version" "7.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^5.2.0" + +"eslint-scope@^7.1.1": + "integrity" "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==" + "resolved" "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz" + "version" "7.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^5.2.0" + +"eslint-utils@^3.0.0": + "integrity" "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==" + "resolved" "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "eslint-visitor-keys" "^2.0.0" + +"eslint-visitor-keys@^2.0.0": + "integrity" "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + "resolved" "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + "version" "2.1.0" + +"eslint-visitor-keys@^3.1.0", "eslint-visitor-keys@^3.3.0": + "integrity" "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" + "resolved" "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz" + "version" "3.3.0" + +"eslint@*", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0", "eslint@^8.13.0", "eslint@>=5", "eslint@>=6.0.0", "eslint@>=7.0.0", "eslint@>=7.28.0": + "integrity" "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==" + "resolved" "https://registry.npmmirror.com/eslint/-/eslint-8.19.0.tgz" + "version" "8.19.0" + dependencies: + "@eslint/eslintrc" "^1.3.0" + "@humanwhocodes/config-array" "^0.9.2" + "ajv" "^6.10.0" + "chalk" "^4.0.0" + "cross-spawn" "^7.0.2" + "debug" "^4.3.2" + "doctrine" "^3.0.0" + "escape-string-regexp" "^4.0.0" + "eslint-scope" "^7.1.1" + "eslint-utils" "^3.0.0" + "eslint-visitor-keys" "^3.3.0" + "espree" "^9.3.2" + "esquery" "^1.4.0" + "esutils" "^2.0.2" + "fast-deep-equal" "^3.1.3" + "file-entry-cache" "^6.0.1" + "functional-red-black-tree" "^1.0.1" + "glob-parent" "^6.0.1" + "globals" "^13.15.0" + "ignore" "^5.2.0" + "import-fresh" "^3.0.0" + "imurmurhash" "^0.1.4" + "is-glob" "^4.0.0" + "js-yaml" "^4.1.0" + "json-stable-stringify-without-jsonify" "^1.0.1" + "levn" "^0.4.1" + "lodash.merge" "^4.6.2" + "minimatch" "^3.1.2" + "natural-compare" "^1.4.0" + "optionator" "^0.9.1" + "regexpp" "^3.2.0" + "strip-ansi" "^6.0.1" + "strip-json-comments" "^3.1.0" + "text-table" "^0.2.0" + "v8-compile-cache" "^2.0.3" + +"esno@^0.14.1": + "integrity" "sha512-yDFYw6dGUjCT1qKsdG7WOc/RzIh/qwxUEVZ+ohCltaxBxEFMNqeqbQL9xjRl6Yvdwrfc5OCjUA9JbFmuu/8BKg==" + "resolved" "https://registry.npmmirror.com/esno/-/esno-0.14.1.tgz" + "version" "0.14.1" + dependencies: + "cross-spawn" "^7.0.3" + "esbuild" ">=0.13.0" + "esbuild-node-loader" "^0.6.5" + "esbuild-register" "^3.3.2" + "import-meta-resolve" "^1.1.1" + +"espree@^9.0.0", "espree@^9.3.2": + "integrity" "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==" + "resolved" "https://registry.npmmirror.com/espree/-/espree-9.3.2.tgz" + "version" "9.3.2" + dependencies: + "acorn" "^8.7.1" + "acorn-jsx" "^5.3.2" + "eslint-visitor-keys" "^3.3.0" + +"esquery@^1.4.0": + "integrity" "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==" + "resolved" "https://registry.npmmirror.com/esquery/-/esquery-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "estraverse" "^5.1.0" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.1.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"estree-walker@^1.0.1": + "integrity" "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + "resolved" "https://registry.npmmirror.com/estree-walker/-/estree-walker-1.0.1.tgz" + "version" "1.0.1" + +"estree-walker@^2.0.1", "estree-walker@^2.0.2": + "integrity" "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "resolved" "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz" + "version" "2.0.2" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"etag@^1.8.1": + "integrity" "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + "resolved" "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"exec-buffer@^3.0.0": + "integrity" "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==" + "resolved" "https://registry.npmmirror.com/exec-buffer/-/exec-buffer-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "execa" "^0.7.0" + "p-finally" "^1.0.0" + "pify" "^3.0.0" + "rimraf" "^2.5.4" + "tempfile" "^2.0.0" + +"execa@^0.7.0": + "integrity" "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==" + "resolved" "https://registry.npmmirror.com/execa/-/execa-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "cross-spawn" "^5.0.1" + "get-stream" "^3.0.0" + "is-stream" "^1.1.0" + "npm-run-path" "^2.0.0" + "p-finally" "^1.0.0" + "signal-exit" "^3.0.0" + "strip-eof" "^1.0.0" + +"execa@^1.0.0": + "integrity" "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==" + "resolved" "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "cross-spawn" "^6.0.0" + "get-stream" "^4.0.0" + "is-stream" "^1.1.0" + "npm-run-path" "^2.0.0" + "p-finally" "^1.0.0" + "signal-exit" "^3.0.0" + "strip-eof" "^1.0.0" + +"execa@^4.0.0": + "integrity" "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==" + "resolved" "https://registry.npmmirror.com/execa/-/execa-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "cross-spawn" "^7.0.0" + "get-stream" "^5.0.0" + "human-signals" "^1.1.1" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.0" + "onetime" "^5.1.0" + "signal-exit" "^3.0.2" + "strip-final-newline" "^2.0.0" + +"execa@^5.0.0", "execa@^5.1.1": + "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" + "resolved" "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.0" + "human-signals" "^2.1.0" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.1" + "onetime" "^5.1.2" + "signal-exit" "^3.0.3" + "strip-final-newline" "^2.0.0" + +"execall@^2.0.0": + "integrity" "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==" + "resolved" "https://registry.npmmirror.com/execall/-/execall-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "clone-regexp" "^2.1.0" + +"executable@^4.1.0": + "integrity" "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==" + "resolved" "https://registry.npmmirror.com/executable/-/executable-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "pify" "^2.2.0" + +"expand-brackets@^2.1.4": + "integrity" "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==" + "resolved" "https://registry.npmmirror.com/expand-brackets/-/expand-brackets-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "debug" "^2.3.3" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "posix-character-classes" "^0.1.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"ext-list@^2.0.0": + "integrity" "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==" + "resolved" "https://registry.npmmirror.com/ext-list/-/ext-list-2.2.2.tgz" + "version" "2.2.2" + dependencies: + "mime-db" "^1.28.0" + +"ext-name@^5.0.0": + "integrity" "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==" + "resolved" "https://registry.npmmirror.com/ext-name/-/ext-name-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "ext-list" "^2.0.0" + "sort-keys-length" "^1.0.0" + +"extend-shallow@^2.0.1": + "integrity" "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==" + "resolved" "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend-shallow@^3.0.0": + "integrity" "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==" + "resolved" "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "assign-symbols" "^1.0.0" + "is-extendable" "^1.0.1" + +"extend-shallow@^3.0.2": + "integrity" "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==" + "resolved" "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "assign-symbols" "^1.0.0" + "is-extendable" "^1.0.1" + +"external-editor@^3.0.3": + "integrity" "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==" + "resolved" "https://registry.npmmirror.com/external-editor/-/external-editor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "chardet" "^0.7.0" + "iconv-lite" "^0.4.24" + "tmp" "^0.0.33" + +"extglob@^2.0.2": + "integrity" "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==" + "resolved" "https://registry.npmmirror.com/extglob/-/extglob-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "array-unique" "^0.3.2" + "define-property" "^1.0.0" + "expand-brackets" "^2.1.4" + "extend-shallow" "^2.0.1" + "fragment-cache" "^0.2.1" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-diff@^1.1.2": + "integrity" "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "resolved" "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.2.0.tgz" + "version" "1.2.0" + +"fast-glob@^3.0.3", "fast-glob@^3.2.11", "fast-glob@^3.2.7", "fast-glob@^3.2.9": + "integrity" "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==" + "resolved" "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.11.tgz" + "version" "3.2.11" + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + "glob-parent" "^5.1.2" + "merge2" "^1.3.0" + "micromatch" "^4.0.4" + +"fast-json-stable-stringify@^2.0.0", "fast-json-stable-stringify@^2.1.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-levenshtein@^2.0.6": + "integrity" "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "resolved" "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + "version" "2.0.6" + +"fast-xml-parser@^3.19.0": + "integrity" "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==" + "resolved" "https://registry.npmmirror.com/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz" + "version" "3.21.1" + dependencies: + "strnum" "^1.0.4" + +"fastest-levenshtein@^1.0.12", "fastest-levenshtein@1.0.12": + "integrity" "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==" + "resolved" "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz" + "version" "1.0.12" + +"fastq@^1.6.0": + "integrity" "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==" + "resolved" "https://registry.npmmirror.com/fastq/-/fastq-1.13.0.tgz" + "version" "1.13.0" + dependencies: + "reusify" "^1.0.4" + +"fd-slicer@~1.1.0": + "integrity" "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==" + "resolved" "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "pend" "~1.2.0" + +"figures@^1.3.5": + "integrity" "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==" + "resolved" "https://registry.npmmirror.com/figures/-/figures-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "escape-string-regexp" "^1.0.5" + "object-assign" "^4.1.0" + +"figures@^3.0.0": + "integrity" "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==" + "resolved" "https://registry.npmmirror.com/figures/-/figures-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "escape-string-regexp" "^1.0.5" + +"file-entry-cache@^6.0.1": + "integrity" "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==" + "resolved" "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "flat-cache" "^3.0.4" + +"file-type@^10.4.0": + "integrity" "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-10.11.0.tgz" + "version" "10.11.0" + +"file-type@^10.5.0": + "integrity" "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-10.11.0.tgz" + "version" "10.11.0" + +"file-type@^12.0.0": + "integrity" "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-12.4.2.tgz" + "version" "12.4.2" + +"file-type@^3.8.0": + "integrity" "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-3.9.0.tgz" + "version" "3.9.0" + +"file-type@^4.2.0": + "integrity" "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-4.4.0.tgz" + "version" "4.4.0" + +"file-type@^5.2.0", "file-type@5.2.0": + "integrity" "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-5.2.0.tgz" + "version" "5.2.0" + +"file-type@^6.1.0": + "integrity" "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + "resolved" "https://registry.npmmirror.com/file-type/-/file-type-6.2.0.tgz" + "version" "6.2.0" + +"file-type@^8.1.0": + "integrity" "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" + "resolved" "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz" + "version" "8.1.0" + +"filelist@^1.0.1": + "integrity" "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==" + "resolved" "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "minimatch" "^5.0.1" + +"filename-reserved-regex@^2.0.0": + "integrity" "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==" + "resolved" "https://registry.npmmirror.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz" + "version" "2.0.0" + +"filenamify@^2.0.0": + "integrity" "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==" + "resolved" "https://registry.npmmirror.com/filenamify/-/filenamify-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "filename-reserved-regex" "^2.0.0" + "strip-outer" "^1.0.0" + "trim-repeated" "^1.0.0" + +"fill-range@^4.0.0": + "integrity" "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==" + "resolved" "https://registry.npmmirror.com/fill-range/-/fill-range-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + "to-regex-range" "^2.1.0" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@1.1.2": + "integrity" "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==" + "resolved" "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "on-finished" "~2.3.0" + "parseurl" "~1.3.3" + "statuses" "~1.5.0" + "unpipe" "~1.0.0" + +"find-up@^1.0.0": + "integrity" "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==" + "resolved" "https://registry.npmmirror.com/find-up/-/find-up-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "path-exists" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"find-up@^2.0.0": + "integrity" "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==" + "resolved" "https://registry.npmmirror.com/find-up/-/find-up-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "locate-path" "^2.0.0" + +"find-up@^4.1.0": + "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" + "resolved" "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "locate-path" "^5.0.0" + "path-exists" "^4.0.0" + +"find-up@^5.0.0": + "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" + "resolved" "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "locate-path" "^6.0.0" + "path-exists" "^4.0.0" + +"find-versions@^3.0.0": + "integrity" "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==" + "resolved" "https://registry.npmmirror.com/find-versions/-/find-versions-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "semver-regex" "^2.0.0" + +"flat-cache@^3.0.4": + "integrity" "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==" + "resolved" "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "flatted" "^3.1.0" + "rimraf" "^3.0.2" + +"flatted@^3.1.0": + "integrity" "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==" + "resolved" "https://registry.npmmirror.com/flatted/-/flatted-3.2.6.tgz" + "version" "3.2.6" + +"follow-redirects@^1.14.0", "follow-redirects@^1.14.8": + "integrity" "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + "resolved" "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz" + "version" "1.15.1" + +"for-in@^1.0.2": + "integrity" "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + "resolved" "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz" + "version" "1.0.2" + +"frac@~1.1.2": + "integrity" "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" + "resolved" "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz" + "version" "1.1.2" + +"fraction.js@^4.2.0": + "integrity" "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" + "resolved" "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.2.0.tgz" + "version" "4.2.0" + +"fragment-cache@^0.2.1": + "integrity" "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==" + "resolved" "https://registry.npmmirror.com/fragment-cache/-/fragment-cache-0.2.1.tgz" + "version" "0.2.1" + dependencies: + "map-cache" "^0.2.2" + +"from2@^2.1.1": + "integrity" "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==" + "resolved" "https://registry.npmmirror.com/from2/-/from2-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "inherits" "^2.0.1" + "readable-stream" "^2.0.0" + +"fs-constants@^1.0.0": + "integrity" "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + "resolved" "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz" + "version" "1.0.0" + +"fs-extra@^10.0.0", "fs-extra@^10.0.1", "fs-extra@^10.1.0": + "integrity" "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==" + "resolved" "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz" + "version" "10.1.0" + dependencies: + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs-extra@^9.0.1": + "integrity" "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==" + "resolved" "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz" + "version" "9.1.0" + dependencies: + "at-least-node" "^1.0.0" + "graceful-fs" "^4.2.0" + "jsonfile" "^6.0.1" + "universalify" "^2.0.0" + +"fs.realpath@^1.0.0": + "integrity" "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "resolved" "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"fsevents@~2.3.2": + "integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" + "resolved" "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz" + "version" "2.3.2" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"function.prototype.name@^1.1.5": + "integrity" "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==" + "resolved" "https://registry.npmmirror.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz" + "version" "1.1.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.0" + "functions-have-names" "^1.2.2" + +"functional-red-black-tree@^1.0.1": + "integrity" "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + "resolved" "https://registry.npmmirror.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + "version" "1.0.1" + +"functions-have-names@^1.2.2": + "integrity" "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + "resolved" "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz" + "version" "1.2.3" + +"gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-caller-file@^2.0.5": + "integrity" "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "resolved" "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz" + "version" "2.0.5" + +"get-intrinsic@^1.0.2", "get-intrinsic@^1.1.0", "get-intrinsic@^1.1.1": + "integrity" "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==" + "resolved" "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-symbols" "^1.0.3" + +"get-own-enumerable-property-symbols@^3.0.0": + "integrity" "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + "resolved" "https://registry.npmmirror.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz" + "version" "3.0.2" + +"get-pkg-repo@^4.0.0": + "integrity" "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==" + "resolved" "https://registry.npmmirror.com/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz" + "version" "4.2.1" + dependencies: + "@hutson/parse-repository-url" "^3.0.0" + "hosted-git-info" "^4.0.0" + "through2" "^2.0.0" + "yargs" "^16.2.0" + +"get-proxy@^2.0.0": + "integrity" "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==" + "resolved" "https://registry.npmmirror.com/get-proxy/-/get-proxy-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "npm-conf" "^1.1.0" + +"get-stdin@^4.0.1": + "integrity" "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==" + "resolved" "https://registry.npmmirror.com/get-stdin/-/get-stdin-4.0.1.tgz" + "version" "4.0.1" + +"get-stdin@^8.0.0": + "integrity" "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==" + "resolved" "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz" + "version" "8.0.0" + +"get-stream@^2.2.0": + "integrity" "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==" + "resolved" "https://registry.npmmirror.com/get-stream/-/get-stream-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "object-assign" "^4.0.1" + "pinkie-promise" "^2.0.0" + +"get-stream@^3.0.0": + "integrity" "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz" + "version" "3.0.0" + +"get-stream@^4.0.0": + "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" + "resolved" "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^5.0.0": + "integrity" "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==" + "resolved" "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "pump" "^3.0.0" + +"get-stream@^6.0.0": + "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "resolved" "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz" + "version" "6.0.1" + +"get-stream@3.0.0": + "integrity" "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==" + "resolved" "https://registry.npmmirror.com/get-stream/-/get-stream-3.0.0.tgz" + "version" "3.0.0" + +"get-symbol-description@^1.0.0": + "integrity" "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==" + "resolved" "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "call-bind" "^1.0.2" + "get-intrinsic" "^1.1.1" + +"get-value@^2.0.3", "get-value@^2.0.6": + "integrity" "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" + "resolved" "https://registry.npmmirror.com/get-value/-/get-value-2.0.6.tgz" + "version" "2.0.6" + +"gifsicle@^5.0.0", "gifsicle@5.2.0": + "integrity" "sha512-vOIS3j0XoTCxq9pkGj43gEix82RkI5FveNgaFZutjbaui/HH+4fR8Y56dwXDuxYo8hR4xOo6/j2h1WHoQW6XLw==" + "resolved" "https://registry.npmmirror.com/gifsicle/-/gifsicle-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.0" + "execa" "^5.0.0" + "logalot" "^2.0.0" + +"git-raw-commits@^2.0.0", "git-raw-commits@^2.0.8": + "integrity" "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==" + "resolved" "https://registry.npmmirror.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz" + "version" "2.0.11" + dependencies: + "dargs" "^7.0.0" + "lodash" "^4.17.15" + "meow" "^8.0.0" + "split2" "^3.0.0" + "through2" "^4.0.0" + +"git-remote-origin-url@^2.0.0": + "integrity" "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==" + "resolved" "https://registry.npmmirror.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "gitconfiglocal" "^1.0.0" + "pify" "^2.3.0" + +"git-semver-tags@^4.1.1": + "integrity" "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==" + "resolved" "https://registry.npmmirror.com/git-semver-tags/-/git-semver-tags-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "meow" "^8.0.0" + "semver" "^6.0.0" + +"gitconfiglocal@^1.0.0": + "integrity" "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==" + "resolved" "https://registry.npmmirror.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "ini" "^1.3.2" + +"glob-parent@^5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob-parent@^6.0.1": + "integrity" "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==" + "resolved" "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz" + "version" "6.0.2" + dependencies: + "is-glob" "^4.0.3" + +"glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob@^7.1.3", "glob@^7.1.6": + "integrity" "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==" + "resolved" "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz" + "version" "7.2.3" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.1.1" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"global-dirs@^0.1.1": + "integrity" "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==" + "resolved" "https://registry.npmmirror.com/global-dirs/-/global-dirs-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "ini" "^1.3.4" + +"global-modules@^2.0.0": + "integrity" "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==" + "resolved" "https://registry.npmmirror.com/global-modules/-/global-modules-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "global-prefix" "^3.0.0" + +"global-prefix@^3.0.0": + "integrity" "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==" + "resolved" "https://registry.npmmirror.com/global-prefix/-/global-prefix-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ini" "^1.3.5" + "kind-of" "^6.0.2" + "which" "^1.3.1" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globals@^13.15.0": + "integrity" "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==" + "resolved" "https://registry.npmmirror.com/globals/-/globals-13.16.0.tgz" + "version" "13.16.0" + dependencies: + "type-fest" "^0.20.2" + +"globby@^10.0.0": + "integrity" "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==" + "resolved" "https://registry.npmmirror.com/globby/-/globby-10.0.2.tgz" + "version" "10.0.2" + dependencies: + "@types/glob" "^7.1.1" + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.0.3" + "glob" "^7.1.3" + "ignore" "^5.1.1" + "merge2" "^1.2.3" + "slash" "^3.0.0" + +"globby@^11.1.0": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"globjoin@^0.1.4": + "integrity" "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==" + "resolved" "https://registry.npmmirror.com/globjoin/-/globjoin-0.1.4.tgz" + "version" "0.1.4" + +"got@^7.0.0": + "integrity" "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==" + "resolved" "https://registry.npmmirror.com/got/-/got-7.1.0.tgz" + "version" "7.1.0" + dependencies: + "decompress-response" "^3.2.0" + "duplexer3" "^0.1.4" + "get-stream" "^3.0.0" + "is-plain-obj" "^1.1.0" + "is-retry-allowed" "^1.0.0" + "is-stream" "^1.0.0" + "isurl" "^1.0.0-alpha5" + "lowercase-keys" "^1.0.0" + "p-cancelable" "^0.3.0" + "p-timeout" "^1.1.1" + "safe-buffer" "^5.0.1" + "timed-out" "^4.0.0" + "url-parse-lax" "^1.0.0" + "url-to-options" "^1.0.1" + +"got@^8.3.1": + "integrity" "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==" + "resolved" "https://registry.npmjs.org/got/-/got-8.3.2.tgz" + "version" "8.3.2" + dependencies: + "@sindresorhus/is" "^0.7.0" + "cacheable-request" "^2.1.1" + "decompress-response" "^3.3.0" + "duplexer3" "^0.1.4" + "get-stream" "^3.0.0" + "into-stream" "^3.1.0" + "is-retry-allowed" "^1.1.0" + "isurl" "^1.0.0-alpha5" + "lowercase-keys" "^1.0.0" + "mimic-response" "^1.0.0" + "p-cancelable" "^0.4.0" + "p-timeout" "^2.0.1" + "pify" "^3.0.0" + "safe-buffer" "^5.1.1" + "timed-out" "^4.0.1" + "url-parse-lax" "^3.0.0" + "url-to-options" "^1.0.1" + +"graceful-fs@^4.1.10", "graceful-fs@^4.1.2", "graceful-fs@^4.1.6", "graceful-fs@^4.2.0", "graceful-fs@^4.2.2": + "integrity" "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "resolved" "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.10.tgz" + "version" "4.2.10" + +"handlebars@^4.7.7": + "integrity" "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==" + "resolved" "https://registry.npmmirror.com/handlebars/-/handlebars-4.7.7.tgz" + "version" "4.7.7" + dependencies: + "minimist" "^1.2.5" + "neo-async" "^2.6.0" + "source-map" "^0.6.1" + "wordwrap" "^1.0.0" + optionalDependencies: + "uglify-js" "^3.1.4" + +"hard-rejection@^2.1.0": + "integrity" "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==" + "resolved" "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz" + "version" "2.1.0" + +"has-ansi@^2.0.0": + "integrity" "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==" + "resolved" "https://registry.npmmirror.com/has-ansi/-/has-ansi-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ansi-regex" "^2.0.0" + +"has-bigints@^1.0.1", "has-bigints@^1.0.2": + "integrity" "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + "resolved" "https://registry.npmmirror.com/has-bigints/-/has-bigints-1.0.2.tgz" + "version" "1.0.2" + +"has-flag@^1.0.0": + "integrity" "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" + "resolved" "https://registry.npmmirror.com/has-flag/-/has-flag-1.0.0.tgz" + "version" "1.0.0" + +"has-flag@^3.0.0": + "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "resolved" "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-property-descriptors@^1.0.0": + "integrity" "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==" + "resolved" "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "get-intrinsic" "^1.1.1" + +"has-symbol-support-x@^1.4.1": + "integrity" "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" + "resolved" "https://registry.npmmirror.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz" + "version" "1.4.2" + +"has-symbols@^1.0.1", "has-symbols@^1.0.2", "has-symbols@^1.0.3": + "integrity" "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "resolved" "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz" + "version" "1.0.3" + +"has-to-string-tag-x@^1.2.0": + "integrity" "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==" + "resolved" "https://registry.npmmirror.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "has-symbol-support-x" "^1.4.1" + +"has-tostringtag@^1.0.0": + "integrity" "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==" + "resolved" "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-symbols" "^1.0.2" + +"has-value@^0.3.1": + "integrity" "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==" + "resolved" "https://registry.npmmirror.com/has-value/-/has-value-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "get-value" "^2.0.3" + "has-values" "^0.1.4" + "isobject" "^2.0.0" + +"has-value@^1.0.0": + "integrity" "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==" + "resolved" "https://registry.npmmirror.com/has-value/-/has-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "get-value" "^2.0.6" + "has-values" "^1.0.0" + "isobject" "^3.0.0" + +"has-values@^0.1.4": + "integrity" "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==" + "resolved" "https://registry.npmmirror.com/has-values/-/has-values-0.1.4.tgz" + "version" "0.1.4" + +"has-values@^1.0.0": + "integrity" "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==" + "resolved" "https://registry.npmmirror.com/has-values/-/has-values-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-number" "^3.0.0" + "kind-of" "^4.0.0" + +"has@^1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmmirror.com/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"hash-sum@^2.0.0": + "integrity" "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + "resolved" "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz" + "version" "2.0.0" + +"he@^1.1.1", "he@^1.2.0", "he@1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmmirror.com/he/-/he-1.2.0.tgz" + "version" "1.2.0" + +"header-case@^2.0.4": + "integrity" "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==" + "resolved" "https://registry.npmmirror.com/header-case/-/header-case-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "capital-case" "^1.0.4" + "tslib" "^2.0.3" + +"hosted-git-info@^2.1.4": + "integrity" "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "resolved" "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + "version" "2.8.9" + +"hosted-git-info@^4.0.0", "hosted-git-info@^4.0.1": + "integrity" "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==" + "resolved" "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "lru-cache" "^6.0.0" + +"html-minifier-terser@^6.1.0": + "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" + "resolved" "https://registry.npmmirror.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "camel-case" "^4.1.2" + "clean-css" "^5.2.2" + "commander" "^8.3.0" + "he" "^1.2.0" + "param-case" "^3.0.4" + "relateurl" "^0.2.7" + "terser" "^5.10.0" + +"html-tags@^3.1.0", "html-tags@^3.2.0": + "integrity" "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==" + "resolved" "https://registry.npmmirror.com/html-tags/-/html-tags-3.2.0.tgz" + "version" "3.2.0" + +"htmlparser2@^3.8.3": + "integrity" "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==" + "resolved" "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-3.10.1.tgz" + "version" "3.10.1" + dependencies: + "domelementtype" "^1.3.1" + "domhandler" "^2.3.0" + "domutils" "^1.5.1" + "entities" "^1.1.1" + "inherits" "^2.0.1" + "readable-stream" "^3.1.1" + +"htmlparser2@^7.1.2": + "integrity" "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==" + "resolved" "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.2" + "domutils" "^2.8.0" + "entities" "^3.0.1" + +"http-cache-semantics@3.8.1": + "integrity" "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + "resolved" "https://registry.npmmirror.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz" + "version" "3.8.1" + +"human-signals@^1.1.1": + "integrity" "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" + "resolved" "https://registry.npmmirror.com/human-signals/-/human-signals-1.1.1.tgz" + "version" "1.1.1" + +"human-signals@^2.1.0": + "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "resolved" "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz" + "version" "2.1.0" + +"husky@^7.0.4": + "integrity" "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==" + "resolved" "https://registry.npmmirror.com/husky/-/husky-7.0.4.tgz" + "version" "7.0.4" + +"iconv-lite@^0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"iconv-lite@^0.6.3": + "integrity" "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==" + "resolved" "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz" + "version" "0.6.3" + dependencies: + "safer-buffer" ">= 2.1.2 < 3.0.0" + +"idb@^6.1.4": + "integrity" "sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==" + "resolved" "https://registry.npmmirror.com/idb/-/idb-6.1.5.tgz" + "version" "6.1.5" + +"ids@^1.0.0": + "integrity" "sha512-Zvtq1xUto4LttpstyOlFum8lKx+i1OmRfg+6A9drFS9iSZsDPMHG4Sof/qwNR4kCU7jBeWFPrY2ocHxiz7cCRw==" + "resolved" "https://registry.npmmirror.com/ids/-/ids-1.0.0.tgz" + "version" "1.0.0" + +"ieee754@^1.1.13": + "integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "resolved" "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz" + "version" "1.2.1" + +"ignore@^5.1.1", "ignore@^5.2.0": + "integrity" "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + "resolved" "https://registry.npmmirror.com/ignore/-/ignore-5.2.0.tgz" + "version" "5.2.0" + +"image-size@^0.5.1", "image-size@~0.5.0": + "integrity" "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==" + "resolved" "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz" + "version" "0.5.5" + +"imagemin-gifsicle@^7.0.0": + "integrity" "sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA==" + "resolved" "https://registry.npmmirror.com/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "execa" "^1.0.0" + "gifsicle" "^5.0.0" + "is-gif" "^3.0.0" + +"imagemin-jpegtran@^7.0.0": + "integrity" "sha512-MJoyTCW8YjMJf56NorFE41SR/WkaGA3IYk4JgvMlRwguJEEd3PnP9UxA8Y2UWjquz8d+On3Ds/03ZfiiLS8xTQ==" + "resolved" "https://registry.npmmirror.com/imagemin-jpegtran/-/imagemin-jpegtran-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "exec-buffer" "^3.0.0" + "is-jpg" "^2.0.0" + "jpegtran-bin" "^5.0.0" + +"imagemin-mozjpeg@^9.0.0": + "integrity" "sha512-TwOjTzYqCFRgROTWpVSt5UTT0JeCuzF1jswPLKALDd89+PmrJ2PdMMYeDLYZ1fs9cTovI9GJd68mRSnuVt691w==" + "resolved" "https://registry.npmmirror.com/imagemin-mozjpeg/-/imagemin-mozjpeg-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "execa" "^4.0.0" + "is-jpg" "^2.0.0" + "mozjpeg" "^7.0.0" + +"imagemin-optipng@^8.0.0": + "integrity" "sha512-CUGfhfwqlPjAC0rm8Fy+R2DJDBGjzy2SkfyT09L8rasnF9jSoHFqJ1xxSZWK6HVPZBMhGPMxCTL70OgTHlLF5A==" + "resolved" "https://registry.npmmirror.com/imagemin-optipng/-/imagemin-optipng-8.0.0.tgz" + "version" "8.0.0" + dependencies: + "exec-buffer" "^3.0.0" + "is-png" "^2.0.0" + "optipng-bin" "^7.0.0" + +"imagemin-pngquant@^9.0.2": + "integrity" "sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg==" + "resolved" "https://registry.npmmirror.com/imagemin-pngquant/-/imagemin-pngquant-9.0.2.tgz" + "version" "9.0.2" + dependencies: + "execa" "^4.0.0" + "is-png" "^2.0.0" + "is-stream" "^2.0.0" + "ow" "^0.17.0" + "pngquant-bin" "^6.0.0" + +"imagemin-svgo@^9.0.0": + "integrity" "sha512-uNgXpKHd99C0WODkrJ8OO/3zW3qjgS4pW7hcuII0RcHN3tnKxDjJWcitdVC/TZyfIqSricU8WfrHn26bdSW62g==" + "resolved" "https://registry.npmmirror.com/imagemin-svgo/-/imagemin-svgo-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "is-svg" "^4.2.1" + "svgo" "^2.1.0" + +"imagemin-webp@^6.0.0": + "integrity" "sha512-DmVCkI8H1csyqAExsk93LzC88gj2uKXaLLW5Ly+WYsvNx7xv5cJAlozXWIx9Z0kEQr9w98gphi5aP2b++iDH8g==" + "resolved" "https://registry.npmmirror.com/imagemin-webp/-/imagemin-webp-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "cwebp-bin" "^5.0.0" + "exec-buffer" "^3.0.0" + "is-cwebp-readable" "^3.0.0" + +"imagemin@^7.0.1": + "integrity" "sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==" + "resolved" "https://registry.npmmirror.com/imagemin/-/imagemin-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "file-type" "^12.0.0" + "globby" "^10.0.0" + "graceful-fs" "^4.2.2" + "junk" "^3.1.0" + "make-dir" "^3.0.0" + "p-pipe" "^3.0.0" + "replace-ext" "^1.0.0" + +"import-fresh@^3.0.0", "import-fresh@^3.2.1": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"import-lazy@^3.1.0": + "integrity" "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==" + "resolved" "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz" + "version" "3.1.0" + +"import-lazy@^4.0.0": + "integrity" "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==" + "resolved" "https://registry.npmmirror.com/import-lazy/-/import-lazy-4.0.0.tgz" + "version" "4.0.0" + +"import-meta-resolve@^1.1.1": + "integrity" "sha512-JiTuIvVyPaUg11eTrNDx5bgQ/yMKMZffc7YSjvQeSMXy58DO2SQ8BtAf3xteZvmzvjYh14wnqNjL8XVeDy2o9A==" + "resolved" "https://registry.npmmirror.com/import-meta-resolve/-/import-meta-resolve-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "builtins" "^4.0.0" + +"imurmurhash@^0.1.4": + "integrity" "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + "resolved" "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"indent-string@^2.1.0": + "integrity" "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==" + "resolved" "https://registry.npmmirror.com/indent-string/-/indent-string-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "repeating" "^2.0.0" + +"indent-string@^4.0.0": + "integrity" "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + "resolved" "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz" + "version" "4.0.0" + +"inflight@^1.0.4": + "integrity" "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" + "resolved" "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.1", "inherits@^2.0.3", "inherits@^2.0.4", "inherits@~2.0.3", "inherits@2": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"ini@^1.3.2", "ini@^1.3.4", "ini@^1.3.5": + "integrity" "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "resolved" "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz" + "version" "1.3.8" + +"inquirer@^8.2.2": + "integrity" "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==" + "resolved" "https://registry.npmmirror.com/inquirer/-/inquirer-8.2.4.tgz" + "version" "8.2.4" + dependencies: + "ansi-escapes" "^4.2.1" + "chalk" "^4.1.1" + "cli-cursor" "^3.1.0" + "cli-width" "^3.0.0" + "external-editor" "^3.0.3" + "figures" "^3.0.0" + "lodash" "^4.17.21" + "mute-stream" "0.0.8" + "ora" "^5.4.1" + "run-async" "^2.4.0" + "rxjs" "^7.5.5" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + "through" "^2.3.6" + "wrap-ansi" "^7.0.0" + +"internal-slot@^1.0.3": + "integrity" "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==" + "resolved" "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "get-intrinsic" "^1.1.0" + "has" "^1.0.3" + "side-channel" "^1.0.4" + +"into-stream@^3.1.0": + "integrity" "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==" + "resolved" "https://registry.npmmirror.com/into-stream/-/into-stream-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "from2" "^2.1.1" + "p-is-promise" "^1.1.0" + +"intro.js@^5.1.0": + "integrity" "sha512-zwWl/duTh00eeNcZRU4o4/xxloNYPFKs4n4lMRDNx59jZr+qRI0jSOnzqYMOuVftD4beGrmxBHz4k8qp9/dCMA==" + "resolved" "https://registry.npmmirror.com/intro.js/-/intro.js-5.1.0.tgz" + "version" "5.1.0" + +"is-accessor-descriptor@^0.1.6": + "integrity" "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==" + "resolved" "https://registry.npmmirror.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "kind-of" "^3.0.2" + +"is-accessor-descriptor@^1.0.0": + "integrity" "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==" + "resolved" "https://registry.npmmirror.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "resolved" "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-bigint@^1.0.1": + "integrity" "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==" + "resolved" "https://registry.npmmirror.com/is-bigint/-/is-bigint-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "has-bigints" "^1.0.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-boolean-object@^1.1.0": + "integrity" "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==" + "resolved" "https://registry.npmmirror.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-buffer@^1.1.5": + "integrity" "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "resolved" "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz" + "version" "1.1.6" + +"is-builtin-module@^3.1.0": + "integrity" "sha512-OV7JjAgOTfAFJmHZLvpSTb4qi0nIILDV1gWPYDnDJUTNFM5aGlRAhk4QcT8i7TuAleeEV5Fdkqn3t4mS+Q11fg==" + "resolved" "https://registry.npmmirror.com/is-builtin-module/-/is-builtin-module-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "builtin-modules" "^3.0.0" + +"is-callable@^1.1.4", "is-callable@^1.2.4": + "integrity" "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "resolved" "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.4.tgz" + "version" "1.2.4" + +"is-core-module@^2.5.0", "is-core-module@^2.9.0": + "integrity" "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==" + "resolved" "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.9.0.tgz" + "version" "2.9.0" + dependencies: + "has" "^1.0.3" + +"is-cwebp-readable@^3.0.0": + "integrity" "sha512-bpELc7/Q1/U5MWHn4NdHI44R3jxk0h9ew9ljzabiRl70/UIjL/ZAqRMb52F5+eke/VC8yTiv4Ewryo1fPWidvA==" + "resolved" "https://registry.npmmirror.com/is-cwebp-readable/-/is-cwebp-readable-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "file-type" "^10.5.0" + +"is-data-descriptor@^0.1.4": + "integrity" "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==" + "resolved" "https://registry.npmmirror.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" + "version" "0.1.4" + dependencies: + "kind-of" "^3.0.2" + +"is-data-descriptor@^1.0.0": + "integrity" "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==" + "resolved" "https://registry.npmmirror.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-date-object@^1.0.1": + "integrity" "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" + "resolved" "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-descriptor@^0.1.0": + "integrity" "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==" + "resolved" "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "is-accessor-descriptor" "^0.1.6" + "is-data-descriptor" "^0.1.4" + "kind-of" "^5.0.0" + +"is-descriptor@^1.0.0", "is-descriptor@^1.0.2": + "integrity" "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==" + "resolved" "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-accessor-descriptor" "^1.0.0" + "is-data-descriptor" "^1.0.0" + "kind-of" "^6.0.2" + +"is-docker@^2.0.0", "is-docker@^2.1.1": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-expression@^4.0.0": + "integrity" "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==" + "resolved" "https://registry.npmmirror.com/is-expression/-/is-expression-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "acorn" "^7.1.1" + "object-assign" "^4.1.1" + +"is-extendable@^0.1.0", "is-extendable@^0.1.1": + "integrity" "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + "resolved" "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extendable@^1.0.1": + "integrity" "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==" + "resolved" "https://registry.npmmirror.com/is-extendable/-/is-extendable-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "is-plain-object" "^2.0.4" + +"is-extglob@^2.1.1": + "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + "resolved" "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-finite@^1.0.0": + "integrity" "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + "resolved" "https://registry.npmmirror.com/is-finite/-/is-finite-1.1.0.tgz" + "version" "1.1.0" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-fullwidth-code-point@^4.0.0": + "integrity" "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==" + "resolved" "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz" + "version" "4.0.0" + +"is-gif@^3.0.0": + "integrity" "sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw==" + "resolved" "https://registry.npmmirror.com/is-gif/-/is-gif-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "file-type" "^10.4.0" + +"is-glob@^4.0.0", "is-glob@^4.0.1", "is-glob@^4.0.3", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-interactive@^1.0.0": + "integrity" "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + "resolved" "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz" + "version" "1.0.0" + +"is-jpg@^2.0.0": + "integrity" "sha512-ODlO0ruzhkzD3sdynIainVP5eoOFNN85rxA1+cwwnPe4dKyX0r5+hxNO5XpCrxlHcmb9vkOit9mhRD2JVuimHg==" + "resolved" "https://registry.npmmirror.com/is-jpg/-/is-jpg-2.0.0.tgz" + "version" "2.0.0" + +"is-module@^1.0.0": + "integrity" "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + "resolved" "https://registry.npmmirror.com/is-module/-/is-module-1.0.0.tgz" + "version" "1.0.0" + +"is-natural-number@^4.0.1": + "integrity" "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" + "resolved" "https://registry.npmmirror.com/is-natural-number/-/is-natural-number-4.0.1.tgz" + "version" "4.0.1" + +"is-negative-zero@^2.0.2": + "integrity" "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + "resolved" "https://registry.npmmirror.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + "version" "2.0.2" + +"is-number-object@^1.0.4": + "integrity" "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==" + "resolved" "https://registry.npmmirror.com/is-number-object/-/is-number-object-1.0.7.tgz" + "version" "1.0.7" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-number@^3.0.0": + "integrity" "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==" + "resolved" "https://registry.npmmirror.com/is-number/-/is-number-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "kind-of" "^3.0.2" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-obj@^1.0.1": + "integrity" "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + "resolved" "https://registry.npmmirror.com/is-obj/-/is-obj-1.0.1.tgz" + "version" "1.0.1" + +"is-obj@^2.0.0": + "integrity" "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + "resolved" "https://registry.npmmirror.com/is-obj/-/is-obj-2.0.0.tgz" + "version" "2.0.0" + +"is-object@^1.0.1": + "integrity" "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" + "resolved" "https://registry.npmmirror.com/is-object/-/is-object-1.0.2.tgz" + "version" "1.0.2" + +"is-plain-obj@^1.0.0", "is-plain-obj@^1.1", "is-plain-obj@^1.1.0": + "integrity" "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" + "resolved" "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz" + "version" "1.1.0" + +"is-plain-object@^2.0.3": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-plain-object@^5.0.0", "is-plain-object@5.0.0": + "integrity" "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + "resolved" "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz" + "version" "5.0.0" + +"is-plain-object@3.0.1": + "integrity" "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==" + "resolved" "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-3.0.1.tgz" + "version" "3.0.1" + +"is-png@^2.0.0": + "integrity" "sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g==" + "resolved" "https://registry.npmmirror.com/is-png/-/is-png-2.0.0.tgz" + "version" "2.0.0" + +"is-regex@^1.0.3", "is-regex@^1.1.4": + "integrity" "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" + "resolved" "https://registry.npmmirror.com/is-regex/-/is-regex-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "call-bind" "^1.0.2" + "has-tostringtag" "^1.0.0" + +"is-regexp@^1.0.0": + "integrity" "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + "resolved" "https://registry.npmmirror.com/is-regexp/-/is-regexp-1.0.0.tgz" + "version" "1.0.0" + +"is-regexp@^2.0.0": + "integrity" "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==" + "resolved" "https://registry.npmmirror.com/is-regexp/-/is-regexp-2.1.0.tgz" + "version" "2.1.0" + +"is-retry-allowed@^1.0.0", "is-retry-allowed@^1.1.0": + "integrity" "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + "resolved" "https://registry.npmmirror.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz" + "version" "1.2.0" + +"is-shared-array-buffer@^1.0.2": + "integrity" "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==" + "resolved" "https://registry.npmmirror.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "call-bind" "^1.0.2" + +"is-stream@^1.0.0": + "integrity" "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + "resolved" "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz" + "version" "1.1.0" + +"is-stream@^1.1.0": + "integrity" "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + "resolved" "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz" + "version" "1.1.0" + +"is-stream@^2.0.0": + "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "resolved" "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz" + "version" "2.0.1" + +"is-string@^1.0.5", "is-string@^1.0.7": + "integrity" "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==" + "resolved" "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz" + "version" "1.0.7" + dependencies: + "has-tostringtag" "^1.0.0" + +"is-svg@^4.2.1": + "integrity" "sha512-mM90duy00JGMyjqIVHu9gNTjywdZV+8qNasX8cm/EEYZ53PHDgajvbBwNVvty5dwSAxLUD3p3bdo+7sR/UMrpw==" + "resolved" "https://registry.npmmirror.com/is-svg/-/is-svg-4.3.2.tgz" + "version" "4.3.2" + dependencies: + "fast-xml-parser" "^3.19.0" + +"is-symbol@^1.0.2", "is-symbol@^1.0.3": + "integrity" "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==" + "resolved" "https://registry.npmmirror.com/is-symbol/-/is-symbol-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "has-symbols" "^1.0.2" + +"is-text-path@^1.0.1": + "integrity" "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==" + "resolved" "https://registry.npmmirror.com/is-text-path/-/is-text-path-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "text-extensions" "^1.0.0" + +"is-unicode-supported@^0.1.0": + "integrity" "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + "resolved" "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + "version" "0.1.0" + +"is-utf8@^0.2.0": + "integrity" "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + "resolved" "https://registry.npmmirror.com/is-utf8/-/is-utf8-0.2.1.tgz" + "version" "0.2.1" + +"is-weakref@^1.0.2": + "integrity" "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==" + "resolved" "https://registry.npmmirror.com/is-weakref/-/is-weakref-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "call-bind" "^1.0.2" + +"is-what@^3.14.1": + "integrity" "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + "resolved" "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz" + "version" "3.14.1" + +"is-windows@^1.0.2": + "integrity" "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "resolved" "https://registry.npmmirror.com/is-windows/-/is-windows-1.0.2.tgz" + "version" "1.0.2" + +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"isarray@~1.0.0", "isarray@1.0.0": + "integrity" "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "resolved" "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isexe@^2.0.0": + "integrity" "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "resolved" "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^2.0.0": + "integrity" "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==" + "resolved" "https://registry.npmmirror.com/isobject/-/isobject-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "isarray" "1.0.0" + +"isobject@^2.1.0": + "integrity" "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==" + "resolved" "https://registry.npmmirror.com/isobject/-/isobject-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "isarray" "1.0.0" + +"isobject@^3.0.0": + "integrity" "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + "resolved" "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"isobject@^3.0.1": + "integrity" "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + "resolved" "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"isurl@^1.0.0-alpha5": + "integrity" "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==" + "resolved" "https://registry.npmmirror.com/isurl/-/isurl-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-to-string-tag-x" "^1.2.0" + "is-object" "^1.0.1" + +"jake@^10.8.5": + "integrity" "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==" + "resolved" "https://registry.npmmirror.com/jake/-/jake-10.8.5.tgz" + "version" "10.8.5" + dependencies: + "async" "^3.2.3" + "chalk" "^4.0.2" + "filelist" "^1.0.1" + "minimatch" "^3.0.4" + +"jest-worker@^26.2.1": + "integrity" "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==" + "resolved" "https://registry.npmmirror.com/jest-worker/-/jest-worker-26.6.2.tgz" + "version" "26.6.2" + dependencies: + "@types/node" "*" + "merge-stream" "^2.0.0" + "supports-color" "^7.0.0" + +"jiti@^1.14.0": + "integrity" "sha512-4IwstlaKQc9vCTC+qUXLM1hajy2ImiL9KnLvVYiaHOtS/v3wRjhLlGl121AmgDgx/O43uKmxownJghS5XMya2A==" + "resolved" "https://registry.npmmirror.com/jiti/-/jiti-1.14.0.tgz" + "version" "1.14.0" + +"jpegtran-bin@^5.0.0": + "integrity" "sha512-4FSmgIcr8d5+V6T1+dHbPZjaFH0ogVyP4UVsE+zri7S9YLO4qAT2our4IN3sW3STVgNTbqPermdIgt2XuAJ4EA==" + "resolved" "https://registry.npmmirror.com/jpegtran-bin/-/jpegtran-bin-5.0.2.tgz" + "version" "5.0.2" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.0" + "logalot" "^2.0.0" + +"jpegtran-bin@^6.0.1": + "integrity" "sha512-WohhhHhqe22de7PU8hXs6Sr5d4BAvkrfA93NR5tGlHyPnFLgvEW/bH+q7fv65JgoiQDsd7SBwwQ/OGRBivU3Mw==" + "resolved" "https://registry.npmmirror.com/jpegtran-bin/-/jpegtran-bin-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.0" + +"js-base64@^2.1.9": + "integrity" "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" + "resolved" "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz" + "version" "2.6.4" + +"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-yaml@^4.1.0": + "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" + "resolved" "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "argparse" "^2.0.1" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + "resolved" "https://registry.npmmirror.com/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-buffer@3.0.0": + "integrity" "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + "resolved" "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.0.tgz" + "version" "3.0.0" + +"json-parse-better-errors@^1.0.1": + "integrity" "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "resolved" "https://registry.npmmirror.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" + "version" "1.0.2" + +"json-parse-even-better-errors@^2.3.0": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json-schema@^0.4.0": + "integrity" "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "resolved" "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz" + "version" "0.4.0" + +"json-stable-stringify-without-jsonify@^1.0.1": + "integrity" "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "resolved" "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + "version" "1.0.1" + +"json-stringify-safe@^5.0.1": + "integrity" "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "resolved" "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + "version" "5.0.1" + +"json5@^1.0.1": + "integrity" "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==" + "resolved" "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "minimist" "^1.2.0" + +"json5@^2.2.0", "json5@^2.2.1": + "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + "version" "2.2.3" + +"jsonfile@^6.0.1": + "integrity" "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==" + "resolved" "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "universalify" "^2.0.0" + optionalDependencies: + "graceful-fs" "^4.1.6" + +"jsonparse@^1.2.0": + "integrity" "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==" + "resolved" "https://registry.npmmirror.com/jsonparse/-/jsonparse-1.3.1.tgz" + "version" "1.3.1" + +"jsonpointer@^5.0.0": + "integrity" "sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==" + "resolved" "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.0.tgz" + "version" "5.0.0" + +"JSONStream@^1.0.4": + "integrity" "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==" + "resolved" "https://registry.npmmirror.com/JSONStream/-/JSONStream-1.3.5.tgz" + "version" "1.3.5" + dependencies: + "jsonparse" "^1.2.0" + "through" ">=2.2.7 <3" + +"junk@^3.1.0": + "integrity" "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==" + "resolved" "https://registry.npmmirror.com/junk/-/junk-3.1.0.tgz" + "version" "3.1.0" + +"keyv@3.0.0": + "integrity" "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==" + "resolved" "https://registry.npmmirror.com/keyv/-/keyv-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "json-buffer" "3.0.0" + +"kind-of@^3.0.2", "kind-of@^3.0.3": + "integrity" "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^3.2.0": + "integrity" "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^4.0.0": + "integrity" "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^5.0.0": + "integrity" "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-5.1.0.tgz" + "version" "5.1.0" + +"kind-of@^5.0.2": + "integrity" "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-5.1.0.tgz" + "version" "5.1.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2", "kind-of@^6.0.3": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"known-css-properties@^0.25.0": + "integrity" "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==" + "resolved" "https://registry.npmmirror.com/known-css-properties/-/known-css-properties-0.25.0.tgz" + "version" "0.25.0" + +"kolorist@^1.5.1": + "integrity" "sha512-lxpCM3HTvquGxKGzHeknB/sUjuVoUElLlfYnXZT73K8geR9jQbroGlSCFBax9/0mpGoD3kzcMLnOlGQPJJNyqQ==" + "resolved" "https://registry.npmmirror.com/kolorist/-/kolorist-1.5.1.tgz" + "version" "1.5.1" + +"less@*", "less@^4.1.2": + "integrity" "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==" + "resolved" "https://registry.npmmirror.com/less/-/less-4.1.3.tgz" + "version" "4.1.3" + dependencies: + "copy-anything" "^2.0.1" + "parse-node-version" "^1.0.1" + "tslib" "^2.3.0" + optionalDependencies: + "errno" "^0.1.1" + "graceful-fs" "^4.1.2" + "image-size" "~0.5.0" + "make-dir" "^2.1.0" + "mime" "^1.4.1" + "needle" "^3.1.0" + "source-map" "~0.6.0" + +"leven@^3.1.0": + "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "resolved" "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz" + "version" "3.1.0" + +"levn@^0.4.1": + "integrity" "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==" + "resolved" "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz" + "version" "0.4.1" + dependencies: + "prelude-ls" "^1.2.1" + "type-check" "~0.4.0" + +"lilconfig@2.0.4": + "integrity" "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" + "resolved" "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.0.4.tgz" + "version" "2.0.4" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"lint-staged@12.3.7": + "integrity" "sha512-/S4D726e2GIsDVWIk1XGvheCaDm1SJRQp8efamZFWJxQMVEbOwSysp7xb49Oo73KYCdy97mIWinhlxcoNqIfIQ==" + "resolved" "https://registry.npmmirror.com/lint-staged/-/lint-staged-12.3.7.tgz" + "version" "12.3.7" + dependencies: + "cli-truncate" "^3.1.0" + "colorette" "^2.0.16" + "commander" "^8.3.0" + "debug" "^4.3.3" + "execa" "^5.1.1" + "lilconfig" "2.0.4" + "listr2" "^4.0.1" + "micromatch" "^4.0.4" + "normalize-path" "^3.0.0" + "object-inspect" "^1.12.0" + "pidtree" "^0.5.0" + "string-argv" "^0.3.1" + "supports-color" "^9.2.1" + "yaml" "^1.10.2" + +"listr2@^4.0.1": + "integrity" "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==" + "resolved" "https://registry.npmmirror.com/listr2/-/listr2-4.0.5.tgz" + "version" "4.0.5" + dependencies: + "cli-truncate" "^2.1.0" + "colorette" "^2.0.16" + "log-update" "^4.0.0" + "p-map" "^4.0.0" + "rfdc" "^1.3.0" + "rxjs" "^7.5.5" + "through" "^2.3.8" + "wrap-ansi" "^7.0.0" + +"load-json-file@^1.0.0": + "integrity" "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==" + "resolved" "https://registry.npmmirror.com/load-json-file/-/load-json-file-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "graceful-fs" "^4.1.2" + "parse-json" "^2.2.0" + "pify" "^2.0.0" + "pinkie-promise" "^2.0.0" + "strip-bom" "^2.0.0" + +"load-json-file@^4.0.0": + "integrity" "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==" + "resolved" "https://registry.npmmirror.com/load-json-file/-/load-json-file-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "graceful-fs" "^4.1.2" + "parse-json" "^4.0.0" + "pify" "^3.0.0" + "strip-bom" "^3.0.0" + +"loader-utils@^1.1.0": + "integrity" "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz" + "version" "1.4.2" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^1.0.1" + +"locate-path@^2.0.0": + "integrity" "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==" + "resolved" "https://registry.npmmirror.com/locate-path/-/locate-path-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "p-locate" "^2.0.0" + "path-exists" "^3.0.0" + +"locate-path@^5.0.0": + "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" + "resolved" "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-locate" "^4.1.0" + +"locate-path@^6.0.0": + "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" + "resolved" "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "p-locate" "^5.0.0" + +"lodash-es@^4.17.15", "lodash-es@^4.17.21": + "integrity" "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + "resolved" "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz" + "version" "4.17.21" + +"lodash.debounce@^4.0.8": + "integrity" "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "resolved" "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.ismatch@^4.4.0": + "integrity" "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==" + "resolved" "https://registry.npmmirror.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz" + "version" "4.4.0" + +"lodash.merge@^4.6.2": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.sortby@^4.7.0": + "integrity" "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + "resolved" "https://registry.npmmirror.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz" + "version" "4.7.0" + +"lodash.truncate@^4.4.2": + "integrity" "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "resolved" "https://registry.npmmirror.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + "version" "4.4.2" + +"lodash@^4.17.15", "lodash@^4.17.19", "lodash@^4.17.20", "lodash@^4.17.21": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"log-symbols@^4.1.0": + "integrity" "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==" + "resolved" "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "chalk" "^4.1.0" + "is-unicode-supported" "^0.1.0" + +"log-update@^4.0.0": + "integrity" "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==" + "resolved" "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ansi-escapes" "^4.3.0" + "cli-cursor" "^3.1.0" + "slice-ansi" "^4.0.0" + "wrap-ansi" "^6.2.0" + +"logalot@^2.0.0", "logalot@^2.1.0": + "integrity" "sha512-Ah4CgdSRfeCJagxQhcVNMi9BfGYyEKLa6d7OA6xSbld/Hg3Cf2QiOa1mDpmG7Ve8LOH6DN3mdttzjQAvWTyVkw==" + "resolved" "https://registry.npmmirror.com/logalot/-/logalot-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "figures" "^1.3.5" + "squeak" "^1.0.0" + +"longest@^1.0.0": + "integrity" "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==" + "resolved" "https://registry.npmmirror.com/longest/-/longest-1.0.1.tgz" + "version" "1.0.1" + +"loose-envify@^1.0.0": + "integrity" "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==" + "resolved" "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"loud-rejection@^1.0.0": + "integrity" "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==" + "resolved" "https://registry.npmmirror.com/loud-rejection/-/loud-rejection-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "currently-unhandled" "^0.4.1" + "signal-exit" "^3.0.0" + +"lower-case@^2.0.2": + "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" + "resolved" "https://registry.npmmirror.com/lower-case/-/lower-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"lowercase-keys@^1.0.0": + "integrity" "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "resolved" "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + "version" "1.0.1" + +"lowercase-keys@1.0.0": + "integrity" "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==" + "resolved" "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz" + "version" "1.0.0" + +"lpad-align@^1.0.1": + "integrity" "sha512-MMIcFmmR9zlGZtBcFOows6c2COMekHCIFJz3ew/rRpKZ1wR4mXDPzvcVqLarux8M33X4TPSq2Jdw8WJj0q0KbQ==" + "resolved" "https://registry.npmmirror.com/lpad-align/-/lpad-align-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "get-stdin" "^4.0.1" + "indent-string" "^2.1.0" + "longest" "^1.0.0" + "meow" "^3.3.0" + +"lru-cache@^4.0.1": + "integrity" "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==" + "resolved" "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz" + "version" "4.1.5" + dependencies: + "pseudomap" "^1.0.2" + "yallist" "^2.1.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"magic-string@^0.25.0": + "integrity" "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==" + "resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz" + "version" "0.25.9" + dependencies: + "sourcemap-codec" "^1.4.8" + +"magic-string@^0.25.7": + "integrity" "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==" + "resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz" + "version" "0.25.9" + dependencies: + "sourcemap-codec" "^1.4.8" + +"magic-string@^0.26.1", "magic-string@^0.26.2": + "integrity" "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==" + "resolved" "https://registry.npmmirror.com/magic-string/-/magic-string-0.26.2.tgz" + "version" "0.26.2" + dependencies: + "sourcemap-codec" "^1.4.8" + +"make-dir@^1.0.0": + "integrity" "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==" + "resolved" "https://registry.npmmirror.com/make-dir/-/make-dir-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "pify" "^3.0.0" + +"make-dir@^1.2.0": + "integrity" "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "pify" "^3.0.0" + +"make-dir@^2.1.0": + "integrity" "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==" + "resolved" "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pify" "^4.0.1" + "semver" "^5.6.0" + +"make-dir@^3.0.0": + "integrity" "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==" + "resolved" "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "semver" "^6.0.0" + +"make-error@^1.1.1": + "integrity" "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "resolved" "https://registry.npmmirror.com/make-error/-/make-error-1.3.6.tgz" + "version" "1.3.6" + +"map-cache@^0.2.2": + "integrity" "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + "resolved" "https://registry.npmmirror.com/map-cache/-/map-cache-0.2.2.tgz" + "version" "0.2.2" + +"map-obj@^1.0.0", "map-obj@^1.0.1": + "integrity" "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==" + "resolved" "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz" + "version" "1.0.1" + +"map-obj@^4.0.0": + "integrity" "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==" + "resolved" "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz" + "version" "4.3.0" + +"map-visit@^1.0.0": + "integrity" "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==" + "resolved" "https://registry.npmmirror.com/map-visit/-/map-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "object-visit" "^1.0.0" + +"mathml-tag-names@^2.1.3": + "integrity" "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==" + "resolved" "https://registry.npmmirror.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz" + "version" "2.1.3" + +"mdn-data@2.0.14": + "integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + "resolved" "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz" + "version" "2.0.14" + +"memorystream@^0.3.1": + "integrity" "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==" + "resolved" "https://registry.npmmirror.com/memorystream/-/memorystream-0.3.1.tgz" + "version" "0.3.1" + +"meow@^3.3.0": + "integrity" "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==" + "resolved" "https://registry.npmmirror.com/meow/-/meow-3.7.0.tgz" + "version" "3.7.0" + dependencies: + "camelcase-keys" "^2.0.0" + "decamelize" "^1.1.2" + "loud-rejection" "^1.0.0" + "map-obj" "^1.0.1" + "minimist" "^1.1.3" + "normalize-package-data" "^2.3.4" + "object-assign" "^4.0.1" + "read-pkg-up" "^1.0.1" + "redent" "^1.0.0" + "trim-newlines" "^1.0.0" + +"meow@^8.0.0": + "integrity" "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==" + "resolved" "https://registry.npmmirror.com/meow/-/meow-8.1.2.tgz" + "version" "8.1.2" + dependencies: + "@types/minimist" "^1.2.0" + "camelcase-keys" "^6.2.2" + "decamelize-keys" "^1.1.0" + "hard-rejection" "^2.1.0" + "minimist-options" "4.1.0" + "normalize-package-data" "^3.0.0" + "read-pkg-up" "^7.0.1" + "redent" "^3.0.0" + "trim-newlines" "^3.0.0" + "type-fest" "^0.18.0" + "yargs-parser" "^20.2.3" + +"meow@^9.0.0": + "integrity" "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==" + "resolved" "https://registry.npmmirror.com/meow/-/meow-9.0.0.tgz" + "version" "9.0.0" + dependencies: + "@types/minimist" "^1.2.0" + "camelcase-keys" "^6.2.2" + "decamelize" "^1.2.0" + "decamelize-keys" "^1.1.0" + "hard-rejection" "^2.1.0" + "minimist-options" "4.1.0" + "normalize-package-data" "^3.0.0" + "read-pkg-up" "^7.0.1" + "redent" "^3.0.0" + "trim-newlines" "^3.0.0" + "type-fest" "^0.18.0" + "yargs-parser" "^20.2.3" + +"merge-options@1.0.1": + "integrity" "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==" + "resolved" "https://registry.npmmirror.com/merge-options/-/merge-options-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "is-plain-obj" "^1.1" + +"merge-stream@^2.0.0": + "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "resolved" "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz" + "version" "2.0.0" + +"merge2@^1.2.3", "merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"micromatch@^4.0.4", "micromatch@^4.0.5": + "integrity" "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==" + "resolved" "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz" + "version" "4.0.5" + dependencies: + "braces" "^3.0.2" + "picomatch" "^2.3.1" + +"micromatch@3.1.0": + "integrity" "sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==" + "resolved" "https://registry.npmmirror.com/micromatch/-/micromatch-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "braces" "^2.2.2" + "define-property" "^1.0.0" + "extend-shallow" "^2.0.1" + "extglob" "^2.0.2" + "fragment-cache" "^0.2.1" + "kind-of" "^5.0.2" + "nanomatch" "^1.2.1" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"mime-db@^1.28.0": + "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "resolved" "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz" + "version" "1.52.0" + +"mime@^1.4.1": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + +"mimic-response@^1.0.0": + "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "resolved" "https://registry.npmmirror.com/mimic-response/-/mimic-response-1.0.1.tgz" + "version" "1.0.1" + +"min-indent@^1.0.0": + "integrity" "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" + "resolved" "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4", "minimatch@^3.1.1", "minimatch@^3.1.2": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@^5.0.1": + "integrity" "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==" + "resolved" "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "brace-expansion" "^2.0.1" + +"minimist-options@4.1.0": + "integrity" "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==" + "resolved" "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "arrify" "^1.0.1" + "is-plain-obj" "^1.1.0" + "kind-of" "^6.0.3" + +"minimist@^1.1.3", "minimist@^1.2.0", "minimist@^1.2.5": + "integrity" "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "resolved" "https://registry.npmmirror.com/minimist/-/minimist-1.2.6.tgz" + "version" "1.2.6" + +"mixin-deep@^1.2.0": + "integrity" "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==" + "resolved" "https://registry.npmmirror.com/mixin-deep/-/mixin-deep-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "for-in" "^1.0.2" + "is-extendable" "^1.0.1" + +"mockjs@^1.1.0", "mockjs@>=1.1.0": + "integrity" "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==" + "resolved" "https://registry.npmmirror.com/mockjs/-/mockjs-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "commander" "*" + +"modify-values@^1.0.0": + "integrity" "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==" + "resolved" "https://registry.npmmirror.com/modify-values/-/modify-values-1.0.1.tgz" + "version" "1.0.1" + +"mousetrap@^1.6.5": + "integrity" "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" + "resolved" "https://registry.npmmirror.com/mousetrap/-/mousetrap-1.6.5.tgz" + "version" "1.6.5" + +"mozjpeg@^7.0.0": + "integrity" "sha512-iIDxWvzhWvLC9mcRJ1uSkiKaj4drF58oCqK2bITm5c2Jt6cJ8qQjSSru2PCaysG+hLIinryj8mgz5ZJzOYTv1A==" + "resolved" "https://registry.npmmirror.com/mozjpeg/-/mozjpeg-7.1.1.tgz" + "version" "7.1.1" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.0" + +"ms@^2.1.1", "ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"ms@2.0.0": + "integrity" "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "resolved" "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"mute-stream@0.0.8": + "integrity" "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "resolved" "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz" + "version" "0.0.8" + +"nanoid@^3.1.32", "nanoid@^3.3.4": + "integrity" "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "resolved" "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz" + "version" "3.3.4" + +"nanomatch@^1.2.1": + "integrity" "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==" + "resolved" "https://registry.npmmirror.com/nanomatch/-/nanomatch-1.2.13.tgz" + "version" "1.2.13" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "fragment-cache" "^0.2.1" + "is-windows" "^1.0.2" + "kind-of" "^6.0.2" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"nanopop@^2.1.0": + "integrity" "sha512-jGTwpFRexSH+fxappnGQtN9dspgE2ipa1aOjtR24igG0pv6JCxImIAmrLRHX+zUF5+1wtsFVbKyfP51kIGAVNw==" + "resolved" "https://registry.npmmirror.com/nanopop/-/nanopop-2.1.0.tgz" + "version" "2.1.0" + +"natural-compare@^1.4.0": + "integrity" "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "resolved" "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz" + "version" "1.4.0" + +"needle@^3.1.0": + "integrity" "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==" + "resolved" "https://registry.npmmirror.com/needle/-/needle-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "debug" "^3.2.6" + "iconv-lite" "^0.6.3" + "sax" "^1.2.4" + +"neo-async@^2.6.0": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"nice-try@^1.0.4": + "integrity" "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "resolved" "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz" + "version" "1.0.5" + +"no-case@^3.0.4": + "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" + "resolved" "https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "lower-case" "^2.0.2" + "tslib" "^2.0.3" + +"node-fetch@^2.6.7", "node-fetch@2.6.7": + "integrity" "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==" + "resolved" "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz" + "version" "2.6.7" + dependencies: + "whatwg-url" "^5.0.0" + +"node-html-parser@^5.3.3": + "integrity" "sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw==" + "resolved" "https://registry.npmmirror.com/node-html-parser/-/node-html-parser-5.3.3.tgz" + "version" "5.3.3" + dependencies: + "css-select" "^4.2.1" + "he" "1.2.0" + +"node-releases@^2.0.5": + "integrity" "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" + "resolved" "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.5.tgz" + "version" "2.0.5" + +"normalize-package-data@^2.3.2", "normalize-package-data@^2.3.4": + "integrity" "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==" + "resolved" "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "hosted-git-info" "^2.1.4" + "resolve" "^1.10.0" + "semver" "2 || 3 || 4 || 5" + "validate-npm-package-license" "^3.0.1" + +"normalize-package-data@^2.5.0": + "integrity" "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==" + "resolved" "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "hosted-git-info" "^2.1.4" + "resolve" "^1.10.0" + "semver" "2 || 3 || 4 || 5" + "validate-npm-package-license" "^3.0.1" + +"normalize-package-data@^3.0.0": + "integrity" "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==" + "resolved" "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz" + "version" "3.0.3" + dependencies: + "hosted-git-info" "^4.0.1" + "is-core-module" "^2.5.0" + "semver" "^7.3.4" + "validate-npm-package-license" "^3.0.1" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"normalize-range@^0.1.2": + "integrity" "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + "resolved" "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz" + "version" "0.1.2" + +"normalize-url@2.0.1": + "integrity" "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==" + "resolved" "https://registry.npmmirror.com/normalize-url/-/normalize-url-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "prepend-http" "^2.0.0" + "query-string" "^5.0.1" + "sort-keys" "^2.0.0" + +"npm-conf@^1.1.0": + "integrity" "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==" + "resolved" "https://registry.npmmirror.com/npm-conf/-/npm-conf-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "config-chain" "^1.1.11" + "pify" "^3.0.0" + +"npm-run-all@^4.1.5": + "integrity" "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==" + "resolved" "https://registry.npmmirror.com/npm-run-all/-/npm-run-all-4.1.5.tgz" + "version" "4.1.5" + dependencies: + "ansi-styles" "^3.2.1" + "chalk" "^2.4.1" + "cross-spawn" "^6.0.5" + "memorystream" "^0.3.1" + "minimatch" "^3.0.4" + "pidtree" "^0.3.0" + "read-pkg" "^3.0.0" + "shell-quote" "^1.6.1" + "string.prototype.padend" "^3.0.0" + +"npm-run-path@^2.0.0": + "integrity" "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==" + "resolved" "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "path-key" "^2.0.0" + +"npm-run-path@^4.0.0", "npm-run-path@^4.0.1": + "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" + "resolved" "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "path-key" "^3.0.0" + +"nprogress@^0.2.0": + "integrity" "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + "resolved" "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz" + "version" "0.2.0" + +"nth-check@^2.0.1": + "integrity" "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==" + "resolved" "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "boolbase" "^1.0.0" + +"object-assign@^4", "object-assign@^4.0.1", "object-assign@^4.1.0", "object-assign@^4.1.1": + "integrity" "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + "resolved" "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-copy@^0.1.0": + "integrity" "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==" + "resolved" "https://registry.npmmirror.com/object-copy/-/object-copy-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "copy-descriptor" "^0.1.0" + "define-property" "^0.2.5" + "kind-of" "^3.0.3" + +"object-inspect@^1.12.0", "object-inspect@^1.9.0": + "integrity" "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + "resolved" "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.2.tgz" + "version" "1.12.2" + +"object-keys@^1.1.1": + "integrity" "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "resolved" "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz" + "version" "1.1.1" + +"object-visit@^1.0.0": + "integrity" "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==" + "resolved" "https://registry.npmmirror.com/object-visit/-/object-visit-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "isobject" "^3.0.0" + +"object.assign@^4.1.0", "object.assign@^4.1.2": + "integrity" "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==" + "resolved" "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "call-bind" "^1.0.0" + "define-properties" "^1.1.3" + "has-symbols" "^1.0.1" + "object-keys" "^1.1.1" + +"object.pick@^1.3.0": + "integrity" "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==" + "resolved" "https://registry.npmmirror.com/object.pick/-/object.pick-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "isobject" "^3.0.1" + +"on-finished@~2.3.0": + "integrity" "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==" + "resolved" "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" + +"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": + "integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" + "resolved" "https://registry.npmmirror.com/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" + +"onetime@^5.1.0", "onetime@^5.1.2": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "mimic-fn" "^2.1.0" + +"open@^8.4.0": + "integrity" "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==" + "resolved" "https://registry.npmmirror.com/open/-/open-8.4.0.tgz" + "version" "8.4.0" + dependencies: + "define-lazy-prop" "^2.0.0" + "is-docker" "^2.1.1" + "is-wsl" "^2.2.0" + +"optionator@^0.9.1": + "integrity" "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==" + "resolved" "https://registry.npmmirror.com/optionator/-/optionator-0.9.1.tgz" + "version" "0.9.1" + dependencies: + "deep-is" "^0.1.3" + "fast-levenshtein" "^2.0.6" + "levn" "^0.4.1" + "prelude-ls" "^1.2.1" + "type-check" "^0.4.0" + "word-wrap" "^1.2.3" + +"optipng-bin@^7.0.0": + "integrity" "sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA==" + "resolved" "https://registry.npmmirror.com/optipng-bin/-/optipng-bin-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.0" + +"ora@^5.4.1": + "integrity" "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==" + "resolved" "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz" + "version" "5.4.1" + dependencies: + "bl" "^4.1.0" + "chalk" "^4.1.0" + "cli-cursor" "^3.1.0" + "cli-spinners" "^2.5.0" + "is-interactive" "^1.0.0" + "is-unicode-supported" "^0.1.0" + "log-symbols" "^4.1.0" + "strip-ansi" "^6.0.0" + "wcwidth" "^1.0.1" + +"os-filter-obj@^2.0.0": + "integrity" "sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==" + "resolved" "https://registry.npmmirror.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "arch" "^2.1.0" + +"os-tmpdir@~1.0.2": + "integrity" "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + "resolved" "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + "version" "1.0.2" + +"ow@^0.17.0": + "integrity" "sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA==" + "resolved" "https://registry.npmmirror.com/ow/-/ow-0.17.0.tgz" + "version" "0.17.0" + dependencies: + "type-fest" "^0.11.0" + +"p-cancelable@^0.3.0": + "integrity" "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + "resolved" "https://registry.npmmirror.com/p-cancelable/-/p-cancelable-0.3.0.tgz" + "version" "0.3.0" + +"p-cancelable@^0.4.0": + "integrity" "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + "resolved" "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz" + "version" "0.4.1" + +"p-event@^1.0.0": + "integrity" "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==" + "resolved" "https://registry.npmmirror.com/p-event/-/p-event-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "p-timeout" "^1.1.1" + +"p-event@^2.1.0": + "integrity" "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==" + "resolved" "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "p-timeout" "^2.0.1" + +"p-finally@^1.0.0": + "integrity" "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + "resolved" "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz" + "version" "1.0.0" + +"p-is-promise@^1.1.0": + "integrity" "sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==" + "resolved" "https://registry.npmmirror.com/p-is-promise/-/p-is-promise-1.1.0.tgz" + "version" "1.1.0" + +"p-limit@^1.1.0": + "integrity" "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" + "resolved" "https://registry.npmmirror.com/p-limit/-/p-limit-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "p-try" "^1.0.0" + +"p-limit@^2.2.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "p-try" "^2.0.0" + +"p-limit@^3.0.2": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "yocto-queue" "^0.1.0" + +"p-locate@^2.0.0": + "integrity" "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==" + "resolved" "https://registry.npmmirror.com/p-locate/-/p-locate-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "p-limit" "^1.1.0" + +"p-locate@^4.1.0": + "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" + "resolved" "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "p-limit" "^2.2.0" + +"p-locate@^5.0.0": + "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" + "resolved" "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-limit" "^3.0.2" + +"p-map-series@^1.0.0": + "integrity" "sha512-4k9LlvY6Bo/1FcIdV33wqZQES0Py+iKISU9Uc8p8AjWoZPnFKMpVIVD3s0EYn4jzLh1I+WeUZkJ0Yoa4Qfw3Kg==" + "resolved" "https://registry.npmmirror.com/p-map-series/-/p-map-series-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "p-reduce" "^1.0.0" + +"p-map@^4.0.0": + "integrity" "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==" + "resolved" "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "aggregate-error" "^3.0.0" + +"p-pipe@^3.0.0": + "integrity" "sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==" + "resolved" "https://registry.npmmirror.com/p-pipe/-/p-pipe-3.1.0.tgz" + "version" "3.1.0" + +"p-reduce@^1.0.0": + "integrity" "sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==" + "resolved" "https://registry.npmmirror.com/p-reduce/-/p-reduce-1.0.0.tgz" + "version" "1.0.0" + +"p-timeout@^1.1.1": + "integrity" "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==" + "resolved" "https://registry.npmmirror.com/p-timeout/-/p-timeout-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "p-finally" "^1.0.0" + +"p-timeout@^2.0.1": + "integrity" "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==" + "resolved" "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "p-finally" "^1.0.0" + +"p-try@^1.0.0": + "integrity" "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" + "resolved" "https://registry.npmmirror.com/p-try/-/p-try-1.0.0.tgz" + "version" "1.0.0" + +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" + +"param-case@^3.0.4": + "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" + "resolved" "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "callsites" "^3.0.0" + +"parse-json@^2.2.0": + "integrity" "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==" + "resolved" "https://registry.npmmirror.com/parse-json/-/parse-json-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "error-ex" "^1.2.0" + +"parse-json@^4.0.0": + "integrity" "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==" + "resolved" "https://registry.npmmirror.com/parse-json/-/parse-json-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "error-ex" "^1.3.1" + "json-parse-better-errors" "^1.0.1" + +"parse-json@^5.0.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "@babel/code-frame" "^7.0.0" + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parse-node-version@^1.0.1": + "integrity" "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + "resolved" "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz" + "version" "1.0.1" + +"parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascal-case@^3.1.2": + "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" + "resolved" "https://registry.npmmirror.com/pascal-case/-/pascal-case-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"pascalcase@^0.1.1": + "integrity" "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==" + "resolved" "https://registry.npmmirror.com/pascalcase/-/pascalcase-0.1.1.tgz" + "version" "0.1.1" + +"path-case@^3.0.4": + "integrity" "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==" + "resolved" "https://registry.npmmirror.com/path-case/-/path-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"path-exists@^2.0.0": + "integrity" "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==" + "resolved" "https://registry.npmmirror.com/path-exists/-/path-exists-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pinkie-promise" "^2.0.0" + +"path-exists@^3.0.0": + "integrity" "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + "resolved" "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz" + "version" "3.0.0" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "resolved" "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-key@^2.0.0", "path-key@^2.0.1": + "integrity" "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + "resolved" "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz" + "version" "2.0.1" + +"path-key@^2.0.1": + "integrity" "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + "resolved" "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz" + "version" "2.0.1" + +"path-key@^3.0.0", "path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@^6.2.0": + "integrity" "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + "resolved" "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz" + "version" "6.2.1" + +"path-type@^1.0.0": + "integrity" "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==" + "resolved" "https://registry.npmmirror.com/path-type/-/path-type-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "graceful-fs" "^4.1.2" + "pify" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"path-type@^3.0.0": + "integrity" "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==" + "resolved" "https://registry.npmmirror.com/path-type/-/path-type-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "pify" "^3.0.0" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"pathe@^0.2.0": + "integrity" "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==" + "resolved" "https://registry.npmmirror.com/pathe/-/pathe-0.2.0.tgz" + "version" "0.2.0" + +"pathe@^0.3.0": + "integrity" "sha512-qhnmX0TOqlCvdWWTkoM83wh5J8fZ2yhbDEc9MlsnAEtEc+JCwxUKEwmd6pkY9hRe6JR1Uecbc14VcAKX2yFSTA==" + "resolved" "https://registry.npmmirror.com/pathe/-/pathe-0.3.2.tgz" + "version" "0.3.2" + +"pend@~1.2.0": + "integrity" "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + "resolved" "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz" + "version" "1.2.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.2", "picomatch@^2.3.1": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pidtree@^0.3.0": + "integrity" "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==" + "resolved" "https://registry.npmmirror.com/pidtree/-/pidtree-0.3.1.tgz" + "version" "0.3.1" + +"pidtree@^0.5.0": + "integrity" "sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==" + "resolved" "https://registry.npmmirror.com/pidtree/-/pidtree-0.5.0.tgz" + "version" "0.5.0" + +"pify@^2.0.0", "pify@^2.2.0", "pify@^2.3.0": + "integrity" "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + "resolved" "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz" + "version" "2.3.0" + +"pify@^3.0.0": + "integrity" "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + "resolved" "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz" + "version" "3.0.0" + +"pify@^4.0.1": + "integrity" "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "resolved" "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + "version" "4.0.1" + +"pinia@2.0.12": + "integrity" "sha512-tUeuYGFrLU5irmGyRAIxp35q1OTcZ8sKpGT4XkPeVcG35W4R6cfXDbCGexzmVqH5lTQJJTXXbNGutIu9yS5yew==" + "resolved" "https://registry.npmmirror.com/pinia/-/pinia-2.0.12.tgz" + "version" "2.0.12" + dependencies: + "@vue/devtools-api" "^6.1.0" + "vue-demi" "*" + +"pinkie-promise@^2.0.0": + "integrity" "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==" + "resolved" "https://registry.npmmirror.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "pinkie" "^2.0.0" + +"pinkie@^2.0.0": + "integrity" "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + "resolved" "https://registry.npmmirror.com/pinkie/-/pinkie-2.0.4.tgz" + "version" "2.0.4" + +"pngquant-bin@^6.0.0": + "integrity" "sha512-Q3PUyolfktf+hYio6wsg3SanQzEU/v8aICg/WpzxXcuCMRb7H2Q81okfpcEztbMvw25ILjd3a87doj2N9kvbpQ==" + "resolved" "https://registry.npmmirror.com/pngquant-bin/-/pngquant-bin-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "bin-build" "^3.0.0" + "bin-wrapper" "^4.0.1" + "execa" "^4.0.0" + +"posix-character-classes@^0.1.0": + "integrity" "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" + "resolved" "https://registry.npmmirror.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz" + "version" "0.1.1" + +"postcss-html@^1.0.0", "postcss-html@^1.4.1": + "integrity" "sha512-OKihuWxPuBQrQeLNsavP7ytJ9IYNj/ViAXB2v7Qjh56LnfESKrkahKA9si4VfPN8xtz6oqUE6KdL0bTPrHJr6g==" + "resolved" "https://registry.npmmirror.com/postcss-html/-/postcss-html-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "htmlparser2" "^7.1.2" + "postcss" "^8.4.0" + "postcss-safe-parser" "^6.0.0" + +"postcss-less@^6.0.0": + "integrity" "sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==" + "resolved" "https://registry.npmmirror.com/postcss-less/-/postcss-less-6.0.0.tgz" + "version" "6.0.0" + +"postcss-media-query-parser@^0.2.3": + "integrity" "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==" + "resolved" "https://registry.npmmirror.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz" + "version" "0.2.3" + +"postcss-prefix-selector@^1.6.0": + "integrity" "sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==" + "resolved" "https://registry.npmmirror.com/postcss-prefix-selector/-/postcss-prefix-selector-1.16.0.tgz" + "version" "1.16.0" + +"postcss-resolve-nested-selector@^0.1.1": + "integrity" "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==" + "resolved" "https://registry.npmmirror.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz" + "version" "0.1.1" + +"postcss-safe-parser@^6.0.0": + "integrity" "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==" + "resolved" "https://registry.npmmirror.com/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz" + "version" "6.0.0" + +"postcss-selector-parser@^6.0.10", "postcss-selector-parser@^6.0.9": + "integrity" "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==" + "resolved" "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz" + "version" "6.0.10" + dependencies: + "cssesc" "^3.0.0" + "util-deprecate" "^1.0.2" + +"postcss-sorting@^7.0.1": + "integrity" "sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==" + "resolved" "https://registry.npmmirror.com/postcss-sorting/-/postcss-sorting-7.0.1.tgz" + "version" "7.0.1" + +"postcss-value-parser@^4.2.0": + "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved" "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + "version" "4.2.0" + +"postcss@^5.2.17": + "integrity" "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==" + "resolved" "https://registry.npmmirror.com/postcss/-/postcss-5.2.18.tgz" + "version" "5.2.18" + dependencies: + "chalk" "^1.1.3" + "js-base64" "^2.1.9" + "source-map" "^0.5.6" + "supports-color" "^3.2.3" + +"postcss@^8.1.0", "postcss@^8.1.10", "postcss@^8.3", "postcss@^8.3.11", "postcss@^8.3.3", "postcss@^8.3.5", "postcss@^8.3.9", "postcss@^8.4.0", "postcss@^8.4.12", "postcss@^8.4.13", "postcss@^8.4.14", "postcss@>4 <9": + "integrity" "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==" + "resolved" "https://registry.npmmirror.com/postcss/-/postcss-8.4.14.tgz" + "version" "8.4.14" + dependencies: + "nanoid" "^3.3.4" + "picocolors" "^1.0.0" + "source-map-js" "^1.0.2" + +"posthtml-parser@^0.2.0", "posthtml-parser@^0.2.1": + "integrity" "sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==" + "resolved" "https://registry.npmmirror.com/posthtml-parser/-/posthtml-parser-0.2.1.tgz" + "version" "0.2.1" + dependencies: + "htmlparser2" "^3.8.3" + "isobject" "^2.1.0" + +"posthtml-rename-id@^1.0": + "integrity" "sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==" + "resolved" "https://registry.npmmirror.com/posthtml-rename-id/-/posthtml-rename-id-1.0.12.tgz" + "version" "1.0.12" + dependencies: + "escape-string-regexp" "1.0.5" + +"posthtml-render@^1.0.5", "posthtml-render@^1.0.6": + "integrity" "sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==" + "resolved" "https://registry.npmmirror.com/posthtml-render/-/posthtml-render-1.4.0.tgz" + "version" "1.4.0" + +"posthtml-svg-mode@^1.0.3": + "integrity" "sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==" + "resolved" "https://registry.npmmirror.com/posthtml-svg-mode/-/posthtml-svg-mode-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "merge-options" "1.0.1" + "posthtml" "^0.9.2" + "posthtml-parser" "^0.2.1" + "posthtml-render" "^1.0.6" + +"posthtml@^0.9.2": + "integrity" "sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==" + "resolved" "https://registry.npmmirror.com/posthtml/-/posthtml-0.9.2.tgz" + "version" "0.9.2" + dependencies: + "posthtml-parser" "^0.2.0" + "posthtml-render" "^1.0.5" + +"preact@^10.4.8": + "integrity" "sha512-jO6/OvCRL+OT8gst/+Q2ir7dMybZAX8ioP02Zmzh3BkQMHLyqZSujvxbUriXvHi8qmhcHKC2Gwbog6Kt+YTh+Q==" + "resolved" "https://registry.npmmirror.com/preact/-/preact-10.9.0.tgz" + "version" "10.9.0" + +"prelude-ls@^1.2.1": + "integrity" "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "resolved" "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz" + "version" "1.2.1" + +"prepend-http@^1.0.1": + "integrity" "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==" + "resolved" "https://registry.npmmirror.com/prepend-http/-/prepend-http-1.0.4.tgz" + "version" "1.0.4" + +"prepend-http@^2.0.0": + "integrity" "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" + "resolved" "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" + "version" "2.0.0" + +"prettier-linter-helpers@^1.0.0": + "integrity" "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==" + "resolved" "https://registry.npmmirror.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "fast-diff" "^1.1.2" + +"prettier@^2.6.2", "prettier@>=2.0.0": + "integrity" "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==" + "resolved" "https://registry.npmmirror.com/prettier/-/prettier-2.7.1.tgz" + "version" "2.7.1" + +"pretty-bytes@^5.3.0", "pretty-bytes@^5.6.0": + "integrity" "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" + "resolved" "https://registry.npmmirror.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz" + "version" "5.6.0" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"proto-list@~1.2.1": + "integrity" "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + "resolved" "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz" + "version" "1.2.4" + +"prr@~1.0.1": + "integrity" "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" + "resolved" "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz" + "version" "1.0.1" + +"pseudomap@^1.0.2": + "integrity" "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + "resolved" "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz" + "version" "1.0.2" + +"pug-error@^2.0.0": + "integrity" "sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==" + "resolved" "https://registry.npmmirror.com/pug-error/-/pug-error-2.0.0.tgz" + "version" "2.0.0" + +"pug-lexer@^5.0.1": + "integrity" "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==" + "resolved" "https://registry.npmmirror.com/pug-lexer/-/pug-lexer-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "character-parser" "^2.2.0" + "is-expression" "^4.0.0" + "pug-error" "^2.0.0" + +"pug-parser@^6.0.0": + "integrity" "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==" + "resolved" "https://registry.npmmirror.com/pug-parser/-/pug-parser-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "pug-error" "^2.0.0" + "token-stream" "1.0.0" + +"pump@^3.0.0": + "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" + "resolved" "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "end-of-stream" "^1.1.0" + "once" "^1.3.1" + +"punycode@^2.1.0": + "integrity" "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "resolved" "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz" + "version" "2.1.1" + +"q@^1.5.1": + "integrity" "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + "resolved" "https://registry.npmmirror.com/q/-/q-1.5.1.tgz" + "version" "1.5.1" + +"qs@^6.10.3": + "integrity" "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==" + "resolved" "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz" + "version" "6.11.0" + dependencies: + "side-channel" "^1.0.4" + +"query-string@^4.3.2": + "integrity" "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==" + "resolved" "https://registry.npmmirror.com/query-string/-/query-string-4.3.4.tgz" + "version" "4.3.4" + dependencies: + "object-assign" "^4.1.0" + "strict-uri-encode" "^1.0.0" + +"query-string@^5.0.1": + "integrity" "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==" + "resolved" "https://registry.npmmirror.com/query-string/-/query-string-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "decode-uri-component" "^0.2.0" + "object-assign" "^4.1.0" + "strict-uri-encode" "^1.0.0" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"quick-lru@^4.0.1": + "integrity" "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" + "resolved" "https://registry.npmmirror.com/quick-lru/-/quick-lru-4.0.1.tgz" + "version" "4.0.1" + +"randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"read-pkg-up@^1.0.1": + "integrity" "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==" + "resolved" "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "find-up" "^1.0.0" + "read-pkg" "^1.0.0" + +"read-pkg-up@^3.0.0": + "integrity" "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==" + "resolved" "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "find-up" "^2.0.0" + "read-pkg" "^3.0.0" + +"read-pkg-up@^7.0.1": + "integrity" "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==" + "resolved" "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "find-up" "^4.1.0" + "read-pkg" "^5.2.0" + "type-fest" "^0.8.1" + +"read-pkg@^1.0.0": + "integrity" "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==" + "resolved" "https://registry.npmmirror.com/read-pkg/-/read-pkg-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "load-json-file" "^1.0.0" + "normalize-package-data" "^2.3.2" + "path-type" "^1.0.0" + +"read-pkg@^3.0.0": + "integrity" "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==" + "resolved" "https://registry.npmmirror.com/read-pkg/-/read-pkg-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "load-json-file" "^4.0.0" + "normalize-package-data" "^2.3.2" + "path-type" "^3.0.0" + +"read-pkg@^5.2.0": + "integrity" "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==" + "resolved" "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz" + "version" "5.2.0" + dependencies: + "@types/normalize-package-data" "^2.4.0" + "normalize-package-data" "^2.5.0" + "parse-json" "^5.0.0" + "type-fest" "^0.6.0" + +"readable-stream@^2.0.0": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^2.3.0", "readable-stream@^2.3.5": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^3.0.0", "readable-stream@^3.1.1", "readable-stream@^3.4.0", "readable-stream@3": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readable-stream@~2.3.6": + "integrity" "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==" + "resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.7.tgz" + "version" "2.3.7" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"redent@^1.0.0": + "integrity" "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==" + "resolved" "https://registry.npmmirror.com/redent/-/redent-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "indent-string" "^2.1.0" + "strip-indent" "^1.0.1" + +"redent@^3.0.0": + "integrity" "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==" + "resolved" "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "indent-string" "^4.0.0" + "strip-indent" "^3.0.0" + +"regenerate-unicode-properties@^10.0.1": + "integrity" "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==" + "resolved" "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + "version" "10.0.1" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.13.4", "regenerator-runtime@^0.13.9": + "integrity" "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "resolved" "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + "version" "0.13.9" + +"regenerator-transform@^0.15.0": + "integrity" "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==" + "resolved" "https://registry.npmmirror.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz" + "version" "0.15.0" + dependencies: + "@babel/runtime" "^7.8.4" + +"regex-not@^1.0.0", "regex-not@^1.0.2": + "integrity" "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==" + "resolved" "https://registry.npmmirror.com/regex-not/-/regex-not-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "extend-shallow" "^3.0.2" + "safe-regex" "^1.1.0" + +"regexp.prototype.flags@^1.4.1", "regexp.prototype.flags@^1.4.3": + "integrity" "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==" + "resolved" "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "functions-have-names" "^1.2.2" + +"regexpp@^3.2.0": + "integrity" "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + "resolved" "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz" + "version" "3.2.0" + +"regexpu-core@^5.1.0": + "integrity" "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==" + "resolved" "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.0.1" + "regjsgen" "^0.6.0" + "regjsparser" "^0.8.2" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.0.0" + +"regjsgen@^0.6.0": + "integrity" "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + "resolved" "https://registry.npmmirror.com/regjsgen/-/regjsgen-0.6.0.tgz" + "version" "0.6.0" + +"regjsparser@^0.8.2": + "integrity" "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==" + "resolved" "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.8.4.tgz" + "version" "0.8.4" + dependencies: + "jsesc" "~0.5.0" + +"relateurl@^0.2.7": + "integrity" "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + "resolved" "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz" + "version" "0.2.7" + +"repeat-element@^1.1.2": + "integrity" "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + "resolved" "https://registry.npmmirror.com/repeat-element/-/repeat-element-1.1.4.tgz" + "version" "1.1.4" + +"repeat-string@^1.6.1": + "integrity" "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" + "resolved" "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"repeating@^2.0.0": + "integrity" "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==" + "resolved" "https://registry.npmmirror.com/repeating/-/repeating-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-finite" "^1.0.0" + +"replace-ext@^1.0.0": + "integrity" "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" + "resolved" "https://registry.npmmirror.com/replace-ext/-/replace-ext-1.0.1.tgz" + "version" "1.0.1" + +"require-directory@^2.1.1": + "integrity" "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + "resolved" "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz" + "version" "2.1.1" + +"require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" + +"resize-observer-polyfill@^1.5.1": + "integrity" "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + "resolved" "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz" + "version" "1.5.1" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-from@^5.0.0", "resolve-from@5.0.0": + "integrity" "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + "resolved" "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz" + "version" "5.0.0" + +"resolve-global@^1.0.0", "resolve-global@1.0.0": + "integrity" "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==" + "resolved" "https://registry.npmmirror.com/resolve-global/-/resolve-global-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "global-dirs" "^0.1.1" + +"resolve-url@^0.2.1": + "integrity" "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" + "resolved" "https://registry.npmmirror.com/resolve-url/-/resolve-url-0.2.1.tgz" + "version" "0.2.1" + +"resolve@^1.10.0", "resolve@^1.14.2", "resolve@^1.19.0", "resolve@^1.22.0": + "integrity" "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==" + "resolved" "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz" + "version" "1.22.1" + dependencies: + "is-core-module" "^2.9.0" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"responselike@1.0.2": + "integrity" "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==" + "resolved" "https://registry.npmmirror.com/responselike/-/responselike-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "lowercase-keys" "^1.0.0" + +"restore-cursor@^3.1.0": + "integrity" "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==" + "resolved" "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "onetime" "^5.1.0" + "signal-exit" "^3.0.2" + +"ret@~0.1.10": + "integrity" "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "resolved" "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz" + "version" "0.1.15" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rfdc@^1.3.0": + "integrity" "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "resolved" "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz" + "version" "1.3.0" + +"rimraf@^2.5.4": + "integrity" "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==" + "resolved" "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz" + "version" "2.7.1" + dependencies: + "glob" "^7.1.3" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"rollup-plugin-purge-icons@^0.8.1": + "integrity" "sha512-7ktMV+gWtXAdOIShE8EtTcnpGhozi5H2hKk1MQVGt+7FmlLkjR+XKu1Nyzjocwd6xJvKube2Lh+SfcJ8FYYySw==" + "resolved" "https://registry.npmmirror.com/rollup-plugin-purge-icons/-/rollup-plugin-purge-icons-0.8.1.tgz" + "version" "0.8.1" + dependencies: + "@purge-icons/core" "^0.8.0" + "@purge-icons/generated" "^0.8.1" + +"rollup-plugin-terser@^7.0.0": + "integrity" "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==" + "resolved" "https://registry.npmmirror.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" + "version" "7.0.2" + dependencies: + "@babel/code-frame" "^7.10.4" + "jest-worker" "^26.2.1" + "serialize-javascript" "^4.0.0" + "terser" "^5.0.0" + +"rollup-plugin-visualizer@^5.6.0": + "integrity" "sha512-CKcc8GTUZjC+LsMytU8ocRr/cGZIfMR7+mdy4YnlyetlmIl/dM8BMnOEpD4JPIGt+ZVW7Db9ZtSsbgyeBH3uTA==" + "resolved" "https://registry.npmmirror.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.6.0.tgz" + "version" "5.6.0" + dependencies: + "nanoid" "^3.1.32" + "open" "^8.4.0" + "source-map" "^0.7.3" + "yargs" "^17.3.1" + +"rollup@^1.20.0 || ^2.0.0", "rollup@^1.20.0||^2.0.0", "rollup@^2.0.0", "rollup@^2.42.0", "rollup@^2.43.1", "rollup@^2.59.0", "rollup@^2.60.2", "rollup@^2.70.2": + "integrity" "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==" + "resolved" "https://registry.npmmirror.com/rollup/-/rollup-2.75.7.tgz" + "version" "2.75.7" + optionalDependencies: + "fsevents" "~2.3.2" + +"run-async@^2.4.0": + "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + "resolved" "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz" + "version" "2.4.1" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"rxjs@^7.2.0", "rxjs@^7.5.5": + "integrity" "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==" + "resolved" "https://registry.npmmirror.com/rxjs/-/rxjs-7.5.5.tgz" + "version" "7.5.5" + dependencies: + "tslib" "^2.1.0" + +"safe-buffer@^5.0.1", "safe-buffer@^5.1.0", "safe-buffer@^5.1.1", "safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-buffer@~5.2.0": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-regex@^1.1.0": + "integrity" "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==" + "resolved" "https://registry.npmmirror.com/safe-regex/-/safe-regex-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "ret" "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" + +"sax@^1.2.4": + "integrity" "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "resolved" "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz" + "version" "1.2.4" + +"scroll-into-view-if-needed@^2.2.25": + "integrity" "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==" + "resolved" "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz" + "version" "2.2.29" + dependencies: + "compute-scroll-into-view" "^1.0.17" + +"seek-bzip@^1.0.5": + "integrity" "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==" + "resolved" "https://registry.npmmirror.com/seek-bzip/-/seek-bzip-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "commander" "^2.8.1" + +"semver-regex@^2.0.0": + "integrity" "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==" + "resolved" "https://registry.npmmirror.com/semver-regex/-/semver-regex-2.0.0.tgz" + "version" "2.0.0" + +"semver-truncate@^1.1.2": + "integrity" "sha512-V1fGg9i4CL3qesB6U0L6XAm4xOJiHmt4QAacazumuasc03BvtFGIMCduv01JWQ69Nv+JST9TqhSCiJoxoY031w==" + "resolved" "https://registry.npmmirror.com/semver-truncate/-/semver-truncate-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "semver" "^5.3.0" + +"semver@^5.3.0": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^5.5.0": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^5.6.0": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@^6.0.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.1.1": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.1.2": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^6.3.0": + "integrity" "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz" + "version" "6.3.0" + +"semver@^7.0.0", "semver@^7.3.4", "semver@^7.3.5", "semver@^7.3.7", "semver@7.3.7": + "integrity" "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz" + "version" "7.3.7" + dependencies: + "lru-cache" "^6.0.0" + +"semver@2 || 3 || 4 || 5": + "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz" + "version" "5.7.1" + +"semver@7.0.0": + "integrity" "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + "resolved" "https://registry.npmmirror.com/semver/-/semver-7.0.0.tgz" + "version" "7.0.0" + +"sentence-case@^3.0.4": + "integrity" "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==" + "resolved" "https://registry.npmmirror.com/sentence-case/-/sentence-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + "upper-case-first" "^2.0.2" + +"serialize-javascript@^4.0.0": + "integrity" "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==" + "resolved" "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "randombytes" "^2.1.0" + +"set-value@^2.0.0", "set-value@^2.0.1": + "integrity" "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==" + "resolved" "https://registry.npmmirror.com/set-value/-/set-value-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "extend-shallow" "^2.0.1" + "is-extendable" "^0.1.1" + "is-plain-object" "^2.0.3" + "split-string" "^3.0.1" + +"shallow-equal@^1.0.0": + "integrity" "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" + "resolved" "https://registry.npmmirror.com/shallow-equal/-/shallow-equal-1.2.1.tgz" + "version" "1.2.1" + +"shebang-command@^1.2.0": + "integrity" "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==" + "resolved" "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "shebang-regex" "^1.0.0" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^1.0.0": + "integrity" "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" + "resolved" "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz" + "version" "1.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.6.1": + "integrity" "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + "resolved" "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.7.3.tgz" + "version" "1.7.3" + +"showdown@^2.1.0": + "integrity" "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==" + "resolved" "https://registry.npmmirror.com/showdown/-/showdown-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "commander" "^9.0.0" + +"side-channel@^1.0.4": + "integrity" "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==" + "resolved" "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "call-bind" "^1.0.0" + "get-intrinsic" "^1.0.2" + "object-inspect" "^1.9.0" + +"signal-exit@^3.0.0", "signal-exit@^3.0.2", "signal-exit@^3.0.3", "signal-exit@^3.0.7": + "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "resolved" "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz" + "version" "3.0.7" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slice-ansi@^3.0.0": + "integrity" "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==" + "resolved" "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "astral-regex" "^2.0.0" + "is-fullwidth-code-point" "^3.0.0" + +"slice-ansi@^4.0.0": + "integrity" "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==" + "resolved" "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "astral-regex" "^2.0.0" + "is-fullwidth-code-point" "^3.0.0" + +"slice-ansi@^5.0.0": + "integrity" "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==" + "resolved" "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "ansi-styles" "^6.0.0" + "is-fullwidth-code-point" "^4.0.0" + +"snake-case@^3.0.4": + "integrity" "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==" + "resolved" "https://registry.npmmirror.com/snake-case/-/snake-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "dot-case" "^3.0.4" + "tslib" "^2.0.3" + +"snapdragon-node@^2.0.1": + "integrity" "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==" + "resolved" "https://registry.npmmirror.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "define-property" "^1.0.0" + "isobject" "^3.0.0" + "snapdragon-util" "^3.0.1" + +"snapdragon-util@^3.0.1": + "integrity" "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==" + "resolved" "https://registry.npmmirror.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^3.2.0" + +"snapdragon@^0.8.1": + "integrity" "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==" + "resolved" "https://registry.npmmirror.com/snapdragon/-/snapdragon-0.8.2.tgz" + "version" "0.8.2" + dependencies: + "base" "^0.11.1" + "debug" "^2.2.0" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "map-cache" "^0.2.2" + "source-map" "^0.5.6" + "source-map-resolve" "^0.5.0" + "use" "^3.1.0" + +"sort-keys-length@^1.0.0": + "integrity" "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==" + "resolved" "https://registry.npmmirror.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "sort-keys" "^1.0.0" + +"sort-keys@^1.0.0": + "integrity" "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==" + "resolved" "https://registry.npmmirror.com/sort-keys/-/sort-keys-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "is-plain-obj" "^1.0.0" + +"sort-keys@^2.0.0": + "integrity" "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==" + "resolved" "https://registry.npmmirror.com/sort-keys/-/sort-keys-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "is-plain-obj" "^1.0.0" + +"sortablejs@^1.15.0": + "integrity" "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + "resolved" "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz" + "version" "1.15.0" + +"source-map-js@^1.0.2": + "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "resolved" "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz" + "version" "1.0.2" + +"source-map-resolve@^0.5.0": + "integrity" "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==" + "resolved" "https://registry.npmmirror.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + "version" "0.5.3" + dependencies: + "atob" "^2.1.2" + "decode-uri-component" "^0.2.0" + "resolve-url" "^0.2.1" + "source-map-url" "^0.4.0" + "urix" "^0.1.0" + +"source-map-support@~0.5.20": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map-url@^0.4.0": + "integrity" "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + "resolved" "https://registry.npmmirror.com/source-map-url/-/source-map-url-0.4.1.tgz" + "version" "0.4.1" + +"source-map@^0.5.6": + "integrity" "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + "resolved" "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0", "source-map@0.6.1": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"source-map@^0.7.3": + "integrity" "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + "resolved" "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz" + "version" "0.7.4" + +"source-map@^0.8.0-beta.0": + "integrity" "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==" + "resolved" "https://registry.npmmirror.com/source-map/-/source-map-0.8.0-beta.0.tgz" + "version" "0.8.0-beta.0" + dependencies: + "whatwg-url" "^7.0.0" + +"sourcemap-codec@^1.4.8": + "integrity" "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + "resolved" "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + "version" "1.4.8" + +"spdx-correct@^3.0.0": + "integrity" "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==" + "resolved" "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "spdx-expression-parse" "^3.0.0" + "spdx-license-ids" "^3.0.0" + +"spdx-exceptions@^2.1.0": + "integrity" "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "resolved" "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + "version" "2.3.0" + +"spdx-expression-parse@^3.0.0": + "integrity" "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==" + "resolved" "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "spdx-exceptions" "^2.1.0" + "spdx-license-ids" "^3.0.0" + +"spdx-license-ids@^3.0.0": + "integrity" "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + "resolved" "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz" + "version" "3.0.11" + +"split-string@^3.0.1", "split-string@^3.0.2": + "integrity" "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==" + "resolved" "https://registry.npmmirror.com/split-string/-/split-string-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "extend-shallow" "^3.0.0" + +"split@^1.0.0": + "integrity" "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==" + "resolved" "https://registry.npmmirror.com/split/-/split-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "through" "2" + +"split2@^3.0.0": + "integrity" "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==" + "resolved" "https://registry.npmmirror.com/split2/-/split2-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "readable-stream" "^3.0.0" + +"squeak@^1.0.0": + "integrity" "sha512-YQL1ulInM+ev8nXX7vfXsCsDh6IqXlrremc1hzi77776BtpWgYJUMto3UM05GSAaGzJgWekszjoKDrVNB5XG+A==" + "resolved" "https://registry.npmmirror.com/squeak/-/squeak-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "chalk" "^1.0.0" + "console-stream" "^0.1.1" + "lpad-align" "^1.0.1" + +"ssf@~0.11.2": + "integrity" "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==" + "resolved" "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz" + "version" "0.11.2" + dependencies: + "frac" "~1.1.2" + +"stable@^0.1.8": + "integrity" "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + "resolved" "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz" + "version" "0.1.8" + +"static-extend@^0.1.1": + "integrity" "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==" + "resolved" "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "define-property" "^0.2.5" + "object-copy" "^0.1.0" + +"statuses@~1.5.0": + "integrity" "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + "resolved" "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"strict-uri-encode@^1.0.0": + "integrity" "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==" + "resolved" "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" + "version" "1.1.0" + +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "safe-buffer" "~5.2.0" + +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-argv@^0.3.1": + "integrity" "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==" + "resolved" "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz" + "version" "0.3.1" + +"string-width@^4.1.0", "string-width@^4.2.0", "string-width@^4.2.3": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + +"string-width@^5.0.0": + "integrity" "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==" + "resolved" "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "eastasianwidth" "^0.2.0" + "emoji-regex" "^9.2.2" + "strip-ansi" "^7.0.1" + +"string.prototype.matchall@^4.0.6": + "integrity" "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==" + "resolved" "https://registry.npmmirror.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz" + "version" "4.0.7" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + "get-intrinsic" "^1.1.1" + "has-symbols" "^1.0.3" + "internal-slot" "^1.0.3" + "regexp.prototype.flags" "^1.4.1" + "side-channel" "^1.0.4" + +"string.prototype.padend@^3.0.0": + "integrity" "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==" + "resolved" "https://registry.npmmirror.com/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz" + "version" "3.1.3" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.3" + "es-abstract" "^1.19.1" + +"string.prototype.trimend@^1.0.5": + "integrity" "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==" + "resolved" "https://registry.npmmirror.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.4" + "es-abstract" "^1.19.5" + +"string.prototype.trimstart@^1.0.5": + "integrity" "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==" + "resolved" "https://registry.npmmirror.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz" + "version" "1.0.5" + dependencies: + "call-bind" "^1.0.2" + "define-properties" "^1.1.4" + "es-abstract" "^1.19.5" + +"stringify-object@^3.3.0": + "integrity" "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==" + "resolved" "https://registry.npmmirror.com/stringify-object/-/stringify-object-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "get-own-enumerable-property-symbols" "^3.0.0" + "is-obj" "^1.0.1" + "is-regexp" "^1.0.0" + +"strip-ansi@^3.0.0": + "integrity" "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==" + "resolved" "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "ansi-regex" "^2.0.0" + +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + +"strip-ansi@^7.0.1": + "integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==" + "resolved" "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "ansi-regex" "^6.0.1" + +"strip-bom@^2.0.0": + "integrity" "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==" + "resolved" "https://registry.npmmirror.com/strip-bom/-/strip-bom-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "is-utf8" "^0.2.0" + +"strip-bom@^3.0.0": + "integrity" "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + "resolved" "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz" + "version" "3.0.0" + +"strip-comments@^2.0.1": + "integrity" "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" + "resolved" "https://registry.npmmirror.com/strip-comments/-/strip-comments-2.0.1.tgz" + "version" "2.0.1" + +"strip-dirs@^2.0.0": + "integrity" "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==" + "resolved" "https://registry.npmmirror.com/strip-dirs/-/strip-dirs-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "is-natural-number" "^4.0.1" + +"strip-eof@^1.0.0": + "integrity" "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" + "resolved" "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz" + "version" "1.0.0" + +"strip-final-newline@^2.0.0": + "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "resolved" "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + "version" "2.0.0" + +"strip-indent@^1.0.1": + "integrity" "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==" + "resolved" "https://registry.npmmirror.com/strip-indent/-/strip-indent-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "get-stdin" "^4.0.1" + +"strip-indent@^3.0.0": + "integrity" "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==" + "resolved" "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "min-indent" "^1.0.0" + +"strip-json-comments@^3.1.0", "strip-json-comments@^3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" + +"strip-outer@^1.0.0": + "integrity" "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==" + "resolved" "https://registry.npmmirror.com/strip-outer/-/strip-outer-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "escape-string-regexp" "^1.0.2" + +"strnum@^1.0.4": + "integrity" "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + "resolved" "https://registry.npmmirror.com/strnum/-/strnum-1.0.5.tgz" + "version" "1.0.5" + +"style-search@^0.1.0": + "integrity" "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==" + "resolved" "https://registry.npmmirror.com/style-search/-/style-search-0.1.0.tgz" + "version" "0.1.0" + +"stylelint-config-html@>=1.0.0": + "integrity" "sha512-rKQUUWDpaYC7ybsS6tLxddjn6DxhjSIXybElSmcTyVQj3ExhmU3q+l41ktrlwHRyY0M5SkTkZiwngvYPYmsgSQ==" + "resolved" "https://registry.npmmirror.com/stylelint-config-html/-/stylelint-config-html-1.0.0.tgz" + "version" "1.0.0" + +"stylelint-config-prettier@^9.0.3": + "integrity" "sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==" + "resolved" "https://registry.npmmirror.com/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz" + "version" "9.0.3" + +"stylelint-config-recommended-vue@^1.4.0": + "integrity" "sha512-DVJqyX2KvMCn9U0+keL12r7xlsH26K4Vg8NrIZuq5MoF7g82DpMp326Om4E0Q+Il1o+bTHuUyejf2XAI0iD04Q==" + "resolved" "https://registry.npmmirror.com/stylelint-config-recommended-vue/-/stylelint-config-recommended-vue-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "semver" "^7.3.5" + "stylelint-config-html" ">=1.0.0" + "stylelint-config-recommended" ">=6.0.0" + +"stylelint-config-recommended@^7.0.0", "stylelint-config-recommended@>=6.0.0": + "integrity" "sha512-yGn84Bf/q41J4luis1AZ95gj0EQwRX8lWmGmBwkwBNSkpGSpl66XcPTulxGa/Z91aPoNGuIGBmFkcM1MejMo9Q==" + "resolved" "https://registry.npmmirror.com/stylelint-config-recommended/-/stylelint-config-recommended-7.0.0.tgz" + "version" "7.0.0" + +"stylelint-config-standard@^25.0.0": + "integrity" "sha512-21HnP3VSpaT1wFjFvv9VjvOGDtAviv47uTp3uFmzcN+3Lt+RYRv6oAplLaV51Kf792JSxJ6svCJh/G18E9VnCA==" + "resolved" "https://registry.npmmirror.com/stylelint-config-standard/-/stylelint-config-standard-25.0.0.tgz" + "version" "25.0.0" + dependencies: + "stylelint-config-recommended" "^7.0.0" + +"stylelint-order@^5.0.0": + "integrity" "sha512-OWQ7pmicXufDw5BlRqzdz3fkGKJPgLyDwD1rFY3AIEfIH/LQY38Vu/85v8/up0I+VPiuGRwbc2Hg3zLAsJaiyw==" + "resolved" "https://registry.npmmirror.com/stylelint-order/-/stylelint-order-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "postcss" "^8.3.11" + "postcss-sorting" "^7.0.1" + +"stylelint@^14.0.0", "stylelint@^14.4.0", "stylelint@^14.7.1", "stylelint@>=11.0.0", "stylelint@>=14.0.0": + "integrity" "sha512-RdAkJdPiLqHawCSnu21nE27MjNXaVd4WcOHA4vK5GtIGjScfhNnaOuWR2wWdfKFAvcWQPOYe311iveiVKSmwsA==" + "resolved" "https://registry.npmmirror.com/stylelint/-/stylelint-14.9.1.tgz" + "version" "14.9.1" + dependencies: + "@csstools/selector-specificity" "^2.0.1" + "balanced-match" "^2.0.0" + "colord" "^2.9.2" + "cosmiconfig" "^7.0.1" + "css-functions-list" "^3.1.0" + "debug" "^4.3.4" + "execall" "^2.0.0" + "fast-glob" "^3.2.11" + "fastest-levenshtein" "^1.0.12" + "file-entry-cache" "^6.0.1" + "get-stdin" "^8.0.0" + "global-modules" "^2.0.0" + "globby" "^11.1.0" + "globjoin" "^0.1.4" + "html-tags" "^3.2.0" + "ignore" "^5.2.0" + "import-lazy" "^4.0.0" + "imurmurhash" "^0.1.4" + "is-plain-object" "^5.0.0" + "known-css-properties" "^0.25.0" + "mathml-tag-names" "^2.1.3" + "meow" "^9.0.0" + "micromatch" "^4.0.5" + "normalize-path" "^3.0.0" + "picocolors" "^1.0.0" + "postcss" "^8.4.14" + "postcss-media-query-parser" "^0.2.3" + "postcss-resolve-nested-selector" "^0.1.1" + "postcss-safe-parser" "^6.0.0" + "postcss-selector-parser" "^6.0.10" + "postcss-value-parser" "^4.2.0" + "resolve-from" "^5.0.0" + "string-width" "^4.2.3" + "strip-ansi" "^6.0.1" + "style-search" "^0.1.0" + "supports-hyperlinks" "^2.2.0" + "svg-tags" "^1.0.0" + "table" "^6.8.0" + "v8-compile-cache" "^2.3.0" + "write-file-atomic" "^4.0.1" + +"supports-color@^2.0.0": + "integrity" "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + "resolved" "https://registry.npmmirror.com/supports-color/-/supports-color-2.0.0.tgz" + "version" "2.0.0" + +"supports-color@^3.2.3": + "integrity" "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==" + "resolved" "https://registry.npmmirror.com/supports-color/-/supports-color-3.2.3.tgz" + "version" "3.2.3" + dependencies: + "has-flag" "^1.0.0" + +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" + +"supports-color@^7.0.0", "supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "has-flag" "^4.0.0" + +"supports-color@^9.2.1": + "integrity" "sha512-XC6g/Kgux+rJXmwokjm9ECpD6k/smUoS5LKlUCcsYr4IY3rW0XyAympon2RmxGrlnZURMpg5T18gWDP9CsHXFA==" + "resolved" "https://registry.npmmirror.com/supports-color/-/supports-color-9.2.2.tgz" + "version" "9.2.2" + +"supports-hyperlinks@^2.2.0": + "integrity" "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==" + "resolved" "https://registry.npmmirror.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "has-flag" "^4.0.0" + "supports-color" "^7.0.0" + +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" + +"svg-baker@1.7.0": + "integrity" "sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==" + "resolved" "https://registry.npmmirror.com/svg-baker/-/svg-baker-1.7.0.tgz" + "version" "1.7.0" + dependencies: + "bluebird" "^3.5.0" + "clone" "^2.1.1" + "he" "^1.1.1" + "image-size" "^0.5.1" + "loader-utils" "^1.1.0" + "merge-options" "1.0.1" + "micromatch" "3.1.0" + "postcss" "^5.2.17" + "postcss-prefix-selector" "^1.6.0" + "posthtml-rename-id" "^1.0" + "posthtml-svg-mode" "^1.0.3" + "query-string" "^4.3.2" + "traverse" "^0.6.6" + +"svg-tags@^1.0.0": + "integrity" "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" + "resolved" "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz" + "version" "1.0.0" + +"svgo@^2.1.0", "svgo@^2.8.0": + "integrity" "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==" + "resolved" "https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "@trysound/sax" "0.2.0" + "commander" "^7.2.0" + "css-select" "^4.1.3" + "css-tree" "^1.1.3" + "csso" "^4.2.0" + "picocolors" "^1.0.0" + "stable" "^0.1.8" + +"systemjs@^6.12.1": + "integrity" "sha512-hqTN6kW+pN6/qro6G9OZ7ceDQOcYno020zBQKpZQLsJhYTDMCMNfXi/Y8duF5iW+4WWZr42ry0MMkcRGpbwG2A==" + "resolved" "https://registry.npmmirror.com/systemjs/-/systemjs-6.12.1.tgz" + "version" "6.12.1" + +"table@^6.8.0": + "integrity" "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==" + "resolved" "https://registry.npmmirror.com/table/-/table-6.8.0.tgz" + "version" "6.8.0" + dependencies: + "ajv" "^8.0.1" + "lodash.truncate" "^4.4.2" + "slice-ansi" "^4.0.0" + "string-width" "^4.2.3" + "strip-ansi" "^6.0.1" + +"tar-stream@^1.5.2": + "integrity" "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==" + "resolved" "https://registry.npmmirror.com/tar-stream/-/tar-stream-1.6.2.tgz" + "version" "1.6.2" + dependencies: + "bl" "^1.0.0" + "buffer-alloc" "^1.2.0" + "end-of-stream" "^1.0.0" + "fs-constants" "^1.0.0" + "readable-stream" "^2.3.0" + "to-buffer" "^1.1.1" + "xtend" "^4.0.0" + +"temp-dir@^1.0.0": + "integrity" "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==" + "resolved" "https://registry.npmmirror.com/temp-dir/-/temp-dir-1.0.0.tgz" + "version" "1.0.0" + +"temp-dir@^2.0.0": + "integrity" "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + "resolved" "https://registry.npmmirror.com/temp-dir/-/temp-dir-2.0.0.tgz" + "version" "2.0.0" + +"tempfile@^2.0.0": + "integrity" "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==" + "resolved" "https://registry.npmmirror.com/tempfile/-/tempfile-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "temp-dir" "^1.0.0" + "uuid" "^3.0.1" + +"tempfile@^3.0.0": + "integrity" "sha512-uNFCg478XovRi85iD42egu+eSFUmmka750Jy7L5tfHI5hQKKtbPnxaSaXAbBqCDYrw3wx4tXjKwci4/QmsZJxw==" + "resolved" "https://registry.npmmirror.com/tempfile/-/tempfile-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "temp-dir" "^2.0.0" + "uuid" "^3.3.2" + +"tempy@^0.6.0": + "integrity" "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==" + "resolved" "https://registry.npmmirror.com/tempy/-/tempy-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "is-stream" "^2.0.0" + "temp-dir" "^2.0.0" + "type-fest" "^0.16.0" + "unique-string" "^2.0.0" + +"terser@^5.0.0", "terser@^5.10.0": + "integrity" "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==" + "resolved" "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz" + "version" "5.16.5" + dependencies: + "@jridgewell/source-map" "^0.3.2" + "acorn" "^8.5.0" + "commander" "^2.20.0" + "source-map-support" "~0.5.20" + +"text-extensions@^1.0.0": + "integrity" "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==" + "resolved" "https://registry.npmmirror.com/text-extensions/-/text-extensions-1.9.0.tgz" + "version" "1.9.0" + +"text-table@^0.2.0": + "integrity" "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "resolved" "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"through@^2.3.6", "through@^2.3.8", "through@>=2.2.7 <3", "through@2": + "integrity" "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "resolved" "https://registry.npmmirror.com/through/-/through-2.3.8.tgz" + "version" "2.3.8" + +"through2@^2.0.0": + "integrity" "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==" + "resolved" "https://registry.npmmirror.com/through2/-/through2-2.0.5.tgz" + "version" "2.0.5" + dependencies: + "readable-stream" "~2.3.6" + "xtend" "~4.0.1" + +"through2@^4.0.0": + "integrity" "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==" + "resolved" "https://registry.npmmirror.com/through2/-/through2-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "readable-stream" "3" + +"timed-out@^4.0.0", "timed-out@^4.0.1": + "integrity" "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==" + "resolved" "https://registry.npmmirror.com/timed-out/-/timed-out-4.0.1.tgz" + "version" "4.0.1" + +"tinycolor2@^1.4.2": + "integrity" "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" + "resolved" "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.4.2.tgz" + "version" "1.4.2" + +"tinymce@^5.10.3": + "integrity" "sha512-9UUjaO0R7FxcFo0oxnd1lMs7H+D0Eh+dDVo5hKbVe1a+VB0nit97vOqlinj+YwgoBDt6/DSCUoWqAYlLI8BLYA==" + "resolved" "https://registry.npmjs.org/tinymce/-/tinymce-5.10.7.tgz" + "version" "5.10.7" + +"tmp@^0.0.33": + "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" + "resolved" "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz" + "version" "0.0.33" + dependencies: + "os-tmpdir" "~1.0.2" + +"to-buffer@^1.1.1": + "integrity" "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + "resolved" "https://registry.npmmirror.com/to-buffer/-/to-buffer-1.1.1.tgz" + "version" "1.1.1" + +"to-fast-properties@^2.0.0": + "integrity" "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + "resolved" "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-object-path@^0.3.0": + "integrity" "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==" + "resolved" "https://registry.npmmirror.com/to-object-path/-/to-object-path-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "kind-of" "^3.0.2" + +"to-regex-range@^2.1.0": + "integrity" "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==" + "resolved" "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"to-regex@^3.0.1": + "integrity" "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==" + "resolved" "https://registry.npmmirror.com/to-regex/-/to-regex-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "regex-not" "^1.0.2" + "safe-regex" "^1.1.0" + +"token-stream@1.0.0": + "integrity" "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==" + "resolved" "https://registry.npmmirror.com/token-stream/-/token-stream-1.0.0.tgz" + "version" "1.0.0" + +"tr46@^1.0.1": + "integrity" "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==" + "resolved" "https://registry.npmmirror.com/tr46/-/tr46-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "punycode" "^2.1.0" + +"tr46@~0.0.3": + "integrity" "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "resolved" "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"traverse@^0.6.6": + "integrity" "sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw==" + "resolved" "https://registry.npmmirror.com/traverse/-/traverse-0.6.6.tgz" + "version" "0.6.6" + +"trim-newlines@^1.0.0": + "integrity" "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==" + "resolved" "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-1.0.0.tgz" + "version" "1.0.0" + +"trim-newlines@^3.0.0": + "integrity" "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==" + "resolved" "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz" + "version" "3.0.1" + +"trim-repeated@^1.0.0": + "integrity" "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==" + "resolved" "https://registry.npmmirror.com/trim-repeated/-/trim-repeated-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "escape-string-regexp" "^1.0.2" + +"ts-node@^10.7.0", "ts-node@^10.8.1": + "integrity" "sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==" + "resolved" "https://registry.npmmirror.com/ts-node/-/ts-node-10.8.2.tgz" + "version" "10.8.2" + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + "acorn" "^8.4.1" + "acorn-walk" "^8.1.1" + "arg" "^4.1.0" + "create-require" "^1.1.0" + "diff" "^4.0.1" + "make-error" "^1.1.1" + "v8-compile-cache-lib" "^3.0.1" + "yn" "3.1.1" + +"tslib@^1.8.1": + "integrity" "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "resolved" "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz" + "version" "1.14.1" + +"tslib@^2.0.3", "tslib@^2.1.0", "tslib@^2.3.0", "tslib@2.3.0": + "integrity" "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + "resolved" "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz" + "version" "2.3.0" + +"tsutils@^3.21.0": + "integrity" "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==" + "resolved" "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz" + "version" "3.21.0" + dependencies: + "tslib" "^1.8.1" + +"tunnel-agent@^0.6.0": + "integrity" "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==" + "resolved" "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz" + "version" "0.6.0" + dependencies: + "safe-buffer" "^5.0.1" + +"type-check@^0.4.0", "type-check@~0.4.0": + "integrity" "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==" + "resolved" "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "prelude-ls" "^1.2.1" + +"type-fest@^0.11.0": + "integrity" "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.11.0.tgz" + "version" "0.11.0" + +"type-fest@^0.16.0": + "integrity" "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.16.0.tgz" + "version" "0.16.0" + +"type-fest@^0.18.0": + "integrity" "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.18.1.tgz" + "version" "0.18.1" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-fest@^0.21.3": + "integrity" "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz" + "version" "0.21.3" + +"type-fest@^0.6.0": + "integrity" "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz" + "version" "0.6.0" + +"type-fest@^0.8.1": + "integrity" "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "resolved" "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz" + "version" "0.8.1" + +"typescript@*", "typescript@^4.4.3", "typescript@^4.6.3", "typescript@>=2.7", "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", "typescript@>=3", "typescript@>=4.4.4": + "integrity" "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==" + "resolved" "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz" + "version" "4.7.4" + +"uglify-js@^3.1.4": + "integrity" "sha512-AaQNokTNgExWrkEYA24BTNMSjyqEXPSfhqoS0AxmHkCJ4U+Dyy5AvbGV/sqxuxficEfGGoX3zWw9R7QpLFfEsg==" + "resolved" "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.16.2.tgz" + "version" "3.16.2" + +"unbox-primitive@^1.0.2": + "integrity" "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==" + "resolved" "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "call-bind" "^1.0.2" + "has-bigints" "^1.0.2" + "has-symbols" "^1.0.3" + "which-boxed-primitive" "^1.0.2" + +"unbzip2-stream@^1.0.9": + "integrity" "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==" + "resolved" "https://registry.npmmirror.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz" + "version" "1.4.3" + dependencies: + "buffer" "^5.2.1" + "through" "^2.3.8" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.0.0": + "integrity" "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + "resolved" "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + "resolved" "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"union-value@^1.0.0": + "integrity" "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==" + "resolved" "https://registry.npmmirror.com/union-value/-/union-value-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "arr-union" "^3.1.0" + "get-value" "^2.0.6" + "is-extendable" "^0.1.1" + "set-value" "^2.0.1" + +"unique-string@^2.0.0": + "integrity" "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==" + "resolved" "https://registry.npmmirror.com/unique-string/-/unique-string-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "crypto-random-string" "^2.0.0" + +"universal-user-agent@^6.0.0": + "integrity" "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + "resolved" "https://registry.npmmirror.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz" + "version" "6.0.0" + +"universalify@^2.0.0": + "integrity" "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "resolved" "https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz" + "version" "2.0.0" + +"unpipe@~1.0.0": + "integrity" "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + "resolved" "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"unset-value@^1.0.0": + "integrity" "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==" + "resolved" "https://registry.npmmirror.com/unset-value/-/unset-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-value" "^0.3.1" + "isobject" "^3.0.0" + +"upath@^1.2.0": + "integrity" "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + "resolved" "https://registry.npmmirror.com/upath/-/upath-1.2.0.tgz" + "version" "1.2.0" + +"upath@^2.0.1": + "integrity" "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==" + "resolved" "https://registry.npmmirror.com/upath/-/upath-2.0.1.tgz" + "version" "2.0.1" + +"update-browserslist-db@^1.0.4": + "integrity" "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==" + "resolved" "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "escalade" "^3.1.1" + "picocolors" "^1.0.0" + +"upper-case-first@^2.0.2": + "integrity" "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==" + "resolved" "https://registry.npmmirror.com/upper-case-first/-/upper-case-first-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"upper-case@^2.0.2": + "integrity" "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==" + "resolved" "https://registry.npmmirror.com/upper-case/-/upper-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"urix@^0.1.0": + "integrity" "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" + "resolved" "https://registry.npmmirror.com/urix/-/urix-0.1.0.tgz" + "version" "0.1.0" + +"url-parse-lax@^1.0.0": + "integrity" "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==" + "resolved" "https://registry.npmmirror.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "prepend-http" "^1.0.1" + +"url-parse-lax@^3.0.0": + "integrity" "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==" + "resolved" "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "prepend-http" "^2.0.0" + +"url-to-options@^1.0.1": + "integrity" "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==" + "resolved" "https://registry.npmmirror.com/url-to-options/-/url-to-options-1.0.1.tgz" + "version" "1.0.1" + +"use@^3.1.0": + "integrity" "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "resolved" "https://registry.npmmirror.com/use/-/use-3.1.1.tgz" + "version" "3.1.1" + +"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": + "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "resolved" "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utils-merge@1.0.1": + "integrity" "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + "resolved" "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^3.0.1", "uuid@^3.3.2": + "integrity" "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "resolved" "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz" + "version" "3.4.0" + +"v8-compile-cache-lib@^3.0.1": + "integrity" "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "resolved" "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + "version" "3.0.1" + +"v8-compile-cache@^2.0.3", "v8-compile-cache@^2.3.0": + "integrity" "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "resolved" "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + "version" "2.3.0" + +"validate-npm-package-license@^3.0.1": + "integrity" "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==" + "resolved" "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "spdx-correct" "^3.0.0" + "spdx-expression-parse" "^3.0.0" + +"vary@^1": + "integrity" "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + "resolved" "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" + +"vditor@^3.8.13": + "integrity" "sha512-BYSBNUuhtvOfu1OU+NhS7R6TcrNP0UmQ8Vtbzq9BnLoG1uIHPZaTjtJIv00OPqHEcZa4KpR7mU+n9P+i+9SHuA==" + "resolved" "https://registry.npmmirror.com/vditor/-/vditor-3.8.15.tgz" + "version" "3.8.15" + dependencies: + "diff-match-patch" "^1.0.5" + +"vite-plugin-compression@^0.5.1": + "integrity" "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz" + "version" "0.5.1" + dependencies: + "chalk" "^4.1.2" + "debug" "^4.3.3" + "fs-extra" "^10.0.0" + +"vite-plugin-html@^3.2.0": + "integrity" "sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==" + "resolved" "https://registry.npmmirror.com/vite-plugin-html/-/vite-plugin-html-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "@rollup/pluginutils" "^4.2.0" + "colorette" "^2.0.16" + "connect-history-api-fallback" "^1.6.0" + "consola" "^2.15.3" + "dotenv" "^16.0.0" + "dotenv-expand" "^8.0.2" + "ejs" "^3.1.6" + "fast-glob" "^3.2.11" + "fs-extra" "^10.0.1" + "html-minifier-terser" "^6.1.0" + "node-html-parser" "^5.3.3" + "pathe" "^0.2.0" + +"vite-plugin-imagemin@^0.6.1": + "integrity" "sha512-cP7LDn8euPrji7WYtDoNQpJEB9nkMxJHm/A+QZnvMrrCSuyo/clpMy/T1v7suDXPBavsDiDdFdVQB5p7VGD2cg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-imagemin/-/vite-plugin-imagemin-0.6.1.tgz" + "version" "0.6.1" + dependencies: + "@types/imagemin" "^7.0.1" + "@types/imagemin-gifsicle" "^7.0.1" + "@types/imagemin-jpegtran" "^5.0.1" + "@types/imagemin-mozjpeg" "^8.0.1" + "@types/imagemin-optipng" "^5.2.1" + "@types/imagemin-svgo" "^10.0.0" + "@types/imagemin-webp" "^7.0.0" + "@types/svgo" "^2.6.1" + "chalk" "^4.1.2" + "debug" "^4.3.3" + "esbuild" "^0.14.14" + "fs-extra" "^10.0.0" + "gifsicle" "5.2.0" + "imagemin" "^7.0.1" + "imagemin-gifsicle" "^7.0.0" + "imagemin-jpegtran" "^7.0.0" + "imagemin-mozjpeg" "^9.0.0" + "imagemin-optipng" "^8.0.0" + "imagemin-pngquant" "^9.0.2" + "imagemin-svgo" "^9.0.0" + "imagemin-webp" "^6.0.0" + "jpegtran-bin" "^6.0.1" + "pathe" "^0.2.0" + +"vite-plugin-mkcert@^1.6.0": + "integrity" "sha512-YEmjMCy2mRs8SXYHQ4TcG0L7xztahnYCCaM+vMGXI9dAjHm/XUOVB9z/I0E5z5p4hraKA31oZynarE41CxoaRA==" + "resolved" "https://registry.npmmirror.com/vite-plugin-mkcert/-/vite-plugin-mkcert-1.7.2.tgz" + "version" "1.7.2" + dependencies: + "@octokit/rest" "^18.12.0" + "axios" "^0.21.4" + "debug" "^4.3.4" + "picocolors" "^1.0.0" + "vite" "^2.9.9" + +"vite-plugin-mock@^2.9.6": + "integrity" "sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-mock/-/vite-plugin-mock-2.9.6.tgz" + "version" "2.9.6" + dependencies: + "@rollup/plugin-node-resolve" "^13.0.4" + "@types/mockjs" "^1.0.4" + "chalk" "^4.1.2" + "chokidar" "^3.5.2" + "connect" "^3.7.0" + "debug" "^4.3.2" + "esbuild" "0.11.3" + "fast-glob" "^3.2.7" + "path-to-regexp" "^6.2.0" + +"vite-plugin-purge-icons@^0.8.1": + "integrity" "sha512-H77YDvECkdzwsgYTu6LR5Nx0wey5Hporw+3/hTYTZh7D7YcarS+RsOvpUEgd2XG5fChgCmMBtMfnr2JmrNanSg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-purge-icons/-/vite-plugin-purge-icons-0.8.1.tgz" + "version" "0.8.1" + dependencies: + "@purge-icons/core" "^0.8.0" + "@purge-icons/generated" "^0.8.1" + "rollup-plugin-purge-icons" "^0.8.1" + +"vite-plugin-pwa@^0.11.13": + "integrity" "sha512-Ssj14m3TRVLfkFEAWSMcFE2d1cSdEZyrVTzfY2lSL+umHYvcIFHVDAY143sygtBCb44OPczsAOmWwBTxwOvh7g==" + "resolved" "https://registry.npmmirror.com/vite-plugin-pwa/-/vite-plugin-pwa-0.11.13.tgz" + "version" "0.11.13" + dependencies: + "debug" "^4.3.3" + "fast-glob" "^3.2.7" + "pretty-bytes" "^5.6.0" + "rollup" "^2.60.2" + "workbox-build" "^6.4.2" + "workbox-window" "^6.4.2" + +"vite-plugin-style-import@^2.0.0": + "integrity" "sha512-qtoHQae5dSUQPo/rYz/8p190VU5y19rtBaeV7ryLa/AYAU/e9CG89NrN/3+k7MR8mJy/GPIu91iJ3zk9foUOSA==" + "resolved" "https://registry.npmmirror.com/vite-plugin-style-import/-/vite-plugin-style-import-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "@rollup/pluginutils" "^4.1.2" + "change-case" "^4.1.2" + "console" "^0.7.2" + "es-module-lexer" "^0.9.3" + "fs-extra" "^10.0.0" + "magic-string" "^0.25.7" + "pathe" "^0.2.0" + +"vite-plugin-svg-icons@^2.0.1": + "integrity" "sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==" + "resolved" "https://registry.npmmirror.com/vite-plugin-svg-icons/-/vite-plugin-svg-icons-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "@types/svgo" "^2.6.1" + "cors" "^2.8.5" + "debug" "^4.3.3" + "etag" "^1.8.1" + "fs-extra" "^10.0.0" + "pathe" "^0.2.0" + "svg-baker" "1.7.0" + "svgo" "^2.8.0" + +"vite-plugin-theme@^0.8.6": + "integrity" "sha512-GyoP9JjGkF106AawBh1kvw2eQZ/CCPeZKN5p5XhQe1ah1LO7A/6aVGY5gYGWk2qHG9nXpM1IvxjdbMsg94bvYg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-theme/-/vite-plugin-theme-0.8.6.tgz" + "version" "0.8.6" + dependencies: + "@types/node" "^14.17.1" + "@types/tinycolor2" "^1.4.2" + "chalk" "^4.1.1" + "clean-css" "^5.1.2" + "debug" "^4.3.2" + "esbuild" "^0.11.23" + "esbuild-plugin-alias" "^0.1.2" + "tinycolor2" "^1.4.2" + +"vite-plugin-vue-setup-extend@^0.4.0": + "integrity" "sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==" + "resolved" "https://registry.npmmirror.com/vite-plugin-vue-setup-extend/-/vite-plugin-vue-setup-extend-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "@vue/compiler-sfc" "^3.2.29" + "magic-string" "^0.25.7" + +"vite-plugin-windicss@^1.8.4": + "integrity" "sha512-D4G4qmumgklPiPrq/ZALqq8Mby6krskFVShbmb5c+0VCSsLUN96qyFRTwi81rNIHwFvlbpqflgh+BpUM/9VjQg==" + "resolved" "https://registry.npmmirror.com/vite-plugin-windicss/-/vite-plugin-windicss-1.8.6.tgz" + "version" "1.8.6" + dependencies: + "@windicss/plugin-utils" "1.8.6" + "debug" "^4.3.4" + "kolorist" "^1.5.1" + "windicss" "^3.5.6" + +"vite@^2.0.0", "vite@^2.0.0-beta.3", "vite@^2.0.1", "vite@^2.5.10", "vite@^2.8.0", "vite@^2.9.5", "vite@^2.9.9", "vite@>=2.0.0", "vite@>=2.0.0-beta.49": + "integrity" "sha512-AsOBAaT0AD7Mhe8DuK+/kE4aWYFMx/i0ZNi98hJclxb4e0OhQcZYUrvLjIaQ8e59Ui7txcvKMiJC1yftqpQoDw==" + "resolved" "https://registry.npmmirror.com/vite/-/vite-2.9.13.tgz" + "version" "2.9.13" + dependencies: + "esbuild" "^0.14.27" + "postcss" "^8.4.13" + "resolve" "^1.22.0" + "rollup" "^2.59.0" + optionalDependencies: + "fsevents" "~2.3.2" + +"vscode-jsonrpc@^8.0.0-next.5": + "integrity" "sha512-N/WKvghIajmEvXpatSzvTvOIz61ZSmOSa4BRA4pTLi+1+jozquQKP/MkaylP9iB68k73Oua1feLQvH3xQuigiQ==" + "resolved" "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.0.1.tgz" + "version" "8.0.1" + +"vscode-languageserver-textdocument@^1.0.3": + "integrity" "sha512-1ah7zyQjKBudnMiHbZmxz5bYNM9KKZYz+5VQLj+yr8l+9w3g+WAhCkUkWbhMEdC5u0ub4Ndiye/fDyS8ghIKQg==" + "resolved" "https://registry.npmmirror.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.5.tgz" + "version" "1.0.5" + +"vscode-languageserver-types@^3.17.0-next.6": + "integrity" "sha512-K3HqVRPElLZVVPtMeKlsyL9aK0GxGQpvtAUTfX4k7+iJ4mc1M+JM+zQwkgGy2LzY0f0IAafe8MKqIkJrxfGGjQ==" + "resolved" "https://registry.npmmirror.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.1.tgz" + "version" "3.17.1" + +"vscode-uri@^3.0.3": + "integrity" "sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==" + "resolved" "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.0.3.tgz" + "version" "3.0.3" + +"vue-demi@*": + "integrity" "sha512-41ukrclEbMddAyP7PvxMSYqnOSzPV6r7GNnyTSKSCNTaz19GehxmTiXyP9kwHSUv2+Dr6hHqiUiF7L1VAw2KdQ==" + "resolved" "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.2.tgz" + "version" "0.13.2" + +"vue-eslint-parser@^8.0.1", "vue-eslint-parser@^8.3.0": + "integrity" "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==" + "resolved" "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz" + "version" "8.3.0" + dependencies: + "debug" "^4.3.2" + "eslint-scope" "^7.0.0" + "eslint-visitor-keys" "^3.1.0" + "espree" "^9.0.0" + "esquery" "^1.4.0" + "lodash" "^4.17.21" + "semver" "^7.3.5" + +"vue-i18n@^9.1.9": + "integrity" "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==" + "resolved" "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.1.10.tgz" + "version" "9.1.10" + dependencies: + "@intlify/core-base" "9.1.10" + "@intlify/shared" "9.1.10" + "@intlify/vue-devtools" "9.1.10" + "@vue/devtools-api" "^6.0.0-beta.7" + +"vue-json-pretty@^2.0.6": + "integrity" "sha512-zl/gWr/zeQU4mUozlBxGu/9ebR/tYywty5VGu8FcHTJwOu9se4OwlPZELruwnzvHODfUOh8rUirSgNTHmLZXVw==" + "resolved" "https://registry.npmmirror.com/vue-json-pretty/-/vue-json-pretty-2.1.1.tgz" + "version" "2.1.1" + +"vue-router@^4.0.14": + "integrity" "sha512-Wp1mEf2xCwT0ez7o9JvgpfBp9JGnVb+dPERzXDbugTatzJAJ60VWOhJKifQty85k+jOreoFHER4r5fu062PhPw==" + "resolved" "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "@vue/devtools-api" "^6.1.4" + +"vue-tsc@^0.33.9": + "integrity" "sha512-s/+r4JNsCh4e3MUdsYrjEA8IgPPDzHL5kEah/OznxIHd1XMlYiIkXGdiyU6JE5J+lzXNOKdOlNliqwwpeETQWw==" + "resolved" "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-0.33.9.tgz" + "version" "0.33.9" + dependencies: + "@volar/vue-typescript" "0.33.9" + +"vue-types@^3.0.0": + "integrity" "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==" + "resolved" "https://registry.npmmirror.com/vue-types/-/vue-types-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "is-plain-object" "3.0.1" + +"vue-types@^4.1.1": + "integrity" "sha512-Jq2GZ/w6rExJbLA/h7nHBFLciu+YNekgox0DB64wN1snZ4IIJMq+qnqp1/vE4fc7vEjZcP5KGhLzkkSjIHLRzw==" + "resolved" "https://registry.npmmirror.com/vue-types/-/vue-types-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "is-plain-object" "5.0.0" + +"vue@^2.0.0 || ^3.0.0", "vue@^2.6.0 || ^3.2.0", "vue@^2.6.14 || ^3.2.0", "vue@^3.0.0", "vue@^3.0.0-0 || ^2.6.0", "vue@^3.0.1", "vue@^3.2.0", "vue@^3.2.25", "vue@^3.2.33", "vue@>=3.0.0", "vue@>=3.0.3", "vue@>=3.2.0", "vue@3.2.37": + "integrity" "sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==" + "resolved" "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz" + "version" "3.2.37" + dependencies: + "@vue/compiler-dom" "3.2.37" + "@vue/compiler-sfc" "3.2.37" + "@vue/runtime-dom" "3.2.37" + "@vue/server-renderer" "3.2.37" + "@vue/shared" "3.2.37" + +"warning@^4.0.0": + "integrity" "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==" + "resolved" "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "loose-envify" "^1.0.0" + +"wcwidth@^1.0.1": + "integrity" "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==" + "resolved" "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "defaults" "^1.0.3" + +"webidl-conversions@^3.0.0": + "integrity" "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "resolved" "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"webidl-conversions@^4.0.2": + "integrity" "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + "resolved" "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz" + "version" "4.0.2" + +"whatwg-url@^5.0.0": + "integrity" "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==" + "resolved" "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" + +"whatwg-url@^7.0.0": + "integrity" "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==" + "resolved" "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-7.1.0.tgz" + "version" "7.1.0" + dependencies: + "lodash.sortby" "^4.7.0" + "tr46" "^1.0.1" + "webidl-conversions" "^4.0.2" + +"which-boxed-primitive@^1.0.2": + "integrity" "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==" + "resolved" "https://registry.npmmirror.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-bigint" "^1.0.1" + "is-boolean-object" "^1.1.0" + "is-number-object" "^1.0.4" + "is-string" "^1.0.5" + "is-symbol" "^1.0.3" + +"which@^1.2.9": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmmirror.com/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^1.3.1": + "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" + "resolved" "https://registry.npmmirror.com/which/-/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmmirror.com/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"windicss@^3.5.6": + "integrity" "sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==" + "resolved" "https://registry.npmmirror.com/windicss/-/windicss-3.5.6.tgz" + "version" "3.5.6" + +"wmf@~1.0.1": + "integrity" "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" + "resolved" "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz" + "version" "1.0.2" + +"word-wrap@^1.2.3": + "integrity" "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "resolved" "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz" + "version" "1.2.3" + +"word@~0.3.0": + "integrity" "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==" + "resolved" "https://registry.npmmirror.com/word/-/word-0.3.0.tgz" + "version" "0.3.0" + +"wordwrap@^1.0.0": + "integrity" "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + "resolved" "https://registry.npmmirror.com/wordwrap/-/wordwrap-1.0.0.tgz" + "version" "1.0.0" + +"workbox-background-sync@6.5.3": + "integrity" "sha512-0DD/V05FAcek6tWv9XYj2w5T/plxhDSpclIcAGjA/b7t/6PdaRkQ7ZgtAX6Q/L7kV7wZ8uYRJUoH11VjNipMZw==" + "resolved" "https://registry.npmmirror.com/workbox-background-sync/-/workbox-background-sync-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "idb" "^6.1.4" + "workbox-core" "6.5.3" + +"workbox-broadcast-update@6.5.3": + "integrity" "sha512-4AwCIA5DiDrYhlN+Miv/fp5T3/whNmSL+KqhTwRBTZIL6pvTgE4lVuRzAt1JltmqyMcQ3SEfCdfxczuI4kwFQg==" + "resolved" "https://registry.npmmirror.com/workbox-broadcast-update/-/workbox-broadcast-update-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-build@^6.4.2": + "integrity" "sha512-8JNHHS7u13nhwIYCDea9MNXBNPHXCs5KDZPKI/ZNTr3f4sMGoD7hgFGecbyjX1gw4z6e9bMpMsOEJNyH5htA/w==" + "resolved" "https://registry.npmmirror.com/workbox-build/-/workbox-build-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "@apideck/better-ajv-errors" "^0.3.1" + "@babel/core" "^7.11.1" + "@babel/preset-env" "^7.11.0" + "@babel/runtime" "^7.11.2" + "@rollup/plugin-babel" "^5.2.0" + "@rollup/plugin-node-resolve" "^11.2.1" + "@rollup/plugin-replace" "^2.4.1" + "@surma/rollup-plugin-off-main-thread" "^2.2.3" + "ajv" "^8.6.0" + "common-tags" "^1.8.0" + "fast-json-stable-stringify" "^2.1.0" + "fs-extra" "^9.0.1" + "glob" "^7.1.6" + "lodash" "^4.17.20" + "pretty-bytes" "^5.3.0" + "rollup" "^2.43.1" + "rollup-plugin-terser" "^7.0.0" + "source-map" "^0.8.0-beta.0" + "stringify-object" "^3.3.0" + "strip-comments" "^2.0.1" + "tempy" "^0.6.0" + "upath" "^1.2.0" + "workbox-background-sync" "6.5.3" + "workbox-broadcast-update" "6.5.3" + "workbox-cacheable-response" "6.5.3" + "workbox-core" "6.5.3" + "workbox-expiration" "6.5.3" + "workbox-google-analytics" "6.5.3" + "workbox-navigation-preload" "6.5.3" + "workbox-precaching" "6.5.3" + "workbox-range-requests" "6.5.3" + "workbox-recipes" "6.5.3" + "workbox-routing" "6.5.3" + "workbox-strategies" "6.5.3" + "workbox-streams" "6.5.3" + "workbox-sw" "6.5.3" + "workbox-window" "6.5.3" + +"workbox-cacheable-response@6.5.3": + "integrity" "sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==" + "resolved" "https://registry.npmmirror.com/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-core@6.5.3": + "integrity" "sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==" + "resolved" "https://registry.npmmirror.com/workbox-core/-/workbox-core-6.5.3.tgz" + "version" "6.5.3" + +"workbox-expiration@6.5.3": + "integrity" "sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==" + "resolved" "https://registry.npmmirror.com/workbox-expiration/-/workbox-expiration-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "idb" "^6.1.4" + "workbox-core" "6.5.3" + +"workbox-google-analytics@6.5.3": + "integrity" "sha512-3GLCHotz5umoRSb4aNQeTbILETcrTVEozSfLhHSBaegHs1PnqCmN0zbIy2TjTpph2AGXiNwDrWGF0AN+UgDNTw==" + "resolved" "https://registry.npmmirror.com/workbox-google-analytics/-/workbox-google-analytics-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-background-sync" "6.5.3" + "workbox-core" "6.5.3" + "workbox-routing" "6.5.3" + "workbox-strategies" "6.5.3" + +"workbox-navigation-preload@6.5.3": + "integrity" "sha512-bK1gDFTc5iu6lH3UQ07QVo+0ovErhRNGvJJO/1ngknT0UQ702nmOUhoN9qE5mhuQSrnK+cqu7O7xeaJ+Rd9Tmg==" + "resolved" "https://registry.npmmirror.com/workbox-navigation-preload/-/workbox-navigation-preload-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-precaching@6.5.3": + "integrity" "sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==" + "resolved" "https://registry.npmmirror.com/workbox-precaching/-/workbox-precaching-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + "workbox-routing" "6.5.3" + "workbox-strategies" "6.5.3" + +"workbox-range-requests@6.5.3": + "integrity" "sha512-pGCP80Bpn/0Q0MQsfETSfmtXsQcu3M2QCJwSFuJ6cDp8s2XmbUXkzbuQhCUzKR86ZH2Vex/VUjb2UaZBGamijA==" + "resolved" "https://registry.npmmirror.com/workbox-range-requests/-/workbox-range-requests-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-recipes@6.5.3": + "integrity" "sha512-IcgiKYmbGiDvvf3PMSEtmwqxwfQ5zwI7OZPio3GWu4PfehA8jI8JHI3KZj+PCfRiUPZhjQHJ3v1HbNs+SiSkig==" + "resolved" "https://registry.npmmirror.com/workbox-recipes/-/workbox-recipes-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-cacheable-response" "6.5.3" + "workbox-core" "6.5.3" + "workbox-expiration" "6.5.3" + "workbox-precaching" "6.5.3" + "workbox-routing" "6.5.3" + "workbox-strategies" "6.5.3" + +"workbox-routing@6.5.3": + "integrity" "sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==" + "resolved" "https://registry.npmmirror.com/workbox-routing/-/workbox-routing-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-strategies@6.5.3": + "integrity" "sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==" + "resolved" "https://registry.npmmirror.com/workbox-strategies/-/workbox-strategies-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + +"workbox-streams@6.5.3": + "integrity" "sha512-vN4Qi8o+b7zj1FDVNZ+PlmAcy1sBoV7SC956uhqYvZ9Sg1fViSbOpydULOssVJ4tOyKRifH/eoi6h99d+sJ33w==" + "resolved" "https://registry.npmmirror.com/workbox-streams/-/workbox-streams-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "workbox-core" "6.5.3" + "workbox-routing" "6.5.3" + +"workbox-sw@6.5.3": + "integrity" "sha512-BQBzm092w+NqdIEF2yhl32dERt9j9MDGUTa2Eaa+o3YKL4Qqw55W9yQC6f44FdAHdAJrJvp0t+HVrfh8AiGj8A==" + "resolved" "https://registry.npmmirror.com/workbox-sw/-/workbox-sw-6.5.3.tgz" + "version" "6.5.3" + +"workbox-window@^6.4.2", "workbox-window@6.5.3": + "integrity" "sha512-GnJbx1kcKXDtoJBVZs/P7ddP0Yt52NNy4nocjBpYPiRhMqTpJCNrSL+fGHZ/i/oP6p/vhE8II0sA6AZGKGnssw==" + "resolved" "https://registry.npmmirror.com/workbox-window/-/workbox-window-6.5.3.tgz" + "version" "6.5.3" + dependencies: + "@types/trusted-types" "^2.0.2" + "workbox-core" "6.5.3" + +"wrap-ansi@^6.2.0": + "integrity" "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==" + "resolved" "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "resolved" "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"write-file-atomic@^4.0.1": + "integrity" "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==" + "resolved" "https://registry.npmmirror.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "imurmurhash" "^0.1.4" + "signal-exit" "^3.0.7" + +"xlsx@^0.18.5": + "integrity" "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==" + "resolved" "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz" + "version" "0.18.5" + dependencies: + "adler-32" "~1.3.0" + "cfb" "~1.2.1" + "codepage" "~1.15.0" + "crc-32" "~1.2.1" + "ssf" "~0.11.2" + "wmf" "~1.0.1" + "word" "~0.3.0" + +"xtend@^4.0.0", "xtend@~4.0.1": + "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "resolved" "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz" + "version" "4.0.2" + +"y18n@^5.0.5": + "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "resolved" "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz" + "version" "5.0.8" + +"yallist@^2.1.2": + "integrity" "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + "resolved" "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz" + "version" "2.1.2" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yaml@^1.10.0", "yaml@^1.10.2": + "integrity" "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + "resolved" "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz" + "version" "1.10.2" + +"yargs-parser@^20.2.2", "yargs-parser@^20.2.3": + "integrity" "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + "resolved" "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz" + "version" "20.2.9" + +"yargs-parser@^21.0.0": + "integrity" "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" + "resolved" "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.0.1.tgz" + "version" "21.0.1" + +"yargs@^16.2.0": + "integrity" "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==" + "resolved" "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz" + "version" "16.2.0" + dependencies: + "cliui" "^7.0.2" + "escalade" "^3.1.1" + "get-caller-file" "^2.0.5" + "require-directory" "^2.1.1" + "string-width" "^4.2.0" + "y18n" "^5.0.5" + "yargs-parser" "^20.2.2" + +"yargs@^17.0.0", "yargs@^17.3.1": + "integrity" "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==" + "resolved" "https://registry.npmmirror.com/yargs/-/yargs-17.5.1.tgz" + "version" "17.5.1" + dependencies: + "cliui" "^7.0.2" + "escalade" "^3.1.1" + "get-caller-file" "^2.0.5" + "require-directory" "^2.1.1" + "string-width" "^4.2.3" + "y18n" "^5.0.5" + "yargs-parser" "^21.0.0" + +"yauzl@^2.4.2": + "integrity" "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==" + "resolved" "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz" + "version" "2.10.0" + dependencies: + "buffer-crc32" "~0.2.3" + "fd-slicer" "~1.1.0" + +"yn@3.1.1": + "integrity" "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "resolved" "https://registry.npmmirror.com/yn/-/yn-3.1.1.tgz" + "version" "3.1.1" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0" + +"zrender@5.3.2": + "integrity" "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==" + "resolved" "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz" + "version" "5.3.2" + dependencies: + "tslib" "2.3.0"