diff options
author | Julius Härtl <jus@bitgrid.net> | 2022-08-14 15:39:20 +0300 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2022-10-03 22:37:14 +0300 |
commit | f3f5be1f03f230c569cea84d2d3fc4abbc822dd0 (patch) | |
tree | 47e90294168e8405a95804e53698da9b093e106d | |
parent | 7d06d575100e208aae38fc39cb1d9ab19214e2c5 (diff) |
Use vue-richtext for rendering paragraph widget
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r-- | src/extensions/RichText.js | 8 | ||||
-rw-r--r-- | src/nodes/Paragraph.js | 17 | ||||
-rw-r--r-- | src/nodes/ParagraphView.vue | 94 |
3 files changed, 112 insertions, 7 deletions
diff --git a/src/extensions/RichText.js b/src/extensions/RichText.js index 9d65be624..616a67ddf 100644 --- a/src/extensions/RichText.js +++ b/src/extensions/RichText.js @@ -24,7 +24,6 @@ import { Extension } from '@tiptap/core' /* eslint-disable import/no-named-as-default */ import Document from '@tiptap/extension-document' -import TipTapParagraph from '@tiptap/extension-paragraph' import Text from '@tiptap/extension-text' import Blockquote from '@tiptap/extension-blockquote' import OrderedList from '@tiptap/extension-ordered-list' @@ -34,6 +33,7 @@ import CodeBlock from '@tiptap/extension-code-block' import HorizontalRule from '@tiptap/extension-horizontal-rule' import Dropcursor from '@tiptap/extension-dropcursor' import FrontMatter from './../nodes/FrontMatter.js' +import Paragraph from './../nodes/Paragraph.js' import HardBreak from './HardBreak.js' import KeepSyntax from './KeepSyntax.js' import Table from './../nodes/Table.js' @@ -48,12 +48,6 @@ import Mention from './../extensions/Mention.js' import { Strong, Italic, Strike, Link, Underline } from './../marks/index.js' -const Paragraph = TipTapParagraph.extend({ - parseHTML() { - return this.parent().map(rule => Object.assign(rule, { preserveWhitespace: 'full' })) - }, -}) - export default Extension.create({ name: 'RichText', diff --git a/src/nodes/Paragraph.js b/src/nodes/Paragraph.js new file mode 100644 index 000000000..6ebec98f3 --- /dev/null +++ b/src/nodes/Paragraph.js @@ -0,0 +1,17 @@ +import TiptapParagraph from '@tiptap/extension-paragraph' +import { VueNodeViewRenderer } from '@tiptap/vue-2' +import ParagraphView from './ParagraphView.vue' + +const Paragraph = TiptapParagraph.extend({ + + addNodeView() { + return VueNodeViewRenderer(ParagraphView) + }, + + parseHTML() { + return this.parent().map(rule => Object.assign(rule, { preserveWhitespace: 'full' })) + }, + +}) + +export default Paragraph diff --git a/src/nodes/ParagraphView.vue b/src/nodes/ParagraphView.vue new file mode 100644 index 000000000..c25e9db6c --- /dev/null +++ b/src/nodes/ParagraphView.vue @@ -0,0 +1,94 @@ +<!-- + - @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> + - + - @author Julius Härtl <jus@bitgrid.net> + - + - @license GNU AGPL version 3 or any later version + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + - + --> + +<template> + <NodeViewWrapper class="vue-component"> + <NodeViewContent class="content" /> + <ReferenceList v-if="text !== null" :text="text" :limit="1" /> + </NodeViewWrapper> +</template> + +<script> +import { NodeViewContent, nodeViewProps, NodeViewWrapper } from '@tiptap/vue-2' +import { ReferenceList } from '@nextcloud/vue-richtext' +import debounce from 'lodash.debounce' + +export default { + name: 'ParagraphView', + components: { + NodeViewWrapper, + NodeViewContent, + ReferenceList, + }, + props: nodeViewProps, + data() { + return { + text: null, + } + }, + watch: { + node: { + handler(newNode) { + this.debouncedUpdateText(newNode) + }, + }, + }, + created() { + this.debouncedUpdateText = debounce((newNode) => { + this.text = this.getTextReference(newNode?.textContent) + }, 500) + this.text = this.getTextReference(this.node?.textContent) + }, + beforeUnmount() { + this.debouncedWatch?.cancel() + }, + methods: { + getTextReference(text) { + const PATTERN = /(^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)($)/ig + if ((new RegExp(PATTERN)).test(text)) { + return text + } + + return null + }, + }, +} +</script> +<style lang="scss" scoped> +.widgets--list { + margin-top: -20px; +} +:deep(div.widgets--list a.widget-default) { + color: var(--color-main-text); + padding: 0; + text-decoration: none; +} +:deep(.widget-default--details) { + overflow:hidden; + p { + margin-bottom: 4px !important; + } +} +</style> +<style lang="scss"> +@import '@nextcloud/vue-richtext/dist/style.css' +</style> |