@editora/plugins 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +173 -110
  2. package/dist/a11y-checker.cjs.js +109 -0
  3. package/dist/a11y-checker.esm.js +509 -0
  4. package/dist/anchor.cjs.js +176 -0
  5. package/dist/anchor.esm.js +400 -0
  6. package/dist/background-color.cjs.js +218 -0
  7. package/dist/background-color.esm.js +482 -0
  8. package/dist/blockquote.cjs.js +1 -0
  9. package/dist/blockquote.esm.js +47 -0
  10. package/dist/bold.cjs.js +1 -0
  11. package/dist/bold.esm.js +44 -0
  12. package/dist/capitalization.cjs.js +1 -0
  13. package/dist/capitalization.esm.js +78 -0
  14. package/dist/checklist.cjs.js +1 -0
  15. package/dist/checklist.esm.js +305 -0
  16. package/dist/clear-formatting.cjs.js +1 -0
  17. package/dist/clear-formatting.esm.js +138 -0
  18. package/dist/code-sample.cjs.js +161 -0
  19. package/dist/code-sample.esm.js +381 -0
  20. package/dist/code.cjs.js +598 -0
  21. package/dist/code.esm.js +2034 -0
  22. package/dist/colorSelectionApply-C0iOfMWb.js +1 -0
  23. package/dist/colorSelectionApply-D8r_gV32.mjs +63 -0
  24. package/dist/comments.cjs.js +354 -0
  25. package/dist/comments.esm.js +692 -0
  26. package/dist/direction.cjs.js +1 -0
  27. package/dist/direction.esm.js +129 -0
  28. package/dist/document-manager.cjs.js +1 -0
  29. package/dist/document-manager.esm.js +6 -0
  30. package/dist/{documentManager-D86di_ZO.mjs → documentManager-DRUc1-Cs.mjs} +3 -3
  31. package/dist/{documentManager-Cw420fPO.js → documentManager-_tQQfQi9.js} +3 -3
  32. package/dist/editorContainerHelpers-C7kdWnS0.mjs +26 -0
  33. package/dist/editorContainerHelpers-CFbfiOJI.js +1 -0
  34. package/dist/embed-iframe.cjs.js +361 -0
  35. package/dist/embed-iframe.esm.js +556 -0
  36. package/dist/emojis.cjs.js +284 -0
  37. package/dist/emojis.esm.js +1080 -0
  38. package/dist/font-family.cjs.js +1 -0
  39. package/dist/font-family.esm.js +152 -0
  40. package/dist/font-size.cjs.js +1 -0
  41. package/dist/font-size.esm.js +278 -0
  42. package/dist/footnote.cjs.js +85 -0
  43. package/dist/footnote.esm.js +397 -0
  44. package/dist/fullscreen.cjs.js +1 -0
  45. package/dist/fullscreen.esm.js +73 -0
  46. package/dist/heading.cjs.js +1 -0
  47. package/dist/heading.esm.js +63 -0
  48. package/dist/history.cjs.js +1 -0
  49. package/dist/history.esm.js +246 -0
  50. package/dist/indent.cjs.js +1 -0
  51. package/dist/indent.esm.js +146 -0
  52. package/dist/index-Bskk414V.mjs +145 -0
  53. package/dist/index-D3pJyAsj.js +1 -0
  54. package/dist/index.cjs.js +1 -1
  55. package/dist/{index.es-B4xMKvwd.js → index.es-Cz1qItab.js} +1 -1
  56. package/dist/{index.es-lzohzZmW.mjs → index.es-DEcRmSTY.mjs} +1 -1
  57. package/dist/index.esm.js +89 -49
  58. package/dist/italic.cjs.js +1 -0
  59. package/dist/italic.esm.js +40 -0
  60. package/dist/line-height.cjs.js +1 -0
  61. package/dist/line-height.esm.js +145 -0
  62. package/dist/link.cjs.js +138 -0
  63. package/dist/link.esm.js +276 -0
  64. package/dist/list.cjs.js +1 -0
  65. package/dist/list.esm.js +102 -0
  66. package/dist/lite.cjs.js +1 -0
  67. package/dist/lite.esm.js +61 -0
  68. package/dist/math.cjs.js +45 -0
  69. package/dist/math.esm.js +249 -0
  70. package/dist/media-manager.cjs.js +619 -0
  71. package/dist/media-manager.esm.js +994 -0
  72. package/dist/merge-tag.cjs.js +93 -0
  73. package/dist/merge-tag.esm.js +412 -0
  74. package/dist/page-break.cjs.js +72 -0
  75. package/dist/page-break.esm.js +295 -0
  76. package/dist/plugins.css +1 -1
  77. package/dist/preview.cjs.js +230 -0
  78. package/dist/preview.esm.js +321 -0
  79. package/dist/print.cjs.js +254 -0
  80. package/dist/print.esm.js +309 -0
  81. package/dist/purify.es-DHhaBdbu.mjs +470 -0
  82. package/dist/purify.es-T2a3nLiC.js +3 -0
  83. package/dist/shared-config.cjs.js +1 -0
  84. package/dist/shared-config.esm.js +30 -0
  85. package/dist/special-characters.cjs.js +257 -0
  86. package/dist/special-characters.esm.js +772 -0
  87. package/dist/spell-check.cjs.js +512 -0
  88. package/dist/spell-check.esm.js +1013 -0
  89. package/dist/strikethrough.cjs.js +1 -0
  90. package/dist/strikethrough.esm.js +71 -0
  91. package/dist/table.cjs.js +35 -0
  92. package/dist/table.esm.js +477 -0
  93. package/dist/template.cjs.js +356 -0
  94. package/dist/template.esm.js +560 -0
  95. package/dist/text-alignment.cjs.js +1 -0
  96. package/dist/text-alignment.esm.js +105 -0
  97. package/dist/text-color.cjs.js +300 -0
  98. package/dist/text-color.esm.js +507 -0
  99. package/dist/underline.cjs.js +1 -0
  100. package/dist/underline.esm.js +34 -0
  101. package/index.d.ts +62 -0
  102. package/package.json +217 -5
  103. package/LICENSE +0 -21
  104. package/dist/index-CnEGPLxN.js +0 -3752
  105. package/dist/index-xwiBh2x6.mjs +0 -11739
