فهرست منبع

fix: various fixes + improvements

NGPixel 1 سال پیش
والد
کامیت
7f4417ee62

+ 36 - 35
.devcontainer/devcontainer.json

@@ -8,43 +8,44 @@
 	"workspaceFolder": "/workspace",
   "shutdownAction": "stopCompose",
 
-	// Set *default* container specific settings.json values on container create.
-	"settings": {
-    "terminal.integrated.defaultProfile.linux": "zsh",
-    "sqltools.connections": [
-      // Default connection to dev DB container
-      {
-          "name": "Local Dev",
-          "server": "db",
-          "port": 5432,
-          "database": "postgres",
-          "username": "postgres",
-          "password": "postgres",
-          "driver": "PostgreSQL",
-          "askForPassword": false,
-          "connectionTimeout": 60
-      }
-    ]
+  "customizations": {
+    "vscode": {
+      "settings": {
+        "terminal.integrated.defaultProfile.linux": "zsh",
+        "sqltools.connections": [
+          // Default connection to dev DB container
+          {
+              "name": "Local Dev",
+              "server": "db",
+              "port": 5432,
+              "database": "postgres",
+              "username": "postgres",
+              "password": "postgres",
+              "driver": "PostgreSQL",
+              "askForPassword": false,
+              "connectionTimeout": 60
+          }
+        ]
+      },
+      "extensions": [
+        "arcanis.vscode-zipfs",
+        "dbaeumer.vscode-eslint",
+        "eamodio.gitlens",
+        "Vue.volar",
+        "oderwat.indent-rainbow",
+        "redhat.vscode-yaml",
+        "VisualStudioExptTeam.vscodeintellicode",
+        "editorconfig.editorconfig",
+        "lokalise.i18n-ally",
+        "mrmlnc.vscode-duplicate",
+        "mtxr.sqltools-driver-pg",
+        "mutantdino.resourcemonitor",
+        "wayou.vscode-todo-highlight",
+        "GraphQL.vscode-graphql"
+      ]
+    }
   },
 
-	// Add the IDs of extensions you want installed when the container is created.
-	"extensions": [
-    "arcanis.vscode-zipfs",
-		"dbaeumer.vscode-eslint",
-		"eamodio.gitlens",
-		"Vue.volar",
-		"oderwat.indent-rainbow",
-		"redhat.vscode-yaml",
-		"VisualStudioExptTeam.vscodeintellicode",
-    "editorconfig.editorconfig",
-    "lokalise.i18n-ally",
-    "mrmlnc.vscode-duplicate",
-    "mtxr.sqltools-driver-pg",
-    "mutantdino.resourcemonitor",
-    "wayou.vscode-todo-highlight",
-    "GraphQL.vscode-graphql"
-	],
-
 	// Use 'forwardPorts' to make a list of ports inside the container available locally.
 	// This can be used to network with other containers or with the host.
 	"forwardPorts": [5432, 8000],

+ 1 - 0
.devcontainer/docker-compose.yml

@@ -45,6 +45,7 @@ services:
       - PGADMIN_DISABLE_POSTFIX=True
       - PGADMIN_LISTEN_PORT=8000
       - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False
+      - PGADMIN_CONFIG_LOGIN_BANNER="Login with dev@js.wiki / 123123"
     network_mode: service:db
     # volumes:
       # - ./pgadmin-servers.json:/pgadmin4/servers.json

+ 47 - 44
README.md

@@ -1,6 +1,9 @@
 <div align="center">
 
-<img src="https://static.requarks.io/logo/wikijs-full.svg" alt="Wiki.js" width="600" />
+<picture>
+  <source media="(prefers-color-scheme: dark)" srcset="https://static.requarks.io/logo/wikijs-full-darktheme.svg">
+  <img alt="Wiki.js" src="https://static.requarks.io/logo/wikijs-full.svg" width="600">
+</picture>
 
 [![License](https://img.shields.io/badge/license-AGPLv3-blue.svg?style=flat)](https://github.com/requarks/wiki/blob/master/LICENSE)
 [![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-green.svg?style=flat&logo=javascript&logoColor=white)](http://standardjs.com/)
@@ -27,66 +30,34 @@ The current stable release (2.x) is available at https://js.wiki
 
 ---
 
-- [Generic Setup](#generic-setup)
-  - [Requirements](#requirements)
-  - [Usage](#usage)
 - [Using VS Code Dev Environment](#using-vs-code-dev-environment) *(recommended)*
   - [Requirements](#requirements-1)
-  - [Usage](#usage-1)
+  - [Usage](#usage)
   - [Server Development](#server-development)
   - [Frontend Development (Quasar/Vue 3)](#frontend-development-quasarvue-3)
   - [pgAdmin](#pgadmin)
-
-## Generic Setup
-
-### Requirements
-
-- Node.js **18.x** or later
-- PostgreSQL **11** or later
-
-### Usage
-
-1. Clone the project
-1. Make a copy of `config.sample.yml` and rename it to `config.yml`
-1. Edit `config.yml` and fill in the database details. **You need an empty PostgreSQL database.**
-1. Run the following commands to install dependencies and generate the client assets:
-    ```sh
-    cd server
-    npm install
-    cd ../ux
-    npm install
-    npm run build
-    cd ..
-    ```
-1. Run this command to start the server:
-    ```sh
-    node server
-    ```
-1. In your browser, navigate to `http://localhost:3000` *(or the IP/hostname of the server and the PORT you defined earlier.)*
-1. Login using the default administrator user:
-    - Email: `admin@example.com`
-    - Password: `12345678`
-
-> **DO NOT** report bugs. This build is **VERY** buggy and **VERY** incomplete. Absolutely **NO** support is provided either.
+- [Generic Setup](#generic-setup)
+  - [Requirements](#requirements)
+  - [Usage](#usage-1)
 
 ## Using VS Code Dev Environment
 
 ### Requirements
 
-- VS Code
-- Docker Desktop
-- **Windows-only:** WSL 2 + WSL Integration enabled in Docker Desktop
+- [VS Code](https://code.visualstudio.com/)
+- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
+- **Windows-only:** [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install) + [WSL Integration](https://docs.docker.com/desktop/wsl/) enabled in Docker Desktop
 
 ### Usage
 
 1. Clone the project.
 1. Open the project in VS Code.
 1. Make sure you have **Dev Containers** extension installed. (On Windows, you need the **WSL** VS Code extension as well.)
-1. Reopen the project in container (from the popup in the lower-right corner of the screen when opening the project, or via the Command Palette (Ctrl+Shift+P) afterwards).
+1. Reopen the project in container (from the popup in the lower-right corner of the screen when opening the project, or via the Command Palette (Ctrl+Shift+P *or* F1) afterwards).
 1. Once in container mode, make a copy of `config.sample.yml` and rename it to `config.yml`. There's no need to edit the file, the default values are ok.
 1. From the Command Palette, run the task "Create terminals":
-    - Launch the Command Palette (Ctrl+Shift+P)
-    - Type "Run Task" and press Enter
+    - Launch the Command Palette (Ctrl+Shift+P *or* F1)
+    - Type `Run Task` and press <kbd>Enter</kbd>
     - Select the task "Create terminals" and press Enter
 1. Two terminals will launch in split-screen mode at the bottom of the screen. **Server** on the left and **UX** on the right.
 1. In the right-side terminal (UX), run the command:
@@ -116,7 +87,7 @@ This will launch the server and automatically restart upon modification of any s
 
 Only precompiled client assets are served in this mode. See the sections below on how to modify the frontend and run in SPA (Single Page Application) mode.
 
-### Frontend Development (Quasar/Vue 3)
+### Frontend Development
 
 > Make sure you are running `npm run dev` in the left-side terminal (Server) first! Requests still need to be forwarded to the server, even in SPA mode!
 
@@ -141,3 +112,35 @@ The server **dev** should already be available under **Servers**. If that's not
 - Username: `postgres`
 - Password: `postgres`
 - Database: `postgres`
+
+## Generic Setup
+
+### Requirements
+
+- Node.js **18.x** or later
+- PostgreSQL **11** or later
+
+### Usage
+
+1. Clone the project
+1. Make a copy of `config.sample.yml` and rename it to `config.yml`
+1. Edit `config.yml` and fill in the database details. **You need an empty PostgreSQL database.**
+1. Run the following commands to install dependencies and generate the client assets:
+    ```sh
+    cd server
+    npm install
+    cd ../ux
+    npm install
+    npm run build
+    cd ..
+    ```
+1. Run this command to start the server:
+    ```sh
+    node server
+    ```
+1. In your browser, navigate to `http://localhost:3000` *(or the IP/hostname of the server and the PORT you defined earlier.)*
+1. Login using the default administrator user:
+    - Email: `admin@example.com`
+    - Password: `12345678`
+
+> **DO NOT** report bugs. This build is **VERY** buggy and **VERY** incomplete. Absolutely **NO** support is provided either.

+ 0 - 28
docker-compose.yml

@@ -1,28 +0,0 @@
-version: '3.8'
-
-services:
-  db:
-    image: postgres:latest
-    restart: unless-stopped
-    volumes:
-      - postgres-data:/var/lib/postgresql/data
-    environment:
-      POSTGRES_PASSWORD: postgres
-      POSTGRES_USER: postgres
-      POSTGRES_DB: postgres
-    ports:
-      - "5432:5432"
-
-  pgadmin:
-    image: dpage/pgadmin4:latest
-    environment:
-      - PGADMIN_DEFAULT_EMAIL=dev@js.wiki
-      - PGADMIN_DEFAULT_PASSWORD=123123
-      - PGADMIN_DISABLE_POSTFIX=True
-      - PGADMIN_LISTEN_PORT=8000
-      - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False
-    ports:
-      - "8000:8000"
-
-volumes:
-  postgres-data:

+ 2 - 1
server/locales/en.json

@@ -336,7 +336,7 @@
   "admin.groups.ruleUntitled": "Untitled Rule",
   "admin.groups.rules": "Rules",
   "admin.groups.rulesNone": "This group doesn't have any rules yet.",
-  "admin.groups.selectedLocales": "Any Locale | {locale} locale only | {count} locales selected",
+  "admin.groups.selectedLocales": "Any Locale | {n} locale only | {count} locales selected",
   "admin.groups.selectedSites": "Any Site | 1 site selected | {count} sites selected",
   "admin.groups.subtitle": "Manage user groups and permissions",
   "admin.groups.title": "Groups",
@@ -1216,6 +1216,7 @@
   "common.actions.rename": "Rename",
   "common.actions.returnToTop": "Return to top",
   "common.actions.save": "Save",
+  "common.actions.saveAndClose": "Save and Close",
   "common.actions.saveChanges": "Save Changes",
   "common.actions.select": "Select",
   "common.actions.update": "Update",

+ 0 - 1
server/models/users.mjs

@@ -575,7 +575,6 @@ export class User extends Model {
           tfaSecret: ''
         }
       },
-      localeCode: 'en',
       hasAvatar: false,
       isSystem: false,
       isActive: true,

+ 309 - 236
server/package-lock.json

@@ -9,21 +9,21 @@
       "version": "3.0.0",
       "license": "AGPL-3.0",
       "dependencies": {
-        "@apollo/server": "4.7.3",
+        "@apollo/server": "4.7.5",
         "@azure/storage-blob": "12.14.0",
         "@exlinc/keycloak-passport": "1.0.2",
         "@graphql-tools/schema": "10.0.0",
         "@graphql-tools/utils": "10.0.1",
-        "@joplin/turndown-plugin-gfm": "1.0.47",
+        "@joplin/turndown-plugin-gfm": "1.0.49",
         "@root/csr": "0.8.1",
         "@root/keypairs": "0.10.3",
         "@root/pem": "1.0.4",
         "acme": "3.0.3",
         "akismet-api": "6.0.0",
-        "aws-sdk": "2.1395.0",
+        "aws-sdk": "2.1409.0",
         "bcryptjs": "2.4.3",
         "body-parser": "1.20.2",
-        "chalk": "5.2.0",
+        "chalk": "5.3.0",
         "cheerio": "1.0.0-rc.12",
         "chokidar": "3.5.3",
         "chromium-pickle-js": "0.2.0",
@@ -39,7 +39,7 @@
         "dependency-graph": "0.11.0",
         "diff": "5.1.0",
         "diff2html": "3.4.35",
-        "dompurify": "3.0.3",
+        "dompurify": "3.0.4",
         "dotize": "0.3.0",
         "emoji-regex": "10.2.1",
         "eventemitter2": "6.4.9",
@@ -50,14 +50,14 @@
         "filesize": "10.0.7",
         "fs-extra": "11.1.1",
         "getos": "3.2.1",
-        "graphql": "16.6.0",
+        "graphql": "16.7.1",
         "graphql-list-fields": "2.0.2",
         "graphql-rate-limit-directive": "2.0.3",
         "graphql-tools": "9.0.0",
         "graphql-upload": "16.0.2",
         "he": "1.2.0",
         "highlight.js": "11.8.0",
-        "i18next": "22.5.1",
+        "i18next": "23.2.6",
         "i18next-node-fs-backend": "2.1.3",
         "image-size": "1.0.2",
         "js-base64": "3.7.5",
@@ -65,7 +65,7 @@
         "js-yaml": "4.1.0",
         "jsdom": "22.1.0",
         "jsonwebtoken": "9.0.0",
-        "katex": "0.16.7",
+        "katex": "0.16.8",
         "klaw": "4.1.0",
         "knex": "2.4.2",
         "lodash": "4.17.21",
@@ -92,7 +92,7 @@
         "node-2fa": "2.0.3",
         "node-cache": "5.1.2",
         "nodemailer": "6.9.3",
-        "objection": "3.0.1",
+        "objection": "3.0.4",
         "passport": "0.6.0",
         "passport-auth0": "1.4.3",
         "passport-azure-ad": "4.3.5",
@@ -114,14 +114,14 @@
         "passport-slack-oauth2": "1.2.0",
         "passport-twitch-strategy": "2.2.0",
         "pem-jwk": "2.0.0",
-        "pg": "8.11.0",
+        "pg": "8.11.1",
         "pg-hstore": "2.3.4",
         "pg-pubsub": "0.8.1",
-        "pg-query-stream": "4.5.0",
+        "pg-query-stream": "4.5.1",
         "pg-tsquery": "8.4.1",
-        "poolifier": "2.6.2",
+        "poolifier": "2.6.5",
         "punycode": "2.3.0",
-        "puppeteer-core": "20.5.0",
+        "puppeteer-core": "20.7.4",
         "qr-image": "3.2.0",
         "rate-limiter-flexible": "2.4.1",
         "remove-markdown": "0.5.0",
@@ -130,13 +130,13 @@
         "safe-regex": "2.1.1",
         "sanitize-filename": "1.6.3",
         "scim-query-filter-parser": "2.0.4",
-        "semver": "7.5.1",
+        "semver": "7.5.3",
         "serve-favicon": "2.5.0",
         "sharp": "0.32.1",
-        "simple-git": "3.19.0",
-        "socket.io": "4.6.2",
+        "simple-git": "3.19.1",
+        "socket.io": "4.7.1",
         "striptags": "3.2.0",
-        "tar-fs": "2.1.1",
+        "tar-fs": "3.0.3",
         "turndown": "7.1.2",
         "twemoji": "14.0.2",
         "uslug": "1.0.4",
@@ -146,7 +146,7 @@
         "yargs": "17.7.2"
       },
       "devDependencies": {
-        "eslint": "8.42.0",
+        "eslint": "8.44.0",
         "eslint-config-requarks": "1.0.7",
         "eslint-config-standard": "17.1.0",
         "eslint-plugin-import": "2.27.5",
@@ -159,10 +159,19 @@
         "node": ">=18.0"
       }
     },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/@apollo/cache-control-types": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@apollo/cache-control-types/-/cache-control-types-1.0.2.tgz",
-      "integrity": "sha512-Por80co1eUm4ATsvjCOoS/tIR8PHxqVjsA6z76I6Vw0rFn4cgyVElQcmQDIZiYsy41k8e5xkrMRECkM2WR8pNw==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@apollo/cache-control-types/-/cache-control-types-1.0.3.tgz",
+      "integrity": "sha512-F17/vCp7QVwom9eG7ToauIKdAxpSoadsJnqIfyryLFSkLSOEqu+eC5Z3N8OXcUVStuOMcNHlyraRsA6rRICu4g==",
       "peerDependencies": {
         "graphql": "14.x || 15.x || 16.x"
       }
@@ -229,13 +238,13 @@
       }
     },
     "node_modules/@apollo/server": {
-      "version": "4.7.3",
-      "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.7.3.tgz",
-      "integrity": "sha512-eFCzHHheNHfVALjYJjIghV7kSgO49ZFr8+4g2CKOLShoDmLplQ3blyL5NsONyC0Z5l8kqm62V8yXGoxy2eNGfw==",
+      "version": "4.7.5",
+      "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.7.5.tgz",
+      "integrity": "sha512-XobKpTnW/jbmr0DuJ+8zBzoeL6uEat4CkBN7kOCjhXEUuCNxiLrQGrWFVDqgV7bSdOJr6o2POmZYBPNQXLdyvA==",
       "dependencies": {
-        "@apollo/cache-control-types": "^1.0.2",
-        "@apollo/server-gateway-interface": "^1.1.0",
-        "@apollo/usage-reporting-protobuf": "^4.1.0",
+        "@apollo/cache-control-types": "^1.0.3",
+        "@apollo/server-gateway-interface": "^1.1.1",
+        "@apollo/usage-reporting-protobuf": "^4.1.1",
         "@apollo/utils.createhash": "^2.0.0",
         "@apollo/utils.fetcher": "^2.0.0",
         "@apollo/utils.isnodelike": "^2.0.0",
@@ -268,11 +277,11 @@
       }
     },
     "node_modules/@apollo/server-gateway-interface": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.0.tgz",
-      "integrity": "sha512-0rhG++QtGfr4YhhIHgxZ9BdMFthaPY6LbhI9Au90osbfLMiZ7f8dmZsEX1mp7O1h8MJwCu6Dp0I/KcGbSvfUGA==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz",
+      "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==",
       "dependencies": {
-        "@apollo/usage-reporting-protobuf": "^4.0.0",
+        "@apollo/usage-reporting-protobuf": "^4.1.1",
         "@apollo/utils.fetcher": "^2.0.0",
         "@apollo/utils.keyvaluecache": "^2.1.0",
         "@apollo/utils.logger": "^2.0.0"
@@ -281,54 +290,6 @@
         "graphql": "14.x || 15.x || 16.x"
       }
     },
-    "node_modules/@apollo/server-gateway-interface/node_modules/@apollo/utils.keyvaluecache": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz",
-      "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==",
-      "dependencies": {
-        "@apollo/utils.logger": "^2.0.1",
-        "lru-cache": "^7.14.1"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@apollo/server-gateway-interface/node_modules/@apollo/utils.logger": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz",
-      "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==",
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@apollo/server-gateway-interface/node_modules/lru-cache": {
-      "version": "7.18.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
-      "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/@apollo/server/node_modules/@apollo/utils.keyvaluecache": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz",
-      "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==",
-      "dependencies": {
-        "@apollo/utils.logger": "^2.0.1",
-        "lru-cache": "^7.14.1"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@apollo/server/node_modules/@apollo/utils.logger": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz",
-      "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==",
-      "engines": {
-        "node": ">=14"
-      }
-    },
     "node_modules/@apollo/server/node_modules/@graphql-tools/merge": {
       "version": "8.4.2",
       "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz",
@@ -375,9 +336,9 @@
       }
     },
     "node_modules/@apollo/usage-reporting-protobuf": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/@apollo/usage-reporting-protobuf/-/usage-reporting-protobuf-4.1.0.tgz",
-      "integrity": "sha512-hXouMuw5pQVkzi8dgMybmr6Y11+eRmMQVoB5TF0HyTwAg9SOq/v3OCuiYqcVUKdBcskU9Msp+XvjAk0GKpWCwQ==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/@apollo/usage-reporting-protobuf/-/usage-reporting-protobuf-4.1.1.tgz",
+      "integrity": "sha512-u40dIUePHaSKVshcedO7Wp+mPiZsaU6xjv9J+VyxpoU/zL6Jle+9zWeG98tr/+SZ0nZ4OXhrbb8SNr0rAPpIDA==",
       "dependencies": {
         "@apollo/protobufjs": "1.2.7"
       }
@@ -421,6 +382,34 @@
         "node": ">=14"
       }
     },
+    "node_modules/@apollo/utils.keyvaluecache": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz",
+      "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==",
+      "dependencies": {
+        "@apollo/utils.logger": "^2.0.1",
+        "lru-cache": "^7.14.1"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": {
+      "version": "7.18.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+      "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@apollo/utils.logger": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz",
+      "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==",
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@apollo/utils.printwithreducedwhitespace": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-2.0.1.tgz",
@@ -628,9 +617,9 @@
       }
     },
     "node_modules/@babel/runtime": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
-      "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+      "version": "7.22.5",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
+      "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
       "dependencies": {
         "regenerator-runtime": "^0.13.11"
       },
@@ -663,14 +652,14 @@
       }
     },
     "node_modules/@eslint/eslintrc": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
-      "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
+      "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
       "dev": true,
       "dependencies": {
         "ajv": "^6.12.4",
         "debug": "^4.3.2",
-        "espree": "^9.5.2",
+        "espree": "^9.6.0",
         "globals": "^13.19.0",
         "ignore": "^5.2.0",
         "import-fresh": "^3.2.1",
@@ -709,9 +698,9 @@
       "dev": true
     },
     "node_modules/@eslint/js": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
-      "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
+      "version": "8.44.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+      "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -837,9 +826,9 @@
       "dev": true
     },
     "node_modules/@joplin/turndown-plugin-gfm": {
-      "version": "1.0.47",
-      "resolved": "https://registry.npmjs.org/@joplin/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.47.tgz",
-      "integrity": "sha512-VjY7ER5O+AUfhPkaxY25hh4N8PnZEc6311kJj040CHIXV9EYH7xuaS/MLeZL296FNLbsPaHbl5aQiOQ3xwTLJw=="
+      "version": "1.0.49",
+      "resolved": "https://registry.npmjs.org/@joplin/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.49.tgz",
+      "integrity": "sha512-4bCIa2JcD1T3wglOM1bWJ0TFVKl2g5t3NODoHQJyu2tq++9zTgk5rmonFpMbGHEn0DryTrqZc2I1nkfJSd8dKQ=="
     },
     "node_modules/@josephg/resolvable": {
       "version": "1.0.1",
@@ -978,15 +967,15 @@
       "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
     },
     "node_modules/@puppeteer/browsers": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.1.tgz",
-      "integrity": "sha512-H43VosMzywHCcYcgv0GXXopvwnV21Ud9g2aXbPlQUJj1Xcz9V0wBwHeFz6saFhx/3VKisZfI1GEKEOhQCau7Vw==",
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.3.tgz",
+      "integrity": "sha512-8Jfkpb8qhPQhMsNBmIY8b6+ic2kvcmHZlyvifmcNKBC5jNZf3MAKq3gryKfmrjFAYFl3naPjiKljPUq5wuolfQ==",
       "dependencies": {
         "debug": "4.3.4",
         "extract-zip": "2.0.1",
         "progress": "2.0.3",
         "proxy-agent": "6.2.1",
-        "tar-fs": "2.1.1",
+        "tar-fs": "3.0.3",
         "unbzip2-stream": "1.4.3",
         "yargs": "17.7.1"
       },
@@ -1380,9 +1369,9 @@
       }
     },
     "node_modules/acorn": {
-      "version": "8.8.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
-      "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
+      "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
       "bin": {
         "acorn": "bin/acorn"
       },
@@ -1669,9 +1658,9 @@
       }
     },
     "node_modules/aws-sdk": {
-      "version": "2.1395.0",
-      "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1395.0.tgz",
-      "integrity": "sha512-e/Ovw2dyBCsUfAxhdKanSMAmLL9/SIpKCC++xWEMe/3OfETz/B5FisjQQNnnVfe5eGJjiLbFKts1V8ZPCelUHw==",
+      "version": "2.1409.0",
+      "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1409.0.tgz",
+      "integrity": "sha512-4tg4lkvqRQs/39Z/wp+WBcNwDv17zwErlwotIxkHg7kCybVD78mC0sTrjcBbRK01kOsgiS/NCImIWj6C8KsMzw==",
       "dependencies": {
         "buffer": "4.9.2",
         "events": "1.1.1",
@@ -1746,6 +1735,11 @@
         "form-data": "^4.0.0"
       }
     },
+    "node_modules/b4a": {
+      "version": "1.6.4",
+      "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
+      "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
+    },
     "node_modules/backoff": {
       "version": "2.5.0",
       "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
@@ -2064,9 +2058,9 @@
       "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
     },
     "node_modules/chalk": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
-      "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
       "engines": {
         "node": "^12.17.0 || ^14.13 || >=16.0.0"
       },
@@ -2142,9 +2136,9 @@
       "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
     },
     "node_modules/chromium-bidi": {
-      "version": "0.4.11",
-      "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.11.tgz",
-      "integrity": "sha512-p03ajLhlQ5gebw3cmbDBFmBc2wnJM5dnXS8Phu6mblGn/KQd76yOVL5VwE0VAisa7oazNfKGTaXlIZ8Q5Bb9OA==",
+      "version": "0.4.16",
+      "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.16.tgz",
+      "integrity": "sha512-7ZbXdWERxRxSwo3txsBjjmc/NLxqb1Bk30mRb0BMS4YIaiV6zvKZqL/UAH+DdqcDYayDWk2n/y8klkBDODrPvA==",
       "dependencies": {
         "mitt": "3.0.0"
       },
@@ -2586,14 +2580,14 @@
       }
     },
     "node_modules/degenerator": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-4.0.2.tgz",
-      "integrity": "sha512-HKwIFvZROUMfH3qI3gBpD61BYh7q3c3GXD5UGZzoVNJwVSYgZKvYl1fRMXc9ozoTxl/VZxKJ5v/bA+19tywFiw==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-4.0.4.tgz",
+      "integrity": "sha512-MTZdZsuNxSBL92rsjx3VFWe57OpRlikyLbcx2B5Dmdv6oScqpMrvpY7zHLMymrUxo3U5+suPUMsNgW/+SZB1lg==",
       "dependencies": {
-        "ast-types": "^0.13.2",
-        "escodegen": "^1.8.1",
-        "esprima": "^4.0.0",
-        "vm2": "^3.9.17"
+        "ast-types": "^0.13.4",
+        "escodegen": "^1.14.3",
+        "esprima": "^4.0.1",
+        "vm2": "^3.9.19"
       },
       "engines": {
         "node": ">= 14"
@@ -2641,9 +2635,9 @@
       }
     },
     "node_modules/devtools-protocol": {
-      "version": "0.0.1120988",
-      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1120988.tgz",
-      "integrity": "sha512-39fCpE3Z78IaIPChJsP6Lhmkbf4dWXOmzLk/KFTdRkNk/0JymRIfUynDVRndV9HoDz8PyalK1UH21ST/ivwW5Q=="
+      "version": "0.0.1135028",
+      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1135028.tgz",
+      "integrity": "sha512-jEcNGrh6lOXNRJvZb9RjeevtZGrgugPKSMJZxfyxWQnhlKawMPhMtk/dfC+Z/6xNXExlzTKlY5LzIAK/fRpQIw=="
     },
     "node_modules/dezalgo": {
       "version": "1.0.4",
@@ -2753,9 +2747,9 @@
       "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
     },
     "node_modules/dompurify": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz",
-      "integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ=="
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.4.tgz",
+      "integrity": "sha512-ae0mA+Qiqp6C29pqZX3fQgK+F91+F7wobM/v8DRzDqJdZJELXiFUx4PP4pK/mzUS0xkiSEx3Ncd9gr69jg3YsQ=="
     },
     "node_modules/domutils": {
       "version": "3.0.1",
@@ -2860,9 +2854,9 @@
       }
     },
     "node_modules/engine.io": {
-      "version": "6.4.2",
-      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz",
-      "integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==",
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.1.tgz",
+      "integrity": "sha512-mGqhI+D7YxS9KJMppR6Iuo37Ed3abhU8NdfgSvJSDUafQutrN+sPTncJYTyM9+tkhSmWodKtVYGPPHyXJEwEQA==",
       "dependencies": {
         "@types/cookie": "^0.4.1",
         "@types/cors": "^2.8.12",
@@ -2872,7 +2866,7 @@
         "cookie": "~0.4.1",
         "cors": "~2.8.5",
         "debug": "~4.3.1",
-        "engine.io-parser": "~5.0.3",
+        "engine.io-parser": "~5.1.0",
         "ws": "~8.11.0"
       },
       "engines": {
@@ -2880,9 +2874,9 @@
       }
     },
     "node_modules/engine.io-parser": {
-      "version": "5.0.7",
-      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.7.tgz",
-      "integrity": "sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
+      "integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==",
       "engines": {
         "node": ">=10.0.0"
       }
@@ -3134,15 +3128,15 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
-      "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
+      "version": "8.44.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
+      "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.4.0",
-        "@eslint/eslintrc": "^2.0.3",
-        "@eslint/js": "8.42.0",
+        "@eslint/eslintrc": "^2.1.0",
+        "@eslint/js": "8.44.0",
         "@humanwhocodes/config-array": "^0.11.10",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -3154,7 +3148,7 @@
         "escape-string-regexp": "^4.0.0",
         "eslint-scope": "^7.2.0",
         "eslint-visitor-keys": "^3.4.1",
-        "espree": "^9.5.2",
+        "espree": "^9.6.0",
         "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
@@ -3174,7 +3168,7 @@
         "lodash.merge": "^4.6.2",
         "minimatch": "^3.1.2",
         "natural-compare": "^1.4.0",
-        "optionator": "^0.9.1",
+        "optionator": "^0.9.3",
         "strip-ansi": "^6.0.1",
         "strip-json-comments": "^3.1.0",
         "text-table": "^0.2.0"
@@ -3632,12 +3626,12 @@
       }
     },
     "node_modules/espree": {
-      "version": "9.5.2",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
-      "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
+      "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
       "dev": true,
       "dependencies": {
-        "acorn": "^8.8.0",
+        "acorn": "^8.9.0",
         "acorn-jsx": "^5.3.2",
         "eslint-visitor-keys": "^3.4.1"
       },
@@ -3950,6 +3944,11 @@
       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
     },
