tiptapify 0.2.4 → 0.2.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 +1 -1
- package/dist/tiptapify.css +1 -1
- package/dist/tiptapify.mjs +84644 -65141
- package/dist/tiptapify.umd.js +86 -84
- package/index.d.ts +23 -2
- package/package.json +45 -45
- package/src/components/Tiptapify.vue +83 -1
- package/src/components/Toolbar/Index.vue +2 -2
- package/src/components/Toolbar/Items.vue +9 -2
- package/src/components/UI/TiptapifyDialog.vue +7 -1
- package/src/extensions/components/ai/Button.vue +1 -1
- package/src/extensions/components/ai/Dialog.vue +337 -27
- package/src/extensions/components/ai/charLimit.test.ts +55 -0
- package/src/extensions/components/ai/charLimit.ts +30 -0
- package/src/extensions/components/ai/characterCount.test.ts +27 -0
- package/src/extensions/components/media/iframe/Button.vue +1 -2
- package/src/extensions/components/media/iframe/IframeDialog.vue +36 -31
- package/src/extensions/components/media/image/Button.vue +1 -1
- package/src/extensions/components/media/link/Button.vue +1 -1
- package/src/extensions/components/media/link/LinkDialog.vue +19 -36
- package/src/extensions/components/media/video/Button.vue +1 -1
- package/src/extensions/components/media/video/VideoDialog.vue +17 -17
- package/src/extensions/components/misc/source/Button.vue +1 -1
- package/src/i18n/locales/ar.json +165 -159
- package/src/i18n/locales/bg.json +212 -0
- package/src/i18n/locales/ch.json +165 -159
- package/src/i18n/locales/cz.json +165 -159
- package/src/i18n/locales/de.json +165 -159
- package/src/i18n/locales/el.json +212 -0
- package/src/i18n/locales/en.json +166 -159
- package/src/i18n/locales/es.json +165 -159
- package/src/i18n/locales/et.json +212 -0
- package/src/i18n/locales/fi.json +165 -159
- package/src/i18n/locales/fr.json +165 -159
- package/src/i18n/locales/he.json +212 -0
- package/src/i18n/locales/hi.json +212 -0
- package/src/i18n/locales/hr.json +212 -0
- package/src/i18n/locales/hu.json +165 -159
- package/src/i18n/locales/id.json +212 -0
- package/src/i18n/locales/it.json +165 -159
- package/src/i18n/locales/ja.json +165 -159
- package/src/i18n/locales/ko.json +165 -159
- package/src/i18n/locales/la.json +165 -159
- package/src/i18n/locales/lt.json +165 -159
- package/src/i18n/locales/nl.json +165 -159
- package/src/i18n/locales/no.json +212 -0
- package/src/i18n/locales/pl.json +165 -159
- package/src/i18n/locales/pt-BR.json +212 -0
- package/src/i18n/locales/pt.json +165 -159
- package/src/i18n/locales/ro.json +212 -0
- package/src/i18n/locales/ru.json +165 -159
- package/src/i18n/locales/se.json +165 -159
- package/src/i18n/locales/sk.json +212 -0
- package/src/i18n/locales/sl.json +212 -0
- package/src/i18n/locales/sr.json +212 -0
- package/src/i18n/locales/th.json +165 -159
- package/src/i18n/locales/tr.json +165 -159
- package/src/i18n/locales/uk.json +165 -159
- package/src/i18n/locales/vi.json +165 -159
- package/src/index.ts +3 -0
- package/src/types/editor.ts +23 -2
- package/src/utils/validateHref.test.ts +68 -0
- package/src/utils/validateHref.ts +21 -0
package/index.d.ts
CHANGED
|
@@ -97,10 +97,17 @@ export interface TiptapifyAiRequest {
|
|
|
97
97
|
model?: string
|
|
98
98
|
messages: TiptapifyAiChatMessage[]
|
|
99
99
|
temperature?: number
|
|
100
|
-
stream?:
|
|
100
|
+
stream?: boolean
|
|
101
101
|
[key: string]: unknown
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
export type TiptapifyAiReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max'
|
|
105
|
+
|
|
106
|
+
export interface TiptapifyAiReasoningEffortOptions {
|
|
107
|
+
options: TiptapifyAiReasoningEffort[]
|
|
108
|
+
default?: TiptapifyAiReasoningEffort
|
|
109
|
+
}
|
|
110
|
+
|
|
104
111
|
export interface TiptapifyAiResponse {
|
|
105
112
|
content: string
|
|
106
113
|
}
|
|
@@ -114,7 +121,17 @@ export interface TiptapifyAiOpenAiResponse {
|
|
|
114
121
|
}>
|
|
115
122
|
}
|
|
116
123
|
|
|
117
|
-
export
|
|
124
|
+
export interface TiptapifyAiStream {
|
|
125
|
+
signal: AbortSignal
|
|
126
|
+
onChunk: (chunk: string) => void
|
|
127
|
+
onReasoning: (chunk: string) => void
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export type TiptapifyAiProvider = (
|
|
131
|
+
request: TiptapifyAiRequest,
|
|
132
|
+
context: TiptapifyAiEditorContext,
|
|
133
|
+
stream?: TiptapifyAiStream,
|
|
134
|
+
) => Promise<TiptapifyAiResponse | TiptapifyAiOpenAiResponse | string>
|
|
118
135
|
|
|
119
136
|
export type TiptapifyAiTokenProvider = () => Promise<string | null> | string | null
|
|
120
137
|
|
|
@@ -132,6 +149,10 @@ export interface TiptapifyAiOptions {
|
|
|
132
149
|
defaultPrompt?: string
|
|
133
150
|
systemPrompt?: string
|
|
134
151
|
temperature?: number
|
|
152
|
+
stream?: boolean
|
|
153
|
+
thinking?: boolean
|
|
154
|
+
reasoningEffort?: TiptapifyAiReasoningEffortOptions
|
|
155
|
+
showReasoning?: boolean
|
|
135
156
|
chatCompletionOptions?: Record<string, unknown>
|
|
136
157
|
createMessages?: (context: TiptapifyAiEditorContext) => TiptapifyAiChatMessage[]
|
|
137
158
|
tokenProvider?: TiptapifyAiTokenProvider
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptapify",
|
|
3
3
|
"types": "./index.d.ts",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"description": "Tiptap3 editor with Vuetify3 menu implementation",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -70,47 +70,47 @@
|
|
|
70
70
|
"packageManager": "pnpm@11.8.0",
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@floating-ui/dom": "^1.7.6",
|
|
73
|
-
"@tiptap/core": "^3.
|
|
74
|
-
"@tiptap/extension-blockquote": "^3.
|
|
75
|
-
"@tiptap/extension-bold": "^3.
|
|
76
|
-
"@tiptap/extension-bubble-menu": "^3.
|
|
77
|
-
"@tiptap/extension-code": "^3.
|
|
78
|
-
"@tiptap/extension-code-block": "^3.
|
|
79
|
-
"@tiptap/extension-code-block-lowlight": "^3.
|
|
80
|
-
"@tiptap/extension-color": "^3.
|
|
81
|
-
"@tiptap/extension-document": "^3.
|
|
82
|
-
"@tiptap/extension-floating-menu": "^3.
|
|
83
|
-
"@tiptap/extension-font-family": "^3.
|
|
84
|
-
"@tiptap/extension-hard-break": "^3.
|
|
85
|
-
"@tiptap/extension-heading": "^3.
|
|
86
|
-
"@tiptap/extension-highlight": "^3.
|
|
87
|
-
"@tiptap/extension-horizontal-rule": "^3.
|
|
88
|
-
"@tiptap/extension-image": "^3.
|
|
89
|
-
"@tiptap/extension-invisible-characters": "^3.
|
|
90
|
-
"@tiptap/extension-italic": "^3.
|
|
91
|
-
"@tiptap/extension-link": "^3.
|
|
92
|
-
"@tiptap/extension-list": "^3.
|
|
93
|
-
"@tiptap/extension-list-item": "^3.
|
|
94
|
-
"@tiptap/extension-paragraph": "^3.
|
|
95
|
-
"@tiptap/extension-placeholder": "^3.
|
|
96
|
-
"@tiptap/extension-strike": "^3.
|
|
97
|
-
"@tiptap/extension-subscript": "^3.
|
|
98
|
-
"@tiptap/extension-superscript": "^3.
|
|
99
|
-
"@tiptap/extension-table": "^3.
|
|
100
|
-
"@tiptap/extension-task-item": "^3.
|
|
101
|
-
"@tiptap/extension-task-list": "^3.
|
|
102
|
-
"@tiptap/extension-text": "^3.
|
|
103
|
-
"@tiptap/extension-text-align": "^3.
|
|
104
|
-
"@tiptap/extension-text-style": "^3.
|
|
105
|
-
"@tiptap/extension-typography": "^3.
|
|
106
|
-
"@tiptap/extension-underline": "^3.
|
|
107
|
-
"@tiptap/extension-youtube": "^3.
|
|
108
|
-
"@tiptap/extensions": "^3.
|
|
109
|
-
"@tiptap/pm": "^3.
|
|
110
|
-
"@tiptap/suggestion": "^3.
|
|
111
|
-
"@tiptap/vue-3": "^3.
|
|
73
|
+
"@tiptap/core": "^3.31.0",
|
|
74
|
+
"@tiptap/extension-blockquote": "^3.31.0",
|
|
75
|
+
"@tiptap/extension-bold": "^3.31.0",
|
|
76
|
+
"@tiptap/extension-bubble-menu": "^3.31.0",
|
|
77
|
+
"@tiptap/extension-code": "^3.31.0",
|
|
78
|
+
"@tiptap/extension-code-block": "^3.31.0",
|
|
79
|
+
"@tiptap/extension-code-block-lowlight": "^3.31.0",
|
|
80
|
+
"@tiptap/extension-color": "^3.31.0",
|
|
81
|
+
"@tiptap/extension-document": "^3.31.0",
|
|
82
|
+
"@tiptap/extension-floating-menu": "^3.31.0",
|
|
83
|
+
"@tiptap/extension-font-family": "^3.31.0",
|
|
84
|
+
"@tiptap/extension-hard-break": "^3.31.0",
|
|
85
|
+
"@tiptap/extension-heading": "^3.31.0",
|
|
86
|
+
"@tiptap/extension-highlight": "^3.31.0",
|
|
87
|
+
"@tiptap/extension-horizontal-rule": "^3.31.0",
|
|
88
|
+
"@tiptap/extension-image": "^3.31.0",
|
|
89
|
+
"@tiptap/extension-invisible-characters": "^3.31.0",
|
|
90
|
+
"@tiptap/extension-italic": "^3.31.0",
|
|
91
|
+
"@tiptap/extension-link": "^3.31.0",
|
|
92
|
+
"@tiptap/extension-list": "^3.31.0",
|
|
93
|
+
"@tiptap/extension-list-item": "^3.31.0",
|
|
94
|
+
"@tiptap/extension-paragraph": "^3.31.0",
|
|
95
|
+
"@tiptap/extension-placeholder": "^3.31.0",
|
|
96
|
+
"@tiptap/extension-strike": "^3.31.0",
|
|
97
|
+
"@tiptap/extension-subscript": "^3.31.0",
|
|
98
|
+
"@tiptap/extension-superscript": "^3.31.0",
|
|
99
|
+
"@tiptap/extension-table": "^3.31.0",
|
|
100
|
+
"@tiptap/extension-task-item": "^3.31.0",
|
|
101
|
+
"@tiptap/extension-task-list": "^3.31.0",
|
|
102
|
+
"@tiptap/extension-text": "^3.31.0",
|
|
103
|
+
"@tiptap/extension-text-align": "^3.31.0",
|
|
104
|
+
"@tiptap/extension-text-style": "^3.31.0",
|
|
105
|
+
"@tiptap/extension-typography": "^3.31.0",
|
|
106
|
+
"@tiptap/extension-underline": "^3.31.0",
|
|
107
|
+
"@tiptap/extension-youtube": "^3.31.0",
|
|
108
|
+
"@tiptap/extensions": "^3.31.0",
|
|
109
|
+
"@tiptap/pm": "^3.31.0",
|
|
110
|
+
"@tiptap/suggestion": "^3.31.0",
|
|
111
|
+
"@tiptap/vue-3": "^3.31.0",
|
|
112
112
|
"emoji.json": "^16.0.0",
|
|
113
|
-
"highlight.js": "^11.
|
|
113
|
+
"highlight.js": "^11.12.0",
|
|
114
114
|
"linkifyjs": "^4.3.3",
|
|
115
115
|
"lowlight": "^3.3.0"
|
|
116
116
|
},
|
|
@@ -142,11 +142,11 @@
|
|
|
142
142
|
"typescript": "^6.0.3",
|
|
143
143
|
"typescript-eslint": "^8.61.1",
|
|
144
144
|
"unplugin-vue-components": "^32.1.0",
|
|
145
|
-
"vite": "^8.
|
|
145
|
+
"vite": "^8.2.2",
|
|
146
146
|
"vite-plugin-vuetify": "^2.1.3",
|
|
147
|
-
"vite-svg-loader": "^5.1.
|
|
148
|
-
"vitest": "^4.1.
|
|
147
|
+
"vite-svg-loader": "^5.1.3",
|
|
148
|
+
"vitest": "^4.1.11",
|
|
149
149
|
"vue-eslint-parser": "^10.4.1",
|
|
150
|
-
"vue-tsc": "^3.3.
|
|
150
|
+
"vue-tsc": "^3.3.11"
|
|
151
151
|
}
|
|
152
152
|
}
|
|
@@ -92,6 +92,14 @@ function contentChanged() {
|
|
|
92
92
|
emit('content-changed', { html: editor.value?.getHTML(), json: editor.value?.getJSON() })
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
function onContainerClick(event: MouseEvent) {
|
|
96
|
+
if ((event.target as Element).closest('.ProseMirror')) {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
editor.value?.chain().focus().run()
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
const editor: ShallowRef<Editor | undefined> = getTiptapEditor(
|
|
96
104
|
props.content,
|
|
97
105
|
computed(() => props.placeholder || t('content.placeholder')).value,
|
|
@@ -150,7 +158,7 @@ onBeforeUnmount(() => {
|
|
|
150
158
|
|
|
151
159
|
<VProgressLinear v-model="loadingProgress" :color="loadingColor" :height="loadingHeight" :indeterminate="loading" />
|
|
152
160
|
|
|
153
|
-
<div class="pa-2 tiptapify-container resizable" :style="computeResizableHeight">
|
|
161
|
+
<div class="pa-2 tiptapify-container resizable" :style="computeResizableHeight" @click="onContainerClick">
|
|
154
162
|
<MenuFloating v-if="floatingMenu" :variant="variantBtn" :theme="currentTheme" />
|
|
155
163
|
|
|
156
164
|
<MenuBubble v-if="bubbleMenu" :variant="variantBtn" :theme="currentTheme" />
|
|
@@ -197,6 +205,7 @@ onBeforeUnmount(() => {
|
|
|
197
205
|
--yellow: rgba(250, 204, 21, .4);
|
|
198
206
|
--yellow-light: #FFFAE5;
|
|
199
207
|
--red: #FF5C33;
|
|
208
|
+
--red-soft: #B24A40;
|
|
200
209
|
--red-light: #FFEBE5;
|
|
201
210
|
--shadow: 0px 12px 33px 0px rgba(0, 0, 0, .06), 0px 3.618px 9.949px 0px rgba(0, 0, 0, .04);
|
|
202
211
|
--border: 1px solid var(--gray-2);
|
|
@@ -207,6 +216,21 @@ onBeforeUnmount(() => {
|
|
|
207
216
|
overflow: auto;
|
|
208
217
|
}
|
|
209
218
|
|
|
219
|
+
.tiptapify-container {
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.tiptapify-container .tiptapify-editor {
|
|
225
|
+
display: flex;
|
|
226
|
+
flex: 1;
|
|
227
|
+
flex-direction: column;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.tiptapify-container .tiptapify-editor > .ProseMirror {
|
|
231
|
+
flex: 1;
|
|
232
|
+
}
|
|
233
|
+
|
|
210
234
|
/* Basic editor styles */
|
|
211
235
|
.tiptap {
|
|
212
236
|
:first-child {
|
|
@@ -560,4 +584,62 @@ onBeforeUnmount(() => {
|
|
|
560
584
|
}
|
|
561
585
|
}
|
|
562
586
|
}
|
|
587
|
+
|
|
588
|
+
/*
|
|
589
|
+
* Dialog layout primitives.
|
|
590
|
+
*
|
|
591
|
+
* Dialogs lay their fields out with a self-contained 12-column grid instead
|
|
592
|
+
* of VRow/VCol. The bundled Vuetify 3 components emit v3 grid classes
|
|
593
|
+
* (.v-col-*, .v-col-md-*), but Vuetify 4 renamed them (.v-col--cols-*), so
|
|
594
|
+
* the consumer's Vuetify stylesheet does not size the columns and every
|
|
595
|
+
* field collapses onto a single row. Keeping the layout inside tiptapify
|
|
596
|
+
* makes it work with Vuetify 3 and 4 alike, regardless of the CSS the
|
|
597
|
+
* consumer loads.
|
|
598
|
+
*
|
|
599
|
+
* The 960px breakpoint preserves the Vuetify 3 "md" threshold
|
|
600
|
+
* (Vuetify 4 lowered it to 840px).
|
|
601
|
+
*/
|
|
602
|
+
.tiptapify-dialog-grid {
|
|
603
|
+
display: grid;
|
|
604
|
+
gap: 24px;
|
|
605
|
+
grid-template-columns: repeat(12, minmax(0, 1fr));
|
|
606
|
+
|
|
607
|
+
> .tiptapify-dialog-col {
|
|
608
|
+
grid-column: 1 / -1;
|
|
609
|
+
min-width: 0;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
@media (min-width: 960px) {
|
|
613
|
+
> .tiptapify-dialog-col--3 {
|
|
614
|
+
grid-column: span 3;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
> .tiptapify-dialog-col--4 {
|
|
618
|
+
grid-column: span 4;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
> .tiptapify-dialog-col--6 {
|
|
622
|
+
grid-column: span 6;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
> .tiptapify-dialog-col--8 {
|
|
626
|
+
grid-column: span 8;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.tiptapify-dialog-actions {
|
|
632
|
+
display: flex;
|
|
633
|
+
flex-wrap: wrap;
|
|
634
|
+
align-items: center;
|
|
635
|
+
justify-content: space-between;
|
|
636
|
+
gap: 8px 16px;
|
|
637
|
+
|
|
638
|
+
> .tiptapify-dialog-actions__start,
|
|
639
|
+
> .tiptapify-dialog-actions__end {
|
|
640
|
+
display: flex;
|
|
641
|
+
align-items: center;
|
|
642
|
+
gap: 8px;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
563
645
|
</style>
|
|
@@ -178,10 +178,10 @@ Object.keys(props.customExtensions).forEach((key: any) => {
|
|
|
178
178
|
<div v-if="editor" class="tiptapify-toolbar">
|
|
179
179
|
<VToolbar elevation="1" :theme="theme" height="auto" :class="`ps-1 pr-1 rounded-t-${rounded}`">
|
|
180
180
|
<VSlideGroup v-if="toolbarScrollable">
|
|
181
|
-
<Items :items="toolbarItems" />
|
|
181
|
+
<Items :items="toolbarItems" :variant-btn="variantBtn" />
|
|
182
182
|
</VSlideGroup>
|
|
183
183
|
|
|
184
|
-
<Items v-else :items="toolbarItems" />
|
|
184
|
+
<Items v-else :items="toolbarItems" :variant-btn="variantBtn" />
|
|
185
185
|
</VToolbar>
|
|
186
186
|
</div>
|
|
187
187
|
</template>
|
|
@@ -20,9 +20,9 @@ defineProps({
|
|
|
20
20
|
<div class="menu-divider" />
|
|
21
21
|
</template>
|
|
22
22
|
<template v-else>
|
|
23
|
-
<VBtnGroup v-if="item.group" elevation="4">
|
|
23
|
+
<VBtnGroup v-if="item.group" elevation="4" :class="{ 'tiptapify-btn-group--elevated': variantBtn === 'elevated' }">
|
|
24
24
|
<template v-for="sectionItem in item.components" :key="sectionItem.name">
|
|
25
|
-
<component :is="sectionItem.component" v-bind="{ ...sectionItem.props ?? {} }" />
|
|
25
|
+
<component :is="sectionItem.component" v-bind="{ variantBtn, ...sectionItem.props ?? {} }" />
|
|
26
26
|
</template>
|
|
27
27
|
</VBtnGroup>
|
|
28
28
|
<template v-else>
|
|
@@ -40,6 +40,13 @@ defineProps({
|
|
|
40
40
|
</template>
|
|
41
41
|
|
|
42
42
|
<style lang="scss" scoped>
|
|
43
|
+
.tiptapify-btn-group--elevated {
|
|
44
|
+
box-shadow:
|
|
45
|
+
0 3px 1px -2px var(--v-shadow-key-umbra-opacity, rgba(0, 0, 0, 0.2)),
|
|
46
|
+
0 2px 2px 0 var(--v-shadow-key-penumbra-opacity, rgba(0, 0, 0, 0.14)),
|
|
47
|
+
0 1px 5px 0 var(--v-shadow-key-ambient-opacity, rgba(0, 0, 0, 0.12));
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
:deep(.v-btn-group) {
|
|
44
51
|
height: 32px !important;
|
|
45
52
|
}
|
|
@@ -144,7 +144,8 @@ onBeforeUnmount(() => {
|
|
|
144
144
|
<VCard>
|
|
145
145
|
<VCardTitle
|
|
146
146
|
ref="movableHandler"
|
|
147
|
-
|
|
147
|
+
class="tiptapify-dialog-header"
|
|
148
|
+
:class="!fullscreen ? 'tiptapify-movable-handler' : ''"
|
|
148
149
|
style="user-select: none;"
|
|
149
150
|
>
|
|
150
151
|
<VLabel>
|
|
@@ -168,6 +169,11 @@ onBeforeUnmount(() => {
|
|
|
168
169
|
</template>
|
|
169
170
|
|
|
170
171
|
<style lang="scss" scoped>
|
|
172
|
+
.tiptapify-dialog-header {
|
|
173
|
+
align-items: center;
|
|
174
|
+
display: flex;
|
|
175
|
+
}
|
|
176
|
+
|
|
171
177
|
:deep(.v-overlay__content) {
|
|
172
178
|
position: fixed;
|
|
173
179
|
}
|