package/README.md CHANGED
@@ -1,11 +1,20 @@
1
1
  # @editora/plugins
2
2
 
3
+ <div align="center">
4
+ <img src="../../images/editora_logo_blocks.svg" alt="Editora Logo" width="200" height="auto">
5
+ </div>
6
+
7
+ <div align="center">
8
+ <img src="../../images/features-overview-7.png" alt="Editora Plugins - Plugin Architecture" width="600" style="border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);">
9
+ <p><em>Comprehensive plugin collection with 40+ plugins for rich text editing</em></p>
10
+ </div>
11
+
3
12
  Comprehensive plugin collection for Editora Rich Text Editor with 40+ plugins for text formatting, media management, accessibility, and more.
4
13
 
5
14
  ## 📦 Installation
6
15
 
7
16
  ```bash
8
- npm install @editora/plugins @editora/core
17
+ npm install @editora/plugins @editora/core @editora/themes
9
18
  ```
10
19
 
11
20
  ## 🎯 Overview
@@ -66,21 +75,46 @@ This package provides a complete set of plugins for building feature-rich text e
66
75
 
67
76
  ## 🚀 Quick Start
68
77
 
78
+ ### Recommended Imports For Smaller Bundles
79
+
80
+ For best bundle size, avoid importing everything from `@editora/plugins` in large apps.
81
+
82
+ Use one of these patterns:
83
+
84
+ ```ts
85
+ // Lightweight preset entry
86
+ import { BoldPlugin, ItalicPlugin, HistoryPlugin } from '@editora/plugins/lite';
87
+
88
+ // Per-plugin subpath entry (most explicit)
89
+ import { BoldPlugin } from '@editora/plugins/bold';
90
+ import { ItalicPlugin } from '@editora/plugins/italic';
91
+ import { SpellCheckPlugin } from '@editora/plugins/spell-check';
92
+ ```
93
+
94
+ Lazy-load heavy plugins only when needed:
95
+
96
+ ```ts
97
+ const { DocumentManagerPlugin } = await import('@editora/plugins/document-manager');
98
+ const { MediaManagerPlugin } = await import('@editora/plugins/media-manager');
99
+ const { SpellCheckPlugin } = await import('@editora/plugins/spell-check');
100
+ ```
101
+
69
102
  ### Basic Formatting
70
103
 
71
104
  ```typescript
72
105
  import {
73
- createBoldPlugin,
74
- createItalicPlugin,
75
- createUnderlinePlugin,
76
- createStrikethroughPlugin
106
+ BoldPlugin,
107
+ ItalicPlugin,
108
+ UnderlinePlugin,
109
+ StrikethroughPlugin
77
110
  } from '@editora/plugins';
78
111
 
112
+ import "@editora/themes/themes/default.css";
79
113
  const plugins = [
80
- createBoldPlugin(),
81
- createItalicPlugin(),
82
- createUnderlinePlugin(),
83
- createStrikethroughPlugin()
114
+ BoldPlugin(),
115
+ ItalicPlugin(),
116
+ UnderlinePlugin(),
117
+ StrikethroughPlugin()
84
118
  ];
85
119
  ```
86
120
 
