feat: add docker shell

pull/48/MERGE
vben 2024-05-24 23:11:03 +08:00
parent d733987042
commit 38d58394e3
25 changed files with 394 additions and 120 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
node_modules
.git
.gitignore
*.md
dist

23
.vscode/settings.json vendored
View File

@ -12,6 +12,8 @@
// editor
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.cursorBlinking": "expand",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.fontFamily": "Input Mono, FiraCode-Retina, monospace",
"editor.fontLigatures": true,
@ -20,9 +22,17 @@
"editor.cursorSmoothCaretAnimation": "on",
"editor.guides.bracketPairs": "active",
"editor.inlineSuggest.enabled": true,
"editor.suggestSelection": "first",
"editor.suggestSelection": "recentlyUsedByPrefix",
"editor.acceptSuggestionOnEnter": "smart",
"editor.suggest.snippetsPreventQuickSuggestions": false,
"editor.stickyScroll.enabled": true,
"editor.hover.sticky": true,
"editor.suggest.insertMode": "replace",
"editor.bracketPairColorization.enabled": true,
"editor.autoClosingBrackets": "beforeWhitespace",
"editor.autoClosingDelete": "always",
"editor.autoClosingOvertype": "always",
"editor.autoClosingQuotes": "beforeWhitespace",
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
@ -38,6 +48,7 @@
"terminal.integrated.persistentSessionReviveProcess": "never",
"terminal.integrated.tabs.enabled": true,
"terminal.integrated.scrollback": 10000,
"terminal.integrated.stickyScroll.enabled": true,
// files
"files.eol": "\n",
@ -46,8 +57,8 @@
"files.associations": {
"*.ejs": "html",
"*.art": "html",
"**/tsconfig.json": "jsonc"
// "*.json": "jsonc"
"**/tsconfig.json": "jsonc",
"*.json": "jsonc"
},
"files.exclude": {
@ -77,6 +88,7 @@
},
// search
"search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false,
// 使/
"search.exclude": {
@ -124,6 +136,10 @@
"stylelint.packageManager": "pnpm",
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
"typescript.inlayHints.enumMemberValues.enabled": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"typescript.preferences.includePackageJsonAutoImports": "on",
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
"eslint.validate": [
@ -179,6 +195,7 @@
"*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
"Dockerfile": "Dockerfile,.docker*,docker-entrypoint.sh,build-local-docker*",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,.ls-lint*",
"tailwind.config.mjs": "postcss.*"
},

30
Dockerfile Normal file
View File

@ -0,0 +1,30 @@
FROM node:20-slim AS builder
# --max-old-space-size
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
ENV NODE_OPTIONS=--max-old-space-size=8192
ENV TZ=Asia/Shanghai
RUN corepack enable
WORKDIR /app
# copy package.json and pnpm-lock.yaml to workspace
COPY . /app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build
RUN echo "Builder Success 🎉"
FROM nginx:stable-alpine as production
COPY --from=builder /app/apps/antd-view/dist /usr/share/nginx/html
COPY ./deploy/nginx.conf /etc/nginx/nginx.conf
EXPOSE 8080
# start nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@ -0,0 +1,33 @@
import '@vben/styles';
import { setupI18n } from '@vben/locales';
import { preference } from '@vben/preference';
import { setupStore } from '@vben/stores';
import { createApp } from 'vue';
import App from './app.vue';
import { router } from './router';
async function bootstrap(namespace: string, env: string) {
const app = createApp(App);
// 国际化 i18n 配置
await setupI18n(app, { defaultLocale: preference.locale });
// 配置 pinia-store
await setupStore(app, { env, namespace });
// 配置路由及路由守卫
app.use(router);
app.mount('#app');
// production mock server
if (import.meta.env.PROD) {
import('./mock-prod-server').then(({ setupProdMockServer }) => {
setupProdMockServer();
});
}
}
export { bootstrap };

View File

@ -2,12 +2,7 @@
import type { NotificationItem } from '@vben/common-ui';
import { Notification, UserDropdown } from '@vben/common-ui';
import {
IcRoundCreditScore,
IcRoundSettingsSuggest,
MdiDriveDocument,
MdiGithub,
} from '@vben/icons';
import { IcRoundCreditScore, MdiDriveDocument, MdiGithub } from '@vben/icons';
import { BasicLayout } from '@vben/layouts';
import { $t } from '@vben/locales';
import { preference } from '@vben/preference';
@ -79,15 +74,6 @@ const menus = computed(() => [
icon: IcRoundCreditScore,
text: $t('widgets.qa'),
},
{
handler: () => {
// openWindow('https://github.com/vbenjs/vue-vben-admin', {
// target: '_blank',
// });
},
icon: IcRoundSettingsSuggest,
text: $t('widgets.setting'),
},
]);
const accessStore = useAccessStore();

