Add new component for html editing
This commit is contained in:
parent
b5ffb3ee29
commit
031e4d58de
|
|
@ -2398,6 +2398,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz",
|
||||
"integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g=="
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.2",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz",
|
||||
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
|
|
@ -2413,6 +2418,82 @@
|
|||
"defer-to-connect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@tiptap/core": {
|
||||
"version": "2.0.0-beta.174",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.0.0-beta.174.tgz",
|
||||
"integrity": "sha512-APQDto40PdvagG1HTwkKlieQS4Vp6GXNe7qgV1Qo2QCgJCLyxc/fXCTghtrOx0CQb+9JT7fjSLZxbSyUFXjx7Q==",
|
||||
"requires": {
|
||||
"@types/prosemirror-commands": "^1.0.4",
|
||||
"@types/prosemirror-keymap": "^1.0.4",
|
||||
"@types/prosemirror-model": "^1.16.0",
|
||||
"@types/prosemirror-schema-list": "^1.0.3",
|
||||
"@types/prosemirror-state": "^1.2.8",
|
||||
"@types/prosemirror-transform": "^1.1.5",
|
||||
"@types/prosemirror-view": "^1.23.1",
|
||||
"prosemirror-commands": "^1.2.1",
|
||||
"prosemirror-keymap": "^1.1.5",
|
||||
"prosemirror-model": "^1.16.1",
|
||||
"prosemirror-schema-list": "^1.1.6",
|
||||
"prosemirror-state": "^1.3.4",
|
||||
"prosemirror-transform": "^1.3.3",
|
||||
"prosemirror-view": "^1.23.6"
|
||||
}
|
||||
},
|
||||
"@tiptap/extension-bubble-menu": {
|
||||
"version": "2.0.0-beta.55",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.55.tgz",
|
||||
"integrity": "sha512-v32/QnwwRbepdbrho8mTYru1/XNW/rJi3Mjrgo3rrIs67R86aEPmhmdzD3QEQUJhAJkduuwdw8zElmVWqIJQ9w==",
|
||||
"requires": {
|
||||
"prosemirror-state": "^1.3.4",
|
||||
"prosemirror-view": "^1.23.6",
|
||||
"tippy.js": "^6.3.7"
|
||||
}
|
||||
},
|
||||
"@tiptap/extension-bullet-list": {
|
||||
"version": "2.0.0-beta.26",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.26.tgz",
|
||||
"integrity": "sha512-1n5HV8gY1tLjPk4x48nva6SZlFHoPlRfF6pqSu9JcJxPO7FUSPxUokuz4swYNe0LRrtykfyNz44dUcxKVhoFow=="
|
||||
},
|
||||
"@tiptap/extension-document": {
|
||||
"version": "2.0.0-beta.15",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.0.0-beta.15.tgz",
|
||||
"integrity": "sha512-ypENC+xUYD5m2t+KOKNYqyXnanXd5fxyIyhR1qeEEwwQwMXGNrO3kCH6O4mIDCpy+/WqHvVay2tV5dVsXnvY8w=="
|
||||
},
|
||||
"@tiptap/extension-floating-menu": {
|
||||
"version": "2.0.0-beta.50",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.50.tgz",
|
||||
"integrity": "sha512-aQu1HtthMIYEPylr6kzioLxMiObLbcgwx9xZzF03KwNnkjQLbjZOeJX2RwSYVpiVgtfPBGOm3N/br6NSYec4yQ==",
|
||||
"requires": {
|
||||
"prosemirror-state": "^1.3.4",
|
||||
"prosemirror-view": "^1.23.6",
|
||||
"tippy.js": "^6.3.7"
|
||||
}
|
||||
},
|
||||
"@tiptap/extension-list-item": {
|
||||
"version": "2.0.0-beta.20",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.20.tgz",
|
||||
"integrity": "sha512-5IPEspJt38t9ROj4xLUesOVEYlTT/R9Skd9meHRxJQZX1qrzBICs5PC/WRIsnexrvTBhdxpYgCYjpvpsJBlKuQ=="
|
||||
},
|
||||
"@tiptap/extension-paragraph": {
|
||||
"version": "2.0.0-beta.23",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.23.tgz",
|
||||
"integrity": "sha512-VWAxyzecErYWk97Kv/Gkghh97zAQTcaVOisEnYYArZAlyYDaYM48qVssAC/vnRRynP2eQxb1EkppbAxE+bMHAA=="
|
||||
},
|
||||
"@tiptap/extension-text": {
|
||||
"version": "2.0.0-beta.15",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz",
|
||||
"integrity": "sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA=="
|
||||
},
|
||||
"@tiptap/vue-2": {
|
||||
"version": "2.0.0-beta.77",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/vue-2/-/vue-2-2.0.0-beta.77.tgz",
|
||||
"integrity": "sha512-/wMi7fkqLqfWGhOpcztiGgVyqiCmOPq7TZ2LFx+cokoMJ1HpM8T7vG12u6ezOubB5Ie7/kL6WBcLJ8hONTdX0Q==",
|
||||
"requires": {
|
||||
"@tiptap/extension-bubble-menu": "^2.0.0-beta.55",
|
||||
"@tiptap/extension-floating-menu": "^2.0.0-beta.50",
|
||||
"prosemirror-view": "^1.23.6"
|
||||
}
|
||||
},
|
||||
"@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
|
|
@ -2611,12 +2692,84 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.12.tgz",
|
||||
"integrity": "sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA=="
|
||||
},
|
||||
"@types/orderedmap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/orderedmap/-/orderedmap-1.0.0.tgz",
|
||||
"integrity": "sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/prosemirror-commands": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz",
|
||||
"integrity": "sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==",
|
||||
"requires": {
|
||||
"@types/prosemirror-model": "*",
|
||||
"@types/prosemirror-state": "*",
|
||||
"@types/prosemirror-view": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-keymap": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz",
|
||||
"integrity": "sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==",
|
||||
"requires": {
|
||||
"@types/prosemirror-commands": "*",
|
||||
"@types/prosemirror-model": "*",
|
||||
"@types/prosemirror-state": "*",
|
||||
"@types/prosemirror-view": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-model": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.16.1.tgz",
|
||||
"integrity": "sha512-SrrCe2cHlYrQ9o55e2i/c3wt1yRajTTpRLvzfmB+2DWjWEbBLTByVWyjrdpKtQTxAaTeU2aeDGo1iuwl/jF27w==",
|
||||
"requires": {
|
||||
"@types/orderedmap": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-schema-list": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz",
|
||||
"integrity": "sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==",
|
||||
"requires": {
|
||||
"@types/orderedmap": "*",
|
||||
"@types/prosemirror-model": "*",
|
||||
"@types/prosemirror-state": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-state": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.2.8.tgz",
|
||||
"integrity": "sha512-mq9uyQWcpu8jeamO6Callrdvf/e1H/aRLR2kZWSpZrPHctEsxWHBbluD/wqVjXBRIOoMHLf6ZvOkrkmGLoCHVA==",
|
||||
"requires": {
|
||||
"@types/prosemirror-model": "*",
|
||||
"@types/prosemirror-transform": "*",
|
||||
"@types/prosemirror-view": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-transform": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.5.tgz",
|
||||
"integrity": "sha512-Wr2HXaEF4JPklWpC17RTxE6PxyU54Taqk5FMhK1ojgcN93J+GpkYW8s0mD3rl7KfTmlhVwZPCHE9o0cYf2Go5A==",
|
||||
"requires": {
|
||||
"@types/prosemirror-model": "*"
|
||||
}
|
||||
},
|
||||
"@types/prosemirror-view": {
|
||||
"version": "1.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.23.1.tgz",
|
||||
"integrity": "sha512-6e1B2oKUnhmZPUrsVvYjDqeVjE6jGezygjtoHsAK4ZENAxHzHqy5NT4jUvdPTWjCYeH0t2Y7pSfRPNrPIyQX4A==",
|
||||
"requires": {
|
||||
"@types/prosemirror-model": "*",
|
||||
"@types/prosemirror-state": "*",
|
||||
"@types/prosemirror-transform": "*"
|
||||
}
|
||||
},
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
|
|
@ -14396,6 +14549,11 @@
|
|||
"log-symbols": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"orderedmap": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.5.tgz",
|
||||
"integrity": "sha512-/fzlCGKRmfayGoI9UUXvJfc2nMZlJHW30QqEvwPvlg8tsX7jyiUSomYie6mYqx7Z9bOMGoag0H/q1PS/0PjYkg=="
|
||||
},
|
||||
"original": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
|
||||
|
|
@ -16602,6 +16760,69 @@
|
|||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"prosemirror-commands": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.2.1.tgz",
|
||||
"integrity": "sha512-S/IkpXfpuLFsRynC2HQ5iYROUPiZskKS1+ClcWycGJvj4HMb/mVfeEkQrixYxgTl96EAh+RZQNWPC06GZXk5tQ==",
|
||||
"requires": {
|
||||
"prosemirror-model": "^1.0.0",
|
||||
"prosemirror-state": "^1.0.0",
|
||||
"prosemirror-transform": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-keymap": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz",
|
||||
"integrity": "sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==",
|
||||
"requires": {
|
||||
"prosemirror-state": "^1.0.0",
|
||||
"w3c-keyname": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-model": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.16.1.tgz",
|
||||
"integrity": "sha512-r1/w0HDU40TtkXp0DyKBnFPYwd8FSlUSJmGCGFv4DeynfeSlyQF2FD0RQbVEMOe6P3PpUSXM6LZBV7W/YNZ4mA==",
|
||||
"requires": {
|
||||
"orderedmap": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-schema-list": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz",
|
||||
"integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==",
|
||||
"requires": {
|
||||
"prosemirror-model": "^1.0.0",
|
||||
"prosemirror-transform": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-state": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz",
|
||||
"integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==",
|
||||
"requires": {
|
||||
"prosemirror-model": "^1.0.0",
|
||||
"prosemirror-transform": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-transform": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.4.tgz",
|
||||
"integrity": "sha512-gTsg3UIeaFuEY6+YmNPMgTpEkCKPedkFIUnsPpOMbclU701fEVI/e4VOXACXh3BO5rZJaBbEBwrnzB0mLp6eBA==",
|
||||
"requires": {
|
||||
"prosemirror-model": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"prosemirror-view": {
|
||||
"version": "1.23.6",
|
||||
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.23.6.tgz",
|
||||
"integrity": "sha512-B4DAzriNpI/AVoW0Lu6SVfX00jZZQxOVwdBQEjWlRbCdT9V0pvk4GQJ3JTFaib+b6BcPdRZ3MjWXz2xvV1rblA==",
|
||||
"requires": {
|
||||
"prosemirror-model": "^1.16.0",
|
||||
"prosemirror-state": "^1.0.0",
|
||||
"prosemirror-transform": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
|
|
@ -19030,6 +19251,14 @@
|
|||
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
|
||||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
|
||||
},
|
||||
"tippy.js": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
|
||||
|
|
@ -20232,6 +20461,11 @@
|
|||
"browser-process-hrtime": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"w3c-keyname": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz",
|
||||
"integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw=="
|
||||
},
|
||||
"walker": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,13 @@
|
|||
"@babel/preset-stage-2": "^7.0.0",
|
||||
"@babel/runtime": "^7.5.4",
|
||||
"@iam4x/cypress-graphql-mock": "0.0.1",
|
||||
"@tiptap/core": "^2.0.0-beta.174",
|
||||
"@tiptap/extension-bullet-list": "^2.0.0-beta.26",
|
||||
"@tiptap/extension-document": "^2.0.0-beta.15",
|
||||
"@tiptap/extension-list-item": "^2.0.0-beta.20",
|
||||
"@tiptap/extension-paragraph": "^2.0.0-beta.23",
|
||||
"@tiptap/extension-text": "^2.0.0-beta.15",
|
||||
"@tiptap/vue-2": "^2.0.0-beta.77",
|
||||
"@vue/composition-api": "^1.4.2",
|
||||
"appolo": "^6.0.19",
|
||||
"autoprefixer": "^7.1.2",
|
||||
|
|
|
|||
|
|
@ -1,32 +1,15 @@
|
|||
<template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div class="text-form">
|
||||
{{ isListLocal }}
|
||||
<toggle
|
||||
:checked="isListLocal"
|
||||
:checked="isList"
|
||||
label="Liste"
|
||||
@input="isListLocal=$event"
|
||||
/>
|
||||
<button
|
||||
class="button"
|
||||
@click="makeList"
|
||||
>
|
||||
Test
|
||||
</button>
|
||||
<div
|
||||
class="text-form__input skillbox-textarea"
|
||||
contenteditable="true"
|
||||
v-once
|
||||
@input="change"
|
||||
v-text="text"
|
||||
@input="toggleList"
|
||||
/>
|
||||
|
||||
<div
|
||||
contenteditable="true"
|
||||
class="text-form__input skillbox-textarea text-form__contenteditable"
|
||||
@input="changeSomeText"
|
||||
@blur="updateSomeText"
|
||||
v-html="localOnlyText"
|
||||
<tip-tap
|
||||
:value="value.text"
|
||||
@input="$emit('change-text', $event)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -34,6 +17,7 @@
|
|||
<script lang="ts">
|
||||
import Vue, {PropType} from "vue";
|
||||
import Toggle from "@/components/ui/Toggle.vue";
|
||||
import TipTap from "@/components/content-forms/TipTap.vue";
|
||||
|
||||
interface Value {
|
||||
text: string;
|
||||
|
|
@ -44,11 +28,20 @@
|
|||
textToStoreWhileFocused: string,
|
||||
textBuffer: string, // text that gets saved, but not updated, when the user is typing
|
||||
htmlBuffer: string, // same as above, but this is the html that's generated
|
||||
isListLocal: boolean,
|
||||
isList: boolean,
|
||||
// listHTML: string
|
||||
}
|
||||
|
||||
const re = /<ul(\/)?>/;
|
||||
const ul = /<\/?ul>/;
|
||||
const li = /<\/?li>/;
|
||||
const br = /<br(\/)?>/;
|
||||
const div = /(<\/?)div(>)/g;
|
||||
const anythingElse = /<(?!\/?(?:ul|li|p))\/?([^>]*)>/;
|
||||
|
||||
// the non-breaking space is used so the cursor is positioned inside the element by default. We remove it later
|
||||
const nonBreakingSpace = ' ';
|
||||
const emptyParagraph = `<p>${nonBreakingSpace}</p>`;
|
||||
const emptyList = `<ul><li>${nonBreakingSpace}</li></ul>`;
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
|
|
@ -58,12 +51,8 @@
|
|||
return Object.prototype.hasOwnProperty.call(value, 'text');
|
||||
},
|
||||
},
|
||||
asList: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {Toggle},
|
||||
components: {TipTap, Toggle},
|
||||
|
||||
data(): Data {
|
||||
return {
|
||||
|
|
@ -73,7 +62,7 @@
|
|||
textToStoreWhileFocused: '', // we need to have a text that always updates for user input
|
||||
textBuffer: '',
|
||||
htmlBuffer: '',
|
||||
isListLocal: false,
|
||||
isList: false,
|
||||
// listHTML: `<ul>
|
||||
// <li>Hello</li>
|
||||
// <li>World</li>
|
||||
|
|
@ -83,31 +72,59 @@
|
|||
|
||||
computed: {
|
||||
text(): string {
|
||||
return this.value.text ? this.value.text.replace(/<br(\/)?>/, '\n').replace(/(<([^>]+)>)/ig, '') : '';
|
||||
// if has ul / li, return as is
|
||||
if (this.isList) {
|
||||
return this.value.text;
|
||||
} else {
|
||||
// need p tags
|
||||
return this.value.text ? this.value.text.replace(/<br(\/)?>/, '\n').replace(/(<([^>]+)>)/ig, '') : emptyParagraph;
|
||||
}
|
||||
},
|
||||
html(): string {
|
||||
return this.value.text;
|
||||
},
|
||||
isList(): boolean {
|
||||
return this.asList || this.value.text.indexOf('<li>') > -1;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
console.log('i was mounted now');
|
||||
// sync this only once, when the component gets mounted
|
||||
this.isList = ul.test(this.value.text);
|
||||
console.log(this.text);
|
||||
this.localOnlyText = this.text;
|
||||
this.textBuffer = this.text;
|
||||
this.htmlBuffer = this.text;
|
||||
// when mounted, we also check if the text already contains some li or ul elements
|
||||
this.isListLocal = this.asList || re.test(this.value.text);
|
||||
// after loading, we use the local data property to determine if we want a list or now
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateSomeText() {
|
||||
console.log('updating some text');
|
||||
console.log('htmlBuffer', this.htmlBuffer);
|
||||
this.localOnlyText = this.htmlBuffer;
|
||||
let newText = this.htmlBuffer.replace(div, '$1p$2')
|
||||
.replace(nonBreakingSpace, '')
|
||||
// .replace(br, '\n')
|
||||
.replace(anythingElse, '');
|
||||
if (newText === '') {
|
||||
// if the new text would be empty, we replace it according to our needs
|
||||
if (this.isList) {
|
||||
newText = emptyList;
|
||||
} else {
|
||||
newText = emptyParagraph;
|
||||
}
|
||||
}
|
||||
this.localOnlyText = newText;
|
||||
console.log(newText);
|
||||
|
||||
},
|
||||
toggleList(checked: boolean) {
|
||||
console.log(checked);
|
||||
if (checked) {
|
||||
this.makeList();
|
||||
} else {
|
||||
this.localOnlyText = this.textBuffer;
|
||||
this.isList = false;
|
||||
}
|
||||
},
|
||||
makeList() {
|
||||
// this.localOnlyText = this.localOnlyText
|
||||
let sep = /\n+/;
|
||||
|
|
@ -121,20 +138,14 @@
|
|||
</ul>`;
|
||||
console.log(list);
|
||||
this.localOnlyText = list;
|
||||
this.isList = true;
|
||||
},
|
||||
changeSomeText(event: Event) {
|
||||
console.log('changing some text');
|
||||
const target = (<HTMLInputElement>event.target);
|
||||
let newHtml = target.innerHTML;
|
||||
let newText = target.innerText;
|
||||
this.htmlBuffer = newHtml;
|
||||
this.textBuffer = newText;
|
||||
console.log("target.innerText");
|
||||
console.log(target.innerText);
|
||||
console.log(target.innerText.indexOf('\n'));
|
||||
console.log(target.innerHTML);
|
||||
console.log('textBuffer', this.textBuffer);
|
||||
console.log('htmlBuffer', this.htmlBuffer);
|
||||
this.$emit('change-text', newHtml);
|
||||
},
|
||||
change(event: Event) {
|
||||
|
|
@ -158,13 +169,22 @@
|
|||
&__contenteditable {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-color: pink;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/deep/ ul {
|
||||
list-style: initial;
|
||||
}
|
||||
|
||||
/deep/ li {
|
||||
@include inputfont;
|
||||
}
|
||||
|
||||
/deep/ div {
|
||||
@include inputfont;
|
||||
}
|
||||
|
||||
/deep/ p {
|
||||
@include inputfont;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<div class="tip-tap">
|
||||
<button @click="makeList">
|
||||
List
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import {Editor, EditorContent} from "@tiptap/vue-2";
|
||||
import Document from '@tiptap/extension-document';
|
||||
import Paragraph from '@tiptap/extension-paragraph';
|
||||
import Text from '@tiptap/extension-text';
|
||||
import BulletList from '@tiptap/extension-bullet-list';
|
||||
import ListItem from '@tiptap/extension-list-item';
|
||||
|
||||
interface Data {
|
||||
editor: Editor | null;
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
EditorContent
|
||||
},
|
||||
|
||||
data(): Data {
|
||||
return {
|
||||
editor: null,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(newVal) {
|
||||
const editor = this.editor as Editor; // editor is always initialized on mount, cast it
|
||||
const isSame = editor.getHTML() === newVal;
|
||||
|
||||
if (isSame) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.commands.setContent(newVal, false);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
console.log('mounted tip tap');
|
||||
this.editor = new Editor({
|
||||
editorProps: {
|
||||
attributes: {
|
||||
class: 'tip-tap__editor'
|
||||
}
|
||||
},
|
||||
content: this.value,
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
BulletList,
|
||||
ListItem
|
||||
],
|
||||
onUpdate: () => {
|
||||
this.$emit('input', (<Editor>this.editor).getHTML());
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor?.destroy();
|
||||
},
|
||||
|
||||
methods: {
|
||||
makeList() {
|
||||
const editor = this.editor as Editor;
|
||||
editor.chain().selectAll().toggleBulletList().run();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~styles/helpers';
|
||||
|
||||
|
||||
.tip-tap {
|
||||
/deep/ &__editor {
|
||||
@include inputstyle;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -215,8 +215,12 @@
|
|||
margin-bottom: $large-spacing;
|
||||
}
|
||||
|
||||
@mixin inputstyle {
|
||||
@mixin inputfont {
|
||||
font-family: $sans-serif-font-family;
|
||||
}
|
||||
|
||||
@mixin inputstyle {
|
||||
@include inputfont;
|
||||
display: flex;
|
||||
padding: $medium-spacing;
|
||||
border-radius: 4px;
|
||||
|
|
|
|||
Loading…
Reference in New Issue