tiptapify 0.0.6 → 0.0.7

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.
Files changed (37) hide show
  1. package/README.md +3 -2
  2. package/dist/tiptapify.css +1 -1
  3. package/dist/{tiptapify.es.js → tiptapify.mjs} +52865 -52006
  4. package/dist/tiptapify.umd.js +41 -43
  5. package/package.json +8 -8
  6. package/src/components/Footer.vue +5 -6
  7. package/src/components/MenuBubble.vue +39 -30
  8. package/src/components/MenuFloating.vue +10 -10
  9. package/src/components/Tiptapify.vue +89 -10
  10. package/src/components/Toolbar/Group.vue +8 -43
  11. package/src/components/Toolbar/GroupDropdown.vue +85 -0
  12. package/src/components/Toolbar/Index.vue +11 -10
  13. package/src/components/Toolbar/items/media.ts +179 -2
  14. package/src/components/Toolbar/items/misc.ts +10 -1
  15. package/src/components/Toolbar/items/style.ts +2 -2
  16. package/src/components/Toolbar/items.ts +1 -0
  17. package/src/components/editorExtensions.ts +6 -4
  18. package/src/components/index.ts +13 -0
  19. package/src/{components/extensions → extensions}/components/LinkDialog.vue +11 -8
  20. package/src/extensions/components/PreviewDialog.vue +45 -0
  21. package/src/{components/extensions/components/ShowSource.vue → extensions/components/ShowSourceDialog.vue} +11 -7
  22. package/src/extensions/components/TableBuilder.vue +138 -0
  23. package/src/extensions/preview.ts +53 -0
  24. package/src/{components/extensions → extensions}/view-source.ts +1 -3
  25. package/src/i18n/locales/de.json +64 -45
  26. package/src/i18n/locales/en.json +21 -2
  27. package/src/i18n/locales/es.json +27 -8
  28. package/src/i18n/locales/fr.json +26 -7
  29. package/src/i18n/locales/it.json +36 -17
  30. package/src/i18n/locales/pl.json +28 -9
  31. package/src/i18n/locales/ru.json +21 -2
  32. package/src/i18n/locales/ua.json +21 -2
  33. package/src/utils/helpers.ts +17 -0
  34. package/src/composable/useEditor.ts +0 -35
  35. /package/src/{components/extensions → extensions}/components/slashCommands/CommandsList.vue +0 -0
  36. /package/src/{components/extensions → extensions}/components/slashCommands/suggestion.ts +0 -0
  37. /package/src/{components/extensions → extensions}/slash-commands.ts +0 -0
@@ -1,8 +1,9 @@
1
1
  import * as mdi from "@mdi/js";
2
2
  import { Editor } from "@tiptap/vue-3";
3
- import { computed } from "vue";
3
+ import TableBuilder from "@tiptapify/extensions/components/TableBuilder.vue";
4
+ import { computed, markRaw, Ref } from "vue";
4
5
 
