tiptapify 0.0.4 → 0.0.5
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 -1
- package/dist/tiptapify.css +1 -1
- package/dist/tiptapify.es.js +19608 -18897
- package/dist/tiptapify.umd.js +39 -32
- package/package.json +23 -10
- package/src/components/Toolbar/Index.vue +2 -0
- package/src/components/Toolbar/fonts.ts +118 -0
- package/src/components/Toolbar/items.ts +39 -129
- package/src/components/editorExtensions.ts +3 -1
- package/src/components/extensions/components/LinkDialog.vue +1 -1
- package/src/components/extensions/components/ShowSource.vue +124 -0
- package/src/components/extensions/view-source.ts +53 -0
- package/src/i18n/locales/de.json +67 -0
- package/src/i18n/locales/en.json +11 -2
- package/src/i18n/locales/es.json +67 -0
- package/src/i18n/locales/fr.json +67 -0
- package/src/i18n/locales/it.json +67 -0
- package/src/i18n/locales/pl.json +67 -0
- package/src/i18n/locales/ru.json +11 -2
- package/src/i18n/locales/ua.json +11 -2
- package/components.d.ts +0 -20
- package/tsconfig.json +0 -22
- package/vite.config.ts +0 -86
package/package.json
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptapify",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Tiptap3 editor with Vuetify3 menu implementation",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
|
-
"import":
|
|
8
|
-
|
|
7
|
+
"import": {
|
|
8
|
+
"default": "./dist/tiptapify.es.js",
|
|
9
|
+
"development": "./src/index.ts"
|
|
10
|
+
},
|
|
11
|
+
"require": {
|
|
12
|
+
"default": "./dist/tiptapify.umd.js",
|
|
13
|
+
"development": "./src/index.ts"
|
|
14
|
+
}
|
|
9
15
|
},
|
|
16
|
+
"./src/*": "./src/*",
|
|
17
|
+
"./dist/*": "./dist/*",
|
|
10
18
|
"./style.css": "./dist/tiptapify.css"
|
|
11
19
|
},
|
|
12
20
|
"main": "./dist/tiptapify.umd.cjs",
|
|
13
21
|
"module": "./dist/tiptapify.js",
|
|
22
|
+
"source": "./src/index.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
14
27
|
"scripts": {
|
|
15
28
|
"dev": "vite",
|
|
16
29
|
"build": "vite build",
|
|
@@ -38,7 +51,6 @@
|
|
|
38
51
|
"repository": "https://github.com/IVoyt/tiptapify",
|
|
39
52
|
"packageManager": "pnpm@10.11.0",
|
|
40
53
|
"dependencies": {
|
|
41
|
-
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
|
42
54
|
"@tiptap/core": "next",
|
|
43
55
|
"@tiptap/extension-blockquote": "next",
|
|
44
56
|
"@tiptap/extension-bold": "next",
|
|
@@ -77,15 +89,9 @@
|
|
|
77
89
|
"@tiptap/starter-kit": "next",
|
|
78
90
|
"@tiptap/suggestion": "next",
|
|
79
91
|
"@tiptap/vue-3": "next",
|
|
80
|
-
"@vitejs/plugin-vue": "^5.2.4",
|
|
81
|
-
"@vitejs/plugin-vue-jsx": "^4.2.0",
|
|
82
92
|
"highlight.js": "^11.11.1",
|
|
83
93
|
"linkifyjs": "^4.3.1",
|
|
84
94
|
"lowlight": "^3.3.0",
|
|
85
|
-
"unplugin-vue-components": "^28.5.0",
|
|
86
|
-
"vite": "^6.3.5",
|
|
87
|
-
"vite-plugin-vuetify": "^2.1.1",
|
|
88
|
-
"vite-svg-loader": "^5.1.0",
|
|
89
95
|
"vue-i18n": "^11.1.4"
|
|
90
96
|
},
|
|
91
97
|
"peerDependencies": {
|
|
@@ -94,11 +100,18 @@
|
|
|
94
100
|
"vuetify": "^3.8.5"
|
|
95
101
|
},
|
|
96
102
|
"devDependencies": {
|
|
103
|
+
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
|
97
104
|
"@rollup/plugin-alias": "^5.1.1",
|
|
98
105
|
"@types/node": "^22.15.21",
|
|
106
|
+
"@vitejs/plugin-vue": "^5.2.4",
|
|
107
|
+
"@vitejs/plugin-vue-jsx": "^4.2.0",
|
|
99
108
|
"rollup-plugin-tsconfig-paths": "^1.5.2",
|
|
100
109
|
"sass-embedded": "^1.89.0",
|
|
101
110
|
"typescript": "^5.8.3",
|
|
111
|
+
"unplugin-vue-components": "^28.5.0",
|
|
112
|
+
"vite": "^6.3.5",
|
|
113
|
+
"vite-plugin-vuetify": "^2.1.1",
|
|
114
|
+
"vite-svg-loader": "^5.1.0",
|
|
102
115
|
"vite-tsconfig-paths": "^5.1.4",
|
|
103
116
|
"vue-tsc": "^2.2.10"
|
|
104
117
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import LinkDialog from "@tiptapify/components/extensions/components/LinkDialog.vue";
|
|
3
|
+
import ShowSource from "@tiptapify/components/extensions/components/ShowSource.vue";
|
|
3
4
|
import { useEditor } from "@tiptapify/composable/useEditor";
|
|
4
5
|
import { computed, defineProps, Ref, ref } from 'vue'
|
|
5
6
|
import { useI18n } from "vue-i18n";
|
|
@@ -111,6 +112,7 @@ const toolbarItemsRef: Ref<ToolbarItemSections> = ref(items)
|
|
|
111
112
|
</template>
|
|
112
113
|
|
|
113
114
|
<LinkDialog ref="toolbarLinkButton" />
|
|
115
|
+
<ShowSource />
|
|
114
116
|
</div>
|
|
115
117
|
</template>
|
|
116
118
|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export const fonts = [
|
|
2
|
+
{
|
|
3
|
+
name: 'Arial',
|
|
4
|
+
fontFamily: 'arial'
|
|
5
|
+
},
|
|
6
|
+
{
|
|
7
|
+
name: 'Arial Black',
|
|
8
|
+
fontFamily: 'arial black'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
name: 'Baskerville',
|
|
12
|
+
fontFamily: 'baskerville'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'Bodoni MT',
|
|
16
|
+
fontFamily: 'bodoni mt'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Brush Script MT',
|
|
20
|
+
fontFamily: 'brush script mt'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Calibri',
|
|
24
|
+
fontFamily: 'calibri'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Calisto MT',
|
|
28
|
+
fontFamily: 'calisto mt'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Cambria',
|
|
32
|
+
fontFamily: 'cambria'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Century Gothic',
|
|
36
|
+
fontFamily: 'century gothic'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Consolas',
|
|
40
|
+
fontFamily: 'consolas'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Comic Sans',
|
|
44
|
+
fontFamily: 'comic sans ms, comic sans'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Courier',
|
|
48
|
+
fontFamily: 'Courier'
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'Courier New',
|
|
52
|
+
fontFamily: 'courier new'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'Cursive',
|
|
56
|
+
fontFamily: 'cursive'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Dejavu Sans',
|
|
60
|
+
fontFamily: 'dejavu sans'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Franklin Gothic',
|
|
64
|
+
fontFamily: 'franklin gothic'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'Garamond',
|
|
68
|
+
fontFamily: 'garamond'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Georgia',
|
|
72
|
+
fontFamily: 'georgia'
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Helvetica',
|
|
76
|
+
fontFamily: 'helvetica'
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'Impact',
|
|
80
|
+
fontFamily: 'impact'
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'Inter',
|
|
84
|
+
fontFamily: 'inter'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Monospace',
|
|
88
|
+
fontFamily: 'monospace'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Optima',
|
|
92
|
+
fontFamily: 'optima'
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'Segoe UI',
|
|
96
|
+
fontFamily: 'segoe ui'
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Serif',
|
|
100
|
+
fontFamily: 'serif'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'Tahoma',
|
|
104
|
+
fontFamily: 'tahoma'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'Time New Roman',
|
|
108
|
+
fontFamily: 'times new roman'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'Trebuchet MS',
|
|
112
|
+
fontFamily: 'trebuchet ms'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'Verdana',
|
|
116
|
+
fontFamily: 'verdana'
|
|
117
|
+
},
|
|
118
|
+
]
|
|
@@ -1,124 +1,6 @@
|
|
|
1
1
|
import { computed, ComputedRef, Ref, ref } from "vue";
|
|
2
2
|
import * as mdi from '@mdi/js'
|
|
3
|
-
|
|
4
|
-
const fonts = ref([
|
|
5
|
-
{
|
|
6
|
-
name: 'Arial',
|
|
7
|
-
fontFamily: 'arial'
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
name: 'Arial Black',
|
|
11
|
-
fontFamily: 'arial black'
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
name: 'Baskerville',
|
|
15
|
-
fontFamily: 'baskerville'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
name: 'Bodoni MT',
|
|
19
|
-
fontFamily: 'bodoni mt'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
name: 'Brush Script MT',
|
|
23
|
-
fontFamily: 'brush script mt'
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
name: 'Calibri',
|
|
27
|
-
fontFamily: 'calibri'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
name: 'Calisto MT',
|
|
31
|
-
fontFamily: 'calisto mt'
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'Cambria',
|
|
35
|
-
fontFamily: 'cambria'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: 'Century Gothic',
|
|
39
|
-
fontFamily: 'century gothic'
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: 'Consolas',
|
|
43
|
-
fontFamily: 'consolas'
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'Comic Sans',
|
|
47
|
-
fontFamily: 'comic sans ms, comic sans'
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'Courier',
|
|
51
|
-
fontFamily: 'Courier'
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'Courier New',
|
|
55
|
-
fontFamily: 'courier new'
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: 'Cursive',
|
|
59
|
-
fontFamily: 'cursive'
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: 'Dejavu Sans',
|
|
63
|
-
fontFamily: 'dejavu sans'
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'Franklin Gothic',
|
|
67
|
-
fontFamily: 'franklin gothic'
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
name: 'Garamond',
|
|
71
|
-
fontFamily: 'garamond'
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
name: 'Georgia',
|
|
75
|
-
fontFamily: 'georgia'
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
name: 'Helvetica',
|
|
79
|
-
fontFamily: 'helvetica'
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: 'Impact',
|
|
83
|
-
fontFamily: 'impact'
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: 'Inter',
|
|
87
|
-
fontFamily: 'inter'
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
name: 'Monospace',
|
|
91
|
-
fontFamily: 'monospace'
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
name: 'Optima',
|
|
95
|
-
fontFamily: 'optima'
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: 'Segoe UI',
|
|
99
|
-
fontFamily: 'segoe ui'
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: 'Serif',
|
|
103
|
-
fontFamily: 'serif'
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
name: 'Tahoma',
|
|
107
|
-
fontFamily: 'tahoma'
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: 'Time New Roman',
|
|
111
|
-
fontFamily: 'times new roman'
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
name: 'Trebuchet MS',
|
|
115
|
-
fontFamily: 'trebuchet ms'
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
name: 'Verdana',
|
|
119
|
-
fontFamily: 'verdana'
|
|
120
|
-
},
|
|
121
|
-
])
|
|
3
|
+
import { fonts } from './fonts'
|
|
122
4
|
|
|
123
5
|
interface MDIIcons {
|
|
124
6
|
[key: string]: string
|
|
@@ -184,7 +66,6 @@ export function toolbarItems(
|
|
|
184
66
|
* font color, backgroundcolor
|
|
185
67
|
* tables
|
|
186
68
|
* media (image, video)
|
|
187
|
-
* unsetmarks, clearnodes
|
|
188
69
|
*/
|
|
189
70
|
heading: {
|
|
190
71
|
name: 'heading',
|
|
@@ -199,23 +80,41 @@ export function toolbarItems(
|
|
|
199
80
|
props: {
|
|
200
81
|
color: computed(() => editor.value.isActive('heading') ? 'primary' : ''),
|
|
201
82
|
},
|
|
202
|
-
children:
|
|
203
|
-
|
|
204
|
-
name: `
|
|
205
|
-
tooltip: `style.
|
|
206
|
-
icon: mdiIcons[`
|
|
83
|
+
children: [
|
|
84
|
+
{
|
|
85
|
+
name: `paragraph`,
|
|
86
|
+
tooltip: `style.paragraph`,
|
|
87
|
+
icon: mdiIcons[`mdiFormatParagraph`],
|
|
207
88
|
noI18n: true,
|
|
208
89
|
enabled: true,
|
|
209
90
|
props: {
|
|
210
91
|
color: computed(() => {
|
|
211
|
-
return editor.value.isActive('
|
|
92
|
+
return editor.value.isActive('paragraph') ? 'primary' : ''
|
|
212
93
|
}),
|
|
213
94
|
},
|
|
214
95
|
attrs: {
|
|
215
|
-
click: () => editor.value.chain().focus().
|
|
96
|
+
click: () => editor.value.chain().focus().setParagraph().run()
|
|
216
97
|
}
|
|
217
98
|
}
|
|
218
|
-
|
|
99
|
+
].concat(
|
|
100
|
+
headingLevels.value.map(level => {
|
|
101
|
+
return {
|
|
102
|
+
name: `H${level}`,
|
|
103
|
+
tooltip: `style.headings.h${level}`,
|
|
104
|
+
icon: mdiIcons[`mdiFormatHeader${level}`],
|
|
105
|
+
noI18n: true,
|
|
106
|
+
enabled: true,
|
|
107
|
+
props: {
|
|
108
|
+
color: computed(() => {
|
|
109
|
+
return editor.value.isActive('heading', { level }) ? 'primary' : ''
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
attrs: {
|
|
113
|
+
click: () => editor.value.chain().focus().toggleHeading({ level }).run()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
)
|
|
219
118
|
},
|
|
220
119
|
fontFamily: {
|
|
221
120
|
name: 'font-family',
|
|
@@ -227,7 +126,7 @@ export function toolbarItems(
|
|
|
227
126
|
attrs: {
|
|
228
127
|
click: () => editor.value.chain().focus().unsetFontFamily().run()
|
|
229
128
|
},
|
|
230
|
-
children: fonts.
|
|
129
|
+
children: fonts.map((font) => {
|
|
231
130
|
return {
|
|
232
131
|
name: font.name,
|
|
233
132
|
tooltip: '',
|
|
@@ -651,6 +550,17 @@ export function toolbarItems(
|
|
|
651
550
|
click: () => editor.value.chain().focus().setHardBreak().run()
|
|
652
551
|
}
|
|
653
552
|
},
|
|
553
|
+
source: {
|
|
554
|
+
name: 'source',
|
|
555
|
+
tooltip: 'misc.source',
|
|
556
|
+
icon: mdi.mdiCodeTags,
|
|
557
|
+
section: 'misc',
|
|
558
|
+
enabled: true,
|
|
559
|
+
props: {},
|
|
560
|
+
attrs: {
|
|
561
|
+
click: () => editor.value.commands.showSource()
|
|
562
|
+
}
|
|
563
|
+
},
|
|
654
564
|
}
|
|
655
565
|
|
|
656
566
|
|
|
@@ -25,6 +25,7 @@ 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'
|
|
28
29
|
import SlashCommands from '@tiptapify/components/extensions/slash-commands'
|
|
29
30
|
import suggestion from '@tiptapify/components/extensions/components/slashCommands/suggestion'
|
|
30
31
|
|
|
@@ -92,7 +93,8 @@ export function editorExtensions (placeholder: string, slashCommands: boolean) {
|
|
|
92
93
|
types: ['heading', 'paragraph'],
|
|
93
94
|
}),
|
|
94
95
|
Placeholder.configure({ placeholder }),
|
|
95
|
-
CharacterCount
|
|
96
|
+
CharacterCount,
|
|
97
|
+
ViewSource
|
|
96
98
|
]
|
|
97
99
|
|
|
98
100
|
if (slashCommands) {
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useEditor } from "@tiptapify/composable/useEditor";
|
|
3
|
+
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
|
4
|
+
import { useI18n } from "vue-i18n";
|
|
5
|
+
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
indent: { type: Number, default: 2 },
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const { t } = useI18n();
|
|
11
|
+
|
|
12
|
+
const editor = useEditor().editor.getInstance()
|
|
13
|
+
|
|
14
|
+
const dialog = ref(false)
|
|
15
|
+
const formatted = ref(false)
|
|
16
|
+
const sourceCode = ref('')
|
|
17
|
+
|
|
18
|
+
const formatHtml = (html: string): string => {
|
|
19
|
+
let formatted = html.replace(/>/g, '>\n');
|
|
20
|
+
|
|
21
|
+
formatted = formatted.replace(/\n</g, '\n<');
|
|
22
|
+
formatted = formatted.replace(/([^>\n])</g, '$1\n<');
|
|
23
|
+
|
|
24
|
+
const lines = formatted.split('\n');
|
|
25
|
+
let indentLevel = 0;
|
|
26
|
+
|
|
27
|
+
return lines
|
|
28
|
+
.map(line => {
|
|
29
|
+
if (line.match(/<\//)) {
|
|
30
|
+
indentLevel = Math.max(0, indentLevel - 1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const indentedLine = ' '.repeat(indentLevel * props.indent) + line;
|
|
34
|
+
|
|
35
|
+
if (line.match(/<[^\/][^>]*>/) && !line.match(/<.*\/>/)) {
|
|
36
|
+
indentLevel++;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return indentedLine;
|
|
40
|
+
})
|
|
41
|
+
.filter(line => line.trim())
|
|
42
|
+
.join('\n');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const unformatHtml = (html: string): string => {
|
|
46
|
+
return html
|
|
47
|
+
.replace(/\n/g, '')
|
|
48
|
+
.replace(/\s+/g, ' ')
|
|
49
|
+
.replace(/>\s+</g, '><')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const showDialog = (event: CustomEvent) => {
|
|
53
|
+
sourceCode.value = event.detail.html
|
|
54
|
+
dialog.value = true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const saveChanges = () => {
|
|
58
|
+
dialog.value = false
|
|
59
|
+
|
|
60
|
+
editor.value.commands.setContent(sourceCode.value, true)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
onMounted(() => {
|
|
64
|
+
window.addEventListener('tiptapify-show-source', showDialog as EventListener)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
onUnmounted(() => {
|
|
68
|
+
window.removeEventListener('tiptapify-show-source', showDialog as EventListener)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
watch(() => formatted.value, () => {
|
|
72
|
+
sourceCode.value = formatted.value ? formatHtml(sourceCode.value) : unformatHtml(sourceCode.value)
|
|
73
|
+
})
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<template>
|
|
77
|
+
<VDialog v-model="dialog" max-width="1500">
|
|
78
|
+
<VCard>
|
|
79
|
+
<VCardTitle>{{ t('dialog.source.title') }}</VCardTitle>
|
|
80
|
+
|
|
81
|
+
<VCardText>
|
|
82
|
+
<VContainer fluid class="pt-0 pl-0 pr-0">
|
|
83
|
+
<VRow>
|
|
84
|
+
<VCol>
|
|
85
|
+
<VBtn v-model="formatted" :color="`${formatted ? 'primary' : ''}`" @click="formatted = !formatted">
|
|
86
|
+
{{ t('dialog.source.prettify') }}
|
|
87
|
+
</VBtn>
|
|
88
|
+
</VCol>
|
|
89
|
+
</VRow>
|
|
90
|
+
</VContainer>
|
|
91
|
+
|
|
92
|
+
<VTextarea
|
|
93
|
+
v-model="sourceCode"
|
|
94
|
+
no-resize
|
|
95
|
+
rows="100"
|
|
96
|
+
variant="outlined"
|
|
97
|
+
class="source-code-area"
|
|
98
|
+
/>
|
|
99
|
+
</VCardText>
|
|
100
|
+
|
|
101
|
+
<VCardActions>
|
|
102
|
+
<VSpacer></VSpacer>
|
|
103
|
+
<VBtn color="primary" @click="dialog = false">
|
|
104
|
+
{{ t('dialog.close') }}
|
|
105
|
+
</VBtn>
|
|
106
|
+
<VBtn color="primary" @click="saveChanges">
|
|
107
|
+
{{ t('dialog.apply') }}
|
|
108
|
+
</VBtn>
|
|
109
|
+
</VCardActions>
|
|
110
|
+
</VCard>
|
|
111
|
+
</VDialog>
|
|
112
|
+
</template>
|
|
113
|
+
|
|
114
|
+
<style scoped lang="scss">
|
|
115
|
+
.source-code-area {
|
|
116
|
+
font-family: monospace;
|
|
117
|
+
white-space: pre-wrap;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
:deep(.source-code-area textarea) {
|
|
121
|
+
max-height: 900px;
|
|
122
|
+
overflow-y: auto;
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core'
|
|
2
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
|
3
|
+
|
|
4
|
+
export interface ViewSourceOptions {
|
|
5
|
+
HTMLAttributes: Record<string, any>
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
declare module '@tiptap/core' {
|
|
9
|
+
interface Commands<ReturnType> {
|
|
10
|
+
viewSource: {
|
|
11
|
+
/**
|
|
12
|
+
* Показать исходный HTML-код
|
|
13
|
+
*/
|
|
14
|
+
showSource: () => ReturnType
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ViewSource = Extension.create<ViewSourceOptions>({
|
|
20
|
+
name: 'viewSource',
|
|
21
|
+
|
|
22
|
+
addOptions() {
|
|
23
|
+
return {
|
|
24
|
+
HTMLAttributes: {},
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
addCommands() {
|
|
29
|
+
return {
|
|
30
|
+
showSource: () => ({ editor }) => {
|
|
31
|
+
const event = new CustomEvent('tiptapify-show-source', {
|
|
32
|
+
detail: {
|
|
33
|
+
// html: editor.getHTML()
|
|
34
|
+
html: editor.getHTML({ blockSeparator: '\n\n' })
|
|
35
|
+
// html: editor.getText({ blockSeparator: '\n\n' })
|
|
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('viewSource'),
|
|
50
|
+
}),
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
})
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"style": {
|
|
3
|
+
"paragraph": "Absatz",
|
|
4
|
+
"heading": "Überschrift",
|
|
5
|
+
"headings": {
|
|
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
|
+
},
|
|
13
|
+
"fontFamily": "Schriftart",
|
|
14
|
+
"fontSize": "Schriftgröße",
|
|
15
|
+
"lineHeight": "Zeilenhöhe"
|
|
16
|
+
},
|
|
17
|
+
"format": {
|
|
18
|
+
"bold": "Fett",
|
|
19
|
+
"italic": "Kursiv",
|
|
20
|
+
"strike": "Durchgestrichen",
|
|
21
|
+
"underline": "Unterstrichen",
|
|
22
|
+
"sup": "Hochgestellt",
|
|
23
|
+
"sub": "Tiefgestellt",
|
|
24
|
+
"break": "Zeilenumbruch",
|
|
25
|
+
"highlight": "Hervorheben",
|
|
26
|
+
"line": "Horizontale Linie",
|
|
27
|
+
"blockquote": "Zitat",
|
|
28
|
+
"code": "Code",
|
|
29
|
+
"codeblock": "Codeblock",
|
|
30
|
+
"link": "Externer Link",
|
|
31
|
+
"formatClear": "Formatierung löschen"
|
|
32
|
+
},
|
|
33
|
+
"action": {
|
|
34
|
+
"undo": "Rückgängig",
|
|
35
|
+
"redo": "Wiederherstellen"
|
|
36
|
+
},
|
|
37
|
+
"alignment": "Ausrichtung",
|
|
38
|
+
"alignments": {
|
|
39
|
+
"left": "Linksbündig",
|
|
40
|
+
"center": "Zentriert",
|
|
41
|
+
"right": "Rechtsbündig",
|
|
42
|
+
"justify": "Blocksatz"
|
|
43
|
+
},
|
|
44
|
+
"list": "Liste",
|
|
45
|
+
"lists": {
|
|
46
|
+
"bullet": "Aufzählungsliste",
|
|
47
|
+
"numbered": "Nummerierte Liste",
|
|
48
|
+
"task": "Aufgabenliste",
|
|
49
|
+
"indent": "Einzug vergrößern",
|
|
50
|
+
"outdent": "Einzug verkleinern"
|
|
51
|
+
},
|
|
52
|
+
"dialog": {
|
|
53
|
+
"close": "Schließen",
|
|
54
|
+
"apply": "Anwenden",
|
|
55
|
+
"link": {
|
|
56
|
+
"title": "Link hinzufügen/bearbeiten",
|
|
57
|
+
"placeholder": "Linkadresse"
|
|
58
|
+
},
|
|
59
|
+
"source": {
|
|
60
|
+
"title": "Quellcode anzeigen",
|
|
61
|
+
"prettify": "prettify"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"misc": {
|
|
65
|
+
"source": "Quellcode anzeigen"
|
|
66
|
+
}
|
|
67
|
+
}
|