braindrops.nicwands.com/shared/RichText.vue
2026-07-17 13:52:32 -04:00

116 lines
2.1 KiB
Vue

<template>
<editor-content class="rich-text" :editor="editor" />
</template>
<script setup>
import { useEditor, EditorContent } from '@tiptap/vue-3'
import StarterKit from '@tiptap/starter-kit'
const props = defineProps({
content: Object,
editable: {
type: Boolean,
default: false,
},
})
const model = defineModel()
const editor = useEditor({
content: props.content || model.value,
extensions: [
StarterKit.configure({
heading: {
levels: [1],
},
}),
],
editable: props.editable,
onUpdate: () => {
model.value = editor.value.getJSON()
},
})
</script>
<style lang="scss">
.rich-text {
font-family: inherit;
h1 {
margin: 2em 0 1em;
@include label;
}
p strong {
font-weight: 700;
}
p em {
font-style: italic;
}
hr {
border: 1px dashed currentColor;
}
ul {
list-style-type: disc;
li {
display: list-item;
margin-left: 1em;
*:not(:last-child) {
margin-bottom: 0.5em;
}
}
}
ol {
list-style-type: decimal;
li {
display: list-item;
margin-left: 1em;
&::marker {
@include p;
}
}
}
li:not(:last-child) {
margin-bottom: 0.5em;
}
a {
color: var(--sea);
cursor: pointer;
}
code {
border: 1px solid var(--theme-grey);
color: var(--theme-contrast);
padding: 0 0.2em;
border-radius: 0.2em;
}
pre code {
display: block;
color: inherit;
padding: 1em;
}
blockquote {
border-left: 4px solid var(--theme-grey);
padding-left: 0.5em;
}
s {
position: relative;
&::after {
content: ' ';
display: block;
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: currentColor;
}
}
u {
text-decoration: underline;
}
}
</style>