5
- export function getMediaItems(editor: Editor, toolbarLinkButton: any) {
6
+ export function getMediaItems(editor: Editor, toolbarLinkButton: Ref) {
6
7
  return {
7
8
  link: {
8
9
  name: 'format.link',
@@ -20,6 +21,182 @@ export function getMediaItems(editor: Editor, toolbarLinkButton: any) {
20
21
  : toolbarLinkButton?.value?.open
21
22
  })
22
23
  }
24
+ },
25
+ table: {
26
+ name: 'tables',
27
+ tooltip: 'format.tables.table',
28
+ icon: mdi.mdiTable,
29
+ modelValue: false,
30
+ enabled: true,
31
+ props: {
32
+ color: computed(() => editor.isActive('table') ? 'primary' : ''),
33
+ disabled: computed(() => !editor.can().chain().focus().insertTable().run()),
34
+ },
35
+ children: [
36
+ {
37
+ name: 'insert table',
38
+ tooltip: 'format.tables.insertTable',
39
+ icon: mdi.mdiTablePlus,
40
+ enabled: true,
41
+ props: {
42
+ disabled: computed(() => !editor.can().chain().focus().insertTable().run()),
43
+ activator: 'parent',
44
+ openOnClick: true,
45
+ openOnHover: false,
46
+ closeOnContentClick: false,
47
+ submenu: true
48
+ },
49
+ component: markRaw(TableBuilder),
50
+ },
51
+ {
52
+ name: 'insert table',
53
+ tooltip: 'format.tables.deleteTable',
54
+ icon: mdi.mdiTableMinus,
55
+ enabled: true,
56
+ props: {
57
+ disabled: computed(() => !editor.can().chain().focus().deleteTable().run()),
58
+ },
59
+ attrs: {
60
+ click: () => editor.chain().focus().deleteTable().run()
61
+ }
62
+ },
63
+ {
64
+ name: 'table row',
65
+ tooltip: 'format.tables.row',
66
+ icon: mdi.mdiTableRow,
67
+ enabled: true,
68
+ props: {
69
+ disabled: computed(
70
+ () =>
71
+ !editor.can().chain().focus().addRowBefore().run() &&
72
+ !editor.can().chain().focus().addRowAfter().run() &&
73
+ !editor.can().chain().focus().deleteRow().run()
74
+ ),
75
+ openOnHover: true,
76
+ openOnClick: true,
77
+ activator: 'parent',
78
+ submenu: true
79
+ },
80
+ children: [
81
+ {
82
+ name: 'insert row before',
83
+ tooltip: 'format.tables.insertRowBefore',
84
+ icon: mdi.mdiTableRowPlusBefore,
85
+ enabled: true,
86
+ props: {
87
+ disabled: computed(() => !editor.can().chain().focus().addRowBefore().run()),
88
+ },
89
+ attrs: {
90
+ click: () => editor.chain().focus().addRowBefore().run()
91
+ }
92
+ },
93
+ {
94
+ name: 'insert row after',
95
+ tooltip: 'format.tables.insertRowAfter',
96
+ icon: mdi.mdiTableRowPlusAfter,
97
+ enabled: true,
98
+ props: {
99
+ disabled: computed(() => !editor.can().chain().focus().addRowAfter().run()),
100
+ },
101
+ attrs: {
102
+ click: () => editor.chain().focus().addRowAfter().run()
103
+ }
104
+ },
105
+ {
106
+ name: 'delete row',
107
+ tooltip: 'format.tables.deleteRow',
108
+ icon: mdi.mdiTableRowRemove,
109
+ enabled: true,
110
+ props: {
111
+ disabled: computed(() => !editor.can().chain().focus().deleteRow().run()),
112
+ },
113
+ attrs: {
114
+ click: () => editor.chain().focus().deleteRow().run()
115
+ }
116
+ },
117
+ ]
118
+ },
119
+ {
120
+ name: 'column',
121
+ tooltip: 'format.tables.col',
122
+ icon: mdi.mdiTableColumn,
123
+ enabled: true,
124
+ props: {
125
+ disabled: computed(
126
+ () =>
127
+ !editor.can().chain().focus().addColumnBefore().run() &&
128
+ !editor.can().chain().focus().addColumnAfter().run() &&
129
+ !editor.can().chain().focus().deleteColumn().run()
130
+ ),
131
+ openOnHover: true,
132
+ openOnClick: true,
133
+ activator: 'parent',
134
+ submenu: true
135
+ },
136
+ children: [
137
+ {
138
+ name: 'insert col before',
139
+ tooltip: 'format.tables.insertColBefore',
140
+ icon: mdi.mdiTableColumnPlusBefore,
141
+ enabled: true,
142
+ props: {
143
+ disabled: computed(() => !editor.can().chain().focus().addColumnBefore().run()),
144
+ },
145
+ attrs: {
146
+ click: () => editor.chain().focus().addColumnBefore().run()
147
+ }
148
+ },
149
+ {
150
+ name: 'insert column after',
151
+ tooltip: 'format.tables.insertColAfter',
152
+ icon: mdi.mdiTableColumnPlusAfter,
153
+ enabled: true,
154
+ props: {
155
+ disabled: computed(() => !editor.can().chain().focus().addColumnAfter().run()),
156
+ },
157
+ attrs: {
158
+ click: () => editor.chain().focus().addColumnAfter().run()
159
+ }
160
+ },
161
+ {
162
+ name: 'delete column',
163
+ tooltip: 'format.tables.deleteCol',
164
+ icon: mdi.mdiTableColumnRemove,
165
+ enabled: true,
166
+ props: {
167
+ disabled: computed(() => !editor.can().chain().focus().deleteColumn().run()),
168
+ },
169
+ attrs: {
170
+ click: () => editor.chain().focus().deleteColumn().run()
171
+ }
172
+ }
173
+ ]
174
+ },
175
+ {
176
+ name: 'merge cells',
177
+ tooltip: 'format.tables.mergeCells',
178
+ icon: mdi.mdiTableMergeCells,
179
+ enabled: true,
180
+ props: {
181
+ disabled: computed(() => !editor.can().chain().focus().mergeCells().run()),
182
+ },
183
+ attrs: {
184
+ click: () => editor.chain().focus().mergeCells().run()
185
+ }
186
+ },
187
+ {
188
+ name: 'split cell',
189
+ tooltip: 'format.tables.splitCell',
190
+ icon: mdi.mdiTableSplitCell,
191
+ enabled: true,
192
+ props: {
193
+ disabled: computed(() => !editor.can().chain().focus().splitCell().run()),
194
+ },
195
+ attrs: {
196
+ click: () => editor.chain().focus().splitCell().run()
197
+ }
198
+ }
199
+ ]
23
200
  }
24
201
  }
