@zanwaar/tiptap-docs-kit 0.1.0
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/LICENSE +21 -0
- package/README.md +273 -0
- package/dist/extensions/ParagraphSpacing.d.ts +16 -0
- package/dist/extensions/ParagraphSpacing.d.ts.map +1 -0
- package/dist/extensions/ParagraphSpacing.js +64 -0
- package/dist/extensions/ParagraphSpacing.js.map +1 -0
- package/dist/extensions/ResizableImage.d.ts +2 -0
- package/dist/extensions/ResizableImage.d.ts.map +1 -0
- package/dist/extensions/ResizableImage.js +82 -0
- package/dist/extensions/ResizableImage.js.map +1 -0
- package/dist/extensions/TextAlign.d.ts +15 -0
- package/dist/extensions/TextAlign.d.ts.map +1 -0
- package/dist/extensions/TextAlign.js +37 -0
- package/dist/extensions/TextAlign.js.map +1 -0
- package/dist/extensions/TextColor.d.ts +14 -0
- package/dist/extensions/TextColor.d.ts.map +1 -0
- package/dist/extensions/TextColor.js +46 -0
- package/dist/extensions/TextColor.js.map +1 -0
- package/dist/extensions/TextFont.d.ts +14 -0
- package/dist/extensions/TextFont.d.ts.map +1 -0
- package/dist/extensions/TextFont.js +55 -0
- package/dist/extensions/TextFont.js.map +1 -0
- package/dist/extensions/TextSize.d.ts +14 -0
- package/dist/extensions/TextSize.d.ts.map +1 -0
- package/dist/extensions/TextSize.js +57 -0
- package/dist/extensions/TextSize.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +420 -0
- package/dist/index.js.map +1 -0
- package/dist/keyboard.d.ts +3 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +61 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/page-model.d.ts +16 -0
- package/dist/page-model.d.ts.map +1 -0
- package/dist/page-model.js +111 -0
- package/dist/page-model.js.map +1 -0
- package/dist/pagination.d.ts +9 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +497 -0
- package/dist/pagination.js.map +1 -0
- package/dist/paste.d.ts +11 -0
- package/dist/paste.d.ts.map +1 -0
- package/dist/paste.js +122 -0
- package/dist/paste.js.map +1 -0
- package/dist/selection-guard.d.ts +4 -0
- package/dist/selection-guard.d.ts.map +1 -0
- package/dist/selection-guard.js +64 -0
- package/dist/selection-guard.js.map +1 -0
- package/dist/style.css +367 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +75 -0
- package/preview.png +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zanwaar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# tiptap-docs-kit
|
|
2
|
+
|
|
3
|
+
`tiptap-docs-kit` adalah extension kit untuk membangun editor dokumen berbasis Tiptap dengan pengalaman seperti word processor (mirip Google Docs / Microsoft Word). Package ini menggabungkan extension umum, halaman A4/Letter, page break, pagination, alignment, warna teks, ukuran font, line spacing, gambar, dan style dokumen dalam satu tempat.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Tautan
|
|
8
|
+
|
|
9
|
+
- Package (repo utama): https://github.com/zanwaar/tiptap-docs-kit
|
|
10
|
+
- Demo implementasi (playground React): https://github.com/zanwaar/playground-react
|
|
11
|
+
|
|
12
|
+
Jalankan demo secara lokal:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git clone https://github.com/zanwaar/playground-react
|
|
16
|
+
cd playground-react
|
|
17
|
+
npm install
|
|
18
|
+
npm run dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Fitur
|
|
22
|
+
|
|
23
|
+
- `DocsKit` sebagai satu extension bundle untuk editor dokumen.
|
|
24
|
+
- Page model seperti Word/Docs dengan node `page` (A4 & Letter, potret/lanskap).
|
|
25
|
+
- Pengaturan halaman: ukuran kertas, orientasi, dan margin (preset atau kustom per sisi dalam cm).
|
|
26
|
+
- Page break dengan node `pageBreak`.
|
|
27
|
+
- Pagination otomatis untuk menjaga konten antar halaman.
|
|
28
|
+
- Heading (1/2/3) dan Normal text.
|
|
29
|
+
- Text alignment untuk paragraph dan heading.
|
|
30
|
+
- Text color, text font, dan text size (berbasis `pt`).
|
|
31
|
+
- Line spacing (1, 1.15, 1.5, 2) plus spasi sebelum/sesudah paragraf.
|
|
32
|
+
- Gambar yang dapat di-resize (drag handle), mendukung base64.
|
|
33
|
+
- Table editing: insert, add/delete row/column, merge/split cell, resize column, dan grid.
|
|
34
|
+
- Table-aware pagination yang memecah tabel panjang per row dengan header berulang.
|
|
35
|
+
- Paragraf otomatis disisipkan di bawah tabel agar mudah lanjut menulis.
|
|
36
|
+
- CSS dokumen satu file lewat `@zanwaar/tiptap-docs-kit/style.css`.
|
|
37
|
+
- Helper untuk membuat dokumen kosong dan template dokumen.
|
|
38
|
+
|
|
39
|
+
## Instalasi
|
|
40
|
+
|
|
41
|
+
Install dari npm:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install @zanwaar/tiptap-docs-kit @tiptap/core @tiptap/pm @tiptap/starter-kit @tiptap/extension-image @tiptap/extension-table @tiptap/extension-table-cell @tiptap/extension-table-header @tiptap/extension-table-row
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`tiptap-docs-kit` memakai package Tiptap di atas sebagai peer dependencies, jadi pastikan ikut terpasang.
|
|
48
|
+
|
|
49
|
+
Untuk local development di monorepo/playground:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@zanwaar/tiptap-docs-kit": "file:../../packages/tiptap-docs-kit"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Install dependency dari aplikasi consumer:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Penggunaan React
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useEditor } from '@tiptap/react'
|
|
69
|
+
import { DocsKit, createBlankWordPageDocument } from '@zanwaar/tiptap-docs-kit'
|
|
70
|
+
import '@zanwaar/tiptap-docs-kit/style.css'
|
|
71
|
+
|
|
72
|
+
export function Editor() {
|
|
73
|
+
const editor = useEditor({
|
|
74
|
+
extensions: [DocsKit],
|
|
75
|
+
content: createBlankWordPageDocument(),
|
|
76
|
+
editorProps: {
|
|
77
|
+
attributes: {
|
|
78
|
+
class: 'word-editor-document',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
return editor
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Pagination
|
|
88
|
+
|
|
89
|
+
Gunakan `bindWordPagePagination` pada container scroll editor.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import { useEffect, useRef } from 'react'
|
|
93
|
+
import { EditorContent } from '@tiptap/react'
|
|
94
|
+
import type { Editor } from '@tiptap/react'
|
|
95
|
+
import { bindWordPagePagination } from '@zanwaar/tiptap-docs-kit'
|
|
96
|
+
|
|
97
|
+
export function Workspace({ editor }: { editor: Editor | null }) {
|
|
98
|
+
const workspaceRef = useRef<HTMLElement>(null)
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (!editor || !workspaceRef.current) return undefined
|
|
102
|
+
|
|
103
|
+
return bindWordPagePagination(editor, workspaceRef.current)
|
|
104
|
+
}, [editor])
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<main className="workspace" ref={workspaceRef}>
|
|
108
|
+
<EditorContent editor={editor} />
|
|
109
|
+
</main>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Commands
|
|
115
|
+
|
|
116
|
+
Package ini menambahkan beberapa command ke Tiptap.
|
|
117
|
+
|
|
118
|
+
### Page
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
editor.chain().focus().insertPage({ pageType: 'body' }).run()
|
|
122
|
+
editor.chain().focus().setPageAttrs({ paperSize: 'a4', orientation: 'portrait', margin: 'narrow' }).run()
|
|
123
|
+
editor.chain().focus().setPageAttrs({ marginValue: '2cm 1.5cm 1.5cm 1.5cm' }).run()
|
|
124
|
+
editor.chain().focus().insertPageBreak().run()
|
|
125
|
+
editor.chain().focus().insertWordPageTemplate('cover').run()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Text Align
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
editor.chain().focus().setTextAlign('left').run()
|
|
132
|
+
editor.chain().focus().setTextAlign('center').run()
|
|
133
|
+
editor.chain().focus().setTextAlign('right').run()
|
|
134
|
+
editor.chain().focus().setTextAlign('justify').run()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Text Color, Font, Size
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
editor.chain().focus().setTextColor('#063f81').run()
|
|
141
|
+
editor.chain().focus().unsetTextColor().run()
|
|
142
|
+
editor.chain().focus().setTextFont('Roboto, Arial, sans-serif').run()
|
|
143
|
+
editor.chain().focus().setTextSize('11pt').run()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Line Spacing
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
editor.chain().focus().setLineSpacing('1.5').run()
|
|
150
|
+
editor.chain().focus().unsetLineSpacing().run()
|
|
151
|
+
editor.chain().focus().setParagraphSpaceBefore('12pt').run()
|
|
152
|
+
editor.chain().focus().setParagraphSpaceAfter('12pt').run()
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Image
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
// Disisipkan sebagai node image. Bisa base64 atau URL.
|
|
159
|
+
editor.chain().focus().insertContent({ type: 'image', attrs: { src, alt: 'Gambar' } }).run()
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Gambar dapat di-resize dengan menarik handle di pojok kanan bawah. Lebar disimpan pada atribut `width` node image.
|
|
163
|
+
|
|
164
|
+
### Table
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
|
|
168
|
+
editor.chain().focus().insertGrid({ rows: 4, cols: 4 }).run()
|
|
169
|
+
editor.chain().focus().addColumnAfter().run()
|
|
170
|
+
editor.chain().focus().addRowAfter().run()
|
|
171
|
+
editor.chain().focus().deleteColumn().run()
|
|
172
|
+
editor.chain().focus().deleteRow().run()
|
|
173
|
+
editor.chain().focus().deleteTable().run()
|
|
174
|
+
editor.chain().focus().mergeCells().run()
|
|
175
|
+
editor.chain().focus().splitCell().run()
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Tabel panjang akan dipisah antar halaman pada batas row. Jika tabel memiliki header row, header akan diulang pada tabel lanjutan di halaman berikutnya.
|
|
179
|
+
|
|
180
|
+
## Konfigurasi DocsKit
|
|
181
|
+
|
|
182
|
+
`DocsKit` bisa dikonfigurasi per extension.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
DocsKit.configure({
|
|
186
|
+
starterKit: {},
|
|
187
|
+
textAlign: { types: ['paragraph', 'heading'] },
|
|
188
|
+
textColor: {},
|
|
189
|
+
textFont: {},
|
|
190
|
+
textSize: {},
|
|
191
|
+
paragraphSpacing: { types: ['paragraph', 'heading'] },
|
|
192
|
+
table: { resizable: true },
|
|
193
|
+
tableCell: {},
|
|
194
|
+
tableHeader: {},
|
|
195
|
+
tableRow: {},
|
|
196
|
+
page: { pasteAsPlainText: true },
|
|
197
|
+
pageBreak: {},
|
|
198
|
+
image: { inline: false, allowBase64: true },
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Set salah satu opsi ke `false` untuk menonaktifkan extension tersebut.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
DocsKit.configure({
|
|
206
|
+
textColor: false,
|
|
207
|
+
})
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## CSS
|
|
211
|
+
|
|
212
|
+
Import style sekali di aplikasi consumer:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import '@zanwaar/tiptap-docs-kit/style.css'
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Style utama dikontrol melalui CSS variables:
|
|
219
|
+
|
|
220
|
+
```css
|
|
221
|
+
.word-editor-document {
|
|
222
|
+
--word-page-width: 794px;
|
|
223
|
+
--word-page-height: 1123px;
|
|
224
|
+
--word-page-padding: 96px;
|
|
225
|
+
--word-page-text-color: #49454f;
|
|
226
|
+
--word-page-font-family: Roboto, Arial, sans-serif;
|
|
227
|
+
--word-page-font-size: 11pt;
|
|
228
|
+
--word-page-line-height: 1.15;
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Exports
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import {
|
|
236
|
+
DocsKit,
|
|
237
|
+
Page,
|
|
238
|
+
PageBreak,
|
|
239
|
+
Table,
|
|
240
|
+
TableCell,
|
|
241
|
+
TableHeader,
|
|
242
|
+
TableRow,
|
|
243
|
+
TextAlign,
|
|
244
|
+
TextColor,
|
|
245
|
+
TextFont,
|
|
246
|
+
TextSize,
|
|
247
|
+
ParagraphSpacing,
|
|
248
|
+
ResizableImage,
|
|
249
|
+
bindWordPagePagination,
|
|
250
|
+
mergeSplitWordParagraphs,
|
|
251
|
+
normalizeWordPages,
|
|
252
|
+
createBlankWordPageDocument,
|
|
253
|
+
createWordPage,
|
|
254
|
+
createWordPageDocument,
|
|
255
|
+
createWordPageTemplate,
|
|
256
|
+
} from '@zanwaar/tiptap-docs-kit'
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
Jalankan dari folder package:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
npm install
|
|
265
|
+
npm run build
|
|
266
|
+
npm run lint
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Build akan menghasilkan output ke `dist/` dan menyalin `src/style.css` menjadi `dist/style.css`.
|
|
270
|
+
|
|
271
|
+
## Catatan Arsitektur
|
|
272
|
+
|
|
273
|
+
Package ini fokus pada logic Tiptap dan CSS dokumen. UI React seperti toolbar, status bar, sidebar, atau dialog color picker sebaiknya tetap berada di aplikasi consumer atau package React terpisah. Lihat contoh implementasi UI lengkap di https://github.com/zanwaar/playground-react.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
export interface ParagraphSpacingOptions {
|
|
3
|
+
types: string[];
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
paragraphSpacing: {
|
|
8
|
+
setLineSpacing: (lineHeight: string) => ReturnType;
|
|
9
|
+
unsetLineSpacing: () => ReturnType;
|
|
10
|
+
setParagraphSpaceBefore: (spaceBefore: string | null) => ReturnType;
|
|
11
|
+
setParagraphSpaceAfter: (spaceAfter: string | null) => ReturnType;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export declare const ParagraphSpacing: Extension<ParagraphSpacingOptions, any>;
|
|
16
|
+
//# sourceMappingURL=ParagraphSpacing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParagraphSpacing.d.ts","sourceRoot":"","sources":["../../src/extensions/ParagraphSpacing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,gBAAgB,EAAE;YAChB,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,CAAA;YAClD,gBAAgB,EAAE,MAAM,UAAU,CAAA;YAClC,uBAAuB,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,KAAK,UAAU,CAAA;YACnE,sBAAsB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,UAAU,CAAA;SAClE,CAAA;KACF;CACF;AAQD,eAAO,MAAM,gBAAgB,yCA+D3B,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
const updateTextblockAttributes = (commands, types, attributes) => types.some((type) => commands.updateAttributes(type, attributes));
|
|
3
|
+
export const ParagraphSpacing = Extension.create({
|
|
4
|
+
name: 'paragraphSpacing',
|
|
5
|
+
addOptions() {
|
|
6
|
+
return {
|
|
7
|
+
types: ['paragraph', 'heading'],
|
|
8
|
+
};
|
|
9
|
+
},
|
|
10
|
+
addGlobalAttributes() {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
types: this.options.types,
|
|
14
|
+
attributes: {
|
|
15
|
+
lineHeight: {
|
|
16
|
+
default: null,
|
|
17
|
+
parseHTML: (element) => element.style.lineHeight || element.getAttribute('data-line-height'),
|
|
18
|
+
renderHTML: (attributes) => {
|
|
19
|
+
if (!attributes.lineHeight)
|
|
20
|
+
return {};
|
|
21
|
+
return {
|
|
22
|
+
'data-line-height': attributes.lineHeight,
|
|
23
|
+
style: `line-height: ${attributes.lineHeight}`,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
spaceBefore: {
|
|
28
|
+
default: null,
|
|
29
|
+
parseHTML: (element) => element.style.marginTop || element.getAttribute('data-space-before'),
|
|
30
|
+
renderHTML: (attributes) => {
|
|
31
|
+
if (!attributes.spaceBefore)
|
|
32
|
+
return {};
|
|
33
|
+
return {
|
|
34
|
+
'data-space-before': attributes.spaceBefore,
|
|
35
|
+
style: `margin-top: ${attributes.spaceBefore}`,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
spaceAfter: {
|
|
40
|
+
default: null,
|
|
41
|
+
parseHTML: (element) => element.style.marginBottom || element.getAttribute('data-space-after'),
|
|
42
|
+
renderHTML: (attributes) => {
|
|
43
|
+
if (!attributes.spaceAfter)
|
|
44
|
+
return {};
|
|
45
|
+
return {
|
|
46
|
+
'data-space-after': attributes.spaceAfter,
|
|
47
|
+
style: `margin-bottom: ${attributes.spaceAfter}`,
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
},
|
|
55
|
+
addCommands() {
|
|
56
|
+
return {
|
|
57
|
+
setLineSpacing: (lineHeight) => ({ commands }) => updateTextblockAttributes(commands, this.options.types, { lineHeight }),
|
|
58
|
+
unsetLineSpacing: () => ({ commands }) => updateTextblockAttributes(commands, this.options.types, { lineHeight: null }),
|
|
59
|
+
setParagraphSpaceBefore: (spaceBefore) => ({ commands }) => updateTextblockAttributes(commands, this.options.types, { spaceBefore }),
|
|
60
|
+
setParagraphSpaceAfter: (spaceAfter) => ({ commands }) => updateTextblockAttributes(commands, this.options.types, { spaceAfter }),
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=ParagraphSpacing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParagraphSpacing.js","sourceRoot":"","sources":["../../src/extensions/ParagraphSpacing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResizableImage.d.ts","sourceRoot":"","sources":["../../src/extensions/ResizableImage.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,kFA0FzB,CAAA"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import Image from '@tiptap/extension-image';
|
|
2
|
+
export const ResizableImage = Image.extend({
|
|
3
|
+
name: 'image',
|
|
4
|
+
addAttributes() {
|
|
5
|
+
return {
|
|
6
|
+
...this.parent?.(),
|
|
7
|
+
width: {
|
|
8
|
+
default: null,
|
|
9
|
+
parseHTML: (element) => element.getAttribute('width') || element.style.width || null,
|
|
10
|
+
renderHTML: (attributes) => {
|
|
11
|
+
if (!attributes.width)
|
|
12
|
+
return {};
|
|
13
|
+
const width = typeof attributes.width === 'number' ? `${attributes.width}px` : attributes.width;
|
|
14
|
+
return { style: `width: ${width}` };
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
addNodeView() {
|
|
20
|
+
return ({ node, editor, getPos }) => {
|
|
21
|
+
const container = document.createElement('div');
|
|
22
|
+
container.className = 'word-page-image-wrapper';
|
|
23
|
+
const image = document.createElement('img');
|
|
24
|
+
image.src = node.attrs.src ?? '';
|
|
25
|
+
if (node.attrs.alt)
|
|
26
|
+
image.alt = node.attrs.alt;
|
|
27
|
+
if (node.attrs.title)
|
|
28
|
+
image.title = node.attrs.title;
|
|
29
|
+
if (node.attrs.width)
|
|
30
|
+
image.style.width = typeof node.attrs.width === 'number' ? `${node.attrs.width}px` : node.attrs.width;
|
|
31
|
+
image.className = 'word-page-image';
|
|
32
|
+
const handle = document.createElement('span');
|
|
33
|
+
handle.className = 'word-page-image-handle';
|
|
34
|
+
handle.setAttribute('contenteditable', 'false');
|
|
35
|
+
container.append(image, handle);
|
|
36
|
+
const startResize = (event) => {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
event.stopPropagation();
|
|
39
|
+
const startX = event.clientX;
|
|
40
|
+
const startWidth = image.getBoundingClientRect().width;
|
|
41
|
+
const onMouseMove = (moveEvent) => {
|
|
42
|
+
const nextWidth = Math.max(40, Math.round(startWidth + (moveEvent.clientX - startX)));
|
|
43
|
+
image.style.width = `${nextWidth}px`;
|
|
44
|
+
};
|
|
45
|
+
const onMouseUp = () => {
|
|
46
|
+
document.removeEventListener('mousemove', onMouseMove);
|
|
47
|
+
document.removeEventListener('mouseup', onMouseUp);
|
|
48
|
+
if (typeof getPos !== 'function')
|
|
49
|
+
return;
|
|
50
|
+
const position = getPos();
|
|
51
|
+
if (typeof position !== 'number')
|
|
52
|
+
return;
|
|
53
|
+
const finalWidth = Math.round(image.getBoundingClientRect().width);
|
|
54
|
+
editor.view.dispatch(editor.view.state.tr.setNodeMarkup(position, undefined, {
|
|
55
|
+
...node.attrs,
|
|
56
|
+
width: `${finalWidth}px`,
|
|
57
|
+
}));
|
|
58
|
+
};
|
|
59
|
+
document.addEventListener('mousemove', onMouseMove);
|
|
60
|
+
document.addEventListener('mouseup', onMouseUp);
|
|
61
|
+
};
|
|
62
|
+
handle.addEventListener('mousedown', startResize);
|
|
63
|
+
return {
|
|
64
|
+
dom: container,
|
|
65
|
+
update: (updatedNode) => {
|
|
66
|
+
if (updatedNode.type.name !== this.name)
|
|
67
|
+
return false;
|
|
68
|
+
image.src = updatedNode.attrs.src ?? '';
|
|
69
|
+
image.alt = updatedNode.attrs.alt ?? '';
|
|
70
|
+
image.style.width = updatedNode.attrs.width
|
|
71
|
+
? (typeof updatedNode.attrs.width === 'number' ? `${updatedNode.attrs.width}px` : updatedNode.attrs.width)
|
|
72
|
+
: '';
|
|
73
|
+
return true;
|
|
74
|
+
},
|
|
75
|
+
destroy: () => {
|
|
76
|
+
handle.removeEventListener('mousedown', startResize);
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=ResizableImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResizableImage.js","sourceRoot":"","sources":["../../src/extensions/ResizableImage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
type TextAlignment = 'left' | 'center' | 'right' | 'justify';
|
|
3
|
+
interface TextAlignOptions {
|
|
4
|
+
types: string[];
|
|
5
|
+
}
|
|
6
|
+
declare module '@tiptap/core' {
|
|
7
|
+
interface Commands<ReturnType> {
|
|
8
|
+
textAlign: {
|
|
9
|
+
setTextAlign: (alignment: TextAlignment) => ReturnType;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare const TextAlign: Extension<TextAlignOptions, any>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=TextAlign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextAlign.d.ts","sourceRoot":"","sources":["../../src/extensions/TextAlign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAExC,KAAK,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5D,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,SAAS,EAAE;YACT,YAAY,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,UAAU,CAAA;SACvD,CAAA;KACF;CACF;AAED,eAAO,MAAM,SAAS,kCAqCpB,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
export const TextAlign = Extension.create({
|
|
3
|
+
name: 'textAlign',
|
|
4
|
+
addOptions() {
|
|
5
|
+
return {
|
|
6
|
+
types: ['paragraph', 'heading'],
|
|
7
|
+
};
|
|
8
|
+
},
|
|
9
|
+
addGlobalAttributes() {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
types: this.options.types,
|
|
13
|
+
attributes: {
|
|
14
|
+
textAlign: {
|
|
15
|
+
default: null,
|
|
16
|
+
parseHTML: (element) => element.style.textAlign || null,
|
|
17
|
+
renderHTML: (attributes) => {
|
|
18
|
+
if (!attributes.textAlign)
|
|
19
|
+
return {};
|
|
20
|
+
return {
|
|
21
|
+
style: `text-align: ${attributes.textAlign}`,
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
},
|
|
29
|
+
addCommands() {
|
|
30
|
+
return {
|
|
31
|
+
setTextAlign: (alignment) => ({ commands }) => this.options.types
|
|
32
|
+
.map((type) => commands.updateAttributes(type, { textAlign: alignment }))
|
|
33
|
+
.some(Boolean),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=TextAlign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextAlign.js","sourceRoot":"","sources":["../../src/extensions/TextAlign.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAgBxC,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAmB;IAC1D,IAAI,EAAE,WAAW;IAEjB,UAAU;QACR,OAAO;YACL,KAAK,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC;SAChC,CAAA;IACH,CAAC;IAED,mBAAmB;QACjB,OAAO;YACL;gBACE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;gBACzB,UAAU,EAAE;oBACV,SAAS,EAAE;wBACT,OAAO,EAAE,IAAI;wBACb,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,IAAI;wBACvD,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE;4BACzB,IAAI,CAAC,UAAU,CAAC,SAAS;gCAAE,OAAO,EAAE,CAAA;4BAEpC,OAAO;gCACL,KAAK,EAAE,eAAe,UAAU,CAAC,SAAS,EAAE;6BAC7C,CAAA;wBACH,CAAC;qBACF;iBACF;aACF;SACF,CAAA;IACH,CAAC;IAED,WAAW;QACT,OAAO;YACL,YAAY,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;iBAC9D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;iBACxE,IAAI,CAAC,OAAO,CAAC;SACjB,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Mark } from '@tiptap/core';
|
|
2
|
+
export interface TextColorOptions {
|
|
3
|
+
HTMLAttributes: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
textColor: {
|
|
8
|
+
setTextColor: (color: string) => ReturnType;
|
|
9
|
+
unsetTextColor: () => ReturnType;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare const TextColor: Mark<TextColorOptions, any>;
|
|
14
|
+
//# sourceMappingURL=TextColor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextColor.d.ts","sourceRoot":"","sources":["../../src/extensions/TextColor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACxC;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,SAAS,EAAE;YACT,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,UAAU,CAAA;YAC3C,cAAc,EAAE,MAAM,UAAU,CAAA;SACjC,CAAA;KACF;CACF;AAED,eAAO,MAAM,SAAS,6BAgDpB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
export const TextColor = Mark.create({
|
|
3
|
+
name: 'textColor',
|
|
4
|
+
addOptions() {
|
|
5
|
+
return {
|
|
6
|
+
HTMLAttributes: {},
|
|
7
|
+
};
|
|
8
|
+
},
|
|
9
|
+
addAttributes() {
|
|
10
|
+
return {
|
|
11
|
+
color: {
|
|
12
|
+
default: null,
|
|
13
|
+
parseHTML: (element) => element.style.color || element.getAttribute('data-text-color'),
|
|
14
|
+
renderHTML: (attributes) => {
|
|
15
|
+
if (!attributes.color)
|
|
16
|
+
return {};
|
|
17
|
+
return {
|
|
18
|
+
'data-text-color': attributes.color,
|
|
19
|
+
style: `color: ${attributes.color}`,
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
parseHTML() {
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
tag: 'span[data-text-color]',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
style: 'color',
|
|
32
|
+
getAttrs: (color) => (typeof color === 'string' ? { color } : false),
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
},
|
|
36
|
+
renderHTML({ HTMLAttributes }) {
|
|
37
|
+
return ['span', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
38
|
+
},
|
|
39
|
+
addCommands() {
|
|
40
|
+
return {
|
|
41
|
+
setTextColor: (color) => ({ commands }) => commands.setMark(this.name, { color }),
|
|
42
|
+
unsetTextColor: () => ({ commands }) => commands.unsetMark(this.name),
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=TextColor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextColor.js","sourceRoot":"","sources":["../../src/extensions/TextColor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAepD,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAmB;IACrD,IAAI,EAAE,WAAW;IAEjB,UAAU;QACR,OAAO;YACL,cAAc,EAAE,EAAE;SACnB,CAAA;IACH,CAAC;IAED,aAAa;QACX,OAAO;YACL,KAAK,EAAE;gBACL,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC;gBACtF,UAAU,EAAE,CAAC,UAAU,EAAE,EAAE;oBACzB,IAAI,CAAC,UAAU,CAAC,KAAK;wBAAE,OAAO,EAAE,CAAA;oBAEhC,OAAO;wBACL,iBAAiB,EAAE,UAAU,CAAC,KAAK;wBACnC,KAAK,EAAE,UAAU,UAAU,CAAC,KAAK,EAAE;qBACpC,CAAA;gBACH,CAAC;aACF;SACF,CAAA;IACH,CAAC;IAED,SAAS;QACP,OAAO;YACL;gBACE,GAAG,EAAE,uBAAuB;aAC7B;YACD;gBACE,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;aACrE;SACF,CAAA;IACH,CAAC;IAED,UAAU,CAAC,EAAE,cAAc,EAAE;QAC3B,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC,CAAA;IAClF,CAAC;IAED,WAAW;QACT,OAAO;YACL,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC;YACjF,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;SACtE,CAAA;IACH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Mark } from '@tiptap/core';
|
|
2
|
+
export interface TextFontOptions {
|
|
3
|
+
HTMLAttributes: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
textFont: {
|
|
8
|
+
setTextFont: (fontFamily: string) => ReturnType;
|
|
9
|
+
unsetTextFont: () => ReturnType;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export declare const TextFont: Mark<TextFontOptions, any>;
|
|
14
|
+
//# sourceMappingURL=TextFont.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextFont.d.ts","sourceRoot":"","sources":["../../src/extensions/TextFont.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAA;AAEpD,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACxC;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,QAAQ,EAAE;YACR,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,UAAU,CAAA;YAC/C,aAAa,EAAE,MAAM,UAAU,CAAA;SAChC,CAAA;KACF;CACF;AAQD,eAAO,MAAM,QAAQ,4BAsDnB,CAAA"}
|