View File

@ -1,40 +1,22 @@
import '@vben/styles';
import { setupPreference } from '@vben/preference';
import { setupI18n } from '@vben/locales';
import { preference, setupPreference } from '@vben/preference';
import { setupStore } from '@vben/stores';
import { createApp } from 'vue';
import App from './app.vue';
import { overridesPreference } from './preference';
import { router } from './router';
async function bootstrap(cachePrefix: string) {
// app偏好设置
/**
*
*/
async function initApplication() {
const namespace = 'antd-view';
const env = import.meta.env.PROD ? 'prod' : 'dev';
// app偏好设置初始化
await setupPreference({
cachePrefix,
env,
namespace,
overrides: overridesPreference,
});
const app = createApp(App);
// 国际化 i18n 配置
await setupI18n(app, { defaultLocale: preference.locale });
// 配置 pinia-store
await setupStore(app, { cachePrefix });
// 配置路由及路由守卫
app.use(router);
app.mount('#app');
// production mock server
if (import.meta.env.PROD) {
import('./mock-prod-server').then(({ setupProdMockServer }) => {
setupProdMockServer();
});
}
import('./bootstrap').then((m) => m.bootstrap(namespace, env));
}
bootstrap('vben-admin-pro-antd');
initApplication();

55
build-local-docker-image.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
LOG_FILE=${SCRIPT_DIR}/build-local-docker-image.log
ERROR=""
IMAGE_NAME="vben-admin-pro-local"
function stop_and_remove_container() {
# Stop and remove the existing container
docker stop ${IMAGE_NAME} >/dev/null 2>&1
docker rm ${IMAGE_NAME} >/dev/null 2>&1
}
function remove_image() {
# Remove the existing image
docker rmi vben-admin-pro >/dev/null 2>&1
}
function install_dependencies() {
# Install all dependencies
cd ${SCRIPT_DIR}
pnpm install || ERROR="install_dependencies failed"
}
function build_image() {
# build docker
docker build . -f Dockerfile -t ${IMAGE_NAME} || ERROR="build_image failed"
}
function log_message() {
if [[ ${ERROR} != "" ]];
then
>&2 echo "build failed, Please check build-local-docker-image.log for more details"
>&2 echo "ERROR: ${ERROR}"
exit 1
else
echo "docker image with tag '${IMAGE_NAME}' built sussessfully. Use below sample command to run the container"
echo ""
echo "docker run -d -p 8010:8080 --name ${IMAGE_NAME} ${IMAGE_NAME}"
fi
}
echo "Info: Stopping and removing existing container and image" | tee ${LOG_FILE}
stop_and_remove_container
remove_image
echo "Info: Installing dependencies" | tee -a ${LOG_FILE}
install_dependencies 1>> ${LOG_FILE} 2>> ${LOG_FILE}
if [[ ${ERROR} == "" ]]; then
echo "Info: Building docker image" | tee -a ${LOG_FILE}
build_image 1>> ${LOG_FILE} 2>> ${LOG_FILE}
fi
log_message | tee -a ${LOG_FILE}

87
deploy/nginx.conf Normal file
View File

@ -0,0 +1,87 @@
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
types {
application/javascript js mjs;
text/css css;
text/html html;
}
sendfile on;
# tcp_nopush on;
#keepalive_timeout 0;
# keepalive_timeout 65;
# gzip on;
# gzip_buffers 32 16k;
# gzip_comp_level 6;
# gzip_min_length 1k;
# gzip_static on;
# gzip_types text/plain
# text/css
# application/javascript
# application/json
# application/x-javascript
# text/xml
# application/xml
# application/xml+rss
# text/javascript; #设置压缩的文件类型
# gzip_vary on;
server {
listen 8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html;
# Enable CORS
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
# stream { # stream 模块配置和 http 模块在相同级别
# upstream redis {
# server 127.0.0.1:6379 max_fails=3 fail_timeout=30s;
# }
# server {
# listen 16379;
# proxy_connect_timeout 1s;
# proxy_timeout 3s;
# proxy_pass redis;
# }
# }

View File

@ -43,7 +43,7 @@
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-i": "^2.29.1",
"eslint-plugin-jsdoc": "^48.2.5",
"eslint-plugin-jsdoc": "^48.2.6",
"eslint-plugin-jsonc": "^2.15.1",
"eslint-plugin-n": "^17.7.0",
"eslint-plugin-no-only-tests": "^3.1.0",

View File

@ -47,14 +47,14 @@
"./*": "./*"
},
"dependencies": {
"@iconify/json": "^2.2.212",
"@iconify/json": "^2.2.213",
"@iconify/tailwind": "^1.1.1",
"@tailwindcss/forms": "^0.5.7",
"autoprefixer": "^10.4.19",
"cssnano": "^7.0.1",
"postcss": "^8.4.38",
"postcss-antd-fixes": "^0.2.0",
"postcss-preset-env": "^9.5.13",
"postcss-preset-env": "^9.5.14",
"tailwindcss": "^3.4.3",
"tailwindcss-animate": "^1.0.7"
},

View File

@ -45,7 +45,8 @@
"format": "vsh lint --format",
"prepare": "is-ci || husky",
"reinstall": "pnpm clean --del-lock && pnpm bootstrap",
"test": "vitest"
"test": "vitest",
"build:docker": "./build-local-docker-image.sh"
},
"devDependencies": {
"@changesets/cli": "^2.27.3",

View File

@ -0,0 +1,3 @@
# @vben-core
系统一些比较基础的SDK和UI组件库请勿将任何业务逻辑和业务包放在这里。

View File

@ -91,6 +91,8 @@ interface Preference {
pageTransitionEnable: boolean;
/** 是否开启半深色菜单只在theme='light'时生效) */
semiDarkMenu: boolean;
/** 是否显示偏好设置 */
showPreference: boolean;
/** 侧边栏是否折叠 */
sideCollapse: boolean;
/** 侧边栏折叠时是否显示title */

View File

@ -80,6 +80,33 @@ type MaybeReadonlyRef<T> = (() => T) | ComputedRef<T>;
*/
type MaybeComputedRef<T> = MaybeReadonlyRef<T> | MaybeRef<T>;
type Merge<O extends object, T extends object> = {
[K in keyof O | keyof T]: K extends keyof T
? T[K]
: K extends keyof O
? O[K]
: never;
};
/**
* T = [
* { name: string; age: number; },
* { sex: 'male' | 'female'; age: string }
* ]
* =>
* MergeAll<T> = {
* name: string;
* sex: 'male' | 'female';
* age: string
* }
*/
type MergeAll<
T extends object[],
R extends object = Record<string, any>,
> = T extends [infer F extends object, ...infer Rest extends object[]]
? MergeAll<Rest, Merge<R, F>>
: R;
export {
type AnyFunction,
type AnyNormalFunction,
@ -89,6 +116,8 @@ export {
type IntervalHandle,
type MaybeComputedRef,
type MaybeReadonlyRef,
type Merge,
type MergeAll,
type NonNullable,
type Nullable,
type ReadonlyRecordable,

View File

@ -22,6 +22,6 @@ const delegatedProps = computed(() => {
<template>
<DropdownMenuSeparator
v-bind="delegatedProps"
:class="cn('bg-muted -mx-1 my-1 h-px', props.class)"
:class="cn('bg-border -mx-1 my-1 h-px', props.class)"
/>
</template>

View File

@ -14,7 +14,7 @@ import {
import { $t } from '@vben/locales';
import { preference, resetPreference, usePreference } from '@vben/preference';
import { useClipboard } from '@vueuse/core';
import { computed, ref } from 'vue';
import { computed } from 'vue';
import {
Animation,
@ -33,6 +33,7 @@ import {
ThemeColor,
} from './blocks';
import Trigger from './trigger.vue';
import { useOpenPreference } from './use-open-preference';
withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
colorPrimaryPresets: () => [],
@ -106,11 +107,7 @@ const showBreadcrumbConfig = computed(() => {
);
});
const openSheet = ref(false);
function handlerOpenSheet() {
openSheet.value = true;
}
const { openPreference } = useOpenPreference();
async function handleCopy() {
await copy(JSON.stringify(diffPreference.value, null, 2));
@ -130,11 +127,12 @@ function handleReset() {
<template>
<div class="z-100 fixed right-0 top-1/3">
<VbenSheet
v-model:open="openPreference"
:description="$t('preference.preferences-subtitle')"
:title="$t('preference.preferences')"
>
<template #trigger>
<Trigger @click="handlerOpenSheet" />
<Trigger />
</template>
<template #extra>
<VbenIconButton

View File

@ -0,0 +1,16 @@
import { ref } from 'vue';
const openPreference = ref(false);
function useOpenPreference() {
function handleOpenPreference() {
openPreference.value = true;
}
return {
handleOpenPreference,
openPreference,
};
}
export { useOpenPreference };

View File

@ -1,5 +1,7 @@
<script setup lang="ts">
import { IcRoundLogout } from '@vben-core/iconify';
import type { AnyFunction } from '@vben/types';
import { IcRoundLogout, IcRoundSettingsSuggest } from '@vben-core/iconify';
import {
Badge,
DropdownMenu,
@ -16,9 +18,11 @@ import {
import type { Component } from 'vue';
import { $t } from '@vben/locales';
import { AnyFunction } from '@vben/types';
import { preference } from '@vben/preference';
import { ref } from 'vue';
import { useOpenPreference } from '../preference/use-open-preference';
interface Props {
/**
* 头像
@ -59,6 +63,8 @@ const emit = defineEmits<{ logout: [] }>();
const openPopover = ref(false);
const openDialog = ref(false);
const { handleOpenPreference } = useOpenPreference();
function handleLogout() {
// emit
openDialog.value = true;
@ -90,8 +96,8 @@ function handleSubmitLogout() {
</div>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent class="mr-2 min-w-[240px] p-0">
<DropdownMenuLabel class="border-border flex items-center border-b p-3">
<DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1">
<DropdownMenuLabel class="flex items-center p-3">
<VbenAvatar
:alt="text"
:src="avatar"
@ -117,22 +123,28 @@ function handleSubmitLogout() {
<DropdownMenuItem
v-for="menu in menus"
:key="menu.text"
class="mx-1 rounded-sm py-2.5"
class="lineh mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="menu.handler"
>
<VbenIcon :icon="menu.icon" class="mr-2 size-4" />
<VbenIcon :icon="menu.icon" class="mr-2 size-5" />
{{ menu.text }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem class="w-full p-0">
<div
class="border-border flex-center hover:bg-accent hover:text-accent-foreground h-10 w-full cursor-pointer border-t"
@click="handleLogout"
>
<IcRoundLogout class="mr-2" />
{{ $t('common.logout') }}
</div>
<DropdownMenuItem
v-if="preference"
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenPreference"
>
<IcRoundSettingsSuggest class="mr-2 size-5" />
{{ $t('preference.preferences') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleLogout"
>
<IcRoundLogout class="mr-2 size-5" />
{{ $t('common.logout') }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

View File

@ -127,7 +127,7 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
(value: boolean) => updatePreference('sideExpandOnHover', value)
"
>
<template #preference>
<template v-if="preference.showPreference" #preference>
<PreferenceWidget />
</template>

View File

@ -2,7 +2,7 @@ import type { Preference } from '@vben-core/typings';
class PreferenceCache {
cachePrefix: string;
constructor(cachePrefix: string = 'vben-admin') {
constructor(cachePrefix: string) {
this.cachePrefix = cachePrefix;
}
@ -24,8 +24,7 @@ class PreferenceCache {
*
*/
getCacheKey(name: string = 'preference') {
const env = import.meta.env.DEV ? 'dev' : 'prod';
return `__${this.cachePrefix}-${name}-${env}__`;
return `__${this.cachePrefix}-${name}__`;
}
/**

View File

@ -34,8 +34,9 @@ const defaultPreference: Preference = {
pageTransition: 'fade-slide',
pageTransitionEnable: true,
semiDarkMenu: true,
showPreference: true,
sideCollapse: false,
sideCollapseShowTitle: false,
sideCollapseShowTitle: true,
sideExpandOnHover: true,
sideExtraCollapse: true,
sideVisible: true,

View File

@ -4,22 +4,24 @@ import { PreferenceCache } from './cache';
import { overridesPreference } from './preference';
interface SetupPreferenceOptions {
/**
* @zh_CN
*/
env: string;
/**
* @zh_CN , @vben/preference appapp
*
*/
cachePrefix?: string;
namespace: string;
/**
* @zh_CN app
*/
overrides?: DeepPartial<Preference>;
}
async function setupPreference(options: SetupPreferenceOptions = {}) {
const { cachePrefix = 'vben-admin-pro', overrides = {} } = options;
const cache = new PreferenceCache(cachePrefix);
async function setupPreference(options: SetupPreferenceOptions) {
const { env, namespace, overrides = {} } = options;
const cache = new PreferenceCache(`${namespace}-${env}`);
overridesPreference(overrides, cache);
}

View File

@ -3,26 +3,29 @@ import type { App } from 'vue';
import { createPinia } from 'pinia';
interface SetupStoreOptions {
/**
* @zh_CN
*/
env: string;
/**
* @zh_CN , @vben/stores appapp
*
*/
cachePrefix?: string;
namespace: string;
}
/**
* @zh_CN pinia
* @param app vue app
*/
async function setupStore(app: App, options: SetupStoreOptions = {}) {
async function setupStore(app: App, options: SetupStoreOptions) {
const { createPersistedState } = await import('pinia-plugin-persistedstate');
const pinia = createPinia();
const { cachePrefix = 'vben-admin-pro' } = options;
const env = import.meta.env.DEV ? 'dev' : 'prod';
const { env, namespace } = options;
pinia.use(
createPersistedState({
// key $appName-$store.id
key: (storeKey) => `__${cachePrefix}-${storeKey}-${env}__`,
key: (storeKey) => `__${namespace}-${env}-${storeKey}__`,
storage: localStorage,
}),
);

View File

@ -19,9 +19,6 @@
"files": [
"dist"
],
"sideEffects": [
"**/*.css"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"imports": {
@ -42,6 +39,10 @@
}
}
},
"peerDependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/design-tokens": "workspace:*"
},
"dependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/design-tokens": "workspace:*"

View File

@ -198,8 +198,8 @@ importers:
specifier: ^2.29.1
version: 2.29.1(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)
eslint-plugin-jsdoc:
specifier: ^48.2.5
version: 48.2.5(eslint@8.57.0)
specifier: ^48.2.6
version: 48.2.6(eslint@8.57.0)
eslint-plugin-jsonc:
specifier: ^2.15.1
version: 2.15.1(eslint@8.57.0)
@ -331,8 +331,8 @@ importers:
internal/tailwind-config:
dependencies:
'@iconify/json':
specifier: ^2.2.212
version: 2.2.212
specifier: ^2.2.213
version: 2.2.213
'@iconify/tailwind':
specifier: ^1.1.1
version: 1.1.1
@ -352,8 +352,8 @@ importers:
specifier: ^0.2.0
version: 0.2.0(postcss@8.4.38)
postcss-preset-env:
specifier: ^9.5.13
version: 9.5.13(postcss@8.4.38)
specifier: ^9.5.14
version: 9.5.14(postcss@8.4.38)
tailwindcss:
specifier: ^3.4.3
version: 3.4.3
@ -1815,8 +1815,8 @@ packages:
'@humanwhocodes/object-schema@2.0.3':
resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
'@iconify/json@2.2.212':
resolution: {integrity: sha512-d1IXjpbSwk8V3C9D+mruRTJRPqZZpCnOWh9zyG/Zc5zJmPDLBEHNTKz+ZmeiJQ6LdzgjwLJai1WgFvt1HWVIPw==}
'@iconify/json@2.2.213':
resolution: {integrity: sha512-5tcEn+ZDoWlBXmlJidYjMsJyFXhXuVscbg7PRpaon86GqrDlwW/cl8mR682C06Oq4AfeypmfVI18YTnczwdqxA==}
'@iconify/tailwind@1.1.1':
resolution: {integrity: sha512-4mmA//qjZigv7D4KlqcVSYTqfRIJzyts2/lSCAJfCL0rVMIE76+ifJnaE5jxCo1+nYGBF8FsFo0qFOs+sX4EnA==}
@ -3643,8 +3643,8 @@ packages:
peerDependencies:
eslint: ^7.2.0 || ^8
eslint-plugin-jsdoc@48.2.5:
resolution: {integrity: sha512-ZeTfKV474W1N9niWfawpwsXGu+ZoMXu4417eBROX31d7ZuOk8zyG66SO77DpJ2+A9Wa2scw/jRqBPnnQo7VbcQ==}
eslint-plugin-jsdoc@48.2.6:
resolution: {integrity: sha512-GNk9jtpYmoEVeD/U6yYYmd6T8vSOoPs7CL8ZeX85iD8P3qifDdLQGze6+cw9boobDthmYnnxvIoHrhuSffj09g==}
engines: {node: '>=18'}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
@ -5554,8 +5554,8 @@ packages:
peerDependencies:
postcss: ^8.2.14
postcss-nesting@12.1.4:
resolution: {integrity: sha512-CcHOq94K137E+U4Ommu7pexcpp0Tjm24zl4UcqWs1oSLAr5cLI+jLrqQ5h/bdjhMX6cMbzunyustVNnvrzF8Zg==}
postcss-nesting@12.1.5:
resolution: {integrity: sha512-N1NgI1PDCiAGWPTYrwqm8wpjv0bgDmkYHH72pNsqTCv9CObxjxftdYu6AKtGN+pnJa7FQjMm3v4sp8QJbFsYdQ==}
engines: {node: ^14 || ^16 || >=18}
peerDependencies:
postcss: ^8.4
@ -5643,8 +5643,8 @@ packages:
peerDependencies:
postcss: ^8.4
postcss-preset-env@9.5.13:
resolution: {integrity: sha512-YQMwWu6MAc4Envrjf/mW2BTrb5J8WkrJ4dV2VostZVDhrmEPpYREOyhmvtlFLDxK1/AmTDY8aXjZViMC1qKu/w==}
postcss-preset-env@9.5.14:
resolution: {integrity: sha512-gTMi+3kENN/mN+K59aR+vEOjlkujTmmXJcM9rnAqGh9Y/euQ/ypdp9rd8mO1eoIjAD8vNS15+xbkBxoi+65BqQ==}
engines: {node: ^14 || ^16 || >=18}
peerDependencies:
postcss: ^8.4
@ -5703,6 +5703,10 @@ packages:
resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==}
engines: {node: '>=4'}
postcss-selector-parser@6.1.0:
resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
engines: {node: '>=4'}
postcss-sorting@8.0.2:
resolution: {integrity: sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==}
peerDependencies:
@ -8036,9 +8040,9 @@ snapshots:
dependencies:
postcss: 8.4.38
'@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.0.16)':
'@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.0)':
dependencies:
postcss-selector-parser: 6.0.16
postcss-selector-parser: 6.1.0
'@csstools/selector-specificity@3.0.3(postcss-selector-parser@6.0.16)':
dependencies:
@ -8048,6 +8052,10 @@ snapshots:
dependencies:
postcss-selector-parser: 6.0.16
'@csstools/selector-specificity@3.1.1(postcss-selector-parser@6.1.0)':
dependencies:
postcss-selector-parser: 6.1.0
'@csstools/utilities@1.0.0(postcss@8.4.38)':
dependencies:
postcss: 8.4.38
@ -8280,7 +8288,7 @@ snapshots:
'@humanwhocodes/object-schema@2.0.3': {}
'@iconify/json@2.2.212':
'@iconify/json@2.2.213':
dependencies:
'@iconify/types': 2.0.0
pathe: 1.1.2
@ -10390,7 +10398,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-jsdoc@48.2.5(eslint@8.57.0):
eslint-plugin-jsdoc@48.2.6(eslint@8.57.0):
dependencies:
'@es-joy/jsdoccomment': 0.43.0
are-docs-informative: 0.0.2
@ -10399,7 +10407,6 @@ snapshots:
escape-string-regexp: 4.0.0
eslint: 8.57.0
esquery: 1.5.0
is-builtin-module: 3.2.1
semver: 7.6.2
spdx-expression-parse: 4.0.0
transitivePeerDependencies:
@ -12353,12 +12360,12 @@ snapshots:
postcss: 8.4.38
postcss-selector-parser: 6.0.16
postcss-nesting@12.1.4(postcss@8.4.38):
postcss-nesting@12.1.5(postcss@8.4.38):
dependencies:
'@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.0.16)
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.0.16)
'@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.1.0)
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.0)
postcss: 8.4.38
postcss-selector-parser: 6.0.16
postcss-selector-parser: 6.1.0
postcss-normalize-charset@7.0.0(postcss@8.4.38):
dependencies:
@ -12429,7 +12436,7 @@ snapshots:
postcss: 8.4.38
postcss-value-parser: 4.2.0
postcss-preset-env@9.5.13(postcss@8.4.38):
postcss-preset-env@9.5.14(postcss@8.4.38):
dependencies:
'@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.38)
'@csstools/postcss-color-function': 3.0.16(postcss@8.4.38)
@ -12484,7 +12491,7 @@ snapshots:
postcss-image-set-function: 6.0.3(postcss@8.4.38)
postcss-lab-function: 6.0.16(postcss@8.4.38)
postcss-logical: 7.0.1(postcss@8.4.38)
postcss-nesting: 12.1.4(postcss@8.4.38)
postcss-nesting: 12.1.5(postcss@8.4.38)
postcss-opacity-percentage: 2.0.0(postcss@8.4.38)
postcss-overflow-shorthand: 5.0.1(postcss@8.4.38)
postcss-page-break: 3.0.4(postcss@8.4.38)
@ -12537,6 +12544,11 @@ snapshots:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-selector-parser@6.1.0:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
postcss-sorting@8.0.2(postcss@8.4.38):
dependencies:
postcss: 8.4.38