25
202
  }
@@ -1,6 +1,6 @@
1
1
  import * as mdi from "@mdi/js";
2
2
  import { Editor } from "@tiptap/vue-3";
3
- import { computed } from "vue";
3
+ import { computed, Ref } from "vue";
4
4
 
5
5
  export function getMiscItems(editor: Editor) {
6
6
  return {
@@ -34,6 +34,15 @@ export function getMiscItems(editor: Editor) {
34
34
  click: () => editor.commands.showSource()
35
35
  }
36
36
  },
37
+ preview: {
38
+ name: 'preview',
39
+ tooltip: 'misc.preview',
40
+ icon: mdi.mdiFileEyeOutline,
41
+ enabled: true,
42
+ attrs: {
43
+ click: () => editor.commands.showPreview()
44
+ }
45
+ },
37
46
  formatClear: {
38
47
  name: 'format clear',
39
48
  tooltip: 'format.formatClear',
@@ -70,7 +70,7 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
70
70
  name: 'font-family',
71
71
  tooltip: 'style.fontFamily',
72
72
  icon: mdi.mdiFormatFont,
73
- modelValue: null,
73
+ modelValue: false,
74
74
  enabled: true,
75
75
  attrs: {
76
76
  click: () => editor.chain().focus().unsetFontFamily().run()
@@ -96,7 +96,7 @@ export function getStyleItems(editor: Editor, fontMeasure: string, customHeading
96
96
  name: 'font-size',
97
97
  tooltip: 'style.fontSize',
98
98
  icon: mdi.mdiFormatSize,
99
- modelValue: computed(() => editor.getAttributes('textStyle').fontSize || null),
99
+ modelValue: false,
100
100
  enabled: true,
101
101
  attrs: {
102
102
  click: () => editor.chain().focus().unsetFontSize().run()
@@ -22,6 +22,7 @@ export interface ToolbarItem {
22
22
  icon: string|ComputedRef<string>,
23
23
  noI18n?: boolean,
24
24
  enabled: boolean,
25
+ component?: any,
25
26
  modelValue?: any,
26
27
  group?: boolean,
27
28
  toggle?: boolean,
@@ -25,9 +25,10 @@ import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
25
25
 
26
26
  import { Link } from '@tiptap/extension-link'
27
27
  import CodeBlockComponent from '@tiptapify/components/CodeBlockComponent.vue'
28
- import { ViewSource } from '@tiptapify/components/extensions/view-source'
29
- import SlashCommands from '@tiptapify/components/extensions/slash-commands'
30
- import suggestion from '@tiptapify/components/extensions/components/slashCommands/suggestion'
28
+ import { ViewSource } from '@tiptapify/extensions/view-source'
29
+ import { Preview } from '@tiptapify/extensions/preview'
30
+ import SlashCommands from '@tiptapify/extensions/slash-commands'
31
+ import suggestion from '@tiptapify/extensions/components/slashCommands/suggestion'
31
32
 
32
33
  // load all languages with "all" or common languages with "common"
33
34
  import { common, createLowlight } from 'lowlight'
@@ -94,7 +95,8 @@ export function editorExtensions (placeholder: string, slashCommands: boolean) {
94
95
  }),
95
96
  Placeholder.configure({ placeholder }),
96
97
  CharacterCount,
97
- ViewSource
98
+ ViewSource,
99
+ Preview
98
100
  ]
99
101
 
100
102
  if (slashCommands) {
@@ -0,0 +1,13 @@
1
+ import { Editor, useEditor } from "@tiptap/vue-3";
2
+ import { editorExtensions } from "@tiptapify/components/editorExtensions";
3
+ import { ShallowRef } from "vue";
4
+
5
+ export function getTiptapEditor (content: any, placeholder: string, slashCommands: boolean = true): ShallowRef<Editor | undefined> {
6
+ const extensions = editorExtensions(placeholder, slashCommands)
7
+ const editor: ShallowRef<Editor | undefined> = useEditor({
8
+ content,
9
+ extensions,
10
+ })
11
+
12
+ return editor
13
+ }
@@ -1,13 +1,17 @@
1
1
  <script setup lang="ts">
2
2
 
3
3
  import * as mdi from '@mdi/js'
4
- import { useEditor } from "@tiptapify/composable/useEditor";
4
+ import { Editor } from "@tiptap/vue-3";
5
5
 
6
6
  import { useI18n } from 'vue-i18n'
7
- import { computed, ref, watch } from 'vue'
7
+ import { computed, inject, Ref, ref, watch } from 'vue'
8
+
9
+ import helpers from '@tiptapify/utils/helpers'
8
10
 
9
11
  defineExpose({ open })
10
12
 
13
+ const { ucFirst } = helpers
14
+
11
15
  interface Props {
12
16
  value?: string
13
17
  target?: '_self' | '_blank'
@@ -20,8 +24,7 @@ const props = withDefaults(defineProps<Props>(), {
20
24
  destroy: undefined
21
25
  })
22
26
 
23
- const editor = useEditor().editor
24
- const editorInstance = editor.getInstance()
27
+ const editor = inject('tiptapifyEditor') as Ref<Editor>
25
28
 
26
29
  const { t } = useI18n()
27
30
 
@@ -45,7 +48,7 @@ function apply() {
45
48
  const { href, target } = attrs.value
46
49
 
47
50
  if (href) {
48
- editorInstance.value.chain().focus().extendMarkRange('link').setLink({ href, target }).run()
51
+ editor.value.chain().focus().extendMarkRange('link').setLink({ href, target }).run()
49
52
  }
50
53
  close()
51
54
  }
@@ -75,7 +78,7 @@ watch(dialog, val => {
75
78
  <VDialog v-model="dialog" max-width="400" absolute @click:outside="close">
76
79
  <VCard>
77
80
  <VToolbar class="px-6" density="compact">
78
- <span class="headline">{{ t('dialog.link.title') }}</span>
81
+ <span class="headline">{{ ucFirst(t('dialog.link.title')) }}</span>
79
82
 
80
83
  <VSpacer />
81
84
 
@@ -85,12 +88,12 @@ watch(dialog, val => {
85
88
  </VToolbar>
86
89
 
87
90
  <VCardText>
88
- <VTextField v-model="attrs.href" :label="t('dialog.link.placeholder')" autofocus />
91
+ <VTextField v-model="attrs.href" :label="ucFirst(t('dialog.link.placeholder'))" autofocus />
89
92
  </VCardText>
90
93
 
91
94
  <VCardActions>
92
95
  <VBtn :disabled="isDisabled" @click="apply">
93
- {{ t('dialog.apply') }}
96
+ {{ ucFirst(t('dialog.apply')) }}
94
97
  </VBtn>
95
98
  </VCardActions>
96
99
  </VCard>
@@ -0,0 +1,45 @@
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
+ console.log('preview event', event)
14
+ content.value = event.detail.html
15
+ dialog.value = true;
16
+ }
17
+
18
+ onMounted(() => {
19
+ window.addEventListener('tiptapify-show-preview', showDialog as EventListener)
20
+ })
21
+
22
+ onUnmounted(() => {
23
+ window.removeEventListener('tiptapify-show-preview', showDialog as EventListener)
24
+ })
25
+ </script>
26
+
27
+ <template>
28
+ <VDialog v-model="dialog" fullscreen>
29
+ <VCard>
30
+ <VToolbar>
31
+ <VBtn :icon="mdi.mdiClose" @click="dialog = false" />
32
+
33
+ <VToolbarTitle>Preview</VToolbarTitle>
34
+ </VToolbar>
35
+
36
+ <VCardItem>
37
+ <div class="tiptap" v-html="content"></div>
38
+ </VCardItem>
39
+ </VCard>
40
+ </VDialog>
41
+ </template>
42
+
43
+ <style lang="scss">
44
+
45
+ </style>
@@ -1,15 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { useEditor } from "@tiptapify/composable/useEditor";
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 },
8
10
  })
9
11
 
12
+ const { ucFirst } = helpers;
13
+
10
14
  const { t } = useI18n();
11
15
 
12
- const editor = useEditor().editor.getInstance()
16
+ const editor = inject('tiptapifyEditor') as Ref<Editor>
13
17
 
14
18
  const dialog = ref(false)
15
19
  const formatted = ref(false)
@@ -76,14 +80,14 @@ watch(() => formatted.value, () => {
76
80
  <template>
77
81
  <VDialog v-model="dialog" max-width="1500">
78
82
  <VCard>
79
- <VCardTitle>{{ t('dialog.source.title') }}</VCardTitle>
83
+ <VCardTitle>{{ ucFirst(t('dialog.source.title')) }}</VCardTitle>
80
84
 
81
85
  <VCardText>
82
86
  <VContainer fluid class="pt-0 pl-0 pr-0">
83
87
  <VRow>
84
88
  <VCol>
85
89
  <VBtn v-model="formatted" :color="`${formatted ? 'primary' : ''}`" @click="formatted = !formatted">
86
- {{ t('dialog.source.prettify') }}
90
+ {{ ucFirst(t('dialog.source.prettify')) }}
87
91
  </VBtn>
88
92
  </VCol>
89
93
  </VRow>
@@ -101,10 +105,10 @@ watch(() => formatted.value, () => {
101
105
  <VCardActions>
102
106
  <VSpacer></VSpacer>
103
107
  <VBtn color="primary" @click="dialog = false">
104
- {{ t('dialog.close') }}
108
+ {{ ucFirst(t('dialog.close')) }}
105
109
  </VBtn>
106
110
  <VBtn color="primary" @click="saveChanges">
107
- {{ t('dialog.apply') }}
111
+ {{ ucFirst(t('dialog.apply')) }}
108
112
  </VBtn>
109
113
  </VCardActions>
110
114
  </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('format.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('format.tables.rows')) }}: {{ rowHover }}
78
+ {{ ucFirst(t('format.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,53 @@
1
+ import { Extension } from '@tiptap/core'
2
+ import { Plugin, PluginKey } from '@tiptap/pm/state'
3
+
4
+ const name: string = 'preview'
5
+
6
+ export interface ViewSourceOptions {
7
+ HTMLAttributes: Record<string, any>
8
+ }
9
+
10
+ declare module '@tiptap/core' {
11
+ interface Commands<ReturnType> {
12
+ preview: {
13
+ /**
14
+ * Показать исходный HTML-код
15
+ */
16
+ showPreview: () => ReturnType
17
+ }
18
+ }
19
+ }
20
+
21
+ export const Preview = Extension.create<ViewSourceOptions>({
22
+ name,
23
+
24
+ addOptions() {
25
+ return {
26
+ HTMLAttributes: {},
27
+ }
28
+ },
29
+
30
+ addCommands() {
31
+ return {
32
+ showPreview: () => ({ editor }) => {
33
+ const event = new CustomEvent('tiptapify-show-preview', {
34
+ detail: {
35
+ html: editor.getHTML()
36
+ }
37
+ })
38
+
39
+ window.dispatchEvent(event)
40
+
41
+ return true
42
+ },
43
+ }
44
+ },
45
+
46
+ addProseMirrorPlugins() {
47
+ return [
48
+ new Plugin({
49
+ key: new PluginKey(name),
50
+ }),
51
+ ]
52
+ },
53
+ })
@@ -30,9 +30,7 @@ export const ViewSource = Extension.create<ViewSourceOptions>({
30
30
  showSource: () => ({ editor }) => {
31
31
  const event = new CustomEvent('tiptapify-show-source', {
32
32
  detail: {
33
- // html: editor.getHTML()
34
- html: editor.getHTML({ blockSeparator: '\n\n' })
35
- // html: editor.getText({ blockSeparator: '\n\n' })
33
+ html: editor.getHTML()
36
34
  }
37
35
  })
38
36