tiptapify 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/tiptapify.css +1 -1
- package/dist/{tiptapify.es.js → tiptapify.mjs} +54979 -52123
- package/dist/tiptapify.umd.js +41 -43
- package/package.json +8 -8
- package/src/components/Footer.vue +5 -6
- package/src/components/MenuBubble.vue +41 -39
- package/src/components/MenuFloating.vue +10 -10
- package/src/components/Tiptapify.vue +95 -14
- package/src/components/Toolbar/Group.vue +8 -43
- package/src/components/Toolbar/GroupDropdown.vue +85 -0
- package/src/components/Toolbar/Index.vue +20 -19
- package/src/components/Toolbar/items/media.ts +195 -9
- package/src/components/Toolbar/items/misc.ts +10 -1
- package/src/components/Toolbar/items/style.ts +2 -2
- package/src/components/Toolbar/items.ts +3 -3
- package/src/components/editorExtensions.ts +11 -7
- package/src/components/index.ts +13 -0
- package/src/extensions/components/ImageDialog.vue +142 -0
- package/src/extensions/components/LinkDialog.vue +142 -0
- package/src/extensions/components/PreviewDialog.vue +44 -0
- package/src/{components/extensions/components/ShowSource.vue → extensions/components/ShowSourceDialog.vue} +16 -10
- package/src/extensions/components/TableBuilder.vue +138 -0
- package/src/extensions/image.ts +31 -0
- package/src/extensions/link.ts +24 -0
- package/src/extensions/preview.ts +40 -0
- package/src/{components/extensions → extensions}/view-source.ts +1 -6
- package/src/i18n/locales/de.json +78 -45
- package/src/i18n/locales/en.json +37 -4
- package/src/i18n/locales/es.json +46 -13
- package/src/i18n/locales/fr.json +54 -21
- package/src/i18n/locales/it.json +51 -18
- package/src/i18n/locales/pl.json +45 -12
- package/src/i18n/locales/ru.json +36 -3
- package/src/i18n/locales/ua.json +36 -3
- package/src/index.ts +0 -1
- package/src/utils/helpers.ts +17 -0
- package/src/components/extensions/components/LinkDialog.vue +0 -98
- package/src/composable/useEditor.ts +0 -35
- /package/src/{components/extensions → extensions}/components/slashCommands/CommandsList.vue +0 -0
- /package/src/{components/extensions → extensions}/components/slashCommands/suggestion.ts +0 -0
- /package/src/{components/extensions → extensions}/slash-commands.ts +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
|
|
3
|
+
import * as mdi from '@mdi/js'
|
|
4
|
+
import { Editor } from "@tiptap/vue-3";
|
|
5
|
+
|
|
6
|
+
import { useI18n } from 'vue-i18n'
|
|
7
|
+
import { computed, inject, onMounted, onUnmounted, Ref, ref } from 'vue'
|
|
8
|
+
|
|
9
|
+
import helpers from '@tiptapify/utils/helpers'
|
|
10
|
+
|
|
11
|
+
defineProps({
|
|
12
|
+
variantBtn: { type: String, default() { return 'elevated' }},
|
|
13
|
+
variantField: { type: String, default() { return 'solo' }}
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const { ucFirst } = helpers
|
|
17
|
+
|
|
18
|
+
const editor = inject('tiptapifyEditor') as Ref<Editor>
|
|
19
|
+
const { t } = useI18n()
|
|
20
|
+
|
|
21
|
+
const generateLinkAttrs = () => ({
|
|
22
|
+
href: '',
|
|
23
|
+
target: '_blank',
|
|
24
|
+
cssClass: '',
|
|
25
|
+
rel: ''
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const relAttrs = ['alternate', 'author', 'bookmark', 'external', 'help', 'license', 'next', 'nofollow', 'noreferrer', 'noopener', 'prev', 'search', 'tag']
|
|
29
|
+
|
|
30
|
+
const attrs = ref(generateLinkAttrs())
|
|
31
|
+
|
|
32
|
+
const dialog = ref<boolean>(false)
|
|
33
|
+
|
|
34
|
+
const isDisabled = computed(() => {
|
|
35
|
+
const { href } = attrs.value
|
|
36
|
+
return !href
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
function apply() {
|
|
40
|
+
let { href, target, rel, cssClass } = attrs.value
|
|
41
|
+
target = target ? '_blank' : '_self'
|
|
42
|
+
rel = rel.join(' ')
|
|
43
|
+
|
|
44
|
+
if (href) {
|
|
45
|
+
editor.value.chain().focus().extendMarkRange('link').setLink({ href, target, rel, class: cssClass }).run()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
close()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function clear() {
|
|
52
|
+
editor.value.chain().focus().extendMarkRange('link').unsetLink().run()
|
|
53
|
+
|
|
54
|
+
close()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function close() {
|
|
58
|
+
dialog.value = false
|
|
59
|
+
|
|
60
|
+
attrs.value = generateLinkAttrs()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const showLink = (event: CustomEvent) => {
|
|
64
|
+
attrs.value.href = event.detail.link?.href
|
|
65
|
+
attrs.value.target = event.detail.link?.target === '_blank'
|
|
66
|
+
attrs.value.rel = event.detail.link?.rel?.split(' ')
|
|
67
|
+
attrs.value.cssClass = event.detail.link?.class
|
|
68
|
+
|
|
69
|
+
dialog.value = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onMounted(() => {
|
|
73
|
+
window.addEventListener('tiptapify-show-link', showLink as EventListener)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
onUnmounted(() => {
|
|
77
|
+
window.removeEventListener('tiptapify-show-link', showLink as EventListener)
|
|
78
|
+
})
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
<template>
|
|
82
|
+
<VDialog v-model="dialog" max-width="800" absolute @click:outside="close">
|
|
83
|
+
<VCard>
|
|
84
|
+
<VToolbar class="px-6" density="compact">
|
|
85
|
+
<span class="headline">{{ ucFirst(t('dialog.link.title')) }}</span>
|
|
86
|
+
|
|
87
|
+
<VSpacer />
|
|
88
|
+
|
|
89
|
+
<VBtn class="mx-0" icon @click="close">
|
|
90
|
+
<VIcon :icon="mdi.mdiClose" />
|
|
91
|
+
</VBtn>
|
|
92
|
+
</VToolbar>
|
|
93
|
+
|
|
94
|
+
<VCardText>
|
|
95
|
+
<VRow>
|
|
96
|
+
<VCol cols="12" md="9">
|
|
97
|
+
<VTextField v-model="attrs.href" :variant="variantField" :label="ucFirst(t('dialog.link.href'))" autofocus />
|
|
98
|
+
</VCol>
|
|
99
|
+
|
|
100
|
+
<VCol cols="12" md="3">
|
|
101
|
+
<VCheckbox v-model="attrs.target" color="primary" :label="ucFirst(t('dialog.link.target'))" />
|
|
102
|
+
</VCol>
|
|
103
|
+
|
|
104
|
+
<VCol cols="12">
|
|
105
|
+
<VSelect
|
|
106
|
+
v-model="attrs.rel"
|
|
107
|
+
:items="relAttrs"
|
|
108
|
+
:label="ucFirst(t('dialog.link.rel'))"
|
|
109
|
+
:variant="variantField"
|
|
110
|
+
multiple
|
|
111
|
+
chips
|
|
112
|
+
closable-chips
|
|
113
|
+
clearable
|
|
114
|
+
/>
|
|
115
|
+
</VCol>
|
|
116
|
+
|
|
117
|
+
<VCol cols="12">
|
|
118
|
+
<VTextField v-model="attrs.cssClass" :variant="variantField" :label="ucFirst(t('dialog.link.class'))" />
|
|
119
|
+
</VCol>
|
|
120
|
+
</VRow>
|
|
121
|
+
</VCardText>
|
|
122
|
+
|
|
123
|
+
<VCardActions>
|
|
124
|
+
<VRow>
|
|
125
|
+
<VCol class="d-flex justify-start">
|
|
126
|
+
<VBtn color="warning" v-if="editor.isActive('link')" :variant="variantBtn" :disabled="isDisabled" @click="clear">
|
|
127
|
+
{{ ucFirst(t('dialog.clear')) }}
|
|
128
|
+
</VBtn>
|
|
129
|
+
</VCol>
|
|
130
|
+
<VCol class="d-flex justify-end">
|
|
131
|
+
<VBtn :variant="variantBtn" @click="close" class="mr-2">
|
|
132
|
+
{{ ucFirst(t('dialog.close')) }}
|
|
133
|
+
</VBtn>
|
|
134
|
+
<VBtn color="primary" :variant="variantBtn" :disabled="isDisabled" @click="apply">
|
|
135
|
+
{{ ucFirst(t('dialog.apply')) }}
|
|
136
|
+
</VBtn>
|
|
137
|
+
</VCol>
|
|
138
|
+
</VRow>
|
|
139
|
+
</VCardActions>
|
|
140
|
+
</VCard>
|
|
141
|
+
</VDialog>
|
|
142
|
+
</template>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, onMounted, onUnmounted } from 'vue'
|
|
3
|
+
import { useI18n } from "vue-i18n";
|
|
4
|
+
import * as mdi from '@mdi/js'
|
|
5
|
+
|
|
6
|
+
const { t } = useI18n();
|
|
7
|
+
|
|
8
|
+
const content = ref()
|
|
9
|
+
|
|
10
|
+
const dialog = ref(false)
|
|
11
|
+
|
|
12
|
+
const showDialog = (event: CustomEvent) => {
|
|
13
|
+
content.value = event.detail.html
|
|
14
|
+
dialog.value = true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
onMounted(() => {
|
|
18
|
+
window.addEventListener('tiptapify-show-preview', showDialog as EventListener)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
onUnmounted(() => {
|
|
22
|
+
window.removeEventListener('tiptapify-show-preview', showDialog as EventListener)
|
|
23
|
+
})
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<VDialog v-model="dialog" fullscreen>
|
|
28
|
+
<VCard>
|
|
29
|
+
<VToolbar>
|
|
30
|
+
<VBtn :icon="mdi.mdiClose" @click="dialog = false" />
|
|
31
|
+
|
|
32
|
+
<VToolbarTitle>Preview</VToolbarTitle>
|
|
33
|
+
</VToolbar>
|
|
34
|
+
|
|
35
|
+
<VCardItem>
|
|
36
|
+
<div class="tiptap" v-html="content"></div>
|
|
37
|
+
</VCardItem>
|
|
38
|
+
</VCard>
|
|
39
|
+
</VDialog>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<style lang="scss">
|
|
43
|
+
|
|
44
|
+
</style>
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
|
2
|
+
import { Editor } from "@tiptap/vue-3";
|
|
3
|
+
import { ref, onMounted, onUnmounted, watch, inject, Ref } from 'vue'
|
|
4
4
|
import { useI18n } from "vue-i18n";
|
|
5
5
|
|
|
6
|
+
import helpers from "@tiptapify/utils/helpers";
|
|
7
|
+
|
|
6
8
|
const props = defineProps({
|
|
7
9
|
indent: { type: Number, default: 2 },
|
|
10
|
+
variantBtn: { type: String, default: 'elevated' },
|
|
11
|
+
variantField: { type: String, default: 'solo' }
|
|
8
12
|
})
|
|
9
13
|
|
|
14
|
+
const { ucFirst } = helpers;
|
|
15
|
+
|
|
10
16
|
const { t } = useI18n();
|
|
11
17
|
|
|
12
|
-
const editor =
|
|
18
|
+
const editor = inject('tiptapifyEditor') as Ref<Editor>
|
|
13
19
|
|
|
14
20
|
const dialog = ref(false)
|
|
15
21
|
const formatted = ref(false)
|
|
@@ -76,14 +82,14 @@ watch(() => formatted.value, () => {
|
|
|
76
82
|
<template>
|
|
77
83
|
<VDialog v-model="dialog" max-width="1500">
|
|
78
84
|
<VCard>
|
|
79
|
-
<VCardTitle>{{ t('dialog.source.title') }}</VCardTitle>
|
|
85
|
+
<VCardTitle>{{ ucFirst(t('dialog.source.title')) }}</VCardTitle>
|
|
80
86
|
|
|
81
87
|
<VCardText>
|
|
82
88
|
<VContainer fluid class="pt-0 pl-0 pr-0">
|
|
83
89
|
<VRow>
|
|
84
90
|
<VCol>
|
|
85
91
|
<VBtn v-model="formatted" :color="`${formatted ? 'primary' : ''}`" @click="formatted = !formatted">
|
|
86
|
-
{{ t('dialog.source.prettify') }}
|
|
92
|
+
{{ ucFirst(t('dialog.source.prettify')) }}
|
|
87
93
|
</VBtn>
|
|
88
94
|
</VCol>
|
|
89
95
|
</VRow>
|
|
@@ -93,18 +99,18 @@ watch(() => formatted.value, () => {
|
|
|
93
99
|
v-model="sourceCode"
|
|
94
100
|
no-resize
|
|
95
101
|
rows="100"
|
|
96
|
-
variant="
|
|
102
|
+
:variant="variantField"
|
|
97
103
|
class="source-code-area"
|
|
98
104
|
/>
|
|
99
105
|
</VCardText>
|
|
100
106
|
|
|
101
107
|
<VCardActions>
|
|
102
108
|
<VSpacer></VSpacer>
|
|
103
|
-
<VBtn
|
|
104
|
-
{{ t('dialog.close') }}
|
|
109
|
+
<VBtn :variant="variantBtn" @click="dialog = false">
|
|
110
|
+
{{ ucFirst(t('dialog.close')) }}
|
|
105
111
|
</VBtn>
|
|
106
|
-
<VBtn color="primary" @click="saveChanges">
|
|
107
|
-
{{ t('dialog.apply') }}
|
|
112
|
+
<VBtn :variant="variantBtn" color="primary" @click="saveChanges">
|
|
113
|
+
{{ ucFirst(t('dialog.apply')) }}
|
|
108
114
|
</VBtn>
|
|
109
115
|
</VCardActions>
|
|
110
116
|
</VCard>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
|
|
3
|
+
import { Editor } from "@tiptap/vue-3";
|
|
4
|
+
import helpers from '@tiptapify/utils/helpers'
|
|
5
|
+
import { useI18n } from 'vue-i18n'
|
|
6
|
+
|
|
7
|
+
import { inject, Ref, ref } from 'vue'
|
|
8
|
+
|
|
9
|
+
const { t } = useI18n()
|
|
10
|
+
|
|
11
|
+
const { ucFirst } = helpers
|
|
12
|
+
|
|
13
|
+
defineExpose({ open })
|
|
14
|
+
|
|
15
|
+
defineProps({
|
|
16
|
+
show: { type: Boolean, default: false },
|
|
17
|
+
maxCols: { type: Number, default: 10 },
|
|
18
|
+
maxRows: { type: Number, default: 10 },
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const emit = defineEmits(['close'])
|
|
22
|
+
|
|
23
|
+
const editor = inject('tiptapifyEditor') as Ref<Editor>
|
|
24
|
+
|
|
25
|
+
const withHeaderRow = ref(false)
|
|
26
|
+
|
|
27
|
+
const colHover = ref(0)
|
|
28
|
+
const rowHover = ref(0)
|
|
29
|
+
|
|
30
|
+
function hoverCell(elm: Element, row: number, col: number) {
|
|
31
|
+
rowHover.value = row
|
|
32
|
+
colHover.value = col
|
|
33
|
+
elm.classList.add('tiptapify-insert-table-col-hover')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function leaveCell(elm: Element) {
|
|
37
|
+
rowHover.value = 0
|
|
38
|
+
colHover.value = 0
|
|
39
|
+
elm.classList.remove('tiptapify-insert-table-col-hover')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function insertTable(rows: number, cols: number) {
|
|
43
|
+
editor.value.chain().focus().insertTable({ rows, cols, withHeaderRow: withHeaderRow.value }).run()
|
|
44
|
+
|
|
45
|
+
emit('close')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function printSelection() {
|
|
49
|
+
return rowHover.value && colHover.value ? `${rowHover.value} x ${colHover.value}` : ''
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<template>
|
|
54
|
+
<VSheet class="pa-2">
|
|
55
|
+
<VCheckbox
|
|
56
|
+
v-model="withHeaderRow"
|
|
57
|
+
density="compact"
|
|
58
|
+
color="primary"
|
|
59
|
+
:label="ucFirst(t('media.tables.insertWithHeaderRow'))" hide-details
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<div v-for="rowNum in maxRows" :key="`row-${rowNum}`" class="tiptapify-insert-table-row">
|
|
63
|
+
<div
|
|
64
|
+
v-for="colNum in maxCols"
|
|
65
|
+
class="tiptapify-insert-table-col"
|
|
66
|
+
:class="{'tiptapify-insert-table-col-hovered': rowNum <= rowHover && colNum <= colHover}"
|
|
67
|
+
@click="insertTable(rowNum, colNum)"
|
|
68
|
+
@mouseover="hoverCell($el.querySelector('.tiptapify-insert-table-col'), rowNum, colNum)"
|
|
69
|
+
@mouseout="leaveCell($el.querySelector('.tiptapify-insert-table-col'))"
|
|
70
|
+
>
|
|
71
|
+
<div class="tiptapify-insert-table-col-button"></div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="tiptapify-table-builder-info">
|
|
76
|
+
<span>
|
|
77
|
+
{{ ucFirst(t('media.tables.rows')) }}: {{ rowHover }}
|
|
78
|
+
{{ ucFirst(t('media.tables.cols')) }}: {{ colHover }}
|
|
79
|
+
</span>
|
|
80
|
+
<span>
|
|
81
|
+
{{ printSelection() }}
|
|
82
|
+
</span>
|
|
83
|
+
</div>
|
|
84
|
+
</VSheet>
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<style lang="scss">
|
|
88
|
+
:root {
|
|
89
|
+
--tiptapify-table-builder-col-hover: #5454ff88;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
$primaryColor: var(--v-theme-primary-color, var(--tiptapify-table-builder-col-hover));
|
|
93
|
+
$mutedColor: var(--v-theme-muted-color, #888888);
|
|
94
|
+
|
|
95
|
+
.tiptapify-insert-table-row {
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.tiptapify-insert-table-col {
|
|
101
|
+
width: 30px;
|
|
102
|
+
height: 30px;
|
|
103
|
+
background: #fff;
|
|
104
|
+
padding: 2px 0;
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.tiptapify-insert-table-col-button {
|
|
111
|
+
margin: 2px;
|
|
112
|
+
width: 100%;
|
|
113
|
+
height: 100%;
|
|
114
|
+
border: 1px solid #888;
|
|
115
|
+
background: #fff;
|
|
116
|
+
border-radius: 4px;
|
|
117
|
+
filter: drop-shadow(2px 2px 4px #88888888);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.tiptapify-insert-table-col-hovered {
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.tiptapify-insert-table-col-hovered > .tiptapify-insert-table-col-button, .tiptapify-insert-table-col-button:hover {
|
|
125
|
+
background: $primaryColor;
|
|
126
|
+
border: 1px solid $primaryColor;
|
|
127
|
+
filter: drop-shadow(2px 2px 4px $primaryColor);
|
|
128
|
+
cursor: pointer;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.tiptapify-table-builder-info {
|
|
132
|
+
display: flex;
|
|
133
|
+
justify-content: space-between;
|
|
134
|
+
margin-top: 10px;
|
|
135
|
+
font-size: 12px;
|
|
136
|
+
color: $mutedColor;
|
|
137
|
+
}
|
|
138
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core'
|
|
2
|
+
|
|
3
|
+
const name: string = 'tiptapifyImage'
|
|
4
|
+
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
tiptapifyImage: {
|
|
8
|
+
showTiptapifyImage: () => ReturnType
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const TiptapifyImage = Extension.create({
|
|
14
|
+
name,
|
|
15
|
+
|
|
16
|
+
addCommands() {
|
|
17
|
+
return {
|
|
18
|
+
showTiptapifyImage: () => ({ editor }) => {
|
|
19
|
+
const event = new CustomEvent(`tiptapify-show-${name}`, {
|
|
20
|
+
detail: {
|
|
21
|
+
image: editor.getAttributes('image')
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
window.dispatchEvent(event)
|
|
26
|
+
|
|
27
|
+
return true
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Link from "@tiptap/extension-link";
|
|
2
|
+
|
|
3
|
+
const name: string = 'link'
|
|
4
|
+
|
|
5
|
+
export const TiptapifyLink = Link.extend({
|
|
6
|
+
name,
|
|
7
|
+
|
|
8
|
+
addCommands() {
|
|
9
|
+
return {
|
|
10
|
+
...this.parent?.(),
|
|
11
|
+
showLink: () => ({ editor }) => {
|
|
12
|
+
const event = new CustomEvent(`tiptapify-show-${name}`, {
|
|
13
|
+
detail: {
|
|
14
|
+
link: editor.getAttributes('link')
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
window.dispatchEvent(event)
|
|
19
|
+
|
|
20
|
+
return true
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core'
|
|
2
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
|
3
|
+
|
|
4
|
+
const name: string = 'preview'
|
|
5
|
+
|
|
6
|
+
declare module '@tiptap/core' {
|
|
7
|
+
interface Commands<ReturnType> {
|
|
8
|
+
preview: {
|
|
9
|
+
showPreview: () => ReturnType
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const Preview = Extension.create({
|
|
15
|
+
name,
|
|
16
|
+
|
|
17
|
+
addCommands() {
|
|
18
|
+
return {
|
|
19
|
+
showPreview: () => ({ editor }) => {
|
|
20
|
+
const event = new CustomEvent(`tiptapify-show-${name}`, {
|
|
21
|
+
detail: {
|
|
22
|
+
html: editor.getHTML()
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
window.dispatchEvent(event)
|
|
27
|
+
|
|
28
|
+
return true
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
addProseMirrorPlugins() {
|
|
34
|
+
return [
|
|
35
|
+
new Plugin({
|
|
36
|
+
key: new PluginKey(name),
|
|
37
|
+
}),
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
})
|
|
@@ -8,9 +8,6 @@ export interface ViewSourceOptions {
|
|
|
8
8
|
declare module '@tiptap/core' {
|
|
9
9
|
interface Commands<ReturnType> {
|
|
10
10
|
viewSource: {
|
|
11
|
-
/**
|
|
12
|
-
* Показать исходный HTML-код
|
|
13
|
-
*/
|
|
14
11
|
showSource: () => ReturnType
|
|
15
12
|
}
|
|
16
13
|
}
|
|
@@ -30,9 +27,7 @@ export const ViewSource = Extension.create<ViewSourceOptions>({
|
|
|
30
27
|
showSource: () => ({ editor }) => {
|
|
31
28
|
const event = new CustomEvent('tiptapify-show-source', {
|
|
32
29
|
detail: {
|
|
33
|
-
|
|
34
|
-
html: editor.getHTML({ blockSeparator: '\n\n' })
|
|
35
|
-
// html: editor.getText({ blockSeparator: '\n\n' })
|
|
30
|
+
html: editor.getHTML()
|
|
36
31
|
}
|
|
37
32
|
})
|
|
38
33
|
|
package/src/i18n/locales/de.json
CHANGED
|
@@ -1,67 +1,100 @@
|
|
|
1
1
|
{
|
|
2
2
|
"style": {
|
|
3
|
-
"paragraph": "
|
|
4
|
-
"heading": "
|
|
3
|
+
"paragraph": "absatz",
|
|
4
|
+
"heading": "überschrift",
|
|
5
5
|
"headings": {
|
|
6
|
-
"h1": "
|
|
7
|
-
"h2": "
|
|
8
|
-
"h3": "
|
|
9
|
-
"h4": "
|
|
10
|
-
"h5": "
|
|
11
|
-
"h6": "
|
|
6
|
+
"h1": "überschrift ebene 1",
|
|
7
|
+
"h2": "überschrift ebene 2",
|
|
8
|
+
"h3": "überschrift ebene 3",
|
|
9
|
+
"h4": "überschrift ebene 4",
|
|
10
|
+
"h5": "überschrift ebene 5",
|
|
11
|
+
"h6": "überschrift ebene 6"
|
|
12
12
|
},
|
|
13
|
-
"fontFamily": "
|
|
14
|
-
"fontSize": "
|
|
15
|
-
"lineHeight": "
|
|
13
|
+
"fontFamily": "schriftart",
|
|
14
|
+
"fontSize": "schriftgröße",
|
|
15
|
+
"lineHeight": "zeilenhöhe"
|
|
16
16
|
},
|
|
17
17
|
"format": {
|
|
18
|
-
"bold": "
|
|
19
|
-
"italic": "
|
|
20
|
-
"strike": "
|
|
21
|
-
"underline": "
|
|
22
|
-
"sup": "
|
|
23
|
-
"sub": "
|
|
24
|
-
"break": "
|
|
25
|
-
"highlight": "
|
|
26
|
-
"line": "
|
|
27
|
-
"blockquote": "
|
|
28
|
-
"code": "
|
|
29
|
-
"codeblock": "
|
|
30
|
-
"
|
|
31
|
-
|
|
18
|
+
"bold": "fett",
|
|
19
|
+
"italic": "kursiv",
|
|
20
|
+
"strike": "durchgestrichen",
|
|
21
|
+
"underline": "unterstrichen",
|
|
22
|
+
"sup": "hochgestellt",
|
|
23
|
+
"sub": "tiefgestellt",
|
|
24
|
+
"break": "harter umbruch",
|
|
25
|
+
"highlight": "hervorheben",
|
|
26
|
+
"line": "horizontale linie",
|
|
27
|
+
"blockquote": "zitat",
|
|
28
|
+
"code": "code",
|
|
29
|
+
"codeblock": "code block",
|
|
30
|
+
"formatClear": "formatierung löschen"
|
|
31
|
+
},
|
|
32
|
+
"media": {
|
|
33
|
+
"link": "externer link",
|
|
34
|
+
"image": "bild",
|
|
35
|
+
"tables": {
|
|
36
|
+
"table": "tabelle",
|
|
37
|
+
"insertTable": "tabelle einfügen",
|
|
38
|
+
"deleteTable": "tabelle löschen",
|
|
39
|
+
"insertWithHeaderRow": "tabelle mit kopfzeile einfügen",
|
|
40
|
+
"rows": "zeilen",
|
|
41
|
+
"row": "zeile",
|
|
42
|
+
"insertRowBefore": "zeile davor einfügen",
|
|
43
|
+
"insertRowAfter": "zeile danach einfügen",
|
|
44
|
+
"deleteRow": "zeile löschen",
|
|
45
|
+
"cols": "spalten",
|
|
46
|
+
"col": "spalte",
|
|
47
|
+
"insertColBefore": "spalte davor einfügen",
|
|
48
|
+
"insertColAfter": "spalte danach einfügen",
|
|
49
|
+
"deleteCol": "spalte löschen",
|
|
50
|
+
"mergeCells": "zellen verbinden",
|
|
51
|
+
"splitCell": "zelle teilen"
|
|
52
|
+
}
|
|
32
53
|
},
|
|
33
54
|
"action": {
|
|
34
|
-
"undo": "
|
|
35
|
-
"redo": "
|
|
55
|
+
"undo": "rückgängig",
|
|
56
|
+
"redo": "wiederholen"
|
|
36
57
|
},
|
|
37
|
-
"alignment": "
|
|
58
|
+
"alignment": "ausrichtung",
|
|
38
59
|
"alignments": {
|
|
39
|
-
"left": "
|
|
40
|
-
"center": "
|
|
41
|
-
"right": "
|
|
42
|
-
"justify": "
|
|
60
|
+
"left": "links ausrichten",
|
|
61
|
+
"center": "zentriert ausrichten",
|
|
62
|
+
"right": "rechts ausrichten",
|
|
63
|
+
"justify": "blocksatz"
|
|
43
64
|
},
|
|
44
|
-
"list": "
|
|
65
|
+
"list": "liste",
|
|
45
66
|
"lists": {
|
|
46
|
-
"bullet": "
|
|
47
|
-
"numbered": "
|
|
48
|
-
"task": "
|
|
49
|
-
"indent": "
|
|
50
|
-
"outdent": "
|
|
67
|
+
"bullet": "ungeordnete liste",
|
|
68
|
+
"numbered": "geordnete liste",
|
|
69
|
+
"task": "aufgabenliste",
|
|
70
|
+
"indent": "listenelement einrücken",
|
|
71
|
+
"outdent": "listenelement ausrücken"
|
|
51
72
|
},
|
|
52
73
|
"dialog": {
|
|
53
|
-
"
|
|
54
|
-
"
|
|
74
|
+
"apply": "anwenden",
|
|
75
|
+
"clear": "löschen",
|
|
76
|
+
"close": "schließen",
|
|
77
|
+
"image": {
|
|
78
|
+
"title": "bild hinzufügen/bearbeiten",
|
|
79
|
+
"src": "quelle",
|
|
80
|
+
"alt": "alt",
|
|
81
|
+
"width": "breite",
|
|
82
|
+
"height": "höhe"
|
|
83
|
+
},
|
|
55
84
|
"link": {
|
|
56
|
-
"title": "
|
|
57
|
-
"
|
|
85
|
+
"title": "link hinzufügen/bearbeiten",
|
|
86
|
+
"href": "link-adresse",
|
|
87
|
+
"target": "in neuem fenster öffnen",
|
|
88
|
+
"rel": "rel",
|
|
89
|
+
"class": "css-klasse"
|
|
58
90
|
},
|
|
59
91
|
"source": {
|
|
60
|
-
"title": "
|
|
61
|
-
"prettify": "
|
|
92
|
+
"title": "quellcode anzeigen",
|
|
93
|
+
"prettify": "verschönern"
|
|
62
94
|
}
|
|
63
95
|
},
|
|
64
96
|
"misc": {
|
|
65
|
-
"source": "
|
|
97
|
+
"source": "quellcode anzeigen",
|
|
98
|
+
"preview": "vorschau"
|
|
66
99
|
}
|
|
67
100
|
}
|