+    "node_modules/fast-fifo": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz",
+      "integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw=="
+    },
     "node_modules/fast-json-stable-stringify": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -4469,9 +4468,9 @@
       "dev": true
     },
     "node_modules/graphql": {
-      "version": "16.6.0",
-      "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
-      "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
+      "version": "16.7.1",
+      "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.7.1.tgz",
+      "integrity": "sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==",
       "engines": {
         "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
       }
@@ -4827,9 +4826,9 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
     "node_modules/i18next": {
-      "version": "22.5.1",
-      "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz",
-      "integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==",
+      "version": "23.2.6",
+      "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.2.6.tgz",
+      "integrity": "sha512-i0P2XBisewaICJ7UQtwymeJj6cXUigM+s8XNIXmWk4oJ8iTok2taCbOTX0ps+u9DFcQ6FWH6xLIU0dLEnMaNbA==",
       "funding": [
         {
           "type": "individual",
@@ -4845,7 +4844,7 @@
         }
       ],
       "dependencies": {
-        "@babel/runtime": "^7.20.6"
+        "@babel/runtime": "^7.22.5"
       }
     },
     "node_modules/i18next-node-fs-backend": {
@@ -5504,9 +5503,9 @@
       }
     },
     "node_modules/katex": {
-      "version": "0.16.7",
-      "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.7.tgz",
-      "integrity": "sha512-Xk9C6oGKRwJTfqfIbtr0Kes9OSv6IFsuhFGc7tW4urlpMJtuh+7YhzU6YEG9n8gmWKcMAFzkp7nr+r69kV0zrA==",
+      "version": "0.16.8",
+      "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
+      "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
       "funding": [
         "https://opencollective.com/katex",
         "https://github.com/sponsors/katex"
@@ -6566,9 +6565,9 @@
       }
     },
     "node_modules/objection": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/objection/-/objection-3.0.1.tgz",
