Browse Source

links in html contentEditable with medium-editor-x

bach 1 month ago
parent
commit
820edbd36e
3 changed files with 201 additions and 19 deletions
  1. 179 17
      package-lock.json
  2. 2 0
      package.json
  3. 20 2
      src/components/editable/ContentEditable.vue

+ 179 - 17
package-lock.json

@@ -18,6 +18,7 @@
         "granim": "^2.0.0",
         "matter-attractors": "^0.1.6",
         "matter-js": "^0.19.0",
+        "medium-editor-x": "^0.0.5",
         "paper": "^0.12.17",
         "pinia": "^2.0.21",
         "poly-decomp": "^0.3.0",
@@ -31,6 +32,7 @@
       "devDependencies": {
         "@rollup/plugin-graphql": "^2.0.0",
         "@rushstack/eslint-patch": "^1.1.4",
+        "@types/medium-editor": "^5.0.8",
         "@vitejs/plugin-vue": "^4.4.0",
         "@vue/eslint-config-prettier": "^8.0.0",
         "axios": "^1.0.0",
@@ -56,9 +58,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.23.0",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
-      "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
+      "version": "7.24.1",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz",
+      "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -517,11 +519,73 @@
       "resolved": "https://registry.npmjs.org/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz",
       "integrity": "sha512-KFrImXx5TKIi6iQXlnyLEBl4rNosNKbTeRnr70ucTdUaciVmd9qK9d/pZAaKt1Ob/8xNnX2GMp8LisyHdKtEgw=="
     },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+      "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.6",
+      "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+      "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
     "node_modules/@jridgewell/sourcemap-codec": {
       "version": "1.4.15",
       "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
       "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
     },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
     "node_modules/@mapbox/node-pre-gyp": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
@@ -685,12 +749,49 @@
       "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-21.0.0.tgz",
       "integrity": "sha512-qVfOiFh0U8ZSkLgA6tf7kj2MciqRbSCWaJZRwftVO7UbtVDNsZAXpWXqvCDtIefvjC83UJB+vHTDOGm5ibXjEA=="
     },
+    "node_modules/@types/eslint": {
+      "version": "8.56.6",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.6.tgz",
+      "integrity": "sha512-ymwc+qb1XkjT/gfoQwxIeHZ6ixH23A+tCT2ADSA/DPVKzAjwYkTXBMCQ/f6fe4wEa85Lhp26VPeUxI7wMhAi7A==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
     "node_modules/@types/estree": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz",
-      "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==",
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+      "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
+      "dev": true
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true,
+      "optional": true,
+      "peer": true
+    },
+    "node_modules/@types/medium-editor": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/@types/medium-editor/-/medium-editor-5.0.8.tgz",
+      "integrity": "sha512-8zj+0E1nirrZ8lW6PbKru11z0klAxShLyO2SikbCz4CV1DbdN0gB9hNq99cJS1giEozUEtfhUQ0SDz+VgzeATQ==",
       "dev": true
     },
+    "node_modules/@types/node": {
+      "version": "20.11.30",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
+      "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "undici-types": "~5.26.4"
+      }
+    },
     "node_modules/@vitejs/plugin-vue": {
       "version": "4.4.0",
       "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz",
@@ -1048,6 +1149,14 @@
         "node": ">=8"
       }
     },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "dev": true,
+      "optional": true,
+      "peer": true
+    },
     "node_modules/bundle-name": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
@@ -2689,6 +2798,11 @@
       "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
       "dev": true
     },
