Add ToastViewer component
authorAdam Dullage <redacted>
Fri, 3 May 2024 10:55:21 +0000 (11:55 +0100)
committerAdam Dullage <redacted>
Fri, 3 May 2024 10:55:21 +0000 (11:55 +0100)
client/components/Toast/ToastViewer.vue [new file with mode: 0644]
client/components/Toast/toastui-editor-overrides.scss [new file with mode: 0644]
package-lock.json
package.json

diff --git a/client/components/Toast/ToastViewer.vue b/client/components/Toast/ToastViewer.vue
new file mode 100644 (file)
index 0000000..bf618ee
--- /dev/null
@@ -0,0 +1,30 @@
+<template>
+  <div ref="viewerElement"></div>
+</template>
+
+<script setup>
+import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all.js";
+import Viewer from "@toast-ui/editor/dist/toastui-editor-viewer";
+import { onMounted, ref } from "vue";
+
+const props = defineProps({
+  initialValue: String,
+});
+
+const viewerElement = ref();
+
+onMounted(() => {
+  new Viewer({
+    el: viewerElement.value,
+    initialValue: props.initialValue,
+    plugins: [codeSyntaxHighlight],
+  });
+});
+</script>
+
+<style>
+@import "@toast-ui/editor/dist/toastui-editor-viewer.css";
+@import "prismjs/themes/prism.css";
+@import "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css";
+@import "./toastui-editor-overrides.scss";
+</style>
diff --git a/client/components/Toast/toastui-editor-overrides.scss b/client/components/Toast/toastui-editor-overrides.scss
new file mode 100644 (file)
index 0000000..cc485a8
--- /dev/null
@@ -0,0 +1,292 @@
+// Disable checkboxes in view mode. See https://github.com/nhn/tui.editor/issues/1087.
+.note-viewer li.task-list-item {
+  pointer-events: none;
+  a {
+    pointer-events: auto;
+  }
+}
+
+.ProseMirror,
+.toastui-editor-defaultUI .ProseMirror,
+.toastui-editor-md-container .toastui-editor-md-preview {
+  padding: 1rem 0 0 0;
+}
+
+.ProseMirror {
+  height: 100%;
+}
+
+.toastui-editor-contents ul > li::before {
+  // Vertically center the bullet point
+  margin-top: 0.7rem;
+}
+
+// Typography
+.ProseMirror,
+.toastui-editor-contents {
+  font-family: "Poppins", sans-serif;
+  font-size: 1rem;
+}
+
+.toastui-editor-contents,
+.ProseMirror {
+  h1,
+  .toastui-editor-md-heading1,
+  h2,
+  .toastui-editor-md-heading2,
+  h3,
+  .toastui-editor-md-heading3,
+  h4,
+  .toastui-editor-md-heading4,
+  h5,
+  .toastui-editor-md-heading5,
+  h6,
+  .toastui-editor-md-heading6 {
+    font-weight: bold;
+    line-height: 1.4;
+    margin: 1em 0 0.5em 0;
+    padding: 0;
+    border-bottom: none;
+
+    &:first-of-type {
+      margin-top: 0;
+    }
+  }
+
+  h1,
+  .toastui-editor-md-heading1 {
+    font-size: 1.75rem;
+  }
+
+  h2,
+  .toastui-editor-md-heading2 {
+    font-size: 1.6rem;
+  }
+
+  h3,
+  .toastui-editor-md-heading3 {
+    font-size: 1.45rem;
+  }
+
+  h4,
+  .toastui-editor-md-heading4 {
+    font-size: 1.3rem;
+  }
+
+  h5,
+  .toastui-editor-md-heading5 {
+    font-size: 1.15rem;
+  }
+
+  h6,
+  .toastui-editor-md-heading6 {
+    font-size: 1rem;
+  }
+
+  p {
+    line-height: 1.6rem;
+    margin: 0 0 1rem 0;
+  }
+}
+
+// Override the default font-family for code blocks as some of the fallbacks are not monospace
+.toastui-editor-contents code,
+.toastui-editor-contents pre,
+.toastui-editor-md-code,
+.toastui-editor-md-code-block {
+  font-family: Consolas, "Lucida Console", Monaco, "Andale Mono", monospace;
+}
+
+// Colours
+.toastui-editor-defaultUI {
+  border: none;
+}
+
+.toastui-editor-contents {
+  h1,
+  h2,
+  h3,
+  h4,
+  h5,
+  h6 {
+    color: rgb(var(--theme-text));
+  }
+  p {
+    color: rgb(var(--theme-text));
+  }
+  pre code {
+    color: rgb(var(--theme-text));
+  }
+}
+
+.toastui-editor-main {
+  background-color: rgb(var(--theme-background));
+}
+
+.toastui-editor-ww-container {
+  background-color: rgb(var(--theme-background));
+}
+
+.toastui-editor-contents ul,
+.toastui-editor-contents menu,
+.toastui-editor-contents ol,
+.toastui-editor-contents dir {
+  color: rgb(var(--theme-text));
+}
+
+// Code Block
+.toastui-editor-contents pre,
+.toastui-editor-md-code-block-line-background {
+  background-color: rgb(var(--theme-background-tint));
+}
+
+.dark-theme .toastui-editor-contents pre,
+.dark-theme .toastui-editor-md-code-block-line-background {
+  background-color: rgb(var(--theme-background-elevated));
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+  background: none;
+}
+
+// Tables
+.toastui-editor-contents table th {
+  color: rgb(var(--theme-text));
+  background-color: rgb(var(--theme-background-tint));
+}
+
+.toastui-editor-contents table {
+  color: rgb(var(--theme-text));
+}
+
+.toastui-editor-md-table .toastui-editor-md-table-cell {
+  color: rgb(var(--theme-text));
+}
+
+// Editor
+.ProseMirror {
+  color: rgb(var(--theme-text));
+}
+
+// Toolbar
+.toastui-editor-defaultUI-toolbar {
+  background-color: rgb(var(--theme-background));
+  border-bottom-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-defaultUI .toastui-editor-md-tab-container {
+  background-color: rgb(var(--theme-background));
+  border-bottom-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-mode-switch {
+  background-color: rgb(var(--theme-background));
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-defaultUI-toolbar button {
+  border: 1px solid rgb(var(--theme-background));
+}
+
+.toastui-editor-defaultUI .tab-item.active {
+  background-color: rgb(var(--theme-background));
+  color: rgb(var(--theme-text));
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-defaultUI .tab-item {
+  background-color: rgb(var(--theme-background-tint));
+  color: rgb(var(--theme-text-muted));
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-md-tab-container .tab-item.active {
+  border-bottom: none;
+}
+
+.toastui-editor-toolbar-divider {
+  background-color: rgb(var(--theme-text));
+}
+
+.dark-theme .toastui-editor-toolbar-icons {
+  // Standard dark theme buttons are dark grey, this position change makes them white
+  background-position-y: -49px;
+}
+
+.toastui-editor-defaultUI-toolbar button:not(:disabled):hover {
+  background-color: rgb(var(--theme-background-tint));
+  border: 1px solid rgb(var(--theme-background));
+}
+
+.toastui-editor-md-block-quote .toastui-editor-md-marked-text {
+  color: rgb(var(--theme-text-muted));
+}
+
+.toastui-editor-md-code,
+.toastui-editor-contents code {
+  background-color: rgb(var(--theme-background-tint));
+}
+
+.dark-theme .toastui-editor-md-code,
+.dark-theme .toastui-editor-contents code {
+  background-color: rgb(var(--theme-background-elevated));
+}
+
+.toastui-editor-popup {
+  background-color: rgb(var(--theme-background));
+  border: 1px solid rgb(var(--theme-border));
+}
+
+.toastui-editor-popup-body {
+  label {
+    color: rgb(var(--theme-text));
+  }
+  input {
+    background-color: rgb(var(--theme-background));
+    border: 1px solid rgb(var(--theme-border));
+  }
+}
+
+.toastui-editor-popup-add-table .toastui-editor-table-cell,
+.toastui-editor-popup-add-table .toastui-editor-table-cell.header {
+  background-color: rgb(var(--theme-background));
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-popup-add-heading ul li:hover {
+  background-color: rgb(var(--theme-background-highlight));
+}
+
+.toastui-editor-popup-add-image .toastui-editor-tabs .tab-item {
+  color: rgb(var(--theme-text));
+  background-color: rgb(var(--theme-background));
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-popup-add-image .toastui-editor-file-name.has-file {
+  color: rgb(var(--theme-text));
+}
+
+.toastui-editor-popup-body input[type="text"] {
+  color: rgb(var(--theme-text));
+  background-color: rgb(var(--theme-background));
+}
+
+.toastui-editor-dropdown-toolbar {
+  background-color: rgb(var(--theme-background));
+  border-color: rgb(var(--theme-border));
+}
+
+// Tables
+.toastui-editor-contents table th,
+.toastui-editor-contents table td {
+  border-color: rgb(var(--theme-border));
+}
+
+.toastui-editor-contents th p {
+  color: rgb(var(--theme-text));
+}
index 86dd7b141246ae9a28ce805829b8844b2a896c8f..7269bab65ac78993ed4b10f82b42d0b214682907 100644 (file)
@@ -12,6 +12,8 @@
         "@jamescoyle/vue-icon": "0.1.2",\r
         "@mdi/js": "7.4.47",\r
         "@mdi/light-js": "0.2.63",\r
+        "@toast-ui/editor": "3.2.2",\r
+        "@toast-ui/editor-plugin-code-syntax-highlight": "3.1.0",\r
         "axios": "1.6.8",\r
         "mousetrap": "1.6.5",\r
         "pinia": "2.1.7",\r
         "win32"\r
       ]\r
     },\r
+    "node_modules/@toast-ui/editor": {\r
+      "version": "3.2.2",\r
+      "resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-3.2.2.tgz",\r
+      "integrity": "sha512-ASX7LFjN2ZYQJrwmkUajPs7DRr9FsM1+RQ82CfTO0Y5ZXorBk1VZS4C2Dpxinx9kl55V4F8/A2h2QF4QMDtRbA==",\r
+      "dependencies": {\r
+        "dompurify": "^2.3.3",\r
+        "prosemirror-commands": "^1.1.9",\r
+        "prosemirror-history": "^1.1.3",\r
+        "prosemirror-inputrules": "^1.1.3",\r
+        "prosemirror-keymap": "^1.1.4",\r
+        "prosemirror-model": "^1.14.1",\r
+        "prosemirror-state": "^1.3.4",\r
+        "prosemirror-view": "^1.18.7"\r
+      }\r
+    },\r
+    "node_modules/@toast-ui/editor-plugin-code-syntax-highlight": {\r
+      "version": "3.1.0",\r
+      "resolved": "https://registry.npmjs.org/@toast-ui/editor-plugin-code-syntax-highlight/-/editor-plugin-code-syntax-highlight-3.1.0.tgz",\r
+      "integrity": "sha512-OgX5pZiTnHREoTTXDAFu1k6RzEspGOxeJNRlt/Lnoi1GvLbIpUTTbBcls9becpXT/Qdls++8G3r5C60cVdellA==",\r
+      "dependencies": {\r
+        "prismjs": "^1.23.0"\r
+      }\r
+    },\r
     "node_modules/@types/estree": {\r
       "version": "1.0.5",\r
       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",\r
       "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",\r
       "dev": true\r
     },\r
+    "node_modules/dompurify": {\r
+      "version": "2.5.2",\r
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.2.tgz",\r
+      "integrity": "sha512-5vSyvxRAb45EoWwAktUT3AYqAwXK4FL7si22Cgj46U6ICsj/YJczCN+Bk7WNABIQmpWRymGfslMhrRUZkQNnqA=="\r
+    },\r
     "node_modules/eastasianwidth": {\r
       "version": "0.2.0",\r
       "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",\r
         "node": ">= 6"\r
       }\r
     },\r
+    "node_modules/orderedmap": {\r
+      "version": "2.1.1",\r
+      "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",\r
+      "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g=="\r
+    },\r
     "node_modules/path-key": {\r
       "version": "3.1.1",\r
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",\r
         "vue": "^3.0.0"\r
       }\r
     },\r
+    "node_modules/prismjs": {\r
+      "version": "1.29.0",\r
+      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",\r
+      "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",\r
+      "engines": {\r
+        "node": ">=6"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-commands": {\r
+      "version": "1.5.2",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.5.2.tgz",\r
+      "integrity": "sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==",\r
+      "dependencies": {\r
+        "prosemirror-model": "^1.0.0",\r
+        "prosemirror-state": "^1.0.0",\r
+        "prosemirror-transform": "^1.0.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-history": {\r
+      "version": "1.4.0",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.0.tgz",\r
+      "integrity": "sha512-UUiGzDVcqo1lovOPdi9YxxUps3oBFWAIYkXLu3Ot+JPv1qzVogRbcizxK3LhHmtaUxclohgiOVesRw5QSlMnbQ==",\r
+      "dependencies": {\r
+        "prosemirror-state": "^1.2.2",\r
+        "prosemirror-transform": "^1.0.0",\r
+        "prosemirror-view": "^1.31.0",\r
+        "rope-sequence": "^1.3.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-inputrules": {\r
+      "version": "1.4.0",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz",\r
+      "integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==",\r
+      "dependencies": {\r
+        "prosemirror-state": "^1.0.0",\r
+        "prosemirror-transform": "^1.0.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-keymap": {\r
+      "version": "1.2.2",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz",\r
+      "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==",\r
+      "dependencies": {\r
+        "prosemirror-state": "^1.0.0",\r
+        "w3c-keyname": "^2.2.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-model": {\r
+      "version": "1.20.0",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.20.0.tgz",\r
+      "integrity": "sha512-q7AY7vMjKYqDCeoedgUiAgrLabliXxndJuuFmcmc2+YU1SblvnOiG2WEACF2lwAZsMlfLpiAilA3L+TWlDqIsQ==",\r
+      "dependencies": {\r
+        "orderedmap": "^2.0.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-state": {\r
+      "version": "1.4.3",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz",\r
+      "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==",\r
+      "dependencies": {\r
+        "prosemirror-model": "^1.0.0",\r
+        "prosemirror-transform": "^1.0.0",\r
+        "prosemirror-view": "^1.27.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-transform": {\r
+      "version": "1.8.0",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.8.0.tgz",\r
+      "integrity": "sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==",\r
+      "dependencies": {\r
+        "prosemirror-model": "^1.0.0"\r
+      }\r
+    },\r
+    "node_modules/prosemirror-view": {\r
+      "version": "1.33.6",\r
+      "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.6.tgz",\r
+      "integrity": "sha512-zRLUNgLIQfd8IfGprsXxWTjdA8xEAFJe8cDNrOptj6Mop9sj+BMeVbJvceyAYCm5G2dOdT2prctH7K9dfnpIMw==",\r
+      "dependencies": {\r
+        "prosemirror-model": "^1.20.0",\r
+        "prosemirror-state": "^1.0.0",\r
+        "prosemirror-transform": "^1.1.0"\r
+      }\r
+    },\r
     "node_modules/proxy-from-env": {\r
       "version": "1.1.0",\r
       "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",\r
         "fsevents": "~2.3.2"\r
       }\r
     },\r
+    "node_modules/rope-sequence": {\r
+      "version": "1.3.4",\r
+      "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",\r
+      "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="\r
+    },\r
     "node_modules/run-parallel": {\r
       "version": "1.2.0",\r
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",\r
         "vue": "^3.2.0"\r
       }\r
     },\r
+    "node_modules/w3c-keyname": {\r
+      "version": "2.2.8",\r
+      "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",\r
+      "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="\r
+    },\r
     "node_modules/which": {\r
       "version": "2.0.2",\r
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",\r
index f6790b3041b9a227cfc60a6f652711355954d4b3..162259dddced15cce5c076c13ba298e44a166c45 100644 (file)
@@ -15,6 +15,8 @@
     "@jamescoyle/vue-icon": "0.1.2",\r
     "@mdi/js": "7.4.47",\r
     "@mdi/light-js": "0.2.63",\r
+    "@toast-ui/editor": "3.2.2",\r
+    "@toast-ui/editor-plugin-code-syntax-highlight": "3.1.0",\r
     "axios": "1.6.8",\r
     "mousetrap": "1.6.5",\r
     "pinia": "2.1.7",\r
git clone https://git.99rst.org/PROJECT