-      "integrity": "sha512-rqNnyQE+C55UHjdpTOJEKQHJGZ/BGtBBtgxdUpKG4DQXRUmqxfmgS/MhPWxB9Pw0mLSVLEltr6soD4c0Sddy0Q==",
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/objection/-/objection-3.0.4.tgz",
+      "integrity": "sha512-0XaStHtOBcux4nlffUj8gOpxUsAPE+sLDZPml6n79WQhInYLBvjctU/uv2kEUPPybAJK8YL6ETkLtft9UOj7nQ==",
       "dependencies": {
         "ajv": "^8.6.2",
         "db-errors": "^0.2.3"
@@ -6577,7 +6576,7 @@
         "node": ">=12.0.0"
       },
       "peerDependencies": {
-        "knex": ">=0.95.0"
+        "knex": ">=1.0.1"
       }
     },
     "node_modules/objection/node_modules/ajv": {
@@ -6650,17 +6649,17 @@
       }
     },
     "node_modules/optionator": {
-      "version": "0.9.1",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
-      "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
       "dev": true,
       "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
         "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"
+        "type-check": "^0.4.0"
       },
       "engines": {
         "node": ">= 0.8.0"
@@ -6770,12 +6769,12 @@
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
     "node_modules/pac-resolver": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-6.0.1.tgz",
-      "integrity": "sha512-dg497MhVT7jZegPRuOScQ/z0aV/5WR0gTdRu1md+Irs9J9o+ls5jIuxjo1WfaTG+eQQkxyn5HMGvWK+w7EIBkQ==",
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-6.0.2.tgz",
+      "integrity": "sha512-EQpuJ2ifOjpZY5sg1Q1ZeAxvtLwR7Mj3RgY8cysPGbsRu3RBXyJFWxnMus9PScjxya/0LzvVDxNh/gl0eXBU4w==",
       "dependencies": {
-        "degenerator": "^4.0.1",
-        "ip": "^1.1.5",
+        "degenerator": "^4.0.4",
+        "ip": "^1.1.8",
         "netmask": "^2.0.2"
       },
       "engines": {
@@ -7269,14 +7268,14 @@
       "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
     },
     "node_modules/pg": {
-      "version": "8.11.0",
-      "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
-      "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
+      "version": "8.11.1",
+      "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.1.tgz",
+      "integrity": "sha512-utdq2obft07MxaDg0zBJI+l/M3mBRfIpEN3iSemsz0G5F2/VXx+XzqF4oxrbIZXQxt2AZzIUzyVg/YM6xOP/WQ==",
       "dependencies": {
         "buffer-writer": "2.0.0",
         "packet-reader": "1.0.0",
-        "pg-connection-string": "^2.6.0",
-        "pg-pool": "^3.6.0",
+        "pg-connection-string": "^2.6.1",
+        "pg-pool": "^3.6.1",
         "pg-protocol": "^1.6.0",
         "pg-types": "^2.1.0",
         "pgpass": "1.x"
@@ -7285,7 +7284,7 @@
         "node": ">= 8.0.0"
       },
       "optionalDependencies": {
-        "pg-cloudflare": "^1.1.0"
+        "pg-cloudflare": "^1.1.1"
       },
       "peerDependencies": {
         "pg-native": ">=3.0.1"
@@ -7297,9 +7296,9 @@
       }
     },
     "node_modules/pg-cloudflare": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz",
-      "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz",
+      "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==",
       "optional": true
     },
     "node_modules/pg-connection-string": {
@@ -7308,9 +7307,9 @@
       "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
     },
     "node_modules/pg-cursor": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.10.0.tgz",