@@ -89,41 +123,70 @@ const plugins = [
89
123
  ```typescript
90
124
  import {
91
125
  // Text formatting
92
- createBoldPlugin,
93
- createItalicPlugin,
94
- createUnderlinePlugin,
95
- createFontFamilyPlugin,
96
- createFontSizePlugin,
97
- createTextColorPlugin,
98
- createBackgroundColorPlugin,
99
-
126
+ BoldPlugin,
127
+ ItalicPlugin,
128
+ UnderlinePlugin,
129
+ FontFamilyPlugin,
130
+ FontSizePlugin,
131
+ TextColorPlugin,
132
+ BackgroundColorPlugin,
133
+
100
134
  // Block elements
101
- createHeadingPlugin,
102
- createParagraphPlugin,
103
- createBlockquotePlugin,
104
- createCodeSamplePlugin,
105
-
135
+ HeadingPlugin,
136
+ BlockquotePlugin,
137
+ CodeSamplePlugin,
138
+
106
139
  // Lists
107
- createListPlugin,
108
- createChecklistPlugin,
109
- createIndentPlugin,
110
- createTextAlignmentPlugin,
111
-
140
+ ListPlugin,
141
+ ChecklistPlugin,
142
+ IndentPlugin,
143
+ TextAlignmentPlugin,
144
+
112
145
  // Media
113
- createImagePlugin,
114
- createLinkPlugin,
115
- createTablePlugin,
116
-
146
+ LinkPlugin,
147
+ TablePlugin,
148
+ MediaManagerPlugin,
149
+
117
150
  // Advanced
118
- createMathPlugin,
119
- createCommentsPlugin,
120
- createHistoryPlugin,
121
- createFullscreenPlugin,
122
- createDocumentManagerPlugin
151
+ MathPlugin,
152
+ CommentsPlugin,
153
+ HistoryPlugin,
154
+ FullscreenPlugin,
155
+ DocumentManagerPlugin
123
156
  } from '@editora/plugins';
124
157
 
125
158
  const plugins = [
126
- // ... initialize all plugins
159
+ // Text formatting
160
+ BoldPlugin(),
161
+ ItalicPlugin(),
162
+ UnderlinePlugin(),
163
+ FontFamilyPlugin(),
164
+ FontSizePlugin(),
165
+ TextColorPlugin(),
166
+ BackgroundColorPlugin(),
167
+
168
+ // Block elements
169
+ HeadingPlugin(),
170
+ BlockquotePlugin(),
171
+ CodeSamplePlugin(),
172
+
173
+ // Lists
174
+ ListPlugin(),
175
+ ChecklistPlugin(),
176
+ IndentPlugin(),
177
+ TextAlignmentPlugin(),
178
+
179
+ // Media
180
+ LinkPlugin(),
181
+ TablePlugin(),
182
+ MediaManagerPlugin(),
183
+
184
+ // Advanced
185
+ MathPlugin(),
186
+ CommentsPlugin(),
187
+ HistoryPlugin(),
188
+ FullscreenPlugin(),
189
+ DocumentManagerPlugin()
127
190
  ];
128
191
  ```
129
192
 
@@ -133,7 +196,7 @@ const plugins = [
133
196
 
134
197
  #### Bold Plugin
135
198
  ```typescript
136
- createBoldPlugin(options?: {
199
+ BoldPlugin(options?: {
137
200
  keyboard?: string; // Default: 'Mod-b'
138
201
  icon?: ReactNode;
139
202
  className?: string;
@@ -142,7 +205,7 @@ createBoldPlugin(options?: {
142
205
 
143
206
  #### Font Family Plugin
144
207
  ```typescript
145
- createFontFamilyPlugin(options?: {
208
+ FontFamilyPlugin(options?: {
146
209
  fonts?: Array<{
147
210
  name: string;
148
211
  value: string;
@@ -152,7 +215,7 @@ createFontFamilyPlugin(options?: {
152
215
  })
153
216
 
154
217
  // Example
155
- const fontFamilyPlugin = createFontFamilyPlugin({
218
+ const fontFamilyPlugin = FontFamilyPlugin({
156
219
  fonts: [
157
220
  { name: 'Arial', value: 'Arial, sans-serif' },
158
221
  { name: 'Times New Roman', value: 'Times New Roman, serif' },
@@ -163,7 +226,7 @@ const fontFamilyPlugin = createFontFamilyPlugin({
163
226
 
164
227
  #### Font Size Plugin
165
228
  ```typescript
166
- createFontSizePlugin(options?: {
229
+ FontSizePlugin(options?: {
167
230
  sizes?: string[]; // Default: ['8pt', '10pt', '12pt', '14pt', '18pt', '24pt', '36pt']
168
231
  defaultSize?: string;
169
232
  })
@@ -171,7 +234,7 @@ createFontSizePlugin(options?: {
171
234
 
172
235
  #### Text Color Plugin
173
236
  ```typescript
174
- createTextColorPlugin(options?: {
237
+ TextColorPlugin(options?: {
175
238
  colors?: string[];
176
239
  customColors?: boolean;
177
240
  recentColors?: boolean;
@@ -182,14 +245,14 @@ createTextColorPlugin(options?: {
182
245
 
183
246
  #### Heading Plugin
184
247
  ```typescript
185
- createHeadingPlugin(options?: {
248
+ HeadingPlugin(options?: {
186
249
  levels?: number[]; // Default: [1, 2, 3, 4, 5, 6]
187
250
  defaultLevel?: number;
188
251
  keyboard?: Record<number, string>;
189
252
  })
190
253
 
191
254
  // Example
192
- const headingPlugin = createHeadingPlugin({
255
+ const headingPlugin = HeadingPlugin({
193
256
  levels: [1, 2, 3],
194
257
  keyboard: {
195
258
  1: 'Mod-Alt-1',
@@ -201,7 +264,7 @@ const headingPlugin = createHeadingPlugin({
201
264
 
202
265
  #### Code Sample Plugin
203
266
  ```typescript
204
- createCodeSamplePlugin(options?: {
267
+ CodeSamplePlugin(options?: {
205
268
  languages?: Array<{
206
269
  name: string;
207
270
  value: string;
@@ -212,7 +275,7 @@ createCodeSamplePlugin(options?: {
212
275
  })
213
276
 
214
277
  // Example
215
- const codeSamplePlugin = createCodeSamplePlugin({
278
+ const codeSamplePlugin = CodeSamplePlugin({
216
279
  languages: [
217
280
  { name: 'JavaScript', value: 'javascript' },
218
281
  { name: 'TypeScript', value: 'typescript' },
@@ -229,7 +292,7 @@ const codeSamplePlugin = createCodeSamplePlugin({
229
292
 
230
293
  #### List Plugin
231
294
  ```typescript
232
- createListPlugin(options?: {
295
+ ListPlugin(options?: {
233
296
  bulletList?: boolean;
234
297
  orderedList?: boolean;
235
298
  keyboard?: {
@@ -241,7 +304,7 @@ createListPlugin(options?: {
241
304
 
242
305
  #### Checklist Plugin
243
306
  ```typescript
244
- createChecklistPlugin(options?: {
307
+ ChecklistPlugin(options?: {
245
308
  nested?: boolean;
246
309
  keyboard?: string;
247
310
  })
@@ -251,7 +314,7 @@ createChecklistPlugin(options?: {
251
314
 
252
315
  #### Image Plugin
253
316
  ```typescript
254
- createImagePlugin(options: {
317
+ MediaManagerPlugin(options: {
255
318
  upload: (file: File) => Promise<string>;
256
319
  validate?: (file: File) => boolean;
257
320
  maxSize?: number; // bytes
@@ -263,7 +326,7 @@ createImagePlugin(options: {
263
326
  })
264
327
 
265
328
  // Example
266
- const imagePlugin = createImagePlugin({
329
+ const imagePlugin = MediaManagerPlugin({
267
330
  upload: async (file) => {
268
331
  const formData = new FormData();
269
332
  formData.append('image', file);
@@ -284,7 +347,7 @@ const imagePlugin = createImagePlugin({
284
347
 
285
348
  #### Link Plugin
286
349
  ```typescript
287
- createLinkPlugin(options?: {
350
+ LinkPlugin(options?: {
288
351
  openOnClick?: boolean;
289
352
  validate?: (url: string) => boolean;
290
353
  onLinkClick?: (url: string) => void;
@@ -293,7 +356,7 @@ createLinkPlugin(options?: {
293
356
  })
294
357
 
295
358
  // Example
296
- const linkPlugin = createLinkPlugin({
359
+ const linkPlugin = LinkPlugin({
297
360
  openOnClick: false,
298
361
  validate: (url) => {
299
362
  return url.startsWith('http://') || url.startsWith('https://');
@@ -309,7 +372,7 @@ const linkPlugin = createLinkPlugin({
309
372
 
310
373
  #### Table Plugin
311
374
  ```typescript
312
- createTablePlugin(options?: {
375
+ TablePlugin(options?: {
313
376
  allowResize?: boolean;
314
377
  defaultRows?: number;
315
378
  defaultCols?: number;
@@ -320,7 +383,7 @@ createTablePlugin(options?: {
320
383
  })
321
384
 
322
385
  // Example
323
- const tablePlugin = createTablePlugin({
386
+ const tablePlugin = TablePlugin({
324
387
  allowResize: true,
325
388
  defaultRows: 3,
326
389
  defaultCols: 3,
@@ -333,7 +396,7 @@ const tablePlugin = createTablePlugin({
333
396
 
334
397
  #### Math Plugin
335
398
  ```typescript
336
- createMathPlugin(options?: {
399
+ MathPlugin(options?: {
337
400
  engine?: 'katex' | 'mathjax';
338
401
  inline?: boolean;
339
402
  display?: boolean;
@@ -341,7 +404,7 @@ createMathPlugin(options?: {
341
404
  })
342
405
 
343
406
  // Example
344
- const mathPlugin = createMathPlugin({
407
+ const mathPlugin = MathPlugin({
345
408
  engine: 'katex',
346
409
  inline: true,
347
410
  display: true,
@@ -354,7 +417,7 @@ const mathPlugin = createMathPlugin({
354
417
 
355
418
  #### Comments Plugin
356
419
  ```typescript
357
- createCommentsPlugin(options?: {
420
+ CommentsPlugin(options?: {
358
421
  onCommentAdd?: (comment: Comment) => void;
359
422
  onCommentEdit?: (comment: Comment) => void;
360
423
  onCommentDelete?: (commentId: string) => void;
@@ -365,7 +428,7 @@ createCommentsPlugin(options?: {
365
428
 
366
429
  #### Document Manager Plugin
367
430
  ```typescript
368
- createDocumentManagerPlugin(options?: {
431
+ DocumentManagerPlugin(options?: {
369
432
  export?: {
370
433
  word?: boolean;
371
434
  pdf?: boolean;
@@ -381,7 +444,7 @@ createDocumentManagerPlugin(options?: {
381
444
  })
382
445
 
383
446
  // Example
384
- const documentManagerPlugin = createDocumentManagerPlugin({
447
+ const documentManagerPlugin = DocumentManagerPlugin({
385
448
  export: {
386
449
  word: true,
387
450
  pdf: true,
@@ -393,7 +456,7 @@ const documentManagerPlugin = createDocumentManagerPlugin({
393
456
 
394
457
  #### Spell Check Plugin
395
458
  ```typescript
396
- createSpellCheckPlugin(options?: {
459
+ SpellCheckPlugin(options?: {
397
460
  language?: string; // Default: 'en-US'
398
461
  customDictionary?: string[];
399
462
  ignoreUppercase?: boolean;
@@ -403,7 +466,7 @@ createSpellCheckPlugin(options?: {
403
466
 
404
467
  #### Accessibility Checker Plugin
405
468
  ```typescript
406
- createA11yCheckerPlugin(options?: {
469
+ A11yCheckerPlugin(options?: {
407
470
  rules?: string[];
408
471
  autoCheck?: boolean;
409
472
  severity?: 'error' | 'warning' | 'info';
@@ -414,7 +477,7 @@ createA11yCheckerPlugin(options?: {
414
477
 
415
478
  #### History Plugin
416
479
  ```typescript
417
- createHistoryPlugin(options?: {
480
+ HistoryPlugin(options?: {
418
481
  depth?: number; // Default: 100
419
482
  keyboard?: {
420
483
  undo?: string; // Default: 'Mod-z'
@@ -425,7 +488,7 @@ createHistoryPlugin(options?: {
425
488
 
426
489
  #### Fullscreen Plugin
427
490
  ```typescript
428
- createFullscreenPlugin(options?: {
491
+ FullscreenPlugin(options?: {
429
492
  keyboard?: string; // Default: 'F11'
430
493
  onEnter?: () => void;
431
494
  onExit?: () => void;
@@ -438,29 +501,29 @@ createFullscreenPlugin(options?: {
438
501
 
439
502
  ```typescript
440
503
  import {
441
- createBoldPlugin,
442
- createItalicPlugin,
443
- createHeadingPlugin,
444
- createParagraphPlugin,
445
- createLinkPlugin,
446
- createImagePlugin,
447
- createListPlugin,
448
- createBlockquotePlugin,
449
- createHistoryPlugin
504
+ BoldPlugin,
505
+ ItalicPlugin,
506
+ HeadingPlugin,
507
+ ParagraphPlugin,
508
+ LinkPlugin,
509
+ MediaManagerPlugin,
510
+ ListPlugin,
511
+ BlockquotePlugin,
512
+ HistoryPlugin
450
513
  } from '@editora/plugins';
451
514
 
452
515
  const blogPlugins = [
453
- createBoldPlugin(),
454
- createItalicPlugin(),
455
- createHeadingPlugin({ levels: [1, 2, 3] }),
456
- createLinkPlugin({ targetBlank: true }),
457
- createImagePlugin({
516
+ BoldPlugin(),
517
+ ItalicPlugin(),
518
+ HeadingPlugin({ levels: [1, 2, 3] }),
519
+ LinkPlugin({ targetBlank: true }),
520
+ MediaManagerPlugin({
458
521
  upload: uploadImage,
459
522
  maxSize: 2 * 1024 * 1024
460
523
  }),
461
- createListPlugin(),
462
- createBlockquotePlugin(),
463
- createHistoryPlugin()
524
+ ListPlugin(),
525
+ BlockquotePlugin(),
526
+ HistoryPlugin()
464
527
  ];
465
528
  ```
466
529
 
@@ -468,23 +531,23 @@ const blogPlugins = [
468
531
 
469
532
  ```typescript
470
533
  import {
471
- createBoldPlugin,
472
- createItalicPlugin,
473
- createCodePlugin,
474
- createCodeSamplePlugin,
475
- createHeadingPlugin,
476
- createTablePlugin,
477
- createLinkPlugin,
478
- createAnchorPlugin,
479
- createMathPlugin,
480
- createHistoryPlugin
534
+ BoldPlugin,
535
+ ItalicPlugin,
536
+ CodePlugin,
537
+ CodeSamplePlugin,
538
+ HeadingPlugin,
539
+ TablePlugin,
540
+ LinkPlugin,
541
+ AnchorPlugin,
542
+ MathPlugin,
543
+ HistoryPlugin
481
544
  } from '@editora/plugins';
482
545
 
483
546
  const docsPlugins = [
484
- createBoldPlugin(),
485
- createItalicPlugin(),
486
- createCodePlugin(),
487
- createCodeSamplePlugin({
547
+ BoldPlugin(),
548
+ ItalicPlugin(),
549
+ CodePlugin(),
550
+ CodeSamplePlugin({
488
551
  languages: [
489
552
  { name: 'JavaScript', value: 'javascript' },
490
553
  { name: 'TypeScript', value: 'typescript' },
@@ -492,12 +555,12 @@ const docsPlugins = [
492
555
  ],
493
556
  lineNumbers: true
494
557
  }),
495
- createHeadingPlugin(),
496
- createTablePlugin({ headerRow: true }),
497
- createLinkPlugin(),
498
- createAnchorPlugin(),
499
- createMathPlugin({ engine: 'katex' }),
500
- createHistoryPlugin()
558
+ HeadingPlugin(),
559
+ TablePlugin({ headerRow: true }),
560
+ LinkPlugin(),
561
+ AnchorPlugin(),
562
+ MathPlugin({ engine: 'katex' }),
563
+ HistoryPlugin()
501
564
  ];
502
565
  ```
503
566
 
@@ -505,17 +568,17 @@ const docsPlugins = [
505
568
 
506
569
  ```typescript
507
570
  import {
508
- createBoldPlugin,
509
- createItalicPlugin,
510
- createCommentsPlugin,
511
- createHistoryPlugin,
512
- createMergeTagPlugin
571
+ BoldPlugin,
572
+ ItalicPlugin,
573
+ CommentsPlugin,
574
+ HistoryPlugin,
575
+ MergeTagPlugin
513
576
  } from '@editora/plugins';
514
577
 
515
578
  const collaborativePlugins = [
516
- createBoldPlugin(),
517
- createItalicPlugin(),
518
- createCommentsPlugin({
579
+ BoldPlugin(),
580
+ ItalicPlugin(),
581
+ CommentsPlugin({
519
582
  onCommentAdd: async (comment) => {
520
583
  await saveComment(comment);
521
584
  },
@@ -523,14 +586,14 @@ const collaborativePlugins = [
523
586
  await resolveComment(commentId);
524
587
  }
525
588
  }),
526
- createMergeTagPlugin({
589
+ MergeTagPlugin({
527
590
  tags: [
528
591
  { label: 'First Name', value: '{{firstName}}' },
529
592
  { label: 'Last Name', value: '{{lastName}}' },
530
593
  { label: 'Email', value: '{{email}}' }
531
594
  ]
532
595
  }),
533
- createHistoryPlugin()
596
+ HistoryPlugin()
534
597
  ];
535
598
  ```
536
599
 
@@ -0,0 +1,109 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const B=new Set,v=[],f=t=>{v.push(t)},x='[data-theme="dark"], .dark, .editora-theme-dark';f({id:"image-alt-text",wcag:"1.1.1",description:"Images must have alt text",severity:"error",selector:"img",evaluate(t,n){const e=t;return e.hasAttribute("role")&&e.getAttribute("role")==="presentation"||e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="image-alt-text"?null:!e.hasAttribute("alt")||e.getAttribute("alt")?.trim()===""?{id:`img-alt-${n.cache.get("imgIdx")}`,rule:"image-alt-text",wcag:"1.1.1",severity:"error",message:"Image missing alt text",nodePath:n.cache.get("imgPath"),element:e,suggestion:"Add descriptive alt text to all images",fixable:!0,fixLabel:"Add empty alt"}:null},fix(t){t.element&&t.element.setAttribute("alt","")}});f({id:"empty-interactive",wcag:"4.1.2",description:"Interactive elements must have accessible names",severity:"error",selector:'button, a, [role="button"]',evaluate(t,n){const e=t;if(e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="empty-interactive")return null;const r=e.textContent?.trim(),a=e.hasAttribute("aria-label"),o=e.hasAttribute("aria-labelledby"),s=e.hasAttribute("title");return!r&&!a&&!o&&!s?{id:`interactive-empty-${n.cache.get("buttonIdx")}`,rule:"empty-interactive",wcag:"4.1.2",severity:"error",message:"Interactive element has no accessible name",nodePath:n.cache.get("buttonPath"),element:e,suggestion:"Add text, aria-label, aria-labelledby, or title",fixable:!0,fixLabel:"Add aria-label"}:null},fix(t){t.element&&t.element.setAttribute("aria-label","Button")}});f({id:"form-label",wcag:"1.3.1",description:"Form controls must have labels",severity:"error",selector:"input, textarea, select",evaluate(t,n){const e=t;if(e.hasAttribute("type")&&e.getAttribute("type")==="hidden"||e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="form-label")return null;const r=n.doc.querySelector(`label[for="${e.getAttribute("id")}"]`),a=e.hasAttribute("aria-label"),o=e.hasAttribute("aria-labelledby");return!r&&!a&&!o?{id:`form-label-${n.cache.get("inputIdx")}`,rule:"form-label",wcag:"1.3.1",severity:"error",message:"Form control missing label",nodePath:n.cache.get("inputPath"),element:e,suggestion:"Add <label>, aria-label, or aria-labelledby",fixable:!0,fixLabel:"Add aria-label"}:null},fix(t){t.element&&t.element.setAttribute("aria-label","Input")}});f({id:"table-headers",wcag:"1.3.1",description:"Tables must have header rows",severity:"error",selector:"table",evaluate(t,n){const e=t;if(e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="table-headers")return null;const r=e.querySelectorAll("th"),a=e.querySelectorAll("tr");return r.length===0&&a.length>0?{id:`table-no-headers-${n.cache.get("tableIdx")}`,rule:"table-headers",wcag:"1.3.1",severity:"error",message:"Table missing header row (<th> elements)",nodePath:n.cache.get("tablePath"),element:e,suggestion:"Add <th> elements to first row",fixable:!0,fixLabel:"Convert first row to headers"}:null},fix(t){if(t.element){const e=t.element.querySelector("tr");e&&Array.from(e.children).forEach(r=>{if(r.tagName==="TD"){const a=document.createElement("th");a.innerHTML=r.innerHTML,e.replaceChild(a,r)}})}}});f({id:"heading-empty",wcag:"1.3.1",description:"Headings must not be empty",severity:"error",selector:"h1, h2, h3, h4, h5, h6",evaluate(t,n){const e=t;if(e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="heading-empty")return null;const r=e.textContent?.replace(/\s+/g,"")||"",a=e.childNodes.length===1&&e.childNodes[0].nodeName==="BR";return!r&&!a?{id:`heading-empty-${n.cache.get("headingIdx")}`,rule:"heading-empty",wcag:"1.3.1",severity:"error",message:`Empty ${e.tagName.toLowerCase()} heading`,nodePath:n.cache.get("headingPath"),element:e,suggestion:"All headings must contain text",fixable:!1}:null}});f({id:"heading-order",wcag:"1.3.1",description:"Headings should not skip levels",severity:"warning",selector:"h1, h2, h3, h4, h5, h6",evaluate(t,n){const e=t,r=parseInt(e.tagName[1]),a=n.cache.get("previousHeadingLevel")||r;return n.cache.set("previousHeadingLevel",r),r-a>1?{id:`heading-order-${n.cache.get("headingIdx")}`,rule:"heading-order",wcag:"1.3.1",severity:"warning",message:`Heading skips level (${a} → ${r})`,nodePath:n.cache.get("headingPath"),element:e,suggestion:`Use heading level ${a+1} instead`,fixable:!1}:null}});f({id:"link-text",wcag:"2.4.4",description:"Links must have descriptive text",severity:"error",selector:"a",evaluate(t,n){const e=t;if(e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="link-text")return null;const r=e.textContent?.replace(/\s+/g,"").toLowerCase()||"",a=e.childNodes.length===1&&e.childNodes[0].nodeName==="BR",o=["clickhere","readmore","link","here","this","page"];return!r&&!a?{id:`link-empty-${n.cache.get("aIdx")}`,rule:"link-text",wcag:"2.4.4",severity:"error",message:"Link has no text content",nodePath:n.cache.get("aPath"),element:e,suggestion:"All links must have descriptive text",fixable:!0,fixLabel:"Insert placeholder"}:o.some(s=>r.includes(s))?{id:`link-vague-${n.cache.get("aIdx")}`,rule:"link-text",wcag:"2.4.4",severity:"warning",message:`Vague link text: "${e.textContent?.trim()}"`,nodePath:n.cache.get("aPath"),element:e,suggestion:"Use descriptive link text",fixable:!1}:null},fix(t){t.element&&(t.element.textContent="Link")}});f({id:"list-structure",wcag:"1.3.1",description:"Lists must only contain <li> children",severity:"error",selector:"ul, ol",evaluate(t,n){const e=t;if(e.hasAttribute("data-a11y-ignore")&&e.getAttribute("data-a11y-ignore")==="list-structure")return null;const r=e.querySelectorAll(":scope > li");return Array.from(e.children).filter(o=>o.tagName!=="LI").length>0?{id:`list-structure-${n.cache.get("ulIdx")}`,rule:"list-structure",wcag:"1.3.1",severity:"error",message:"List contains non-li elements",nodePath:n.cache.get("ulPath"),element:e,suggestion:"All direct children of ul/ol must be li elements",fixable:!1}:r.length===0?{id:`list-empty-${n.cache.get("ulIdx")}`,rule:"list-structure",wcag:"1.3.1",severity:"warning",message:"Empty list element",nodePath:n.cache.get("ulPath"),element:e,suggestion:"Remove empty lists or add list items",fixable:!1}:null}});const A=()=>{const t=window.getSelection();if(t&&t.rangeCount>0){let e=t.getRangeAt(0).startContainer;for(;e&&e!==document.body;){if(e.nodeType===Node.ELEMENT_NODE){const r=e;if(r.getAttribute("contenteditable")==="true")return r}e=e.parentNode}}const n=document.activeElement;if(n){if(n.getAttribute("contenteditable")==="true")return n;const e=n.closest('[contenteditable="true"]');if(e)return e}return document.querySelector('[contenteditable="true"]')},T=()=>{if(A()?.closest(x))return!0;const n=window.getSelection();if(n&&n.rangeCount>0){const r=n.getRangeAt(0).startContainer;if((r.nodeType===Node.ELEMENT_NODE?r:r.parentElement)?.closest(x))return!0}return document.activeElement?.closest(x)?!0:document.body.matches(x)||document.documentElement.matches(x)},w=()=>{const t=A();if(!t)return[];const n=[],e={doc:t.ownerDocument||document,cache:new Map},r=e.doc.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,null);let a=r.currentNode,o={},s={},p=0;for(;a&&p<5e3;){const h=a,i=h.tagName?.toLowerCase?.()||"";if(h.hidden||h.style.display==="none"||h.style.visibility==="hidden"){a=r.nextNode(),p++;continue}o[i]=(o[i]||0)+1,s[i]=`${i}[${o[i]-1}]`;for(const u of v){if(B.has(u.id)||u.selector&&!a.matches?.(u.selector))continue;e.cache.set(`${i}Idx`,o[i]-1),e.cache.set(`${i}Path`,s[i]),/^h[1-6]$/.test(i)&&(e.cache.set("headingIdx",o[i]-1),e.cache.set("headingPath",s[i])),i==="a"&&(e.cache.set("aIdx",o[i]-1),e.cache.set("aPath",s[i])),i==="table"&&(e.cache.set("tableIdx",o[i]-1),e.cache.set("tablePath",s[i])),i==="button"&&(e.cache.set("buttonIdx",o[i]-1),e.cache.set("buttonPath",s[i])),i==="input"&&(e.cache.set("inputIdx",o[i]-1),e.cache.set("inputPath",s[i])),(i==="ul"||i==="ol")&&(e.cache.set("ulIdx",o[i]-1),e.cache.set("ulPath",s[i]));const m=u.evaluate(a,e);m&&n.push(m)}a=r.nextNode(),p++}return n},b=(t,n=!0)=>{t.element&&(n?(t.element.classList.add("a11y-highlighted"),t.element.style.outline="2px solid #ff9800",t.element.style.backgroundColor="#fff3cd"):(t.element.classList.remove("a11y-highlighted"),t.element.style.outline="",t.element.style.backgroundColor=""))},I=t=>{t||(t=w());const n=t.filter(a=>a.severity==="error").length,e=t.filter(a=>a.severity==="warning").length;let r=100-n*20-e*5;return Math.max(0,r)},P=t=>{const n=v.find(e=>e.id===t.rule);n&&n.fix&&n.fix(t)},k=()=>{const t=w(),n=I(t),r=T()?{overlay:"rgba(0, 0, 0, 0.62)",dialogBg:"#1f2937",panelBg:"#222d3a",border:"#3b4657",text:"#e2e8f0",muted:"#9fb0c6",closeHover:"#334155",summaryBg:"#111827",issueBg:"#1f2937",issueHoverBg:"#273244",issueBorder:"#4b5563",issueHoverBorder:"#58a6ff",fixBtn:"#3b82f6",fixBtnHover:"#2563eb"}:{overlay:"rgba(0, 0, 0, 0.5)",dialogBg:"#ffffff",panelBg:"#ffffff",border:"#e0e0e0",text:"#1f2937",muted:"#666666",closeHover:"#f0f0f0",summaryBg:"#f5f5f5",issueBg:"#ffffff",issueHoverBg:"#f5f9ff",issueBorder:"#e0e0e0",issueHoverBorder:"#2196f3",fixBtn:"#2196f3",fixBtnHover:"#1976d2"},a=document.createElement("div");a.className="a11y-dialog-overlay",a.style.cssText=`
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ right: 0;
6
+ bottom: 0;
7
+ background: ${r.overlay};
8
+ z-index: 10000;
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ `;const o=document.createElement("div");o.className="a11y-dialog",o.style.cssText=`
13
+ background: ${r.dialogBg};
14
+ border: 1px solid ${r.border};
15
+ color: ${r.text};
16
+ border-radius: 8px;
17
+ max-width: 800px;
18
+ width: 90%;
19
+ max-height: 80vh;
20
+ display: flex;
21
+ flex-direction: column;
22
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
23
+ `;const s=document.createElement("div");s.style.cssText=`
24
+ padding: 20px;
25
+ border-bottom: 1px solid ${r.border};
26
+ background: ${r.panelBg};
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: space-between;
30
+ `;const p=document.createElement("h2");p.style.cssText=`margin: 0; font-size: 20px; font-weight: 600; color: ${r.text};`,p.textContent="Accessibility Checker";const h=document.createElement("div");h.style.cssText=`
31
+ font-size: 24px;
32
+ font-weight: bold;
33
+ padding: 8px 16px;
34
+ border-radius: 4px;
35
+ background: ${n>=80?"#4caf50":n>=60?"#ff9800":"#f44336"};
36
+ color: white;
37
+ `,h.textContent=`${n}/100`;const i=document.createElement("button");i.textContent="✕",i.style.cssText=`
38
+ background: none;
39
+ border: none;
40
+ font-size: 24px;
41
+ cursor: pointer;
42
+ padding: 0;
43
+ width: 32px;
44
+ height: 32px;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ border-radius: 4px;
49
+ color: ${r.muted};
50
+ `,i.onmouseover=()=>{i.style.background=r.closeHover,i.style.color="#f8fafc"},i.onmouseout=()=>{i.style.background="none",i.style.color=r.muted},i.onclick=()=>{t.forEach(g=>b(g,!1)),a.remove()};const u=document.createElement("div");u.style.cssText="display: flex; align-items: center; gap: 16px;",u.appendChild(p),u.appendChild(h),s.appendChild(u),s.appendChild(i);const m=document.createElement("div");if(m.style.cssText=`
51
+ flex: 1;
52
+ overflow-y: auto;
53
+ padding: 20px;
54
+ background: ${r.dialogBg};
55
+ `,t.length===0)m.innerHTML=`
56
+ <div style="text-align: center; padding: 40px 20px;">
57
+ <div style="font-size: 48px; margin-bottom: 16px;">✅</div>
58
+ <h3 style="margin: 0 0 8px 0; color: #4caf50;">No issues found!</h3>
59
+ <p style="margin: 0; color: ${r.muted};">Your content meets WCAG 2.1 AA standards.</p>
60
+ </div>
61
+ `;else{const g=document.createElement("div");g.style.cssText=`
62
+ background: ${r.summaryBg};
63
+ border: 1px solid ${r.border};
64
+ padding: 12px 16px;
65
+ border-radius: 6px;
66
+ margin-bottom: 20px;
67
+ display: flex;
68
+ gap: 20px;
69
+ `;const y=t.filter(l=>l.severity==="error").length,$=t.filter(l=>l.severity==="warning").length,E=t.filter(l=>l.severity==="info").length;g.innerHTML=`
70
+ <div><strong style="color: #f44336;">${y}</strong> <span style="color: ${r.muted};">Errors</span></div>
71
+ <div><strong style="color: #ff9800;">${$}</strong> <span style="color: ${r.muted};">Warnings</span></div>
72
+ <div><strong style="color: #2196f3;">${E}</strong> <span style="color: ${r.muted};">Info</span></div>
73
+ `,m.appendChild(g),t.forEach(l=>{const c=document.createElement("div");c.style.cssText=`
74
+ border: 1px solid ${r.issueBorder};
75
+ border-radius: 6px;
76
+ padding: 16px;
77
+ margin-bottom: 12px;
78
+ transition: all 0.2s;
79
+ background: ${r.issueBg};
80
+ color: ${r.text};
81
+ `,c.onmouseover=()=>{c.style.borderColor=r.issueHoverBorder,c.style.background=r.issueHoverBg,b(l,!0)},c.onmouseout=()=>{c.style.borderColor=r.issueBorder,c.style.background=r.issueBg,b(l,!1)};const L=l.severity==="error"?"#f44336":l.severity==="warning"?"#ff9800":"#2196f3";if(c.innerHTML=`
82
+ <div style="display: flex; align-items: start; gap: 12px; margin-bottom: 8px;">
83
+ <span style="
84
+ background: ${L};
85
+ color: white;
86
+ padding: 2px 8px;
87
+ border-radius: 4px;
88
+ font-size: 12px;
89
+ font-weight: 600;
90
+ text-transform: uppercase;
91
+ ">${l.severity}</span>
92
+ <div style="flex: 1;">
93
+ <div style="font-weight: 600; margin-bottom: 4px;">${l.message}</div>
94
+ <div style="font-size: 12px; color: ${r.muted};">WCAG ${l.wcag} · ${l.rule}</div>
95
+ </div>
96
+ </div>
97
+ <div style="font-size: 14px; color: ${r.text}; margin-bottom: 8px; padding-left: 68px;">
98
+ ${l.suggestion||""}
99
+ </div>
100
+ `,l.fixable){const d=document.createElement("button");d.textContent=`🔧 ${l.fixLabel||"Auto-fix"}`,d.style.cssText=`
101
+ background: ${r.fixBtn};
102
+ color: white;
103
+ border: none;
104
+ padding: 6px 12px;
105
+ border-radius: 4px;
106
+ cursor: pointer;
107
+ font-size: 13px;
108
+ margin-left: 68px;
109
+ `,d.onmouseover=()=>d.style.background=r.fixBtnHover,d.onmouseout=()=>d.style.background=r.fixBtn,d.onclick=()=>{P(l),d.textContent="✓ Fixed",d.style.background="#4caf50",d.disabled=!0,d.style.cursor="not-allowed",b(l,!1),setTimeout(()=>{a.remove(),k()},1e3)},c.appendChild(d)}m.appendChild(c)})}o.appendChild(s),o.appendChild(m),a.appendChild(o),document.body.appendChild(a),a.onclick=g=>{g.target===a&&(t.forEach(y=>b(y,!1)),a.remove())};const C=g=>{g.key==="Escape"&&(t.forEach(y=>b(y,!1)),a.remove(),document.removeEventListener("keydown",C))};document.addEventListener("keydown",C)},H=()=>({name:"a11yChecker",toolbar:[{label:"Accessibility",command:"toggleA11yChecker",icon:'<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" clip-rule="evenodd" d="M9 6.82954C10.1652 6.4177 11 5.30646 11 4.00024C11 2.34339 9.65686 1.00024 8 1.00024C6.34315 1.00024 5 2.34339 5 4.00024C5 5.30646 5.83481 6.4177 7 6.82954V12.0002C7 13.6571 8.34315 15.0002 10 15.0002H14.9296C15.264 15.0002 15.5762 15.1673 15.7617 15.4455L18.4913 19.54C19.1914 20.5901 20.6772 20.7373 21.5696 19.8448L22.7071 18.7074C23.0976 18.3168 23.0976 17.6837 22.7071 17.2931C22.3166 16.9026 21.6834 16.9026 21.2929 17.2931L20.1554 18.4306L17.4258 14.3361C16.8694 13.5015 15.9327 13.0002 14.9296 13.0002H10C9.44772 13.0002 9 12.5525 9 12.0002V11.0002H15C15.5523 11.0002 16 10.5525 16 10.0002C16 9.44796 15.5523 9.00025 15 9.00025H9V6.82954ZM8 5.10758C7.38844 5.10758 6.89267 4.61181 6.89267 4.00024C6.89267 3.38868 7.38844 2.89291 8 2.89291C8.61157 2.89291 9.10734 3.38868 9.10734 4.00024C9.10734 4.61181 8.61157 5.10758 8 5.10758Z" fill="#0F0F0F"></path> <path d="M4.6328 9.07414C5.10517 8.78987 5.69738 9.0279 5.91645 9.53381C6.13552 10.0397 5.89604 10.6205 5.43795 10.9272C4.92993 11.2673 4.48018 11.6911 4.10882 12.1826C3.53598 12.9408 3.16922 13.8345 3.04425 14.7765C2.91928 15.7185 3.04036 16.6768 3.3957 17.5582C3.75103 18.4395 4.32852 19.2138 5.07194 19.8058C5.81535 20.3977 6.69937 20.787 7.63791 20.9359C8.57646 21.0847 9.53756 20.988 10.4276 20.6552C11.3177 20.3223 12.1065 19.7647 12.7171 19.0366C13.1129 18.5645 13.4251 18.0313 13.6428 17.46C13.8391 16.9448 14.3514 16.5813 14.8936 16.6815C15.4357 16.7816 15.8004 17.3054 15.6291 17.8295C15.3326 18.7372 14.8644 19.583 14.2468 20.3194C13.4147 21.3117 12.3399 22.0716 11.1269 22.5252C9.91394 22.9787 8.6042 23.1105 7.32518 22.9077C6.04617 22.7048 4.84148 22.1742 3.82838 21.3676C2.81528 20.561 2.02831 19.5058 1.54407 18.3047C1.05983 17.1037 0.894836 15.7977 1.06514 14.5139C1.23545 13.2302 1.73525 12.0124 2.51589 10.9791C3.09523 10.2123 3.81459 9.56654 4.6328 9.07414Z" fill="#0F0F0F"></path> </g></svg>',shortcut:"Mod-Shift-Alt-a"}],commands:{toggleA11yChecker:()=>{try{return k(),!0}catch(t){return console.error("Failed to open accessibility checker:",t),!1}}},keymap:{"Mod-Shift-Alt-a":"toggleA11yChecker"}});exports.A11yCheckerPlugin=H;