+    "node_modules/medium-editor-x": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/medium-editor-x/-/medium-editor-x-0.0.5.tgz",
+      "integrity": "sha512-23j3eDPI729nDathQrC44Ju+s/PQZrfNGUMVjdvTgsBpv4ZrOn5QvDAZv2+QxhDckvzWZxWMCDLcofhqc4wAtQ=="
+    },
     "node_modules/merge-stream": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -2833,9 +2947,9 @@
       "optional": true
     },
     "node_modules/nanoid": {
-      "version": "3.3.6",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
-      "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+      "version": "3.3.7",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+      "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
       "funding": [
         {
           "type": "github",
@@ -3223,9 +3337,9 @@
       }
     },
     "node_modules/postcss": {
-      "version": "8.4.31",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
-      "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+      "version": "8.4.38",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+      "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
       "funding": [
         {
           "type": "opencollective",
@@ -3241,9 +3355,9 @@
         }
       ],
       "dependencies": {
-        "nanoid": "^3.3.6",
+        "nanoid": "^3.3.7",
         "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.2"
+        "source-map-js": "^1.2.0"
       },
       "engines": {
         "node": "^10 || ^12 || >=14"
@@ -3711,13 +3825,25 @@
       }
     },
     "node_modules/source-map-js": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
-      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
+      "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
       "engines": {
         "node": ">=0.10.0"
       }
     },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
     "node_modules/string_decoder": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -3852,6 +3978,34 @@
         "node": ">=10"
       }
     },
+    "node_modules/terser": {
+      "version": "5.30.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.0.tgz",
+      "integrity": "sha512-Y/SblUl5kEyEFzhMAQdsxVHh+utAxd4IuRNJzKywY/4uzSogh3G219jqbDDxYu4MXO9CzY3tSEqmZvW6AoEDJw==",
+      "dev": true,
+      "optional": true,
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.8.2",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/terser/node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "dev": true,
+      "optional": true,
+      "peer": true
+    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -3939,6 +4093,14 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/undici-types": {
+      "version": "5.26.5",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+      "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+      "dev": true,
+      "optional": true,
+      "peer": true
+    },
     "node_modules/universalify": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",

+ 2 - 0
package.json

@@ -18,6 +18,7 @@
     "granim": "^2.0.0",
     "matter-attractors": "^0.1.6",
     "matter-js": "^0.19.0",
+    "medium-editor-x": "^0.0.5",
     "paper": "^0.12.17",
     "pinia": "^2.0.21",
     "poly-decomp": "^0.3.0",
@@ -31,6 +32,7 @@
   "devDependencies": {
     "@rollup/plugin-graphql": "^2.0.0",
     "@rushstack/eslint-patch": "^1.1.4",
+    "@types/medium-editor": "^5.0.8",
     "@vitejs/plugin-vue": "^4.4.0",
     "@vue/eslint-config-prettier": "^8.0.0",
     "axios": "^1.0.0",

+ 20 - 2
src/components/editable/ContentEditable.vue

@@ -7,6 +7,10 @@ import { ConcernementsStore } from '@stores/concernements'
 import { UserStore } from '@stores/user'
 
 
+import MediumEditor from 'medium-editor-x'
+import 'medium-editor-x/dist/css/medium-editor.css'
+import 'medium-editor-x/dist/css/themes/beagle.css'
+
 export default {
   props: {
     tag: String, 
@@ -24,7 +28,8 @@ export default {
   emits: ['updated'],
   data(){
     return {
-      
+      editor: null,
+      spellcheck: false
     }
   },
   computed: {
@@ -34,7 +39,14 @@ export default {
     console.log('ContentEditable created');
   },
   mounted () {
-
+    this.editor = new MediumEditor(this.$refs.html_editable, {
+      toolbar: {
+        allowMultiParagraphSelection: false,
+        buttons: ['anchor'],
+      }
+    });
+  },
+  beforeUnmount() {
   },
   methods: {
     ...mapActions(ConcernementsStore, ['reloadConcernements']),
@@ -84,6 +96,8 @@ export default {
         })
     }
   },
+  components: {
+  }
 }
 </script>
 
@@ -92,13 +106,17 @@ export default {
     v-if="!html" 
     :is="tag"
     :contenteditable="contenteditable"
+    :spellcheck="speelcheck"
     @focusout="onContentEditableFocusOut"
   >{{ value }}</component>
   <component
     v-else
     :is="tag"
+    class="html-editable"
+    ref="html_editable"
     v-html="value"
     :contenteditable="contenteditable"
+    :spellcheck="speelcheck"
     @focusout="onContentEditableFocusOut"
   />
 </template>