-      "integrity": "sha512-azXIjeIGBwlv/icYyuki5xJYfVSXeirGn4+mvAmYTB8SY0gS1xhluc2CENnq1JrcVSA81lWZgtqc1GAAhH/UuQ==",
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.10.1.tgz",
+      "integrity": "sha512-t4bjqL/gtohsNoByFcD4EKjHVppOuJipBYVhunVUm25TnaS2xEEr2jy3vumOX2z44SHROaf4K7QWPY9xnKT3HA==",
       "peerDependencies": {
         "pg": "^8"
       }
@@ -7348,9 +7347,9 @@
       }
     },
     "node_modules/pg-pool": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
-      "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
+      "version": "3.6.1",
+      "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz",
+      "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==",
       "peerDependencies": {
         "pg": ">=8.0"
       }
@@ -7375,11 +7374,11 @@
       }
     },
     "node_modules/pg-query-stream": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/pg-query-stream/-/pg-query-stream-4.5.0.tgz",
-      "integrity": "sha512-9slxIXMssuqKUVyCtuVU5/pr2+RLTKva5VE90PFzi6Mi8o3crbyZQvReoWJimgm9c1zY2+Jv3lvYYsqvaKmQ4g==",
+      "version": "4.5.1",
+      "resolved": "https://registry.npmjs.org/pg-query-stream/-/pg-query-stream-4.5.1.tgz",
+      "integrity": "sha512-KI57YzN5MT6QTfO3J4HoWdnkcyC8BUgeyXWLB0WAFw0ST4ja/5l4o8X5CwJG8Heq1qhl+Q8FbvFJWDXvJXPXYw==",
       "dependencies": {
-        "pg-cursor": "^2.10.0"
+        "pg-cursor": "^2.10.1"
       },
       "peerDependencies": {
         "pg": "^8"
@@ -7409,9 +7408,9 @@
       }
     },
     "node_modules/pg/node_modules/pg-connection-string": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
-      "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.1.tgz",
+      "integrity": "sha512-w6ZzNu6oMmIzEAYVw+RLK0+nqHPt8K3ZnknKi+g48Ak2pr3dtljJW3o+D/n2zzCG07Zoe9VOX3aiKpj+BN0pjg=="
     },
     "node_modules/pgpass": {
       "version": "1.0.5",
@@ -7449,9 +7448,9 @@
       }
     },
     "node_modules/poolifier": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/poolifier/-/poolifier-2.6.2.tgz",
-      "integrity": "sha512-3/bYzHdoFwJ+LCWlgVELuD9kEN1jho3RH4kG/YOo+2IX0ASVQD9SogGJ2YEW7+y9GD6vMuv9rcCkoTf2LxgaoQ==",
+      "version": "2.6.5",
+      "resolved": "https://registry.npmjs.org/poolifier/-/poolifier-2.6.5.tgz",
+      "integrity": "sha512-lSyoqFAsaWcZAY4n40qyxnnsdGLD0XuWNM/l76tcbuwbmhRaZPQtzwmtRRgvrYE4NtTifdzGVbK56e8HajgWNA==",
       "funding": [
         {
           "type": "opencollective",
@@ -7528,6 +7527,45 @@
         "node": ">=10"
       }
     },
