From f75a05438f95c41aeec45dc373d7ccc7b35e1618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E4=B8=B4?= <155876693+wsxiaolin@users.noreply.github.com> Date: Thu, 14 May 2026 23:11:12 +0800 Subject: [PATCH 1/3] Use i18n for Royter editor copy --- package-lock.json | 793 ++++++++++++++++++++++++++++- package.json | 3 +- src/i18n/de.ts | 23 + src/i18n/en.ts | 23 + src/i18n/fr.ts | 23 + src/i18n/ja.ts | 23 + src/i18n/zh.ts | 23 + src/router/index.ts | 6 + src/services/editor/cloudWorks.ts | 168 ++++++ src/views/RoyterMarkdownEditor.vue | 437 ++++++++++++++++ 10 files changed, 1519 insertions(+), 3 deletions(-) create mode 100644 src/services/editor/cloudWorks.ts create mode 100644 src/views/RoyterMarkdownEditor.vue diff --git a/package-lock.json b/package-lock.json index 3c319ae..0b61c98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "date-fns": "^4.1.0", "highlight.js": "^11.11.1", "katex": "^0.16.45", + "md-editor-v3": "^6.5.0", "mermaid": "^11.14.0", "prettier": "^3.6.2", "vue": "^3.5.24", @@ -1474,6 +1475,407 @@ "integrity": "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==", "license": "Apache-2.0" }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.2.tgz", + "integrity": "sha512-G5FPkgIiLjOgZMjqVjvuKQ1rGPtHogLldJr33eFJdVLtmwY+giGrlv/ewljLz6b9BSQLkjxuwBc6g6omDM+YxQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-angular": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.4.tgz", + "integrity": "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.3" + } + }, + "node_modules/@codemirror/lang-cpp": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", + "integrity": "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/cpp": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-go": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", + "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/go": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-java": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz", + "integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/java": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-jinja": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-jinja/-/lang-jinja-6.0.1.tgz", + "integrity": "sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-less": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", + "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-liquid": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.3.2.tgz", + "integrity": "sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", + "integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-php": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.2.tgz", + "integrity": "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", + "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/lang-rust": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", + "integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/rust": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sass": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", + "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/sass": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sql": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", + "integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-vue": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", + "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-wast": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", + "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.3.tgz", + "integrity": "sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.0.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/language-data": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/language-data/-/language-data-6.5.2.tgz", + "integrity": "sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg==", + "license": "MIT", + "dependencies": { + "@codemirror/lang-angular": "^0.1.0", + "@codemirror/lang-cpp": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-go": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-java": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/lang-jinja": "^6.0.0", + "@codemirror/lang-json": "^6.0.0", + "@codemirror/lang-less": "^6.0.0", + "@codemirror/lang-liquid": "^6.0.0", + "@codemirror/lang-markdown": "^6.0.0", + "@codemirror/lang-php": "^6.0.0", + "@codemirror/lang-python": "^6.0.0", + "@codemirror/lang-rust": "^6.0.0", + "@codemirror/lang-sass": "^6.0.0", + "@codemirror/lang-sql": "^6.0.0", + "@codemirror/lang-vue": "^0.1.1", + "@codemirror/lang-wast": "^6.0.0", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/lang-yaml": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/legacy-modes": "^6.4.0" + } + }, + "node_modules/@codemirror/legacy-modes": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.3.tgz", + "integrity": "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.6.tgz", + "integrity": "sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.0.tgz", + "integrity": "sha512-ZvGm99wc/s2cITtMT15LFdn8aH/aS+V+DqyGq/N5ZlV5vWtH+nILvC2nw0zX7ByNoHHDZ2IxxdW38O0tc5nVHg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.0.tgz", + "integrity": "sha512-V7ZCLQO3Jus9hzh2jVCCPW3mO4IBMr43O37PqSUYautJSnnJF41YlgLw21x0fLJTYvJ+Vkm6Gp+qKGH9pltgXA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@css-render/plugin-bem": { "version": "0.15.14", "dev": true, @@ -1825,6 +2227,189 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.5.tgz", + "integrity": "sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/go": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz", + "integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/java": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", + "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.3.tgz", + "integrity": "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/php": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.5.tgz", + "integrity": "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz", + "integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/rust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", + "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/sass": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.1.0.tgz", + "integrity": "sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.4.tgz", + "integrity": "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@mermaid-js/parser": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.0.tgz", @@ -2534,6 +3119,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.20", "dev": true, @@ -2547,6 +3138,22 @@ "@types/lodash": "*" } }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "24.10.1", "dev": true, @@ -2807,6 +3414,18 @@ "d3-transition": "^3.0.1" } }, + "node_modules/@vavt/copy2clipboard": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@vavt/copy2clipboard/-/copy2clipboard-1.0.3.tgz", + "integrity": "sha512-HtG48r2FBYp9eRvGB3QGmtRBH1zzRRAVvFbGgFstOwz4/DDaNiX0uZc3YVKPydqgOav26pibr9MtoCaWxn7aeA==", + "license": "MIT" + }, + "node_modules/@vavt/util": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vavt/util/-/util-2.1.2.tgz", + "integrity": "sha512-L3UbSJthJwr3wq0x93O5TrCepimrmVZaIl2ciZbeL18G5++gBhJXNhcH7RcVk/6rr3SavWOvwhig0mqRLoR7dw==", + "license": "MIT" + }, "node_modules/@vitejs/plugin-vue": { "version": "6.0.1", "dev": true, @@ -3079,7 +3698,6 @@ }, "node_modules/argparse": { "version": "2.0.1", - "dev": true, "license": "Python-2.0" }, "node_modules/array-buffer-byte-length": { @@ -3426,6 +4044,21 @@ "chevrotain": "^12.0.0" } }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -3444,7 +4077,6 @@ }, "node_modules/commander": { "version": "2.20.3", - "dev": true, "license": "MIT" }, "node_modules/common-tags": { @@ -3492,6 +4124,12 @@ "layout-base": "^1.0.0" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "dev": true, @@ -3538,6 +4176,12 @@ "node": ">=4" } }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", + "license": "MIT" + }, "node_modules/csstype": { "version": "3.2.0", "license": "MIT" @@ -5804,6 +6448,15 @@ "node": ">= 0.8.0" } }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -5852,6 +6505,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-vue-next": { + "version": "0.543.0", + "resolved": "https://registry.npmjs.org/lucide-vue-next/-/lucide-vue-next-0.543.0.tgz", + "integrity": "sha512-Az5kpNm/koKAwSNIKjsZ4uHV2tVfmlQlcHwFBygQ8gc5/jFg7An9OrxgDy/aE5m+HLx7VfLYqDxLr8gWecZbQA==", + "license": "ISC", + "peerDependencies": { + "vue": ">=3.0.1" + } + }, "node_modules/magic-string": { "version": "0.30.21", "license": "MIT", @@ -5859,6 +6521,47 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-image-figures": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-image-figures/-/markdown-it-image-figures-2.1.1.tgz", + "integrity": "sha512-mwXSQ2nPeVUzCMIE3HlLvjRioopiqyJLNph0pyx38yf9mpqFDhNGnMpAXF9/A2Xv0oiF2cVyg9xwfF0HNAz05g==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/markdown-it-sub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-2.0.0.tgz", + "integrity": "sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA==", + "license": "MIT" + }, + "node_modules/markdown-it-sup": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-2.0.0.tgz", + "integrity": "sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA==", + "license": "MIT" + }, "node_modules/marked": { "version": "16.4.2", "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", @@ -5879,6 +6582,49 @@ "node": ">= 0.4" } }, + "node_modules/md-editor-v3": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/md-editor-v3/-/md-editor-v3-6.5.0.tgz", + "integrity": "sha512-GhGhPebfJeOrFuybFMUZRM6GzLMhu7Sg03MWLwO6tuIKMkRN71/SeTbLYYzY95qpaMbXDMWKlTkj3UNf9Bz4dg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.18.7", + "@codemirror/commands": "^6.8.1", + "@codemirror/lang-markdown": "^6.3.4", + "@codemirror/language": "^6.11.3", + "@codemirror/language-data": "^6.5.1", + "@codemirror/search": "^6.5.11", + "@codemirror/state": "^6.5.2", + "@codemirror/view": "^6.38.2", + "@lezer/highlight": "^1.2.1", + "@types/markdown-it": "^14.0.1", + "@vavt/copy2clipboard": "^1.0.1", + "@vavt/util": "^2.1.2", + "codemirror": "^6.0.2", + "lucide-vue-next": "^0.543.0", + "markdown-it": "^14.0.0", + "markdown-it-image-figures": "^2.1.1", + "markdown-it-sub": "^2.0.0", + "markdown-it-sup": "^2.0.0", + "medium-zoom": "^1.1.0", + "xss": "^1.0.15" + }, + "peerDependencies": { + "vue": "^3.5.3" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/medium-zoom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.1.0.tgz", + "integrity": "sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==", + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", "dev": true, @@ -6379,6 +7125,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "dev": true, @@ -7133,6 +7888,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/stylis": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", @@ -7375,6 +8136,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/ufo": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", @@ -7800,6 +8567,12 @@ "vue": "^3.0.11" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/webidl-conversions": { "version": "4.0.2", "dev": true, @@ -8322,6 +9095,22 @@ "node": ">=12" } }, + "node_modules/xss": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz", + "integrity": "sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==", + "license": "MIT", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "dev": true, diff --git a/package.json b/package.json index 5e79c80..b05f4d8 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "date-fns": "^4.1.0", "highlight.js": "^11.11.1", "katex": "^0.16.45", + "md-editor-v3": "^6.5.0", "mermaid": "^11.14.0", "prettier": "^3.6.2", "vue": "^3.5.24", @@ -41,4 +42,4 @@ "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.60.1" } -} \ No newline at end of file +} diff --git a/src/i18n/de.ts b/src/i18n/de.ts index b9b13b5..6bfa2ce 100644 --- a/src/i18n/de.ts +++ b/src/i18n/de.ts @@ -135,6 +135,29 @@ export default { off: "Aus", }, }, + royterEditor: { + title: "Royter Markdown-Editor", + refreshWorks: "Aktualisieren", + workListAria: "Werkliste", + searchPlaceholder: "Werke suchen", + emptyWorks: "Keine bearbeitbaren Werke.", + subjectPlaceholder: "Titel", + save: "Speichern", + previewTitle: "Vorschau", + rendering: "Wird gerendert...", + selectWork: "Wählen Sie links ein Werk aus.", + loginRequiredTitle: "Anmeldung erforderlich", + loginRequiredContent: "Melden Sie sich an, bevor Sie Werke bearbeiten.", + login: "Anmelden", + saveSuccess: "Gespeichert", + emptyPreview: "Kein Inhalt", + untitled: "Ohne Titel", + noPermission: "Dieses Konto kann dieses Werk nicht bearbeiten.", + readSummaryFailed: "Werkzusammenfassung konnte nicht gelesen werden: {status}", + fetchWorksFailed: "Werke konnten nicht geladen werden: {status}", + readWorkspaceFailed: "Arbeitsbereich konnte nicht gelesen werden: {status}", + saveWorkFailed: "Werk konnte nicht gespeichert werden: {status}", + }, footer: { home: "Startseite", blackHole: "Schwarzes Loch", diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 047043b..8e1b169 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -133,6 +133,29 @@ export default { off: "Off", }, }, + royterEditor: { + title: "Royter Markdown Editor", + refreshWorks: "Refresh", + workListAria: "Work list", + searchPlaceholder: "Search works", + emptyWorks: "No editable works.", + subjectPlaceholder: "Title", + save: "Save", + previewTitle: "Preview", + rendering: "Rendering...", + selectWork: "Select a work on the left.", + loginRequiredTitle: "Login required", + loginRequiredContent: "Log in before editing works.", + login: "Login", + saveSuccess: "Saved", + emptyPreview: "No content", + untitled: "Untitled", + noPermission: "This account cannot edit this work.", + readSummaryFailed: "Failed to read work summary: {status}", + fetchWorksFailed: "Failed to fetch works: {status}", + readWorkspaceFailed: "Failed to read workspace: {status}", + saveWorkFailed: "Failed to save work: {status}", + }, footer: { home: "Home", blackHole: "Black Hole", diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts index 33ed75e..37fc58c 100644 --- a/src/i18n/fr.ts +++ b/src/i18n/fr.ts @@ -134,6 +134,29 @@ export default { off: "Désactivé", }, }, + royterEditor: { + title: "Éditeur Markdown Royter", + refreshWorks: "Actualiser", + workListAria: "Liste des œuvres", + searchPlaceholder: "Rechercher des œuvres", + emptyWorks: "Aucune œuvre modifiable.", + subjectPlaceholder: "Titre", + save: "Enregistrer", + previewTitle: "Aperçu", + rendering: "Rendu...", + selectWork: "Sélectionnez une œuvre à gauche.", + loginRequiredTitle: "Connexion requise", + loginRequiredContent: "Connectez-vous avant de modifier des œuvres.", + login: "Connexion", + saveSuccess: "Enregistré", + emptyPreview: "Aucun contenu", + untitled: "Sans titre", + noPermission: "Ce compte ne peut pas modifier cette œuvre.", + readSummaryFailed: "Impossible de lire le résumé de l’œuvre : {status}", + fetchWorksFailed: "Impossible de charger les œuvres : {status}", + readWorkspaceFailed: "Impossible de lire l’espace de travail : {status}", + saveWorkFailed: "Impossible d’enregistrer l’œuvre : {status}", + }, footer: { home: "Accueil", blackHole: "Trou noir", diff --git a/src/i18n/ja.ts b/src/i18n/ja.ts index 0414198..e0a6cf5 100644 --- a/src/i18n/ja.ts +++ b/src/i18n/ja.ts @@ -133,6 +133,29 @@ export default { off: "オフ", }, }, + royterEditor: { + title: "Royter Markdown エディター", + refreshWorks: "更新", + workListAria: "作品リスト", + searchPlaceholder: "作品を検索", + emptyWorks: "編集できる作品がありません。", + subjectPlaceholder: "タイトル", + save: "保存", + previewTitle: "プレビュー", + rendering: "レンダリング中...", + selectWork: "左側から作品を選択してください。", + loginRequiredTitle: "ログインが必要です", + loginRequiredContent: "作品を編集する前にログインしてください。", + login: "ログイン", + saveSuccess: "保存しました", + emptyPreview: "内容がありません", + untitled: "無題", + noPermission: "このアカウントではこの作品を編集できません。", + readSummaryFailed: "作品概要の読み込みに失敗しました: {status}", + fetchWorksFailed: "作品一覧の取得に失敗しました: {status}", + readWorkspaceFailed: "ワークスペースの読み込みに失敗しました: {status}", + saveWorkFailed: "作品の保存に失敗しました: {status}", + }, footer: { home: "ホーム", blackHole: "ブラックホール", diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 383396b..9d32e6b 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -130,6 +130,29 @@ export default { off: "关闭", }, }, + royterEditor: { + title: "Royter Markdown 编辑器", + refreshWorks: "刷新作品", + workListAria: "作品列表", + searchPlaceholder: "搜索作品", + emptyWorks: "没有可编辑的作品。", + subjectPlaceholder: "标题", + save: "保存", + previewTitle: "预览", + rendering: "渲染中...", + selectWork: "请从左侧选择作品。", + loginRequiredTitle: "需要登录", + loginRequiredContent: "请先登录后再编辑作品。", + login: "去登录", + saveSuccess: "保存成功", + emptyPreview: "暂无内容", + untitled: "未命名", + noPermission: "当前账号没有编辑该作品的权限。", + readSummaryFailed: "读取作品摘要失败:{status}", + fetchWorksFailed: "获取作品列表失败:{status}", + readWorkspaceFailed: "读取工作区失败:{status}", + saveWorkFailed: "保存作品失败:{status}", + }, footer: { home: "首页", blackHole: "黑洞", diff --git a/src/router/index.ts b/src/router/index.ts index a382a34..4b0ebd8 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -62,6 +62,12 @@ const routes = [ component: () => import("../views/Settings.vue"), meta: { keepAlive: false }, }, + { + path: "/royter", + name: "RoyterMarkdownEditor", + component: () => import("../views/RoyterMarkdownEditor.vue"), + meta: { keepAlive: false }, + }, { path: "/:catchAll(.*)", component: () => import("../views/NotFound.vue"), diff --git a/src/services/editor/cloudWorks.ts b/src/services/editor/cloudWorks.ts new file mode 100644 index 0000000..30eef76 --- /dev/null +++ b/src/services/editor/cloudWorks.ts @@ -0,0 +1,168 @@ +import i18n from "@i18n/index"; +import { getData } from "@services/api/getData.ts"; +import storageManager from "@storage/index.ts"; +import type { + Category, + ExperimentQuery, + Result, + Summary, + UserInfo, + Workspace, +} from "@services/../pl-serve-type-main/type/main"; + +export type EditorWork = { + id: string; + contentId: string; + category: Category; + subject: string; + markdown: string; + language: string; + rawSummary: Summary; +}; + +export type SaveEditorWorkResult = { + requestBody: Record; + response: Result | Result; +}; + +const EDITABLE_VERIFICATIONS = new Set(["Editor", "Administrator"]); + +function t(key: string, params?: Record): string { + return i18n.global.t(key, params || {}) as string; +} + +function getCurrentUser(): UserInfo | null { + return storageManager.getObj("userInfo").value as UserInfo | null; +} + +export function getCurrentUserId(): string { + return getCurrentUser()?.ID || ""; +} + +export function canEditSummary(summary: Summary): boolean { + const currentUser = getCurrentUser(); + if (!currentUser?.ID) return false; + if (summary.User?.ID === currentUser.ID) return true; + if (summary.Coauthors?.some((user) => user.ID === currentUser.ID)) return true; + return EDITABLE_VERIFICATIONS.has(String(currentUser.Verification || "")); +} + +function normalizeDescription(description: Summary["Description"]): string { + if (Array.isArray(description)) return description.join("\n"); + return ""; +} + +function toEditorWork(summary: Summary): EditorWork { + return { + id: summary.ID, + contentId: summary.ContentID || summary.ID, + category: summary.Category || "Discussion", + subject: summary.Subject || t("royterEditor.untitled"), + markdown: normalizeDescription(summary.Description), + language: summary.Language || "Chinese", + rawSummary: summary, + }; +} + +async function fetchSummary(category: Category, id: string): Promise { + const res = await getData("/Contents/GetSummary", { + ContentID: id, + Category: category, + }); + if (res.Status !== 200 || !res.Data) { + throw new Error( + res.Message || t("royterEditor.readSummaryFailed", { status: res.Status }), + ); + } + return res.Data; +} + +export async function fetchEditableWorks(take = 50): Promise { + const userId = getCurrentUserId(); + if (!userId) return []; + + const query: ExperimentQuery = { + Category: "Discussion", + Languages: [], + ExcludeLanguages: [], + Tags: [], + ExcludeTags: [], + ModelTags: [], + ModelID: undefined, + ParentID: undefined, + UserID: userId, + Special: null, + From: undefined, + Skip: 0, + Take: take, + Days: 0, + Sort: 0, + ShowAnnouncement: false, + }; + + const res = await getData("/Contents/QueryExperiments", { Query: query }); + if (res.Status !== 200) { + throw new Error( + res.Message || t("royterEditor.fetchWorksFailed", { status: res.Status }), + ); + } + + const summaries = res.Data?.$values || []; + const detailed = await Promise.all( + summaries.map((item) => fetchSummary((item.Category || "Discussion") as Category, item.ID)), + ); + return detailed.filter(canEditSummary).map(toEditorWork); +} + +export async function fetchWorkspace(work: EditorWork): Promise { + const res = await getData("/Contents/GetWorkspace", { + ContentID: work.contentId, + Language: work.language || "Chinese", + }); + if (res.Status !== 200) { + throw new Error( + res.Message || t("royterEditor.readWorkspaceFailed", { status: res.Status }), + ); + } + return res.Data || null; +} + +export async function saveEditorWork( + work: EditorWork, + markdown: string, + subject: string, +): Promise { + if (!canEditSummary(work.rawSummary)) { + throw new Error(t("royterEditor.noPermission")); + } + + const workspace = await fetchWorkspace(work); + const summary: Summary = { + ...work.rawSummary, + Subject: subject.trim() || work.subject, + Description: markdown.split("\n"), + Language: work.language as Summary["Language"], + }; + + const requestBody: Record = { + Summary: summary, + Workspace: workspace ? { ...workspace, Summary: null } : null, + }; + + const response = (await getData( + "/Contents/SubmitExperiment" as any, + requestBody, + )) as Result; + if (response.Status !== 200) { + throw new Error( + response.Message || + t("royterEditor.saveWorkFailed", { status: response.Status }), + ); + } + + work.subject = summary.Subject || work.subject; + work.markdown = markdown; + work.rawSummary = summary; + + return { requestBody, response }; +} diff --git a/src/views/RoyterMarkdownEditor.vue b/src/views/RoyterMarkdownEditor.vue new file mode 100644 index 0000000..8d805f9 --- /dev/null +++ b/src/views/RoyterMarkdownEditor.vue @@ -0,0 +1,437 @@ + + + + + From 8ebc42c6ba540dc3ff4a060ad50fd1cd445c10f5 Mon Sep 17 00:00:00 2001 From: gushishang <117088703+gushishang@users.noreply.github.com> Date: Fri, 29 May 2026 23:43:58 +0800 Subject: [PATCH 2/3] temp --- .gitignore | 15 + src/i18n/de.ts | 5 + src/i18n/en.ts | 5 + src/i18n/fr.ts | 7 +- src/i18n/ja.ts | 5 + src/i18n/zh.ts | 7 +- src/router/index.ts | 6 +- src/services/editor/cloudWorks.ts | 103 +++- src/views/Editor.vue | 905 +++++++++++++++++++++++++++++ src/views/ExperimentSummary.vue | 30 +- src/views/RoyterMarkdownEditor.vue | 437 -------------- 11 files changed, 1061 insertions(+), 464 deletions(-) create mode 100644 src/views/Editor.vue delete mode 100644 src/views/RoyterMarkdownEditor.vue diff --git a/.gitignore b/.gitignore index 93fa91f..bf27f9a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,18 @@ dev-dist # debugs *.http +temp +phyEngine/ +*Circuit*/ +*circuit*/ +src/views/CircuitLab2D.vue +src/views/CircuitLab2D_Simple.vue +src/services/circuitSav.ts +src/config/components.ts +src/composables/useSimulation.ts +src/composables/useCircuitEngine.ts +src/assets/styles/circuit-lab.css +src/composables/useCamera.ts +.gitignore +src/types/circuit.ts +src/composables/useDragAndDrop.ts diff --git a/src/i18n/de.ts b/src/i18n/de.ts index 6bfa2ce..fdcc243 100644 --- a/src/i18n/de.ts +++ b/src/i18n/de.ts @@ -99,6 +99,7 @@ export default { copyInternalLink: "Internen Link kopieren", copyExternalLink: "Externen Link kopieren", changeCover: "Cover ändern", + editWork: "Werk bearbeiten", }, date: { justNow: "Gerade eben", @@ -157,6 +158,10 @@ export default { fetchWorksFailed: "Werke konnten nicht geladen werden: {status}", readWorkspaceFailed: "Arbeitsbereich konnte nicht gelesen werden: {status}", saveWorkFailed: "Werk konnte nicht gespeichert werden: {status}", + changeCover: "Cover ändern", + uploadImgHint: "Bild-Upload wird noch nicht unterstützt", + editTags: "Tags bearbeiten", + tagPlaceholder: "Tag eingeben und Enter drücken", }, footer: { home: "Startseite", diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 8e1b169..42d6387 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -97,6 +97,7 @@ export default { copyInternalLink: "Copy Internal Link", copyExternalLink: "Copy External Link", changeCover: "Change Cover", + editWork: "Edit Work", }, date: { justNow: "Just now", @@ -155,6 +156,10 @@ export default { fetchWorksFailed: "Failed to fetch works: {status}", readWorkspaceFailed: "Failed to read workspace: {status}", saveWorkFailed: "Failed to save work: {status}", + changeCover: "Change Cover", + uploadImgHint: "Image upload is not supported yet", + editTags: "Edit Tags", + tagPlaceholder: "Type tag and press Enter", }, footer: { home: "Home", diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts index 37fc58c..f74de6c 100644 --- a/src/i18n/fr.ts +++ b/src/i18n/fr.ts @@ -98,6 +98,7 @@ export default { copyInternalLink: "Copier le lien interne", copyExternalLink: "Copier le lien de partage", changeCover: "Changer la couverture", + editWork: "Modifier l'œuvre", }, date: { justNow: "À l'instant", @@ -155,7 +156,11 @@ export default { readSummaryFailed: "Impossible de lire le résumé de l’œuvre : {status}", fetchWorksFailed: "Impossible de charger les œuvres : {status}", readWorkspaceFailed: "Impossible de lire l’espace de travail : {status}", - saveWorkFailed: "Impossible d’enregistrer l’œuvre : {status}", + saveWorkFailed: "Impossible d'enregistrer l'œuvre : {status}", + changeCover: "Changer la couverture", + uploadImgHint: "Le téléchargement d'image n'est pas encore pris en charge", + editTags: "Modifier les étiquettes", + tagPlaceholder: "Saisir une étiquette et appuyer sur Entrée", }, footer: { home: "Accueil", diff --git a/src/i18n/ja.ts b/src/i18n/ja.ts index e0a6cf5..1cf8996 100644 --- a/src/i18n/ja.ts +++ b/src/i18n/ja.ts @@ -97,6 +97,7 @@ export default { copyInternalLink: "内部リンクをコピー", copyExternalLink: "外部リンクをコピー", changeCover: "カバーを変更", + editWork: "作品を編集", }, date: { justNow: "たった今", @@ -155,6 +156,10 @@ export default { fetchWorksFailed: "作品一覧の取得に失敗しました: {status}", readWorkspaceFailed: "ワークスペースの読み込みに失敗しました: {status}", saveWorkFailed: "作品の保存に失敗しました: {status}", + changeCover: "カバーを変更", + uploadImgHint: "画像アップロードは未対応", + editTags: "タグを編集", + tagPlaceholder: "タグを入力してEnter", }, footer: { home: "ホーム", diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 9d32e6b..122c725 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -95,6 +95,7 @@ export default { copyInternalLink: "复制内部链接", copyExternalLink: "复制外部链接", changeCover: "更换封面", + editWork: "编辑作品", }, date: { justNow: "刚刚", @@ -131,7 +132,7 @@ export default { }, }, royterEditor: { - title: "Royter Markdown 编辑器", + title: "Markdown 编辑器", refreshWorks: "刷新作品", workListAria: "作品列表", searchPlaceholder: "搜索作品", @@ -152,6 +153,10 @@ export default { fetchWorksFailed: "获取作品列表失败:{status}", readWorkspaceFailed: "读取工作区失败:{status}", saveWorkFailed: "保存作品失败:{status}", + changeCover: "更换封面", + uploadImgHint: "暂不支持图片上传", + editTags: "编辑标签", + tagPlaceholder: "输入标签后回车", }, footer: { home: "首页", diff --git a/src/router/index.ts b/src/router/index.ts index 4b0ebd8..18c6541 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -63,9 +63,9 @@ const routes = [ meta: { keepAlive: false }, }, { - path: "/royter", - name: "RoyterMarkdownEditor", - component: () => import("../views/RoyterMarkdownEditor.vue"), + path: "/e/:category?/:id?", + name: "Editor", + component: () => import("../views/Editor.vue"), meta: { keepAlive: false }, }, { diff --git a/src/services/editor/cloudWorks.ts b/src/services/editor/cloudWorks.ts index 30eef76..196f5a9 100644 --- a/src/services/editor/cloudWorks.ts +++ b/src/services/editor/cloudWorks.ts @@ -6,6 +6,7 @@ import type { ExperimentQuery, Result, Summary, + SummaryTag, UserInfo, Workspace, } from "@services/../pl-serve-type-main/type/main"; @@ -17,12 +18,25 @@ export type EditorWork = { subject: string; markdown: string; language: string; - rawSummary: Summary; + tags: SummaryTag[]; + rawSummary?: Summary; }; export type SaveEditorWorkResult = { requestBody: Record; - response: Result | Result; + response: Result; + updatedWork: EditorWork; +}; + +export type CategoryCursor = { + category: Category; + from?: string; +}; + +export type FetchWorksResult = { + works: EditorWork[]; + hasMore: boolean; + cursors: CategoryCursor[]; }; const EDITABLE_VERIFICATIONS = new Set(["Editor", "Administrator"]); @@ -60,6 +74,7 @@ function toEditorWork(summary: Summary): EditorWork { subject: summary.Subject || t("royterEditor.untitled"), markdown: normalizeDescription(summary.Description), language: summary.Language || "Chinese", + tags: summary.Tags || [], rawSummary: summary, }; } @@ -77,12 +92,14 @@ async function fetchSummary(category: Category, id: string): Promise { return res.Data; } -export async function fetchEditableWorks(take = 50): Promise { - const userId = getCurrentUserId(); - if (!userId) return []; - +async function queryCategory( + userId: string, + category: Category, + from: string | undefined, + take: number, +): Promise<{ summaries: Summary[]; lastId: string }> { const query: ExperimentQuery = { - Category: "Discussion", + Category: category, Languages: [], ExcludeLanguages: [], Tags: [], @@ -92,7 +109,7 @@ export async function fetchEditableWorks(take = 50): Promise { ParentID: undefined, UserID: userId, Special: null, - From: undefined, + From: from || null, Skip: 0, Take: take, Days: 0, @@ -107,11 +124,50 @@ export async function fetchEditableWorks(take = 50): Promise { ); } - const summaries = res.Data?.$values || []; - const detailed = await Promise.all( - summaries.map((item) => fetchSummary((item.Category || "Discussion") as Category, item.ID)), + const summaries: Summary[] = res.Data?.$values || []; + const lastId = summaries.length > 0 ? summaries[summaries.length - 1].ID : (from || ""); + return { summaries, lastId }; +} + +export async function fetchEditableWorks( + cursors: CategoryCursor[], + take = 20, +): Promise { + const userId = getCurrentUserId(); + if (!userId) return { works: [], hasMore: false, cursors: [] }; + + const cats = cursors.length ? cursors : [{ category: "Discussion" as Category }]; + + const results = await Promise.all( + cats.map((c) => queryCategory(userId, c.category, c.from, take)), ); - return detailed.filter(canEditSummary).map(toEditorWork); + + const allSummaries = results.flatMap((r) => r.summaries); + const works = allSummaries.filter(canEditSummary).map(toEditorWork); + const hasMore = results.some((r) => r.summaries.length >= take); + + const nextCursors: CategoryCursor[] = cats.map((c, i) => ({ + category: c.category, + from: results[i].lastId, + })); + + return { works, hasMore, cursors: nextCursors }; +} + +export async function fetchEditableWork(category: Category, id: string): Promise { + const summary = await fetchSummary(category, id); + if (!canEditSummary(summary)) { + throw new Error(t("royterEditor.noPermission")); + } + return toEditorWork(summary); +} + +export async function loadWorkDetail(work: EditorWork): Promise { + const summary = await fetchSummary(work.category, work.id); + return { + ...toEditorWork(summary), + contentId: summary.ContentID || summary.ID, + }; } export async function fetchWorkspace(work: EditorWork): Promise { @@ -132,6 +188,9 @@ export async function saveEditorWork( markdown: string, subject: string, ): Promise { + if (!work.rawSummary) { + throw new Error(t("royterEditor.noPermission")); + } if (!canEditSummary(work.rawSummary)) { throw new Error(t("royterEditor.noPermission")); } @@ -149,10 +208,10 @@ export async function saveEditorWork( Workspace: workspace ? { ...workspace, Summary: null } : null, }; - const response = (await getData( - "/Contents/SubmitExperiment" as any, - requestBody, - )) as Result; + const response = await getData( + "/Contents/SubmitExperiment", + requestBody as any, + ) as unknown as Result; if (response.Status !== 200) { throw new Error( response.Message || @@ -160,9 +219,13 @@ export async function saveEditorWork( ); } - work.subject = summary.Subject || work.subject; - work.markdown = markdown; - work.rawSummary = summary; + const updatedWork: EditorWork = { + ...work, + subject: summary.Subject || work.subject, + markdown, + tags: summary.Tags || [], + rawSummary: summary, + }; - return { requestBody, response }; + return { requestBody, response, updatedWork }; } diff --git a/src/views/Editor.vue b/src/views/Editor.vue new file mode 100644 index 0000000..504b323 --- /dev/null +++ b/src/views/Editor.vue @@ -0,0 +1,905 @@ + + + + + diff --git a/src/views/ExperimentSummary.vue b/src/views/ExperimentSummary.vue index 4362db6..518e628 100644 --- a/src/views/ExperimentSummary.vue +++ b/src/views/ExperimentSummary.vue @@ -44,6 +44,16 @@ > {{ t("expeSummary.enterExp") }} + + {{ t("expeSummary.editWork") }} + @@ -173,8 +183,9 @@ - - From 634ce80801135cfd0d46cb19f8335ce7a3cf591d Mon Sep 17 00:00:00 2001 From: gushishang <117088703+gushishang@users.noreply.github.com> Date: Sat, 30 May 2026 09:11:35 +0800 Subject: [PATCH 3/3] .. --- src/i18n/de.ts | 2 +- src/i18n/en.ts | 2 +- src/i18n/fr.ts | 2 +- src/i18n/ja.ts | 2 +- src/i18n/zh.ts | 2 +- src/views/Editor.vue | 2 +- src/views/ExperimentSummary.vue | 29 +++++++++++------------------ 7 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/i18n/de.ts b/src/i18n/de.ts index fdcc243..91af24f 100644 --- a/src/i18n/de.ts +++ b/src/i18n/de.ts @@ -143,7 +143,7 @@ export default { searchPlaceholder: "Werke suchen", emptyWorks: "Keine bearbeitbaren Werke.", subjectPlaceholder: "Titel", - save: "Speichern", + publish: "Veröffentlichen", previewTitle: "Vorschau", rendering: "Wird gerendert...", selectWork: "Wählen Sie links ein Werk aus.", diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 42d6387..bddb555 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -141,7 +141,7 @@ export default { searchPlaceholder: "Search works", emptyWorks: "No editable works.", subjectPlaceholder: "Title", - save: "Save", + publish: "Publish", previewTitle: "Preview", rendering: "Rendering...", selectWork: "Select a work on the left.", diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts index f74de6c..9e25091 100644 --- a/src/i18n/fr.ts +++ b/src/i18n/fr.ts @@ -142,7 +142,7 @@ export default { searchPlaceholder: "Rechercher des œuvres", emptyWorks: "Aucune œuvre modifiable.", subjectPlaceholder: "Titre", - save: "Enregistrer", + publish: "Publier", previewTitle: "Aperçu", rendering: "Rendu...", selectWork: "Sélectionnez une œuvre à gauche.", diff --git a/src/i18n/ja.ts b/src/i18n/ja.ts index 1cf8996..511b9aa 100644 --- a/src/i18n/ja.ts +++ b/src/i18n/ja.ts @@ -141,7 +141,7 @@ export default { searchPlaceholder: "作品を検索", emptyWorks: "編集できる作品がありません。", subjectPlaceholder: "タイトル", - save: "保存", + publish: "公開", previewTitle: "プレビュー", rendering: "レンダリング中...", selectWork: "左側から作品を選択してください。", diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 122c725..abf90d2 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -138,7 +138,7 @@ export default { searchPlaceholder: "搜索作品", emptyWorks: "没有可编辑的作品。", subjectPlaceholder: "标题", - save: "保存", + publish: "发布", previewTitle: "预览", rendering: "渲染中...", selectWork: "请从左侧选择作品。", diff --git a/src/views/Editor.vue b/src/views/Editor.vue index 504b323..9892d58 100644 --- a/src/views/Editor.vue +++ b/src/views/Editor.vue @@ -83,7 +83,7 @@ class="subject-input" /> - {{ t("royterEditor.save") }} +{{ t("royterEditor.publish") }} diff --git a/src/views/ExperimentSummary.vue b/src/views/ExperimentSummary.vue index 518e628..6bcb10b 100644 --- a/src/views/ExperimentSummary.vue +++ b/src/views/ExperimentSummary.vue @@ -44,16 +44,6 @@ > {{ t("expeSummary.enterExp") }} - - {{ t("expeSummary.editWork") }} - @@ -356,7 +346,7 @@ async function copy(text: string) { } // eslint-disable-next-line max-lines-per-function function copySubject() { - let list = [ + const list: { label: string }[] = [ { label: t("expeSummary.copyID") }, { label: t("expeSummary.copyInternalLink") }, { label: t("expeSummary.copyExternalLink") }, @@ -364,19 +354,23 @@ function copySubject() { if (data.value.User.ID === storageManager.getObj("userInfo")?.value?.ID) { list.push({ label: t("expeSummary.changeCover") }); } + if (canEdit.value) { + list.push({ label: t("expeSummary.editWork") }); + } // eslint-disable-next-line max-lines-per-function showActionSheet(list, (idx) => { - if (idx === 0) { + const action = list[idx]?.label; + if (action === t("expeSummary.copyID")) { copy(data.value.ID); - } else if (idx === 1) { + } else if (action === t("expeSummary.copyInternalLink")) { copy( `<${(route.params.category as string).toLowerCase()}=${route.params.id}>${data.value.Subject}`, ); - } else if (idx === 2) { + } else if (action === t("expeSummary.copyExternalLink")) { copy( `${data.value.Subject}[web]`, ); - } else if (idx === 3) { + } else if (action === t("expeSummary.changeCover")) { try { // ask user to select an image const input = document.createElement("input"); @@ -633,6 +627,8 @@ function copySubject() { duration: 2000, }); } + } else if (action === t("expeSummary.editWork")) { + goToEditor(); } }); } @@ -735,9 +731,6 @@ onActivated(() => { bottom: calc(50px + env(safe-area-inset-bottom)); } - .edit-btn { - display: inline-flex; - } } @media (max-aspect-ratio: 1/1) {