vue2-bbl-editor 1.3.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/CHANGELOG.md +659 -0
- package/COMPONENT_USAGE_GUIDE.md +2590 -0
- package/CONTENT_WRAPPER_GUIDE.md +385 -0
- package/EXTERNAL_HTML_RENDERING.md +266 -0
- package/EXTERNAL_INTEGRATION_GUIDE.md +833 -0
- package/INSTALLATION.md +282 -0
- package/LICENSE +21 -0
- package/PACKAGE_DOCUMENTATION.md +1386 -0
- package/QUICK_SETUP.md +99 -0
- package/README.md +1694 -0
- package/dist/demo.html +10 -0
- package/dist/vue2-bbl-editor.common.js +24486 -0
- package/dist/vue2-bbl-editor.common.js.map +1 -0
- package/dist/vue2-bbl-editor.css +1 -0
- package/dist/vue2-bbl-editor.umd.js +24497 -0
- package/dist/vue2-bbl-editor.umd.js.map +1 -0
- package/dist/vue2-bbl-editor.umd.min.js +6 -0
- package/dist/vue2-bbl-editor.umd.min.js.map +1 -0
- package/package.json +172 -0
- package/types/index.d.ts +266 -0
package/README.md
ADDED
|
@@ -0,0 +1,1694 @@
|
|
|
1
|
+
# Vue 2 Premium BBL Editor
|
|
2
|
+
|
|
3
|
+
A production-ready, fully configurable rich text editor for Vue 2.6 applications. Built with Tiptap and designed for professional use with extensive customization options and advanced upload management system.
|
|
4
|
+
|
|
5
|
+
## ๐ Features
|
|
6
|
+
|
|
7
|
+
- โ
**Vue 2.6 Compatible** - Full support for Vue 2.6+ applications
|
|
8
|
+
- โ
**Production Ready** - Thoroughly tested and optimized for production use
|
|
9
|
+
- โ
**Fully Configurable** - Extensive props for customizing every aspect
|
|
10
|
+
- โ
**Rich Text Editing** - Complete formatting options (bold, italic, underline, etc.)
|
|
11
|
+
- โ
**Advanced Media** - Resizable images and videos with upload support
|
|
12
|
+
- โ
**Smart Tables** - Interactive tables with cell controls and resizing
|
|
13
|
+
- โ
**Upload Management** - Comprehensive upload system with multiple adapters
|
|
14
|
+
- โ
**Multiple Themes** - Default, minimal, and dark themes included
|
|
15
|
+
- โ
**TypeScript Support** - Full TypeScript definitions included
|
|
16
|
+
- โ
**Accessibility** - WCAG compliant with keyboard navigation
|
|
17
|
+
- โ
**Auto-save** - Built-in auto-save functionality
|
|
18
|
+
- โ
**Source Code View** - Toggle between visual and HTML source editing
|
|
19
|
+
- โ
**External Integration** - Easy integration with existing projects
|
|
20
|
+
|
|
21
|
+
## ๐ฆ Installation
|
|
22
|
+
|
|
23
|
+
### NPM Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install vue2-bbl-editor
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### CDN for HTML Output Styling
|
|
30
|
+
|
|
31
|
+
For rendering editor HTML content in external projects (React, Vue, Angular, etc.), use the CDN:
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<!-- Global CDN styles for HTML output rendering -->
|
|
35
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue2-bbl-editor/dist/editor-content.css" />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then wrap your editor HTML content with the `.bbl-html-section` class:
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<div class="bbl-html-section">
|
|
42
|
+
<!-- Your editor HTML content here -->
|
|
43
|
+
</div>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
See [External HTML Rendering Guide](EXTERNAL_HTML_RENDERING.md) for detailed usage in different frameworks.
|
|
47
|
+
|
|
48
|
+
### PREVIEW
|
|
49
|
+
|
|
50
|
+
<img src="https://github.com/kazi-shahin/vue2-bbl-editor/blob/main/public/preview.png?raw=true" style="width: 100%"/>
|
|
51
|
+
|
|
52
|
+
## ๐ฏ Quick Start
|
|
53
|
+
|
|
54
|
+
### Global Registration (Recommended)
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import Vue from 'vue'
|
|
58
|
+
import PremiumBblEditor from 'vue2-bbl-editor'
|
|
59
|
+
|
|
60
|
+
// Register globally
|
|
61
|
+
Vue.use(PremiumBblEditor)
|
|
62
|
+
|
|
63
|
+
// Or register with options
|
|
64
|
+
Vue.use(PremiumBblEditor, {
|
|
65
|
+
registerAllComponents: true // Registers all sub-components globally
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### HTML Output with CDN Styling
|
|
70
|
+
|
|
71
|
+
The editor automatically wraps HTML output with the `bbl-html-section` class for CDN styling compatibility:
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// HTML output is automatically wrapped
|
|
75
|
+
const htmlContent = this.$refs.editor.getContent()
|
|
76
|
+
// Returns: <div class="bbl-html-section">...your content...</div>
|
|
77
|
+
|
|
78
|
+
// To get unwrapped content
|
|
79
|
+
const unwrappedContent = this.$refs.editor.getContent('html', false)
|
|
80
|
+
// Returns: ...your content...
|
|
81
|
+
|
|
82
|
+
// Control wrapping via prop
|
|
83
|
+
<PremiumBblEditor
|
|
84
|
+
:wrap-with-content-class="false"
|
|
85
|
+
v-model="content"
|
|
86
|
+
/>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Component Registration
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// Composition API version (requires @vue/composition-api)
|
|
93
|
+
import { PremiumBblEditor } from 'vue2-bbl-editor'
|
|
94
|
+
|
|
95
|
+
// Options API version (pure Vue 2)
|
|
96
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
97
|
+
|
|
98
|
+
export default {
|
|
99
|
+
components: {
|
|
100
|
+
PremiumBblEditor,
|
|
101
|
+
// or
|
|
102
|
+
PremiumBblEditorOptionsAPI
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Basic Usage
|
|
108
|
+
|
|
109
|
+
#### Composition API Version
|
|
110
|
+
|
|
111
|
+
```vue
|
|
112
|
+
<template>
|
|
113
|
+
<div>
|
|
114
|
+
<PremiumBblEditor
|
|
115
|
+
v-model="content"
|
|
116
|
+
placeholder="Start writing your content..."
|
|
117
|
+
@input="handleInput"
|
|
118
|
+
@ready="handleReady"
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
</template>
|
|
122
|
+
|
|
123
|
+
<script>
|
|
124
|
+
export default {
|
|
125
|
+
data() {
|
|
126
|
+
return {
|
|
127
|
+
content: '<p>Hello World!</p>'
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
methods: {
|
|
131
|
+
handleInput(content) {
|
|
132
|
+
console.log('Content updated:', content)
|
|
133
|
+
},
|
|
134
|
+
handleReady(editor) {
|
|
135
|
+
console.log('Editor is ready:', editor)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
</script>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Options API Version
|
|
143
|
+
|
|
144
|
+
```vue
|
|
145
|
+
<template>
|
|
146
|
+
<div>
|
|
147
|
+
<PremiumBblEditorOptionsAPI
|
|
148
|
+
v-model="content"
|
|
149
|
+
placeholder="Start writing your content..."
|
|
150
|
+
@input="handleInput"
|
|
151
|
+
@ready="handleReady"
|
|
152
|
+
/>
|
|
153
|
+
</div>
|
|
154
|
+
</template>
|
|
155
|
+
|
|
156
|
+
<script>
|
|
157
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
158
|
+
|
|
159
|
+
export default {
|
|
160
|
+
components: {
|
|
161
|
+
PremiumBblEditorOptionsAPI
|
|
162
|
+
},
|
|
163
|
+
data() {
|
|
164
|
+
return {
|
|
165
|
+
content: '<p>Hello World with Options API!</p>'
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
methods: {
|
|
169
|
+
handleInput(content) {
|
|
170
|
+
console.log('Content updated:', content)
|
|
171
|
+
},
|
|
172
|
+
handleReady(editor) {
|
|
173
|
+
console.log('Options API Editor is ready:', editor)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
</script>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## ๐ Complete Component API
|
|
181
|
+
|
|
182
|
+
### Props
|
|
183
|
+
|
|
184
|
+
#### Content & Basic Configuration
|
|
185
|
+
|
|
186
|
+
| Prop | Type | Default | Description |
|
|
187
|
+
|------|------|---------|-------------|
|
|
188
|
+
| `value` | String | `''` | Editor content (v-model) |
|
|
189
|
+
| `placeholder` | String | `'Start writing...'` | Placeholder text when editor is empty |
|
|
190
|
+
| `editable` | Boolean | `true` | Whether editor content can be modified |
|
|
191
|
+
| `outputFormat` | String | `'html'` | Output format: 'html' or 'json' |
|
|
192
|
+
| `autofocus` | Boolean | `false` | Auto-focus editor on mount |
|
|
193
|
+
| `spellcheck` | Boolean | `true` | Enable browser spellcheck |
|
|
194
|
+
|
|
195
|
+
#### Layout & Appearance
|
|
196
|
+
|
|
197
|
+
| Prop | Type | Default | Description |
|
|
198
|
+
|------|------|---------|-------------|
|
|
199
|
+
| `maxHeight` | String/Number | `null` | Maximum editor height (px or CSS value) |
|
|
200
|
+
| `minHeight` | String/Number | `200` | Minimum editor height (px or CSS value) |
|
|
201
|
+
| `theme` | String | `'default'` | Theme: 'default', 'minimal', 'dark' |
|
|
202
|
+
| `editorClass` | String/Array/Object | `''` | Custom CSS classes for editor container |
|
|
203
|
+
| `toolbarClass` | String/Array/Object | `''` | Custom CSS classes for toolbar |
|
|
204
|
+
| `contentClass` | String/Array/Object | `''` | Custom CSS classes for content area |
|
|
205
|
+
|
|
206
|
+
#### UI Component Visibility
|
|
207
|
+
|
|
208
|
+
| Prop | Type | Default | Description |
|
|
209
|
+
|------|------|---------|-------------|
|
|
210
|
+
| `showToolbar` | Boolean | `true` | Show/hide main toolbar |
|
|
211
|
+
| `showBubbleMenu` | Boolean | `true` | Show/hide text selection bubble menu |
|
|
212
|
+
| `showTableBubbleMenu` | Boolean | `true` | Show/hide table-specific bubble menu |
|
|
213
|
+
| `showImageBubbleMenu` | Boolean | `true` | Show/hide image-specific bubble menu |
|
|
214
|
+
| `showVideoBubbleMenu` | Boolean | `true` | Show/hide video-specific bubble menu |
|
|
215
|
+
|
|
216
|
+
#### Toolbar Configuration
|
|
217
|
+
|
|
218
|
+
| Prop | Type | Default | Description |
|
|
219
|
+
|------|------|---------|-------------|
|
|
220
|
+
| `toolbarConfig` | Object | See below | Configure which toolbar buttons to show |
|
|
221
|
+
|
|
222
|
+
**Default Toolbar Configuration:**
|
|
223
|
+
```javascript
|
|
224
|
+
{
|
|
225
|
+
// Text formatting
|
|
226
|
+
bold: true,
|
|
227
|
+
italic: true,
|
|
228
|
+
underline: true,
|
|
229
|
+
strike: true,
|
|
230
|
+
code: true,
|
|
231
|
+
|
|
232
|
+
// Text styling
|
|
233
|
+
textColor: true,
|
|
234
|
+
highlight: true,
|
|
235
|
+
fontFamily: true,
|
|
236
|
+
fontSize: true,
|
|
237
|
+
|
|
238
|
+
// Alignment and spacing
|
|
239
|
+
textAlign: true,
|
|
240
|
+
lineHeight: true,
|
|
241
|
+
|
|
242
|
+
// Structure
|
|
243
|
+
headings: true,
|
|
244
|
+
lists: true,
|
|
245
|
+
blockquote: true,
|
|
246
|
+
codeBlock: true,
|
|
247
|
+
horizontalRule: true,
|
|
248
|
+
|
|
249
|
+
// Media
|
|
250
|
+
link: true,
|
|
251
|
+
image: true,
|
|
252
|
+
video: true,
|
|
253
|
+
table: true,
|
|
254
|
+
|
|
255
|
+
// Utilities
|
|
256
|
+
clearFormatting: true,
|
|
257
|
+
sourceCode: true,
|
|
258
|
+
undo: true,
|
|
259
|
+
redo: true
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Extension Configuration
|
|
264
|
+
|
|
265
|
+
| Prop | Type | Default | Description |
|
|
266
|
+
|------|------|---------|-------------|
|
|
267
|
+
| `extensionConfig` | Object | See below | Configure extension behavior |
|
|
268
|
+
|
|
269
|
+
**Default Extension Configuration:**
|
|
270
|
+
```javascript
|
|
271
|
+
{
|
|
272
|
+
image: {
|
|
273
|
+
allowResize: true,
|
|
274
|
+
allowAlignment: true,
|
|
275
|
+
allowDelete: true,
|
|
276
|
+
maxWidth: '100%',
|
|
277
|
+
quality: 0.8
|
|
278
|
+
},
|
|
279
|
+
video: {
|
|
280
|
+
allowResize: true,
|
|
281
|
+
allowAlignment: true,
|
|
282
|
+
allowDelete: true,
|
|
283
|
+
maxWidth: '100%',
|
|
284
|
+
autoplay: false
|
|
285
|
+
},
|
|
286
|
+
table: {
|
|
287
|
+
resizable: true,
|
|
288
|
+
allowRowControls: true,
|
|
289
|
+
allowColumnControls: true,
|
|
290
|
+
cellSelection: true
|
|
291
|
+
},
|
|
292
|
+
link: {
|
|
293
|
+
openOnClick: false,
|
|
294
|
+
autolink: true,
|
|
295
|
+
linkOnPaste: true
|
|
296
|
+
},
|
|
297
|
+
textAlign: {
|
|
298
|
+
types: ['heading', 'paragraph']
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### Upload & Media Handling
|
|
304
|
+
|
|
305
|
+
| Prop | Type | Default | Description |
|
|
306
|
+
|------|------|---------|-------------|
|
|
307
|
+
| `uploadHandler` | Function | `null` | Custom upload handler function |
|
|
308
|
+
| `imageUploadUrl` | String | `null` | URL endpoint for image uploads |
|
|
309
|
+
| `videoUploadUrl` | String | `null` | URL endpoint for video uploads |
|
|
310
|
+
| `maxFileSize` | Number | `10485760` | Maximum file size in bytes (10MB) |
|
|
311
|
+
| `allowedImageTypes` | Array | `['image/jpeg', 'image/png', 'image/gif', 'image/webp']` | Allowed image MIME types |
|
|
312
|
+
| `allowedVideoTypes` | Array | `['video/mp4', 'video/webm', 'video/ogg']` | Allowed video MIME types |
|
|
313
|
+
|
|
314
|
+
#### Local File Base64 Management
|
|
315
|
+
|
|
316
|
+
| Prop | Type | Default | Description |
|
|
317
|
+
|------|------|---------|-------------|
|
|
318
|
+
| `useBase64Upload` | Boolean | `false` | Force base64 conversion even when upload URLs are provided |
|
|
319
|
+
| `base64Quality` | Number | `0.8` | Image compression quality (0.1 - 1.0) |
|
|
320
|
+
| `base64MaxWidth` | Number | `1920` | Maximum width for compressed images (px) |
|
|
321
|
+
| `base64MaxHeight` | Number | `1080` | Maximum height for compressed images (px) |
|
|
322
|
+
| `enableImageCompression` | Boolean | `true` | Enable automatic image compression |
|
|
323
|
+
| `preserveOriginalFileName` | Boolean | `true` | Preserve original file names in alt text |
|
|
324
|
+
| `base64Prefix` | String | `'data:'` | Custom prefix for base64 data URLs |
|
|
325
|
+
|
|
326
|
+
#### Content Restrictions
|
|
327
|
+
|
|
328
|
+
| Prop | Type | Default | Description |
|
|
329
|
+
|------|------|---------|-------------|
|
|
330
|
+
| `maxContentLength` | Number | `null` | Maximum content length in characters |
|
|
331
|
+
| `allowedHeadings` | Array | `[1, 2, 3, 4, 5, 6]` | Allowed heading levels |
|
|
332
|
+
|
|
333
|
+
#### Styling Options
|
|
334
|
+
|
|
335
|
+
| Prop | Type | Default | Description |
|
|
336
|
+
|------|------|---------|-------------|
|
|
337
|
+
| `fontFamilies` | Array | See below | Available font families |
|
|
338
|
+
| `fontSizes` | Array | See below | Available font sizes |
|
|
339
|
+
| `lineHeights` | Array | See below | Available line heights |
|
|
340
|
+
|
|
341
|
+
**Default Font Options:**
|
|
342
|
+
```javascript
|
|
343
|
+
// Font Families
|
|
344
|
+
['Inter', 'Arial', 'Helvetica', 'Times New Roman', 'Georgia', 'Courier New', 'Monaco', 'Menlo']
|
|
345
|
+
|
|
346
|
+
// Font Sizes
|
|
347
|
+
['12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px']
|
|
348
|
+
|
|
349
|
+
// Line Heights
|
|
350
|
+
['1', '1.2', '1.4', '1.6', '1.8', '2', '2.5', '3']
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### Auto-save Configuration
|
|
354
|
+
|
|
355
|
+
| Prop | Type | Default | Description |
|
|
356
|
+
|------|------|---------|-------------|
|
|
357
|
+
| `autoSave` | Boolean | `false` | Enable automatic content saving |
|
|
358
|
+
| `autoSaveInterval` | Number | `30000` | Auto-save interval in milliseconds |
|
|
359
|
+
|
|
360
|
+
### Events
|
|
361
|
+
|
|
362
|
+
| Event | Payload | Description |
|
|
363
|
+
|-------|---------|-------------|
|
|
364
|
+
| `input` | `content: string` | Emitted when content changes (v-model) |
|
|
365
|
+
| `update` | `content: string` | Emitted when content updates |
|
|
366
|
+
| `ready` | `editor: Editor` | Emitted when editor is ready for use |
|
|
367
|
+
| `created` | `editor: Editor` | Emitted when editor instance is created |
|
|
368
|
+
| `focus` | - | Emitted when editor gains focus |
|
|
369
|
+
| `blur` | - | Emitted when editor loses focus |
|
|
370
|
+
| `destroyed` | - | Emitted when editor is destroyed |
|
|
371
|
+
| `auto-save` | `content: string` | Emitted during auto-save |
|
|
372
|
+
| `content-limit-exceeded` | `{current: number, max: number}` | Emitted when content exceeds limit |
|
|
373
|
+
| `image-compressed` | `{originalSize: number, compressedSize: number, originalDimensions: object, compressedDimensions: object, compressionRatio: number}` | Emitted when image is compressed |
|
|
374
|
+
| `error` | `{type: string, message: string, ...}` | Emitted when errors occur |
|
|
375
|
+
|
|
376
|
+
### Methods
|
|
377
|
+
|
|
378
|
+
Access editor methods via template ref:
|
|
379
|
+
|
|
380
|
+
```vue
|
|
381
|
+
<template>
|
|
382
|
+
<PremiumBblEditor
|
|
383
|
+
ref="editor"
|
|
384
|
+
v-model="content"
|
|
385
|
+
/>
|
|
386
|
+
</template>
|
|
387
|
+
|
|
388
|
+
<script>
|
|
389
|
+
export default {
|
|
390
|
+
methods: {
|
|
391
|
+
focusEditor() {
|
|
392
|
+
this.$refs.editor.focus()
|
|
393
|
+
},
|
|
394
|
+
getContent() {
|
|
395
|
+
return this.$refs.editor.getContent()
|
|
396
|
+
},
|
|
397
|
+
setContent(content) {
|
|
398
|
+
this.$refs.editor.setContent(content)
|
|
399
|
+
},
|
|
400
|
+
executeCommand(command, options) {
|
|
401
|
+
this.$refs.editor.executeCommand(command, options)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
</script>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
**Available Methods:**
|
|
409
|
+
- `focus()` - Focus the editor
|
|
410
|
+
- `blur()` - Blur the editor
|
|
411
|
+
- `getContent(format?)` - Get editor content ('html' or 'json')
|
|
412
|
+
- `setContent(content, emitUpdate?)` - Set editor content
|
|
413
|
+
- `executeCommand(command, options?)` - Execute editor command
|
|
414
|
+
|
|
415
|
+
## ๐ก Usage Examples
|
|
416
|
+
|
|
417
|
+
### 1. Basic Editor
|
|
418
|
+
|
|
419
|
+
#### Composition API Version
|
|
420
|
+
```vue
|
|
421
|
+
<template>
|
|
422
|
+
<PremiumBblEditor
|
|
423
|
+
v-model="content"
|
|
424
|
+
placeholder="Start writing..."
|
|
425
|
+
@input="handleInput"
|
|
426
|
+
@ready="handleReady"
|
|
427
|
+
/>
|
|
428
|
+
</template>
|
|
429
|
+
|
|
430
|
+
<script>
|
|
431
|
+
export default {
|
|
432
|
+
data() {
|
|
433
|
+
return {
|
|
434
|
+
content: '<p>Hello World!</p>'
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
methods: {
|
|
438
|
+
handleInput(content) {
|
|
439
|
+
console.log('Content updated:', content)
|
|
440
|
+
},
|
|
441
|
+
handleReady(editor) {
|
|
442
|
+
console.log('Editor is ready:', editor)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
</script>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### Options API Version
|
|
450
|
+
```vue
|
|
451
|
+
<template>
|
|
452
|
+
<PremiumBblEditorOptionsAPI
|
|
453
|
+
v-model="content"
|
|
454
|
+
placeholder="Start writing..."
|
|
455
|
+
@input="handleInput"
|
|
456
|
+
@ready="handleReady"
|
|
457
|
+
/>
|
|
458
|
+
</template>
|
|
459
|
+
|
|
460
|
+
<script>
|
|
461
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
462
|
+
|
|
463
|
+
export default {
|
|
464
|
+
components: {
|
|
465
|
+
PremiumBblEditorOptionsAPI
|
|
466
|
+
},
|
|
467
|
+
data() {
|
|
468
|
+
return {
|
|
469
|
+
content: '<p>Hello World with Options API!</p>'
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
methods: {
|
|
473
|
+
handleInput(content) {
|
|
474
|
+
console.log('Content updated:', content)
|
|
475
|
+
},
|
|
476
|
+
handleReady(editor) {
|
|
477
|
+
console.log('Options API Editor is ready:', editor)
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
</script>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
### 2. Minimal Configuration
|
|
485
|
+
|
|
486
|
+
#### Composition API Version
|
|
487
|
+
```vue
|
|
488
|
+
<template>
|
|
489
|
+
<PremiumBblEditor
|
|
490
|
+
v-model="content"
|
|
491
|
+
theme="minimal"
|
|
492
|
+
:toolbar-config="{
|
|
493
|
+
bold: true,
|
|
494
|
+
italic: true,
|
|
495
|
+
underline: true,
|
|
496
|
+
link: true,
|
|
497
|
+
lists: true,
|
|
498
|
+
undo: true,
|
|
499
|
+
redo: true
|
|
500
|
+
}"
|
|
501
|
+
placeholder="Minimal editor..."
|
|
502
|
+
/>
|
|
503
|
+
</template>
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
#### Options API Version
|
|
507
|
+
```vue
|
|
508
|
+
<template>
|
|
509
|
+
<PremiumBblEditorOptionsAPI
|
|
510
|
+
v-model="content"
|
|
511
|
+
theme="minimal"
|
|
512
|
+
:toolbar-config="minimalToolbarConfig"
|
|
513
|
+
placeholder="Minimal editor with Options API..."
|
|
514
|
+
/>
|
|
515
|
+
</template>
|
|
516
|
+
|
|
517
|
+
<script>
|
|
518
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
519
|
+
|
|
520
|
+
export default {
|
|
521
|
+
components: {
|
|
522
|
+
PremiumBblEditorOptionsAPI
|
|
523
|
+
},
|
|
524
|
+
data() {
|
|
525
|
+
return {
|
|
526
|
+
content: '<p>This is a minimal editor with limited features.</p>',
|
|
527
|
+
minimalToolbarConfig: {
|
|
528
|
+
bold: true,
|
|
529
|
+
italic: true,
|
|
530
|
+
underline: true,
|
|
531
|
+
link: true,
|
|
532
|
+
lists: true,
|
|
533
|
+
undo: true,
|
|
534
|
+
redo: true
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
</script>
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 3. Advanced Configuration with Upload
|
|
543
|
+
|
|
544
|
+
#### Composition API Version
|
|
545
|
+
```vue
|
|
546
|
+
<template>
|
|
547
|
+
<PremiumBblEditor
|
|
548
|
+
v-model="content"
|
|
549
|
+
:max-height="400"
|
|
550
|
+
:auto-save="true"
|
|
551
|
+
:auto-save-interval="15000"
|
|
552
|
+
:upload-handler="customUploadHandler"
|
|
553
|
+
:font-families="['Inter', 'Arial', 'Georgia']"
|
|
554
|
+
:extension-config="{
|
|
555
|
+
image: {
|
|
556
|
+
allowResize: true,
|
|
557
|
+
maxWidth: '800px'
|
|
558
|
+
},
|
|
559
|
+
table: {
|
|
560
|
+
resizable: true,
|
|
561
|
+
cellSelection: true
|
|
562
|
+
}
|
|
563
|
+
}"
|
|
564
|
+
@auto-save="handleAutoSave"
|
|
565
|
+
@ready="handleReady"
|
|
566
|
+
/>
|
|
567
|
+
</template>
|
|
568
|
+
|
|
569
|
+
<script>
|
|
570
|
+
export default {
|
|
571
|
+
data() {
|
|
572
|
+
return {
|
|
573
|
+
content: '<h2>Advanced Editor</h2><p>With custom upload handling...</p>'
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
methods: {
|
|
577
|
+
async customUploadHandler(file) {
|
|
578
|
+
const formData = new FormData()
|
|
579
|
+
formData.append('file', file)
|
|
580
|
+
|
|
581
|
+
const response = await fetch('/api/upload', {
|
|
582
|
+
method: 'POST',
|
|
583
|
+
body: formData
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
const data = await response.json()
|
|
587
|
+
return { src: data.url, alt: file.name }
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
handleAutoSave(content) {
|
|
591
|
+
// Save to your backend
|
|
592
|
+
this.saveToServer(content)
|
|
593
|
+
},
|
|
594
|
+
|
|
595
|
+
handleReady(editor) {
|
|
596
|
+
console.log('Editor ready with advanced features')
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
</script>
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### Options API Version
|
|
604
|
+
```vue
|
|
605
|
+
<template>
|
|
606
|
+
<PremiumBblEditorOptionsAPI
|
|
607
|
+
v-model="content"
|
|
608
|
+
:max-height="maxHeight"
|
|
609
|
+
:auto-save="autoSave"
|
|
610
|
+
:auto-save-interval="autoSaveInterval"
|
|
611
|
+
:upload-handler="customUploadHandler"
|
|
612
|
+
:font-families="fontFamilies"
|
|
613
|
+
:extension-config="extensionConfig"
|
|
614
|
+
@auto-save="handleAutoSave"
|
|
615
|
+
@ready="handleReady"
|
|
616
|
+
/>
|
|
617
|
+
</template>
|
|
618
|
+
|
|
619
|
+
<script>
|
|
620
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
621
|
+
|
|
622
|
+
export default {
|
|
623
|
+
components: {
|
|
624
|
+
PremiumBblEditorOptionsAPI
|
|
625
|
+
},
|
|
626
|
+
data() {
|
|
627
|
+
return {
|
|
628
|
+
content: '<h2>Advanced Options API Editor</h2><p>With comprehensive configuration...</p>',
|
|
629
|
+
maxHeight: 400,
|
|
630
|
+
autoSave: true,
|
|
631
|
+
autoSaveInterval: 15000,
|
|
632
|
+
fontFamilies: ['Inter', 'Arial', 'Georgia'],
|
|
633
|
+
extensionConfig: {
|
|
634
|
+
image: {
|
|
635
|
+
allowResize: true,
|
|
636
|
+
maxWidth: '800px',
|
|
637
|
+
quality: 0.9
|
|
638
|
+
},
|
|
639
|
+
table: {
|
|
640
|
+
resizable: true,
|
|
641
|
+
cellSelection: true,
|
|
642
|
+
allowRowControls: true
|
|
643
|
+
},
|
|
644
|
+
link: {
|
|
645
|
+
autolink: true,
|
|
646
|
+
linkOnPaste: true
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
},
|
|
651
|
+
methods: {
|
|
652
|
+
async customUploadHandler(file) {
|
|
653
|
+
try {
|
|
654
|
+
const formData = new FormData()
|
|
655
|
+
formData.append('file', file)
|
|
656
|
+
|
|
657
|
+
const response = await fetch('/api/upload', {
|
|
658
|
+
method: 'POST',
|
|
659
|
+
headers: {
|
|
660
|
+
'Authorization': `Bearer ${this.getAuthToken()}`
|
|
661
|
+
},
|
|
662
|
+
body: formData
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
if (!response.ok) {
|
|
666
|
+
throw new Error(`Upload failed: ${response.statusText}`)
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
const data = await response.json()
|
|
670
|
+
return {
|
|
671
|
+
src: data.url,
|
|
672
|
+
alt: file.name,
|
|
673
|
+
width: data.width,
|
|
674
|
+
height: data.height
|
|
675
|
+
}
|
|
676
|
+
} catch (error) {
|
|
677
|
+
console.error('Upload error:', error)
|
|
678
|
+
throw error
|
|
679
|
+
}
|
|
680
|
+
},
|
|
681
|
+
|
|
682
|
+
handleAutoSave(content) {
|
|
683
|
+
console.log('Auto-saving content...')
|
|
684
|
+
this.saveToServer(content)
|
|
685
|
+
},
|
|
686
|
+
|
|
687
|
+
handleReady(editor) {
|
|
688
|
+
console.log('Options API Editor ready with advanced features')
|
|
689
|
+
// Store editor reference for later use
|
|
690
|
+
this.editor = editor
|
|
691
|
+
},
|
|
692
|
+
|
|
693
|
+
async saveToServer(content) {
|
|
694
|
+
try {
|
|
695
|
+
await fetch('/api/save', {
|
|
696
|
+
method: 'POST',
|
|
697
|
+
headers: {
|
|
698
|
+
'Content-Type': 'application/json',
|
|
699
|
+
'Authorization': `Bearer ${this.getAuthToken()}`
|
|
700
|
+
},
|
|
701
|
+
body: JSON.stringify({ content })
|
|
702
|
+
})
|
|
703
|
+
console.log('Content saved successfully')
|
|
704
|
+
} catch (error) {
|
|
705
|
+
console.error('Save failed:', error)
|
|
706
|
+
}
|
|
707
|
+
},
|
|
708
|
+
|
|
709
|
+
getAuthToken() {
|
|
710
|
+
return localStorage.getItem('authToken') || ''
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
</script>
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### 4. Read-only Display
|
|
718
|
+
|
|
719
|
+
#### Composition API Version
|
|
720
|
+
```vue
|
|
721
|
+
<template>
|
|
722
|
+
<PremiumBblEditor
|
|
723
|
+
v-model="content"
|
|
724
|
+
:editable="false"
|
|
725
|
+
:show-toolbar="false"
|
|
726
|
+
:show-bubble-menu="false"
|
|
727
|
+
/>
|
|
728
|
+
</template>
|
|
729
|
+
|
|
730
|
+
<script>
|
|
731
|
+
export default {
|
|
732
|
+
data() {
|
|
733
|
+
return {
|
|
734
|
+
content: `
|
|
735
|
+
<h3>Read-only Content</h3>
|
|
736
|
+
<p>This content is displayed in <strong>read-only mode</strong>.</p>
|
|
737
|
+
<blockquote>
|
|
738
|
+
<p>Perfect for displaying formatted content without editing capabilities.</p>
|
|
739
|
+
</blockquote>
|
|
740
|
+
`
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
</script>
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
#### Options API Version
|
|
748
|
+
```vue
|
|
749
|
+
<template>
|
|
750
|
+
<PremiumBblEditorOptionsAPI
|
|
751
|
+
v-model="content"
|
|
752
|
+
:editable="editable"
|
|
753
|
+
:show-toolbar="showToolbar"
|
|
754
|
+
:show-bubble-menu="showBubbleMenu"
|
|
755
|
+
:show-table-bubble-menu="showTableBubbleMenu"
|
|
756
|
+
:show-image-bubble-menu="showImageBubbleMenu"
|
|
757
|
+
:show-video-bubble-menu="showVideoBubbleMenu"
|
|
758
|
+
/>
|
|
759
|
+
</template>
|
|
760
|
+
|
|
761
|
+
<script>
|
|
762
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
763
|
+
|
|
764
|
+
export default {
|
|
765
|
+
components: {
|
|
766
|
+
PremiumBblEditorOptionsAPI
|
|
767
|
+
},
|
|
768
|
+
data() {
|
|
769
|
+
return {
|
|
770
|
+
content: `
|
|
771
|
+
<h3>Read-only Content (Options API)</h3>
|
|
772
|
+
<p>This content is displayed in <strong>read-only mode</strong> using Options API.</p>
|
|
773
|
+
<blockquote>
|
|
774
|
+
<p>Perfect for displaying formatted content without editing capabilities.</p>
|
|
775
|
+
</blockquote>
|
|
776
|
+
<ul>
|
|
777
|
+
<li>No toolbar visible</li>
|
|
778
|
+
<li>No bubble menus</li>
|
|
779
|
+
<li>Content cannot be modified</li>
|
|
780
|
+
</ul>
|
|
781
|
+
`,
|
|
782
|
+
editable: false,
|
|
783
|
+
showToolbar: false,
|
|
784
|
+
showBubbleMenu: false,
|
|
785
|
+
showTableBubbleMenu: false,
|
|
786
|
+
showImageBubbleMenu: false,
|
|
787
|
+
showVideoBubbleMenu: false
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
</script>
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### 5. Custom Styling & Dark Theme
|
|
795
|
+
|
|
796
|
+
#### Composition API Version
|
|
797
|
+
```vue
|
|
798
|
+
<template>
|
|
799
|
+
<PremiumBblEditor
|
|
800
|
+
v-model="content"
|
|
801
|
+
theme="dark"
|
|
802
|
+
editor-class="custom-editor"
|
|
803
|
+
toolbar-class="custom-toolbar"
|
|
804
|
+
content-class="custom-content"
|
|
805
|
+
placeholder="Dark themed editor..."
|
|
806
|
+
/>
|
|
807
|
+
</template>
|
|
808
|
+
|
|
809
|
+
<style>
|
|
810
|
+
.custom-editor {
|
|
811
|
+
border-radius: 12px;
|
|
812
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.custom-toolbar {
|
|
816
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
.custom-content {
|
|
820
|
+
font-family: 'Georgia', serif;
|
|
821
|
+
}
|
|
822
|
+
</style>
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
#### Options API Version
|
|
826
|
+
```vue
|
|
827
|
+
<template>
|
|
828
|
+
<PremiumBblEditorOptionsAPI
|
|
829
|
+
v-model="content"
|
|
830
|
+
:theme="theme"
|
|
831
|
+
:editor-class="editorClass"
|
|
832
|
+
:toolbar-class="toolbarClass"
|
|
833
|
+
:content-class="contentClass"
|
|
834
|
+
:placeholder="placeholder"
|
|
835
|
+
/>
|
|
836
|
+
</template>
|
|
837
|
+
|
|
838
|
+
<script>
|
|
839
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
840
|
+
|
|
841
|
+
export default {
|
|
842
|
+
components: {
|
|
843
|
+
PremiumBblEditorOptionsAPI
|
|
844
|
+
},
|
|
845
|
+
data() {
|
|
846
|
+
return {
|
|
847
|
+
content: '<p>This Options API editor uses custom styling and dark theme.</p>',
|
|
848
|
+
theme: 'dark',
|
|
849
|
+
placeholder: 'Dark themed Options API editor...',
|
|
850
|
+
editorClass: 'custom-editor-options',
|
|
851
|
+
toolbarClass: 'custom-toolbar-options',
|
|
852
|
+
contentClass: 'custom-content-options'
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
</script>
|
|
857
|
+
|
|
858
|
+
<style scoped>
|
|
859
|
+
.custom-editor-options {
|
|
860
|
+
border-radius: 12px;
|
|
861
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
862
|
+
border: 2px solid #4f46e5;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.custom-toolbar-options {
|
|
866
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
867
|
+
border-bottom: 1px solid #4f46e5;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
.custom-content-options {
|
|
871
|
+
font-family: 'Georgia', serif;
|
|
872
|
+
line-height: 1.8;
|
|
873
|
+
}
|
|
874
|
+
</style>
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
### 6. Local Base64 File Management
|
|
878
|
+
|
|
879
|
+
#### Composition API Version
|
|
880
|
+
```vue
|
|
881
|
+
<template>
|
|
882
|
+
<PremiumBblEditor
|
|
883
|
+
v-model="content"
|
|
884
|
+
:use-base64-upload="true"
|
|
885
|
+
:enable-image-compression="true"
|
|
886
|
+
:base64-quality="0.8"
|
|
887
|
+
:base64-max-width="1920"
|
|
888
|
+
:base64-max-height="1080"
|
|
889
|
+
:preserve-original-file-name="true"
|
|
890
|
+
placeholder="Upload images for local base64 conversion..."
|
|
891
|
+
@image-compressed="handleImageCompressed"
|
|
892
|
+
@ready="handleReady"
|
|
893
|
+
/>
|
|
894
|
+
</template>
|
|
895
|
+
|
|
896
|
+
<script>
|
|
897
|
+
export default {
|
|
898
|
+
data() {
|
|
899
|
+
return {
|
|
900
|
+
content: '<p>Upload images to see base64 conversion with compression!</p>'
|
|
901
|
+
}
|
|
902
|
+
},
|
|
903
|
+
methods: {
|
|
904
|
+
handleImageCompressed(compressionData) {
|
|
905
|
+
console.log('Image compressed:', {
|
|
906
|
+
originalSize: compressionData.originalSize,
|
|
907
|
+
compressedSize: compressionData.compressedSize,
|
|
908
|
+
compressionRatio: compressionData.compressionRatio,
|
|
909
|
+
savings: Math.round(((compressionData.originalSize - compressionData.compressedSize) / compressionData.originalSize) * 100) + '%'
|
|
910
|
+
})
|
|
911
|
+
},
|
|
912
|
+
|
|
913
|
+
handleReady(editor) {
|
|
914
|
+
console.log('Editor ready with base64 management')
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
</script>
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
#### Options API Version
|
|
922
|
+
```vue
|
|
923
|
+
<template>
|
|
924
|
+
<PremiumBblEditorOptionsAPI
|
|
925
|
+
v-model="content"
|
|
926
|
+
:use-base64-upload="useBase64"
|
|
927
|
+
:enable-image-compression="enableCompression"
|
|
928
|
+
:base64-quality="quality"
|
|
929
|
+
:base64-max-width="maxWidth"
|
|
930
|
+
:base64-max-height="maxHeight"
|
|
931
|
+
:preserve-original-file-name="preserveNames"
|
|
932
|
+
placeholder="Options API with base64 management..."
|
|
933
|
+
@image-compressed="onImageCompressed"
|
|
934
|
+
@ready="onEditorReady"
|
|
935
|
+
/>
|
|
936
|
+
</template>
|
|
937
|
+
|
|
938
|
+
<script>
|
|
939
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
940
|
+
|
|
941
|
+
export default {
|
|
942
|
+
components: {
|
|
943
|
+
PremiumBblEditorOptionsAPI
|
|
944
|
+
},
|
|
945
|
+
data() {
|
|
946
|
+
return {
|
|
947
|
+
content: '<p>Options API editor with base64 file management!</p>',
|
|
948
|
+
useBase64: true,
|
|
949
|
+
enableCompression: true,
|
|
950
|
+
quality: 0.8,
|
|
951
|
+
maxWidth: 1920,
|
|
952
|
+
maxHeight: 1080,
|
|
953
|
+
preserveNames: true
|
|
954
|
+
}
|
|
955
|
+
},
|
|
956
|
+
methods: {
|
|
957
|
+
onImageCompressed(data) {
|
|
958
|
+
console.log('Options API - Image compressed:', data)
|
|
959
|
+
|
|
960
|
+
// Show compression statistics
|
|
961
|
+
this.showCompressionStats(data)
|
|
962
|
+
},
|
|
963
|
+
|
|
964
|
+
onEditorReady(editor) {
|
|
965
|
+
console.log('Options API Editor ready with base64 management')
|
|
966
|
+
this.editorInstance = editor
|
|
967
|
+
},
|
|
968
|
+
|
|
969
|
+
showCompressionStats(data) {
|
|
970
|
+
const savings = Math.round(((data.originalSize - data.compressedSize) / data.originalSize) * 100)
|
|
971
|
+
alert(`Image compressed successfully!\nOriginal: ${this.formatFileSize(data.originalSize)}\nCompressed: ${this.formatFileSize(data.compressedSize)}\nSavings: ${savings}%`)
|
|
972
|
+
},
|
|
973
|
+
|
|
974
|
+
formatFileSize(bytes) {
|
|
975
|
+
if (bytes === 0) return '0 Bytes'
|
|
976
|
+
const k = 1024
|
|
977
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
|
978
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
979
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
</script>
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
### 7. Event Handling & Method Access
|
|
987
|
+
|
|
988
|
+
#### Composition API Version
|
|
989
|
+
```vue
|
|
990
|
+
<template>
|
|
991
|
+
<div>
|
|
992
|
+
<PremiumBblEditor
|
|
993
|
+
ref="editor"
|
|
994
|
+
v-model="content"
|
|
995
|
+
@input="handleInput"
|
|
996
|
+
@focus="handleFocus"
|
|
997
|
+
@blur="handleBlur"
|
|
998
|
+
@ready="handleReady"
|
|
999
|
+
@auto-save="handleAutoSave"
|
|
1000
|
+
@content-limit-exceeded="handleLimitExceeded"
|
|
1001
|
+
/>
|
|
1002
|
+
|
|
1003
|
+
<div class="editor-controls">
|
|
1004
|
+
<button @click="focusEditor">Focus Editor</button>
|
|
1005
|
+
<button @click="getEditorContent">Get Content</button>
|
|
1006
|
+
<button @click="setEditorContent">Set Content</button>
|
|
1007
|
+
<button @click="executeCustomCommand">Bold Text</button>
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
</template>
|
|
1011
|
+
|
|
1012
|
+
<script>
|
|
1013
|
+
export default {
|
|
1014
|
+
data() {
|
|
1015
|
+
return {
|
|
1016
|
+
content: '<p>Editor with comprehensive event handling...</p>'
|
|
1017
|
+
}
|
|
1018
|
+
},
|
|
1019
|
+
methods: {
|
|
1020
|
+
handleInput(content) {
|
|
1021
|
+
console.log('Content changed:', content.length, 'characters')
|
|
1022
|
+
},
|
|
1023
|
+
|
|
1024
|
+
handleFocus() {
|
|
1025
|
+
console.log('Editor focused')
|
|
1026
|
+
},
|
|
1027
|
+
|
|
1028
|
+
handleBlur() {
|
|
1029
|
+
console.log('Editor blurred')
|
|
1030
|
+
},
|
|
1031
|
+
|
|
1032
|
+
handleReady(editor) {
|
|
1033
|
+
console.log('Editor ready:', editor)
|
|
1034
|
+
},
|
|
1035
|
+
|
|
1036
|
+
handleAutoSave(content) {
|
|
1037
|
+
console.log('Auto-saving content...')
|
|
1038
|
+
// Save to backend
|
|
1039
|
+
},
|
|
1040
|
+
|
|
1041
|
+
handleLimitExceeded({ current, max }) {
|
|
1042
|
+
alert(`Content limit exceeded: ${current}/${max} characters`)
|
|
1043
|
+
},
|
|
1044
|
+
|
|
1045
|
+
// Method examples
|
|
1046
|
+
focusEditor() {
|
|
1047
|
+
this.$refs.editor.focus()
|
|
1048
|
+
},
|
|
1049
|
+
|
|
1050
|
+
getEditorContent() {
|
|
1051
|
+
const content = this.$refs.editor.getContent()
|
|
1052
|
+
console.log('Current content:', content)
|
|
1053
|
+
},
|
|
1054
|
+
|
|
1055
|
+
setEditorContent() {
|
|
1056
|
+
this.$refs.editor.setContent('<p>New content set programmatically!</p>')
|
|
1057
|
+
},
|
|
1058
|
+
|
|
1059
|
+
executeCustomCommand() {
|
|
1060
|
+
this.$refs.editor.executeCommand('toggleBold')
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
</script>
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
#### Options API Version
|
|
1068
|
+
```vue
|
|
1069
|
+
<template>
|
|
1070
|
+
<div>
|
|
1071
|
+
<PremiumBblEditorOptionsAPI
|
|
1072
|
+
ref="editorOptionsAPI"
|
|
1073
|
+
v-model="content"
|
|
1074
|
+
:max-content-length="maxContentLength"
|
|
1075
|
+
:auto-save="autoSave"
|
|
1076
|
+
:auto-save-interval="autoSaveInterval"
|
|
1077
|
+
@input="handleInput"
|
|
1078
|
+
@focus="handleFocus"
|
|
1079
|
+
@blur="handleBlur"
|
|
1080
|
+
@ready="handleReady"
|
|
1081
|
+
@auto-save="handleAutoSave"
|
|
1082
|
+
@content-limit-exceeded="handleLimitExceeded"
|
|
1083
|
+
@error="handleError"
|
|
1084
|
+
/>
|
|
1085
|
+
|
|
1086
|
+
<div class="editor-controls">
|
|
1087
|
+
<button @click="focusEditor">Focus Editor</button>
|
|
1088
|
+
<button @click="blurEditor">Blur Editor</button>
|
|
1089
|
+
<button @click="getEditorContent">Get Content</button>
|
|
1090
|
+
<button @click="setEditorContent">Set Content</button>
|
|
1091
|
+
<button @click="executeCustomCommand">Toggle Bold</button>
|
|
1092
|
+
<button @click="checkActiveState">Check Bold State</button>
|
|
1093
|
+
<button @click="clearContent">Clear Content</button>
|
|
1094
|
+
</div>
|
|
1095
|
+
|
|
1096
|
+
<div class="editor-status" v-if="editorStatus">
|
|
1097
|
+
<h4>Editor Status</h4>
|
|
1098
|
+
<p>Content Length: {{ contentLength }}</p>
|
|
1099
|
+
<p>Is Bold Active: {{ isBoldActive }}</p>
|
|
1100
|
+
<p>Last Action: {{ lastAction }}</p>
|
|
1101
|
+
</div>
|
|
1102
|
+
</div>
|
|
1103
|
+
</template>
|
|
1104
|
+
|
|
1105
|
+
<script>
|
|
1106
|
+
import { PremiumBblEditorOptionsAPI } from 'vue2-bbl-editor'
|
|
1107
|
+
|
|
1108
|
+
export default {
|
|
1109
|
+
components: {
|
|
1110
|
+
PremiumBblEditorOptionsAPI
|
|
1111
|
+
},
|
|
1112
|
+
data() {
|
|
1113
|
+
return {
|
|
1114
|
+
content: '<p>Options API Editor with comprehensive event handling and method access...</p>',
|
|
1115
|
+
maxContentLength: 5000,
|
|
1116
|
+
autoSave: true,
|
|
1117
|
+
autoSaveInterval: 20000,
|
|
1118
|
+
editorInstance: null,
|
|
1119
|
+
editorStatus: true,
|
|
1120
|
+
contentLength: 0,
|
|
1121
|
+
isBoldActive: false,
|
|
1122
|
+
lastAction: 'None'
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
methods: {
|
|
1126
|
+
handleInput(content) {
|
|
1127
|
+
this.contentLength = content.length
|
|
1128
|
+
this.lastAction = 'Content changed'
|
|
1129
|
+
console.log('Options API - Content changed:', content.length, 'characters')
|
|
1130
|
+
},
|
|
1131
|
+
|
|
1132
|
+
handleFocus() {
|
|
1133
|
+
this.lastAction = 'Editor focused'
|
|
1134
|
+
console.log('Options API - Editor focused')
|
|
1135
|
+
},
|
|
1136
|
+
|
|
1137
|
+
handleBlur() {
|
|
1138
|
+
this.lastAction = 'Editor blurred'
|
|
1139
|
+
console.log('Options API - Editor blurred')
|
|
1140
|
+
},
|
|
1141
|
+
|
|
1142
|
+
handleReady(editor) {
|
|
1143
|
+
this.editorInstance = editor
|
|
1144
|
+
this.lastAction = 'Editor ready'
|
|
1145
|
+
console.log('Options API - Editor ready:', editor)
|
|
1146
|
+
},
|
|
1147
|
+
|
|
1148
|
+
handleAutoSave(content) {
|
|
1149
|
+
this.lastAction = 'Auto-saved'
|
|
1150
|
+
console.log('Options API - Auto-saving content...')
|
|
1151
|
+
this.saveToServer(content)
|
|
1152
|
+
},
|
|
1153
|
+
|
|
1154
|
+
handleLimitExceeded({ current, max }) {
|
|
1155
|
+
this.lastAction = `Content limit exceeded: ${current}/${max}`
|
|
1156
|
+
alert(`Content limit exceeded: ${current}/${max} characters`)
|
|
1157
|
+
},
|
|
1158
|
+
|
|
1159
|
+
handleError(error) {
|
|
1160
|
+
this.lastAction = `Error: ${error.type}`
|
|
1161
|
+
console.error('Options API - Editor error:', error)
|
|
1162
|
+
},
|
|
1163
|
+
|
|
1164
|
+
// Method examples using the Options API component
|
|
1165
|
+
focusEditor() {
|
|
1166
|
+
this.$refs.editorOptionsAPI.focus()
|
|
1167
|
+
this.lastAction = 'Focus method called'
|
|
1168
|
+
},
|
|
1169
|
+
|
|
1170
|
+
blurEditor() {
|
|
1171
|
+
this.$refs.editorOptionsAPI.blur()
|
|
1172
|
+
this.lastAction = 'Blur method called'
|
|
1173
|
+
},
|
|
1174
|
+
|
|
1175
|
+
getEditorContent() {
|
|
1176
|
+
const htmlContent = this.$refs.editorOptionsAPI.getContent('html')
|
|
1177
|
+
const jsonContent = this.$refs.editorOptionsAPI.getContent('json')
|
|
1178
|
+
|
|
1179
|
+
console.log('HTML Content:', htmlContent)
|
|
1180
|
+
console.log('JSON Content:', jsonContent)
|
|
1181
|
+
this.lastAction = 'Get content method called'
|
|
1182
|
+
},
|
|
1183
|
+
|
|
1184
|
+
setEditorContent() {
|
|
1185
|
+
const newContent = `
|
|
1186
|
+
<h3>New Content Set Programmatically</h3>
|
|
1187
|
+
<p>This content was set using the <strong>setContent</strong> method in Options API.</p>
|
|
1188
|
+
<ul>
|
|
1189
|
+
<li>Method called at: ${new Date().toLocaleTimeString()}</li>
|
|
1190
|
+
<li>Using Options API component</li>
|
|
1191
|
+
</ul>
|
|
1192
|
+
`
|
|
1193
|
+
this.$refs.editorOptionsAPI.setContent(newContent)
|
|
1194
|
+
this.lastAction = 'Set content method called'
|
|
1195
|
+
},
|
|
1196
|
+
|
|
1197
|
+
executeCustomCommand() {
|
|
1198
|
+
this.$refs.editorOptionsAPI.executeCommand('toggleBold')
|
|
1199
|
+
this.checkActiveState()
|
|
1200
|
+
this.lastAction = 'Toggle bold command executed'
|
|
1201
|
+
},
|
|
1202
|
+
|
|
1203
|
+
checkActiveState() {
|
|
1204
|
+
this.isBoldActive = this.$refs.editorOptionsAPI.isActive('bold')
|
|
1205
|
+
this.lastAction = 'Checked bold active state'
|
|
1206
|
+
},
|
|
1207
|
+
|
|
1208
|
+
clearContent() {
|
|
1209
|
+
this.$refs.editorOptionsAPI.setContent('<p></p>')
|
|
1210
|
+
this.lastAction = 'Content cleared'
|
|
1211
|
+
},
|
|
1212
|
+
|
|
1213
|
+
async saveToServer(content) {
|
|
1214
|
+
try {
|
|
1215
|
+
// Simulate API call
|
|
1216
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
1217
|
+
console.log('Options API - Content saved to server')
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
console.error('Options API - Save failed:', error)
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
</script>
|
|
1225
|
+
|
|
1226
|
+
<style scoped>
|
|
1227
|
+
.editor-controls {
|
|
1228
|
+
margin: 20px 0;
|
|
1229
|
+
display: flex;
|
|
1230
|
+
gap: 10px;
|
|
1231
|
+
flex-wrap: wrap;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.editor-controls button {
|
|
1235
|
+
padding: 8px 16px;
|
|
1236
|
+
background: #3b82f6;
|
|
1237
|
+
color: white;
|
|
1238
|
+
border: none;
|
|
1239
|
+
border-radius: 4px;
|
|
1240
|
+
cursor: pointer;
|
|
1241
|
+
font-size: 14px;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
.editor-controls button:hover {
|
|
1245
|
+
background: #2563eb;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
.editor-status {
|
|
1249
|
+
margin-top: 20px;
|
|
1250
|
+
padding: 15px;
|
|
1251
|
+
background: #f8f9fa;
|
|
1252
|
+
border: 1px solid #dee2e6;
|
|
1253
|
+
border-radius: 6px;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
.editor-status h4 {
|
|
1257
|
+
margin-top: 0;
|
|
1258
|
+
color: #495057;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
.editor-status p {
|
|
1262
|
+
margin: 5px 0;
|
|
1263
|
+
font-size: 14px;
|
|
1264
|
+
color: #6c757d;
|
|
1265
|
+
}
|
|
1266
|
+
</style>
|
|
1267
|
+
```
|
|
1268
|
+
|
|
1269
|
+
## ๐ Upload System Integration
|
|
1270
|
+
|
|
1271
|
+
The editor includes a comprehensive upload management system for handling file uploads with multiple adapters.
|
|
1272
|
+
|
|
1273
|
+
### Basic Upload Setup
|
|
1274
|
+
|
|
1275
|
+
```vue
|
|
1276
|
+
<template>
|
|
1277
|
+
<PremiumBblEditor
|
|
1278
|
+
v-model="content"
|
|
1279
|
+
@ready="onEditorReady"
|
|
1280
|
+
/>
|
|
1281
|
+
</template>
|
|
1282
|
+
|
|
1283
|
+
<script>
|
|
1284
|
+
import {
|
|
1285
|
+
UploadManager,
|
|
1286
|
+
LocalStorageAdapter,
|
|
1287
|
+
integrateTipTapUpload,
|
|
1288
|
+
createUploadConfig
|
|
1289
|
+
} from 'vue2-bbl-editor'
|
|
1290
|
+
|
|
1291
|
+
export default {
|
|
1292
|
+
data() {
|
|
1293
|
+
return {
|
|
1294
|
+
content: '<p>Try uploading images...</p>',
|
|
1295
|
+
uploadManager: null
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
|
|
1299
|
+
async created() {
|
|
1300
|
+
// Create upload configuration
|
|
1301
|
+
const config = createUploadConfig('localStorage', {
|
|
1302
|
+
validation: {
|
|
1303
|
+
maxSize: 5 * 1024 * 1024, // 5MB
|
|
1304
|
+
allowedTypes: ['image/jpeg', 'image/png', 'image/gif']
|
|
1305
|
+
}
|
|
1306
|
+
})
|
|
1307
|
+
|
|
1308
|
+
// Initialize upload manager
|
|
1309
|
+
this.uploadManager = new UploadManager(config)
|
|
1310
|
+
|
|
1311
|
+
// Register local storage adapter
|
|
1312
|
+
const adapter = new LocalStorageAdapter()
|
|
1313
|
+
this.uploadManager.registerAdapter(adapter)
|
|
1314
|
+
this.uploadManager.setDefaultAdapter('local-storage')
|
|
1315
|
+
},
|
|
1316
|
+
|
|
1317
|
+
methods: {
|
|
1318
|
+
onEditorReady(editor) {
|
|
1319
|
+
// Integrate upload system with editor
|
|
1320
|
+
integrateTipTapUpload(editor, this.uploadManager, {
|
|
1321
|
+
onStart: () => console.log('Upload started'),
|
|
1322
|
+
onEnd: () => console.log('Upload finished')
|
|
1323
|
+
})
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
</script>
|
|
1328
|
+
```
|
|
1329
|
+
|
|
1330
|
+
### Custom Upload Adapter
|
|
1331
|
+
|
|
1332
|
+
```javascript
|
|
1333
|
+
// Create custom adapter for your API
|
|
1334
|
+
class CustomApiAdapter {
|
|
1335
|
+
constructor(options) {
|
|
1336
|
+
this.name = 'custom-api'
|
|
1337
|
+
this.apiUrl = options.apiUrl
|
|
1338
|
+
this.headers = options.headers || {}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
async upload(file, options) {
|
|
1342
|
+
const formData = new FormData()
|
|
1343
|
+
formData.append('file', file)
|
|
1344
|
+
|
|
1345
|
+
const response = await fetch(this.apiUrl, {
|
|
1346
|
+
method: 'POST',
|
|
1347
|
+
headers: this.headers,
|
|
1348
|
+
body: formData
|
|
1349
|
+
})
|
|
1350
|
+
|
|
1351
|
+
if (!response.ok) {
|
|
1352
|
+
throw new Error(`Upload failed: ${response.statusText}`)
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
const result = await response.json()
|
|
1356
|
+
return {
|
|
1357
|
+
url: result.url,
|
|
1358
|
+
size: file.size,
|
|
1359
|
+
metadata: {
|
|
1360
|
+
fileName: file.name,
|
|
1361
|
+
fileType: file.type
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
// Register and use
|
|
1368
|
+
const adapter = new CustomApiAdapter({
|
|
1369
|
+
apiUrl: '/api/upload',
|
|
1370
|
+
headers: { 'Authorization': 'Bearer your-token' }
|
|
1371
|
+
})
|
|
1372
|
+
uploadManager.registerAdapter(adapter)
|
|
1373
|
+
uploadManager.setDefaultAdapter('custom-api')
|
|
1374
|
+
```
|
|
1375
|
+
|
|
1376
|
+
### Upload Event Handling
|
|
1377
|
+
|
|
1378
|
+
```javascript
|
|
1379
|
+
// Listen to upload events
|
|
1380
|
+
uploadManager.on('progress', (progress) => {
|
|
1381
|
+
console.log(`Upload progress: ${progress.percentage}%`)
|
|
1382
|
+
})
|
|
1383
|
+
|
|
1384
|
+
uploadManager.on('uploadCompleted', (event) => {
|
|
1385
|
+
console.log('Upload completed:', event.result.url)
|
|
1386
|
+
})
|
|
1387
|
+
|
|
1388
|
+
uploadManager.on('uploadFailed', (event) => {
|
|
1389
|
+
console.error('Upload failed:', event.error.message)
|
|
1390
|
+
})
|
|
1391
|
+
```
|
|
1392
|
+
|
|
1393
|
+
## ๐งฉ Individual Component Usage
|
|
1394
|
+
|
|
1395
|
+
Import and use individual components for custom implementations:
|
|
1396
|
+
|
|
1397
|
+
```javascript
|
|
1398
|
+
import {
|
|
1399
|
+
PremiumBblEditor,
|
|
1400
|
+
PremiumBblEditorOptionsAPI,
|
|
1401
|
+
ToolbarMain,
|
|
1402
|
+
ToolbarGroup,
|
|
1403
|
+
ToolbarButton,
|
|
1404
|
+
EditorBubbleMenu,
|
|
1405
|
+
TableBubbleMenu,
|
|
1406
|
+
ImageBubbleMenu,
|
|
1407
|
+
VideoBubbleMenu,
|
|
1408
|
+
ImageModal,
|
|
1409
|
+
VideoModal,
|
|
1410
|
+
LinkModal,
|
|
1411
|
+
DiagnosticTool,
|
|
1412
|
+
DebugHelper,
|
|
1413
|
+
useEditor
|
|
1414
|
+
} from 'vue2-bbl-editor'
|
|
1415
|
+
```
|
|
1416
|
+
|
|
1417
|
+
### Available Components
|
|
1418
|
+
|
|
1419
|
+
#### Main Components
|
|
1420
|
+
- `PremiumBblEditor` - Main editor component (Composition API)
|
|
1421
|
+
- `PremiumBblEditorOptionsAPI` - Main editor component (Options API)
|
|
1422
|
+
- `DiagnosticTool` - Built-in diagnostic and troubleshooting tool
|
|
1423
|
+
- `DebugHelper` - Development debugging helper
|
|
1424
|
+
|
|
1425
|
+
#### Toolbar Components
|
|
1426
|
+
- `ToolbarMain` - Complete toolbar component
|
|
1427
|
+
- `ToolbarGroup` - Toolbar button group container
|
|
1428
|
+
- `ToolbarButton` - Individual toolbar button
|
|
1429
|
+
|
|
1430
|
+
#### Menu Components
|
|
1431
|
+
- `EditorBubbleMenu` - Text selection bubble menu
|
|
1432
|
+
- `TableBubbleMenu` - Table-specific bubble menu
|
|
1433
|
+
- `ImageBubbleMenu` - Image-specific bubble menu
|
|
1434
|
+
- `VideoBubbleMenu` - Video-specific bubble menu
|
|
1435
|
+
|
|
1436
|
+
#### Modal Components
|
|
1437
|
+
- `ImageModal` - Image upload and configuration modal
|
|
1438
|
+
- `VideoModal` - Video upload and configuration modal
|
|
1439
|
+
- `LinkModal` - Link creation and editing modal
|
|
1440
|
+
|
|
1441
|
+
#### Composables
|
|
1442
|
+
- `useEditor` - Core editor composable for custom implementations
|
|
1443
|
+
|
|
1444
|
+
### Custom Implementation Example
|
|
1445
|
+
|
|
1446
|
+
```vue
|
|
1447
|
+
<template>
|
|
1448
|
+
<div class="custom-editor">
|
|
1449
|
+
<ToolbarMain
|
|
1450
|
+
v-if="editor"
|
|
1451
|
+
:editor="editor"
|
|
1452
|
+
:config="toolbarConfig"
|
|
1453
|
+
@execute-command="executeCommand"
|
|
1454
|
+
/>
|
|
1455
|
+
|
|
1456
|
+
<div class="editor-content">
|
|
1457
|
+
<editor-content :editor="editor" />
|
|
1458
|
+
</div>
|
|
1459
|
+
|
|
1460
|
+
<EditorBubbleMenu
|
|
1461
|
+
v-if="editor"
|
|
1462
|
+
:editor="editor"
|
|
1463
|
+
:config="toolbarConfig"
|
|
1464
|
+
/>
|
|
1465
|
+
</div>
|
|
1466
|
+
</template>
|
|
1467
|
+
|
|
1468
|
+
<script>
|
|
1469
|
+
import { EditorContent } from '@tiptap/vue-2'
|
|
1470
|
+
import { ToolbarMain, EditorBubbleMenu, useEditor } from 'vue2-bbl-editor'
|
|
1471
|
+
|
|
1472
|
+
export default {
|
|
1473
|
+
components: {
|
|
1474
|
+
EditorContent,
|
|
1475
|
+
ToolbarMain,
|
|
1476
|
+
EditorBubbleMenu
|
|
1477
|
+
},
|
|
1478
|
+
|
|
1479
|
+
setup() {
|
|
1480
|
+
const { editor, executeCommand } = useEditor({
|
|
1481
|
+
content: '<p>Custom editor implementation</p>',
|
|
1482
|
+
extensions: [
|
|
1483
|
+
// Your custom extensions
|
|
1484
|
+
]
|
|
1485
|
+
})
|
|
1486
|
+
|
|
1487
|
+
return {
|
|
1488
|
+
editor,
|
|
1489
|
+
executeCommand,
|
|
1490
|
+
toolbarConfig: {
|
|
1491
|
+
bold: true,
|
|
1492
|
+
italic: true,
|
|
1493
|
+
underline: true
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
</script>
|
|
1499
|
+
```
|
|
1500
|
+
|
|
1501
|
+
## ๐ Extensions & Customization
|
|
1502
|
+
|
|
1503
|
+
The package includes custom extensions that enhance the editing experience:
|
|
1504
|
+
|
|
1505
|
+
### Available Extensions
|
|
1506
|
+
- `ResizableImage` - Enhanced image handling with resize controls
|
|
1507
|
+
- `ResizableVideo` - Video embedding with resize functionality
|
|
1508
|
+
- `CustomTableCell` - Enhanced table cell with controls
|
|
1509
|
+
- `CustomTableHeader` - Enhanced table header with controls
|
|
1510
|
+
|
|
1511
|
+
### Using Extensions Directly
|
|
1512
|
+
|
|
1513
|
+
```javascript
|
|
1514
|
+
import { ResizableImage, ResizableVideo } from 'vue2-bbl-editor'
|
|
1515
|
+
import { Editor } from '@tiptap/vue-2'
|
|
1516
|
+
|
|
1517
|
+
const editor = new Editor({
|
|
1518
|
+
extensions: [
|
|
1519
|
+
ResizableImage.configure({
|
|
1520
|
+
allowResize: true,
|
|
1521
|
+
allowAlignment: true,
|
|
1522
|
+
maxWidth: '800px'
|
|
1523
|
+
}),
|
|
1524
|
+
ResizableVideo.configure({
|
|
1525
|
+
allowResize: true,
|
|
1526
|
+
autoplay: false
|
|
1527
|
+
})
|
|
1528
|
+
]
|
|
1529
|
+
})
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
## ๐ External Project Integration
|
|
1533
|
+
|
|
1534
|
+
For detailed integration instructions for external projects, see our [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md).
|
|
1535
|
+
|
|
1536
|
+
### Quick Integration
|
|
1537
|
+
|
|
1538
|
+
```bash
|
|
1539
|
+
# Install in your existing project
|
|
1540
|
+
npm install vue2-bbl-editor
|
|
1541
|
+
|
|
1542
|
+
# Install required dependencies
|
|
1543
|
+
npm install @vue/composition-api @tiptap/core @tiptap/vue-2 @tiptap/starter-kit
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
```vue
|
|
1547
|
+
<template>
|
|
1548
|
+
<PremiumBblEditor
|
|
1549
|
+
v-model="content"
|
|
1550
|
+
@ready="onEditorReady"
|
|
1551
|
+
/>
|
|
1552
|
+
</template>
|
|
1553
|
+
|
|
1554
|
+
<script>
|
|
1555
|
+
import { PremiumBblEditor } from 'vue2-bbl-editor'
|
|
1556
|
+
|
|
1557
|
+
export default {
|
|
1558
|
+
components: { PremiumBblEditor },
|
|
1559
|
+
data() {
|
|
1560
|
+
return {
|
|
1561
|
+
content: '<p>Start editing...</p>'
|
|
1562
|
+
}
|
|
1563
|
+
},
|
|
1564
|
+
methods: {
|
|
1565
|
+
onEditorReady(editor) {
|
|
1566
|
+
console.log('Editor ready in external project!')
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
</script>
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
## ๐งช Development & Testing
|
|
1574
|
+
|
|
1575
|
+
```bash
|
|
1576
|
+
# Install dependencies
|
|
1577
|
+
npm install
|
|
1578
|
+
|
|
1579
|
+
# Run development server
|
|
1580
|
+
npm run serve
|
|
1581
|
+
|
|
1582
|
+
# Build library
|
|
1583
|
+
npm run build:lib
|
|
1584
|
+
|
|
1585
|
+
# Run tests
|
|
1586
|
+
npm test
|
|
1587
|
+
|
|
1588
|
+
# Lint code
|
|
1589
|
+
npm run lint
|
|
1590
|
+
```
|
|
1591
|
+
|
|
1592
|
+
### Development Tools
|
|
1593
|
+
|
|
1594
|
+
The package includes built-in development and diagnostic tools:
|
|
1595
|
+
|
|
1596
|
+
```vue
|
|
1597
|
+
<template>
|
|
1598
|
+
<div>
|
|
1599
|
+
<!-- Your editor -->
|
|
1600
|
+
<PremiumBblEditor v-model="content" />
|
|
1601
|
+
|
|
1602
|
+
<!-- Development tools -->
|
|
1603
|
+
<DiagnosticTool v-if="isDevelopment" />
|
|
1604
|
+
<DebugHelper v-if="isDevelopment" />
|
|
1605
|
+
</div>
|
|
1606
|
+
</template>
|
|
1607
|
+
|
|
1608
|
+
<script>
|
|
1609
|
+
import { PremiumBblEditor, DiagnosticTool, DebugHelper } from 'vue2-bbl-editor'
|
|
1610
|
+
|
|
1611
|
+
export default {
|
|
1612
|
+
components: {
|
|
1613
|
+
PremiumBblEditor,
|
|
1614
|
+
DiagnosticTool,
|
|
1615
|
+
DebugHelper
|
|
1616
|
+
},
|
|
1617
|
+
computed: {
|
|
1618
|
+
isDevelopment() {
|
|
1619
|
+
return process.env.NODE_ENV === 'development'
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
</script>
|
|
1624
|
+
```
|
|
1625
|
+
|
|
1626
|
+
## ๐ง Troubleshooting
|
|
1627
|
+
|
|
1628
|
+
### Common Issues
|
|
1629
|
+
|
|
1630
|
+
1. **Editor not loading**: Check if all required dependencies are installed
|
|
1631
|
+
2. **Upload not working**: Verify upload handler configuration
|
|
1632
|
+
3. **Styling issues**: Ensure CSS is properly imported
|
|
1633
|
+
4. **TypeScript errors**: Check type definitions import
|
|
1634
|
+
|
|
1635
|
+
### Diagnostic Tools
|
|
1636
|
+
|
|
1637
|
+
Use the built-in diagnostic tool to identify issues:
|
|
1638
|
+
|
|
1639
|
+
```vue
|
|
1640
|
+
<template>
|
|
1641
|
+
<div>
|
|
1642
|
+
<PremiumBblEditor v-model="content" />
|
|
1643
|
+
<DiagnosticTool />
|
|
1644
|
+
</div>
|
|
1645
|
+
</template>
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
### Debug Mode
|
|
1649
|
+
|
|
1650
|
+
Enable debug mode for detailed logging:
|
|
1651
|
+
|
|
1652
|
+
```vue
|
|
1653
|
+
<template>
|
|
1654
|
+
<PremiumBblEditor
|
|
1655
|
+
v-model="content"
|
|
1656
|
+
:debug="true"
|
|
1657
|
+
/>
|
|
1658
|
+
</template>
|
|
1659
|
+
```
|
|
1660
|
+
|
|
1661
|
+
For more troubleshooting help, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).
|
|
1662
|
+
|
|
1663
|
+
## ๐ Documentation
|
|
1664
|
+
|
|
1665
|
+
- [Installation Guide](INSTALLATION.md)
|
|
1666
|
+
- [External Integration Guide](EXTERNAL_INTEGRATION_GUIDE.md)
|
|
1667
|
+
- [Upload System Documentation](src/upload/README.md)
|
|
1668
|
+
- [Troubleshooting Guide](TROUBLESHOOTING.md)
|
|
1669
|
+
- [API Reference](types/index.d.ts)
|
|
1670
|
+
- [Examples](examples/)
|
|
1671
|
+
|
|
1672
|
+
## ๐ License
|
|
1673
|
+
|
|
1674
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
1675
|
+
|
|
1676
|
+
## ๐ค Contributing
|
|
1677
|
+
|
|
1678
|
+
1. Fork the repository
|
|
1679
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
1680
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
1681
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
1682
|
+
5. Open a Pull Request
|
|
1683
|
+
|
|
1684
|
+
## ๐ Support
|
|
1685
|
+
|
|
1686
|
+
- ๐ง Email: support@example.com
|
|
1687
|
+
- ๐ Issues: [GitHub Issues](https://github.com/Mahadi74/vue2-bbl-editor/issues)
|
|
1688
|
+
- ๐ Documentation: [Full Documentation](https://github.com/Mahadi74/vue2-bbl-editor/wiki)
|
|
1689
|
+
|
|
1690
|
+
## ๐ Acknowledgments
|
|
1691
|
+
|
|
1692
|
+
- [Tiptap](https://tiptap.dev/) - The headless editor framework
|
|
1693
|
+
- [ProseMirror](https://prosemirror.net/) - The foundation
|
|
1694
|
+
- [Vue.js](https://vuejs.org/) - The progressive framework
|