+    "node_modules/prebuild-install/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/prebuild-install/node_modules/tar-fs": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+      "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+      "dependencies": {
+        "chownr": "^1.1.1",
+        "mkdirp-classic": "^0.5.2",
+        "pump": "^3.0.0",
+        "tar-stream": "^2.1.4"
+      }
+    },
+    "node_modules/prebuild-install/node_modules/tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "dependencies": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/precond": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
@@ -7724,15 +7762,15 @@
       }
     },
     "node_modules/puppeteer-core": {
-      "version": "20.5.0",
-      "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.5.0.tgz",
-      "integrity": "sha512-9ddHXUQ7jpliGei87zYTuEZYQvFj6Lzk5R8w4vT4gMmNArkEqC5CX72TnVIJiTUbiTpOXJkvMQaXIHYopjdUtQ==",
+      "version": "20.7.4",
+      "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-20.7.4.tgz",
+      "integrity": "sha512-7YZ1LmTo+5yM9uBNFTMJpE+lJjcIoNjKVarsYIk7o5WhgQNI9o5XgiQK5f71y1vWwr7sT/eGG75HXAehjnTBTg==",
       "dependencies": {
-        "@puppeteer/browsers": "1.4.1",
-        "chromium-bidi": "0.4.11",
+        "@puppeteer/browsers": "1.4.3",
+        "chromium-bidi": "0.4.16",
         "cross-fetch": "3.1.6",
         "debug": "4.3.4",
-        "devtools-protocol": "0.0.1120988",
+        "devtools-protocol": "0.0.1135028",
         "ws": "8.13.0"
       },
       "engines": {
@@ -7837,6 +7875,11 @@
         }
       ]
     },
+    "node_modules/queue-tick": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
+      "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
+    },
     "node_modules/random-bytes": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -8309,9 +8352,9 @@
       }
     },
     "node_modules/semver": {
-      "version": "7.5.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
-      "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+      "version": "7.5.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
+      "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
       "dependencies": {
         "lru-cache": "^6.0.0"
       },
@@ -8423,6 +8466,45 @@
         "url": "https://opencollective.com/libvips"
       }
     },
+    "node_modules/sharp/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/sharp/node_modules/tar-fs": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+      "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+      "dependencies": {
+        "chownr": "^1.1.1",
+        "mkdirp-classic": "^0.5.2",
+        "pump": "^3.0.0",
+        "tar-stream": "^2.1.4"
+      }
+    },
+    "node_modules/sharp/node_modules/tar-stream": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+      "dependencies": {
+        "bl": "^4.0.3",
+        "end-of-stream": "^1.4.1",
+        "fs-constants": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^3.1.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/shebang-command": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -8501,9 +8583,9 @@
       }
     },
     "node_modules/simple-git": {
-      "version": "3.19.0",
-      "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.0.tgz",
-      "integrity": "sha512-hyH2p9Ptxjf/xPuL7HfXbpYt9gKhC1yWDh3KYIAYJJePAKV7AEjLN4xhp7lozOdNiaJ9jlVvAbBymVlcS2jRiA==",
+      "version": "3.19.1",
+      "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz",
+      "integrity": "sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w==",
       "dependencies": {
         "@kwsites/file-exists": "^1.1.1",
         "@kwsites/promise-deferred": "^1.1.1",
@@ -8579,14 +8661,15 @@
       }
     },
     "node_modules/socket.io": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.2.tgz",
-      "integrity": "sha512-Vp+lSks5k0dewYTfwgPT9UeGGd+ht7sCpB7p0e83VgO4X/AHYWhXITMrNk/pg8syY2bpx23ptClCQuHhqi2BgQ==",
+      "version": "4.7.1",
+      "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.1.tgz",
+      "integrity": "sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==",
       "dependencies": {
         "accepts": "~1.3.4",
         "base64id": "~2.0.0",
+        "cors": "~2.8.5",
         "debug": "~4.3.2",
-        "engine.io": "~6.4.2",
+        "engine.io": "~6.5.0",
         "socket.io-adapter": "~2.5.2",
         "socket.io-parser": "~4.2.4"
       },
@@ -8808,6 +8891,15 @@
         "node": ">=0.8.0"
       }
     },
+    "node_modules/streamx": {
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.0.tgz",
+      "integrity": "sha512-HcxY6ncGjjklGs1xsP1aR71INYcsXFJet5CU1CHqihQ2J5nOsbd4OjgjHO42w/4QNv9gZb3BueV+Vxok5pLEXg==",
+      "dependencies": {
+        "fast-fifo": "^1.1.0",
+        "queue-tick": "^1.0.1"
+      }
+    },
     "node_modules/string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -9022,42 +9114,23 @@
       "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
     },
     "node_modules/tar-fs": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
-      "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.3.tgz",
+      "integrity": "sha512-ZK36riGYnFI6LujIBfBRoDfeaaWUkStIFKwtPjnDWCKnsDE9kuQthG09aQjLjpzoRtVElEMZ/AIAURNb7N9mkA==",
       "dependencies": {
-        "chownr": "^1.1.1",
         "mkdirp-classic": "^0.5.2",
         "pump": "^3.0.0",
-        "tar-stream": "^2.1.4"
+        "tar-stream": "^3.1.0"
       }
     },
     "node_modules/tar-stream": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
-      "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
-      "dependencies": {
-        "bl": "^4.0.3",
-        "end-of-stream": "^1.4.1",
-        "fs-constants": "^1.0.0",
-        "inherits": "^2.0.3",
-        "readable-stream": "^3.1.1"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/tar-stream/node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.4.tgz",
+      "integrity": "sha512-IlHr7ZOW6XaVBCrSCokUJG4IqUuRcWW76B8XbrtCotbaDh6zVGE7WPCzaSz1CN+acFmWiwoa+cE4RZsom0RzXg==",
       "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
+        "b4a": "^1.6.4",
+        "fast-fifo": "^1.2.0",
+        "streamx": "^2.15.0"
       }
     },
     "node_modules/tarn": {

+ 18 - 18
server/package.json

@@ -34,21 +34,21 @@
     "node": ">=18.0"
   },
   "dependencies": {
-    "@apollo/server": "4.7.3",
+    "@apollo/server": "4.7.5",
     "@azure/storage-blob": "12.14.0",
     "@exlinc/keycloak-passport": "1.0.2",
     "@graphql-tools/schema": "10.0.0",
     "@graphql-tools/utils": "10.0.1",
-    "@joplin/turndown-plugin-gfm": "1.0.47",
+    "@joplin/turndown-plugin-gfm": "1.0.49",
     "@root/csr": "0.8.1",
     "@root/keypairs": "0.10.3",
     "@root/pem": "1.0.4",
     "acme": "3.0.3",
     "akismet-api": "6.0.0",
-    "aws-sdk": "2.1395.0",
+    "aws-sdk": "2.1409.0",
     "bcryptjs": "2.4.3",
     "body-parser": "1.20.2",
-    "chalk": "5.2.0",
+    "chalk": "5.3.0",
     "cheerio": "1.0.0-rc.12",
     "chokidar": "3.5.3",
     "chromium-pickle-js": "0.2.0",
@@ -64,7 +64,7 @@
     "dependency-graph": "0.11.0",
     "diff": "5.1.0",
     "diff2html": "3.4.35",
-    "dompurify": "3.0.3",
+    "dompurify": "3.0.4",
     "dotize": "0.3.0",
     "emoji-regex": "10.2.1",
     "eventemitter2": "6.4.9",
@@ -75,14 +75,14 @@
     "filesize": "10.0.7",
     "fs-extra": "11.1.1",
     "getos": "3.2.1",
-    "graphql": "16.6.0",
+    "graphql": "16.7.1",
     "graphql-list-fields": "2.0.2",
     "graphql-rate-limit-directive": "2.0.3",
     "graphql-tools": "9.0.0",
     "graphql-upload": "16.0.2",
     "he": "1.2.0",
     "highlight.js": "11.8.0",
-    "i18next": "22.5.1",
+    "i18next": "23.2.6",
     "i18next-node-fs-backend": "2.1.3",
     "image-size": "1.0.2",
     "js-base64": "3.7.5",
@@ -90,7 +90,7 @@
     "js-yaml": "4.1.0",
     "jsdom": "22.1.0",
     "jsonwebtoken": "9.0.0",
-    "katex": "0.16.7",
+    "katex": "0.16.8",
     "klaw": "4.1.0",
     "knex": "2.4.2",
     "lodash": "4.17.21",
@@ -117,7 +117,7 @@
     "node-2fa": "2.0.3",
     "node-cache": "5.1.2",
     "nodemailer": "6.9.3",
-    "objection": "3.0.1",
+    "objection": "3.0.4",
     "passport": "0.6.0",
     "passport-auth0": "1.4.3",
     "passport-azure-ad": "4.3.5",
@@ -139,14 +139,14 @@
     "passport-slack-oauth2": "1.2.0",
     "passport-twitch-strategy": "2.2.0",
     "pem-jwk": "2.0.0",
-    "pg": "8.11.0",
+    "pg": "8.11.1",
     "pg-hstore": "2.3.4",
     "pg-pubsub": "0.8.1",
-    "pg-query-stream": "4.5.0",
+    "pg-query-stream": "4.5.1",
     "pg-tsquery": "8.4.1",
-    "poolifier": "2.6.2",
+    "poolifier": "2.6.5",
     "punycode": "2.3.0",
-    "puppeteer-core": "20.5.0",
+    "puppeteer-core": "20.7.4",
     "qr-image": "3.2.0",
     "rate-limiter-flexible": "2.4.1",
     "remove-markdown": "0.5.0",
@@ -155,13 +155,13 @@
     "safe-regex": "2.1.1",
     "sanitize-filename": "1.6.3",
     "scim-query-filter-parser": "2.0.4",
-    "semver": "7.5.1",
+    "semver": "7.5.3",
     "serve-favicon": "2.5.0",
     "sharp": "0.32.1",
-    "simple-git": "3.19.0",
-    "socket.io": "4.6.2",
+    "simple-git": "3.19.1",
+    "socket.io": "4.7.1",
     "striptags": "3.2.0",
-    "tar-fs": "2.1.1",
+    "tar-fs": "3.0.3",
     "turndown": "7.1.2",
     "twemoji": "14.0.2",
     "uslug": "1.0.4",
@@ -171,7 +171,7 @@
     "yargs": "17.7.2"
   },
   "devDependencies": {
-    "eslint": "8.42.0",
+    "eslint": "8.44.0",
     "eslint-config-requarks": "1.0.7",
     "eslint-config-standard": "17.1.0",
     "eslint-plugin-import": "2.27.5",

+ 0 - 33
ux/README.md

@@ -1,33 +0,0 @@
-# Wiki.js (ux)
-
-The most powerful and extensible open source Wiki software
-
-## Install the dependencies
-```bash
-yarn
-# or
-npm install
-```
-
-### Start the app in development mode (hot-code reloading, error reporting, etc.)
-```bash
-quasar dev
-```
-
-
-### Lint the files
-```bash
-yarn lint
-# or
-npm run lint
-```
-
-
-
-### Build the app for production
-```bash
-quasar build
-```
-
-### Customize the configuration
-See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js).

+ 101 - 86
ux/package-lock.json

@@ -8,7 +8,7 @@
       "name": "wiki-ux",
       "version": "3.0.0",
       "dependencies": {
-        "@apollo/client": "3.7.15",
+        "@apollo/client": "3.7.16",
         "@lezer/common": "1.0.3",
         "@mdi/font": "7.2.96",
         "@quasar/extras": "1.16.4",
@@ -51,7 +51,7 @@
         "highlight.js": "11.8.0",
         "js-cookie": "3.0.5",
         "jwt-decode": "3.1.2",
-        "katex": "0.16.7",
+        "katex": "0.16.8",
         "lodash-es": "4.17.21",
         "lowlight": "2.9.0",
         "luxon": "3.3.0",
@@ -71,7 +71,7 @@
         "mitt": "3.0.0",
         "monaco-editor": "0.39.0",
         "pako": "2.1.0",
-        "pinia": "2.1.3",
+        "pinia": "2.1.4",
         "prosemirror-commands": "1.5.2",
         "prosemirror-history": "1.3.2",
         "prosemirror-keymap": "1.2.2",
@@ -79,16 +79,16 @@
         "prosemirror-schema-list": "1.3.0",
         "prosemirror-state": "1.4.3",
         "prosemirror-transform": "1.7.3",
-        "prosemirror-view": "1.31.4",
+        "prosemirror-view": "1.31.5",
         "pug": "3.0.2",
-        "quasar": "2.12.0",
+        "quasar": "2.12.1",
         "slugify": "1.6.6",
-        "socket.io-client": "4.6.2",
+        "socket.io-client": "4.7.1",
         "tabulator-tables": "5.5.0",
         "tippy.js": "6.3.7",
         "twemoji": "14.0.2",
         "uuid": "9.0.0",
-        "v-network-graph": "0.9.3",
+        "v-network-graph": "0.9.4",
         "vue": "3.3.4",
         "vue-i18n": "9.2.2",
         "vue-router": "4.2.2",
@@ -104,22 +104,31 @@
         "@volar/vue-language-plugin-pug": "1.6.5",
         "autoprefixer": "10.4.14",
         "browserlist": "latest",
-        "eslint": "8.42.0",
+        "eslint": "8.44.0",
         "eslint-config-standard": "17.1.0",
         "eslint-plugin-import": "2.27.5",
-        "eslint-plugin-n": "16.0.0",
+        "eslint-plugin-n": "16.0.1",
         "eslint-plugin-promise": "6.1.1",
-        "eslint-plugin-vue": "9.14.1"
+        "eslint-plugin-vue": "9.15.1"
       },
       "engines": {
         "node": ">= 18.0",
         "npm": ">= 6.13.4"
       }
     },
+    "node_modules/@aashutoshrathi/word-wrap": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/@apollo/client": {
-      "version": "3.7.15",
-      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.15.tgz",
-      "integrity": "sha512-pLScjo4GAQRWKWyEg2J3FlQr9fbUAuADT0EI2+JlLf2BjaU9I7WUaZVD9w+0qNPE8BZqs53MRQq0OCm1QCW+eg==",
+      "version": "3.7.16",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.16.tgz",
+      "integrity": "sha512-rdhoc7baSD7ZzcjavEpYN8gZJle1KhjEKj4SJeMgBpcnO4as7oXUVU4LtFpotzZdFlo57qaLrNzfvppSTsKvZQ==",
       "dependencies": {
         "@graphql-typed-document-node/core": "^3.1.1",
         "@wry/context": "^0.7.0",
@@ -237,14 +246,14 @@
       }
     },
     "node_modules/@eslint/eslintrc": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
-      "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
+      "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
       "dev": true,
       "dependencies": {
         "ajv": "^6.12.4",
         "debug": "^4.3.2",
-        "espree": "^9.5.2",
+        "espree": "^9.6.0",
         "globals": "^13.19.0",
         "ignore": "^5.2.0",
         "import-fresh": "^3.2.1",
@@ -260,9 +269,9 @@
       }
     },
     "node_modules/@eslint/js": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
-      "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
+      "version": "8.44.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+      "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2911,21 +2920,21 @@
       }
     },
     "node_modules/engine.io-client": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz",
-      "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==",
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.1.tgz",
+      "integrity": "sha512-hE5wKXH8Ru4L19MbM1GgYV/2Qo54JSMh1rlJbfpa40bEWkCKNo3ol2eOtGmowcr+ysgbI7+SGL+by42Q3pt/Ng==",
       "dependencies": {
         "@socket.io/component-emitter": "~3.1.0",
         "debug": "~4.3.1",
-        "engine.io-parser": "~5.0.3",
+        "engine.io-parser": "~5.1.0",
         "ws": "~8.11.0",
         "xmlhttprequest-ssl": "~2.0.0"
       }
     },
     "node_modules/engine.io-parser": {
-      "version": "5.0.6",
-      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz",
-      "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
+      "integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w==",
       "engines": {
         "node": ">=10.0.0"
       }
@@ -3265,15 +3274,15 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.42.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
-      "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
+      "version": "8.44.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
+      "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.4.0",
-        "@eslint/eslintrc": "^2.0.3",
-        "@eslint/js": "8.42.0",
+        "@eslint/eslintrc": "^2.1.0",
+        "@eslint/js": "8.44.0",
         "@humanwhocodes/config-array": "^0.11.10",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -3285,7 +3294,7 @@
         "escape-string-regexp": "^4.0.0",
         "eslint-scope": "^7.2.0",
         "eslint-visitor-keys": "^3.4.1",
-        "espree": "^9.5.2",
+        "espree": "^9.6.0",
         "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
@@ -3305,7 +3314,7 @@
         "lodash.merge": "^4.6.2",
         "minimatch": "^3.1.2",
         "natural-compare": "^1.4.0",
-        "optionator": "^0.9.1",
+        "optionator": "^0.9.3",
         "strip-ansi": "^6.0.1",
         "strip-json-comments": "^3.1.0",
         "text-table": "^0.2.0"
@@ -3392,9 +3401,9 @@
       }
     },
     "node_modules/eslint-plugin-es-x": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-6.2.1.tgz",
-      "integrity": "sha512-uR34zUhZ9EBoiSD2DdV5kHLpydVEvwWqjteUr9sXRgJknwbKZJZhdJ7uFnaTtd+Nr/2G3ceJHnHXrFhJ67n3Tw==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz",
+      "integrity": "sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.1.2",
@@ -3466,19 +3475,19 @@
       }
     },
     "node_modules/eslint-plugin-n": {
-      "version": "16.0.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.0.tgz",
-      "integrity": "sha512-akkZTE3hsHBrq6CwmGuYCzQREbVUrA855kzcHqe6i0FLBkeY7Y/6tThCVkjUnjhvRBAlc+8lILcSe5QvvDpeZQ==",
+      "version": "16.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz",
+      "integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
         "builtins": "^5.0.1",
-        "eslint-plugin-es-x": "^6.1.0",
-        "ignore": "^5.1.1",
-        "is-core-module": "^2.12.0",
+        "eslint-plugin-es-x": "^7.1.0",
+        "ignore": "^5.2.4",
+        "is-core-module": "^2.12.1",
         "minimatch": "^3.1.2",
         "resolve": "^1.22.2",
-        "semver": "^7.5.0"
+        "semver": "^7.5.3"
       },
       "engines": {
         "node": ">=16.0.0"
@@ -3502,9 +3511,9 @@
       }
     },
     "node_modules/eslint-plugin-vue": {
-      "version": "9.14.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.14.1.tgz",
-      "integrity": "sha512-LQazDB1qkNEKejLe/b5a9VfEbtbczcOaui5lQ4Qw0tbRBbQYREyxxOV5BQgNDTqGPs9pxqiEpbMi9ywuIaF7vw==",
+      "version": "9.15.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.15.1.tgz",
+      "integrity": "sha512-CJE/oZOslvmAR9hf8SClTdQ9JLweghT6JCBQNrT2Iel1uVw0W0OLJxzvPd6CxmABKCvLrtyDnqGV37O7KQv6+A==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.3.0",
@@ -3573,12 +3582,12 @@
       }
     },
     "node_modules/espree": {
-      "version": "9.5.2",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
-      "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
+      "version": "9.6.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
+      "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
       "dev": true,
       "dependencies": {
-        "acorn": "^8.8.0",
+        "acorn": "^8.9.0",
         "acorn-jsx": "^5.3.2",
         "eslint-visitor-keys": "^3.4.1"
       },
@@ -3590,9 +3599,9 @@
       }
     },
     "node_modules/espree/node_modules/acorn": {
-      "version": "8.8.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
-      "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+      "version": "8.9.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
+      "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
       "dev": true,
       "bin": {
         "acorn": "bin/acorn"
@@ -4238,7 +4247,8 @@
     },
     "node_modules/graphql": {
       "version": "16.6.0",
-      "license": "MIT",
+      "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
+      "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
       "engines": {
         "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
       }
@@ -4429,9 +4439,10 @@
       "license": "BSD-3-Clause"
     },
     "node_modules/ignore": {
-      "version": "5.2.0",
+      "version": "5.2.4",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
       "dev": true,
-      "license": "MIT",
       "engines": {
         "node": ">= 4"
       }
@@ -5023,9 +5034,9 @@
       "license": "MIT"
     },
     "node_modules/katex": {
-      "version": "0.16.7",
-      "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.7.tgz",
-      "integrity": "sha512-Xk9C6oGKRwJTfqfIbtr0Kes9OSv6IFsuhFGc7tW4urlpMJtuh+7YhzU6YEG9n8gmWKcMAFzkp7nr+r69kV0zrA==",
+      "version": "0.16.8",
+      "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz",
+      "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==",
       "funding": [
         "https://opencollective.com/katex",
         "https://github.com/sponsors/katex"
@@ -5090,8 +5101,9 @@
     },
     "node_modules/levn": {
       "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
         "prelude-ls": "^1.2.1",
         "type-check": "~0.4.0"
@@ -5713,16 +5725,17 @@
       }
     },
     "node_modules/optionator": {
-      "version": "0.9.1",
+      "version": "0.9.3",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
+        "@aashutoshrathi/word-wrap": "^1.2.3",
         "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"
+        "type-check": "^0.4.0"
       },
       "engines": {
         "node": ">= 0.8.0"
@@ -5873,9 +5886,9 @@
       }
     },
     "node_modules/pinia": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.3.tgz",
-      "integrity": "sha512-XNA/z/ye4P5rU1pieVmh0g/hSuDO98/a5UC8oSP0DNdvt6YtetJNHTrXwpwsQuflkGT34qKxAEcp7lSxXNjf/A==",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.4.tgz",
+      "integrity": "sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==",
       "dependencies": {
         "@vue/devtools-api": "^6.5.0",
         "vue-demi": ">=0.14.5"
@@ -5980,8 +5993,9 @@
     },
     "node_modules/prelude-ls": {
       "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
       "dev": true,
-      "license": "MIT",
       "engines": {
         "node": ">= 0.8.0"
       }
@@ -6194,9 +6208,9 @@
       }
     },
     "node_modules/prosemirror-view": {
-      "version": "1.31.4",
-      "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.31.4.tgz",
-      "integrity": "sha512-nJzH2LpYbonSTYFqQ1BUdEhbd1WPN/rp/K9T9qxBEYpgg3jK3BvEUCR45Ymc9IHpO0m3nBJwPm19RBxZdoBVuw==",
+      "version": "1.31.5",
+      "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.31.5.tgz",
+      "integrity": "sha512-tobRCDeCp61elR1d97XE/JTL9FDIfswZpWeNs7GKJjAJvWyMGHWYFCq29850p6bbG2bckP+i9n1vT56RifosbA==",
       "dependencies": {
         "prosemirror-model": "^1.16.0",
         "prosemirror-state": "^1.0.0",
@@ -6335,9 +6349,9 @@
       }
     },
     "node_modules/quasar": {
-      "version": "2.12.0",
-      "resolved": "https://registry.npmjs.org/quasar/-/quasar-2.12.0.tgz",
-      "integrity": "sha512-B8xoeOWNs/Iv7M+FGRvXGYI1qDnJH8AtIb7RiP+zMfMkBcEp+6HJHU/9ODPemC4yteDjO+HPX2f7OhNZKgsPIw==",
+      "version": "2.12.1",
+      "resolved": "https://registry.npmjs.org/quasar/-/quasar-2.12.1.tgz",
+      "integrity": "sha512-d7uPATVP2dpoLCSwwtwNiJhkCklLFlonYw4QyZG8khuMEO7ENjzkU+DKoOY+esjLmkbOXbDlhrE69tdxvrHr0g==",
       "engines": {
         "node": ">= 10.18.1",
         "npm": ">= 6.13.4",
@@ -6717,9 +6731,9 @@
       "license": "MIT"
     },
     "node_modules/semver": {
-      "version": "7.5.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
-      "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+      "version": "7.5.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
+      "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
       "dev": true,
       "dependencies": {
         "lru-cache": "^6.0.0"
@@ -6880,13 +6894,13 @@
       }
     },
     "node_modules/socket.io-client": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz",
-      "integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==",
+      "version": "4.7.1",
+      "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.1.tgz",
+      "integrity": "sha512-Qk3Xj8ekbnzKu3faejo4wk2MzXA029XppiXtTF/PkbTg+fcwaTw1PlDrTrrrU4mKoYC4dvlApOnSeyLCKwek2w==",
       "dependencies": {
         "@socket.io/component-emitter": "~3.1.0",
         "debug": "~4.3.2",
-        "engine.io-client": "~6.4.0",
+        "engine.io-client": "~6.5.1",
         "socket.io-parser": "~4.2.4"
       },
       "engines": {
@@ -7290,8 +7304,9 @@
     },
     "node_modules/type-check": {
       "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
       "dev": true,
-      "license": "MIT",
       "dependencies": {
         "prelude-ls": "^1.2.1"
       },
@@ -7481,9 +7496,9 @@
       }
     },
     "node_modules/v-network-graph": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/v-network-graph/-/v-network-graph-0.9.3.tgz",
-      "integrity": "sha512-po6IyJ7VBNSsXa6EV+oyjuktZnQM+pCSLR/DAcMkZjJ9c2oNLi0G6Et9RjK/mCO/4r3mnk8u1Z/XmjkRPLbT5w==",
+      "version": "0.9.4",
+      "resolved": "https://registry.npmjs.org/v-network-graph/-/v-network-graph-0.9.4.tgz",
+      "integrity": "sha512-ZuRYfDZeXvxqkhzxMybHk5e4MEAT28CLtKyCxjbECvGPiN1DGCOwZNQxO7kHKqPpnU8Usqe6wXHqo3lePcjqHg==",
       "dependencies": {
         "@dash14/svg-pan-zoom": "^3.6.9",
         "lodash-es": "^4.17.21",

+ 10 - 10
ux/package.json

@@ -13,7 +13,7 @@
     "ncu-u": "ncu -u -x codemirror,codemirror-asciidoc"
   },
   "dependencies": {
-    "@apollo/client": "3.7.15",
+    "@apollo/client": "3.7.16",
     "@lezer/common": "1.0.3",
     "@mdi/font": "7.2.96",
     "@quasar/extras": "1.16.4",
@@ -56,7 +56,7 @@
     "highlight.js": "11.8.0",
     "js-cookie": "3.0.5",
     "jwt-decode": "3.1.2",
-    "katex": "0.16.7",
+    "katex": "0.16.8",
     "lodash-es": "4.17.21",
     "lowlight": "2.9.0",
     "luxon": "3.3.0",
@@ -76,7 +76,7 @@
     "mitt": "3.0.0",
     "monaco-editor": "0.39.0",
     "pako": "2.1.0",
-    "pinia": "2.1.3",
+    "pinia": "2.1.4",
     "prosemirror-commands": "1.5.2",
     "prosemirror-history": "1.3.2",
     "prosemirror-keymap": "1.2.2",
@@ -84,16 +84,16 @@
     "prosemirror-schema-list": "1.3.0",
     "prosemirror-state": "1.4.3",
     "prosemirror-transform": "1.7.3",
-    "prosemirror-view": "1.31.4",
+    "prosemirror-view": "1.31.5",
     "pug": "3.0.2",
-    "quasar": "2.12.0",
+    "quasar": "2.12.1",
     "slugify": "1.6.6",
-    "socket.io-client": "4.6.2",
+    "socket.io-client": "4.7.1",
     "tabulator-tables": "5.5.0",
     "tippy.js": "6.3.7",
     "twemoji": "14.0.2",
     "uuid": "9.0.0",
-    "v-network-graph": "0.9.3",
+    "v-network-graph": "0.9.4",
     "vue": "3.3.4",
     "vue-i18n": "9.2.2",
     "vue-router": "4.2.2",
@@ -109,12 +109,12 @@
     "@volar/vue-language-plugin-pug": "1.6.5",
     "autoprefixer": "10.4.14",
     "browserlist": "latest",
-    "eslint": "8.42.0",
+    "eslint": "8.44.0",
     "eslint-config-standard": "17.1.0",
     "eslint-plugin-import": "2.27.5",
-    "eslint-plugin-n": "16.0.0",
+    "eslint-plugin-n": "16.0.1",
     "eslint-plugin-promise": "6.1.1",
-    "eslint-plugin-vue": "9.14.1"
+    "eslint-plugin-vue": "9.15.1"
   },
   "engines": {
     "node": ">= 18.0",

+ 3 - 0
ux/src/components/FileManager.vue

@@ -825,6 +825,9 @@ async function uploadNewFiles () {
           idx++
           state.uploadPercentage = totalFiles > 1 ? Math.round(idx / totalFiles * 100) : 90
           const resp = await APOLLO_CLIENT.mutate({
+            context: {
+              uploadMode: true
+            },
             mutation: gql`
               mutation uploadAssets (
                 $folderId: UUID

+ 30 - 10
ux/src/components/GroupEditOverlay.vue

@@ -152,7 +152,7 @@ q-layout(view='hHh lpR fFf', container)
           flat
           color='grey'
           type='a'
-          href='https://docs.js.wiki/admin/groups#rules'
+          :href='siteStore.docsBase + `/admin/groups#rules`'
           target='_blank'
           )
         q-btn.acrylic-btn.q-mr-sm(
@@ -221,12 +221,21 @@ q-layout(view='hHh lpR fFf', container)
                     use-chips
                     stack-label
                     )
+                    template(v-slot:selected-item='scope')
+                      q-chip(
+                        square
+                        dense
+                        :tabindex='scope.tabindex'
+                        :color='getRuleModeBgColor(rule.mode)'
+                        text-color='white'
+                        )
+                        span.text-caption {{ scope.opt.title }}
                     template(v-slot:option='{ itemProps, itemEvents, opt, selected, toggleOption }')
                       q-item(v-bind='itemProps', v-on='itemEvents')
                         q-item-section(side)
                           q-toggle(
-                            :value='selected'
-                            @input='toggleOption(opt)'
+                            :model-value='selected'
+                            @update:model-value='toggleOption(opt)'
                             color='primary'
                             checked-icon='las la-check'
                             unchecked-icon='las la-times'
@@ -273,8 +282,8 @@ q-layout(view='hHh lpR fFf', container)
                             q-item-label {{opt.title}}
                           q-item-section(side)
                             q-toggle(
-                              :value='selected'
-                              @input='toggleOption(opt)'
+                              :model-value='selected'
+                              @update:model-value='toggleOption(opt)'
                               color='primary'
                               checked-icon='las la-check'
                               unchecked-icon='las la-times'
@@ -292,7 +301,7 @@ q-layout(view='hHh lpR fFf', container)
                       option-label='name'
                       multiple
                       behavior='dialog'
-                      :display-value='t(`admin.groups.selectedLocales`, rule.locales.length, { count: rule.locales.length, locale: rule.locales.length === 1 ? rule.locales[0].toUpperCase() : `` })'
+                      :display-value='t(`admin.groups.selectedLocales`, { n: rule.locales.length > 0 ? rule.locales[0].toUpperCase() : rule.locales.length }, rule.locales.length)'
                       )
                       template(v-slot:option='{ itemProps, opt, selected, toggleOption }')
                         q-item(v-bind='itemProps')
@@ -350,7 +359,7 @@ q-layout(view='hHh lpR fFf', container)
                     flat
                     color='grey'
                     type='a'
-                    href='https://docs.js.wiki/admin/groups#permissions'
+                    :href='siteStore.docsBase + `/admin/groups#permissions`'
                     target='_blank'
                     )
               template(v-for='(perm, idx) of permissions', :key='perm.permission')
@@ -388,7 +397,7 @@ q-layout(view='hHh lpR fFf', container)
           flat
           color='grey'
           type='a'
-          href='https://docs.js.wiki/admin/groups#users'
+          :href='siteStore.docsBase + `/admin/groups#users`'
           target='_blank'
           )
         q-input.denser.fill-outline.q-mr-sm(
@@ -504,6 +513,7 @@ import { computed, onMounted, reactive, watch } from 'vue'
 import { useRouter, useRoute } from 'vue-router'
 
 import { useAdminStore } from 'src/stores/admin'
+import { useSiteStore } from 'src/stores/site'
 
 // QUASAR
 
@@ -512,6 +522,7 @@ const $q = useQuasar()
 // STORES
 
 const adminStore = useAdminStore()
+const siteStore = useSiteStore()
 
 // ROUTER
 
@@ -693,7 +704,7 @@ const rules = [
   },
   {
     permission: 'read:source',
-    title: 'View Pages Source',
+    title: 'View Page Source',
     hint: 'Can view pages source.',
     warning: false,
     restrictedForSystem: false,
@@ -802,6 +813,14 @@ function getRuleModeColor (mode) {
   })[mode]
 }
 
+function getRuleModeBgColor (mode) {
+  return ({
+    DENY: 'negative',
+    ALLOW: 'positive',
+    FORCEALLOW: 'blue'
+  })[mode]
+}
+
 function getRuleModeClass (mode) {
   return 'is-' + mode.toLowerCase()
 }
@@ -913,7 +932,8 @@ function exportRules () {
       message: t('admin.groups.exportRulesNoneError')
     })
   }
-  exportFile('rules.json', JSON.stringify(state.group.rules, null, 2), { mimeType: 'application/json;charset=UTF-8' })
+  const rules = state.group.rules.map(({ __typename, ...r }) => r)
+  exportFile('rules.json', JSON.stringify(rules, null, 2), { mimeType: 'application/json;charset=UTF-8' })
 }
 
 async function importRules () {

+ 22 - 10
ux/src/components/PageHeader.vue

@@ -149,19 +149,31 @@
         no-caps
         @click='createPage'
       )
-      q-btn.acrylic-btn.q-ml-sm(
+      q-btn-group.q-ml-sm(
         v-else
         flat
-        icon='las la-check'
-        color='positive'
-        :label='t(`common.actions.saveChanges`)'
-        :aria-label='t(`common.actions.saveChanges`)'
-        :disabled='!editorStore.hasPendingChanges'
-        no-caps
-        @click.exact='saveChanges(false)'
-        @click.ctrl.exact='saveChanges(true)'
         )
-        q-tooltip {{ t(`editor.saveAndCloseTip`) }}
+        q-btn.acrylic-btn(
+          flat
+          icon='las la-check'
+          color='positive'
+          :label='t(`common.actions.saveChanges`)'
+          :aria-label='t(`common.actions.saveChanges`)'
+          :disabled='!editorStore.hasPendingChanges'
+          no-caps
+          @click.exact='saveChanges(false)'
+          @click.ctrl.exact='saveChanges(true)'
+          )
+        q-separator(vertical, dark)
+        q-btn.acrylic-btn(
+          flat
+          icon='las la-check-double'
+          color='positive'
+          :aria-label='t(`common.actions.saveAndClose`)'
+          :disabled='!editorStore.hasPendingChanges'
+          @click='saveChanges(true)'
+          )
+          q-tooltip {{ t(`common.actions.saveAndClose`) }}
     template(v-else-if='userStore.can(`edit:pages`)')
       q-btn.acrylic-btn.q-ml-md(
         flat

+ 13 - 13
ux/src/components/PageNewMenu.vue

@@ -19,14 +19,14 @@ q-menu.translucent-menu(
       )
       blueprint-icon(icon='markdown')
       q-item-section.q-pr-sm New Markdown Page
-    q-item(
-      clickable
-      @click='create(`asciidoc`)'
-      v-if='siteStore.editors.asciidoc'
-      )
-      blueprint-icon(icon='asciidoc')
-      q-item-section.q-pr-sm New AsciiDoc Page
     template(v-if='flagsStore.experimental')
+      q-item(
+        clickable
+        @click='create(`asciidoc`)'
+        v-if='siteStore.editors.asciidoc'
+        )
+        blueprint-icon(icon='asciidoc')
+        q-item-section.q-pr-sm New AsciiDoc Page
       q-item(
         clickable
         @click='create(`channel`)'
@@ -45,12 +45,12 @@ q-menu.translucent-menu(
         )
         blueprint-icon(icon='api')
         q-item-section.q-pr-sm New API Documentation
-    q-item(
-      clickable
-      @click='create(`redirect`)'
-      )
-      blueprint-icon(icon='advance')
-      q-item-section.q-pr-sm New Redirection
+      q-item(
+        clickable
+        @click='create(`redirect`)'
+        )
+        blueprint-icon(icon='advance')
+        q-item-section.q-pr-sm New Redirection
     template(v-if='props.hideAssetBtn === false')
       q-separator.q-my-sm(inset)
       q-item(

+ 1 - 51
ux/src/pages/AdminLocale.vue

@@ -62,7 +62,7 @@ q-page.admin-locale
               )
         q-separator.q-my-sm(inset)
         q-item(tag='label')
-          blueprint-icon(icon='unit')
+          blueprint-icon(icon='close-pane')
           q-item-section
             q-item-label {{t(`admin.locale.forcePrefix`)}}
             q-item-label(caption) {{t(`admin.locale.forcePrefixHint`)}}
@@ -113,8 +113,6 @@ q-page.admin-locale
 import gql from 'graphql-tag'
 import { cloneDeep, sortBy } from 'lodash-es'
 
-import LocaleInstallDialog from '../components/LocaleInstallDialog.vue'
-
 import { useI18n } from 'vue-i18n'
 import { useMeta, useQuasar } from 'quasar'
 import { computed, onMounted, reactive, watch } from 'vue'
@@ -164,14 +162,6 @@ watch(() => state.selectedLocale, (newValue) => {
 
 // METHODS
 
-function installNewLocale () {
-  $q.dialog({
-    component: LocaleInstallDialog
-  }).onOk(() => {
-    this.load()
-  })
-}
-
 async function load () {
   state.loading++
   $q.loading.show()
@@ -218,46 +208,6 @@ async function load () {
   state.loading--
 }
 
-async function download (lc) {
-  lc.isDownloading = true
-  const respRaw = await APOLLO_CLIENT.mutate({
-    mutation: gql`
-      mutation downloadLocale ($locale: String!) {
-        localization {
-          downloadLocale (locale: $locale) {
-            responseResult {
-              succeeded
-              errorCode
-              slug
-              message
-            }
-          }
-        }
-      }
-    `,
-    variables: {
-      locale: lc.code
-    }
-  })
-  const resp = respRaw?.data?.localization?.downloadLocale?.responseResult || {}
-  if (resp.succeeded) {
-    lc.isDownloading = false
-    lc.isInstalled = true
-    lc.updatedAt = new Date().toISOString()
-    lc.installDate = lc.updatedAt
-    $q.notify({
-      message: `Locale ${lc.name} has been installed successfully.`,
-      type: 'positive'
-    })
-  } else {
-    $q.notify({
-      type: 'negative',
-      message: resp.message
-    })
-  }
-  state.isDownloading = false
-}
-
 async function save () {
   state.loading = true
   const respRaw = await APOLLO_CLIENT.mutate({

+ 1 - 1
ux/src/pages/AdminScheduler.vue

@@ -30,7 +30,7 @@ q-page.admin-terminal
         flat
         color='grey'
         :aria-label='t(`common.actions.viewDocs`)'
-        :href='siteStore.docsBase + `/admin/scheduler`'
+        :href='siteStore.docsBase + `/system/scheduler`'
         target='_blank'
         type='a'
         )