neiki-editor 2.8.0 → 2.9.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/README.md +729 -716
- package/dist/neiki-editor.css +2212 -2204
- package/dist/neiki-editor.js +5140 -5003
- package/dist/neiki-editor.min.css +1 -1
- package/dist/neiki-editor.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,716 +1,729 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
</
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript">
|
|
9
|
-
<img src="https://img.shields.io/badge/php-%23777BB4.svg?style=for-the-badge&logo=php&logoColor=white" alt="PHP">
|
|
10
|
-
<img src="https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white" alt="HTML5">
|
|
11
|
-
<img src="https://img.shields.io/badge/css-%23663399.svg?style=for-the-badge&logo=css&logoColor=white" alt="CSS">
|
|
12
|
-
<br>
|
|
13
|
-
<img src="https://img.shields.io/badge/License-MIT-2563EB?style=for-the-badge&logo=open-source-initiative&logoColor=white&labelColor=000F15&logoWidth=20" alt="License">
|
|
14
|
-
<img src="https://img.shields.io/badge/Version-2.
|
|
15
|
-
</p>
|
|
16
|
-
|
|
17
|
-
<p align="center">
|
|
18
|
-
<b>Lightweight WYSIWYG Rich Text Editor</b><br>
|
|
19
|
-
<i>Easy to integrate, fully customizable, zero dependencies.</i>
|
|
20
|
-
</p>
|
|
21
|
-
|
|
22
|
-
<p align="center">
|
|
23
|
-
<img src="https://img.shields.io/badge/Features-30%2B%20Tools-3b82f6?style=flat&labelColor=383C43" />
|
|
24
|
-
<img src="https://img.shields.io/badge/Themes-Light%20%26%20Dark-8b5cf6?style=flat&labelColor=383C43" />
|
|
25
|
-
<img src="https://img.shields.io/badge/Setup-Zero%20Config-22c55e?style=flat&labelColor=383C43" />
|
|
26
|
-
<img src="https://img.shields.io/badge/Size-Lightweight-f97316?style=flat&labelColor=383C43" />
|
|
27
|
-
</p>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
</p>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
|
175
|
-
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
|
189
|
-
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
|
216
|
-
|
|
217
|
-
| `
|
|
218
|
-
| `
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
222
|
-
|
|
223
|
-
###
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
|
228
|
-
|
|
229
|
-
|
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
| **
|
|
244
|
-
| **
|
|
245
|
-
| **
|
|
246
|
-
| **
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
|
258
|
-
|
|
|
259
|
-
|
|
|
260
|
-
|
|
|
261
|
-
|
|
|
262
|
-
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
//
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
```javascript
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
editor.
|
|
380
|
-
editor.
|
|
381
|
-
|
|
382
|
-
editor.
|
|
383
|
-
editor.
|
|
384
|
-
|
|
385
|
-
editor.
|
|
386
|
-
editor.
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
editor.
|
|
403
|
-
editor.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
##
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
- **
|
|
514
|
-
- **
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
###
|
|
612
|
-
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
├──
|
|
700
|
-
├──
|
|
701
|
-
├──
|
|
702
|
-
├──
|
|
703
|
-
└──
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.png" alt="Neiki's Editor" width="400">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Neiki's Editor</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E" alt="JavaScript">
|
|
9
|
+
<img src="https://img.shields.io/badge/php-%23777BB4.svg?style=for-the-badge&logo=php&logoColor=white" alt="PHP">
|
|
10
|
+
<img src="https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white" alt="HTML5">
|
|
11
|
+
<img src="https://img.shields.io/badge/css-%23663399.svg?style=for-the-badge&logo=css&logoColor=white" alt="CSS">
|
|
12
|
+
<br>
|
|
13
|
+
<img src="https://img.shields.io/badge/License-MIT-2563EB?style=for-the-badge&logo=open-source-initiative&logoColor=white&labelColor=000F15&logoWidth=20" alt="License">
|
|
14
|
+
<img src="https://img.shields.io/badge/Version-2.9.0-2563EB?style=for-the-badge&logo=semantic-release&logoColor=white&labelColor=000F15&logoWidth=20" alt="Version">
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<b>Lightweight WYSIWYG Rich Text Editor</b><br>
|
|
19
|
+
<i>Easy to integrate, fully customizable, zero dependencies.</i>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<img src="https://img.shields.io/badge/Features-30%2B%20Tools-3b82f6?style=flat&labelColor=383C43" />
|
|
24
|
+
<img src="https://img.shields.io/badge/Themes-Light%20%26%20Dark-8b5cf6?style=flat&labelColor=383C43" />
|
|
25
|
+
<img src="https://img.shields.io/badge/Setup-Zero%20Config-22c55e?style=flat&labelColor=383C43" />
|
|
26
|
+
<img src="https://img.shields.io/badge/Size-Lightweight-f97316?style=flat&labelColor=383C43" />
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
<p align="center">
|
|
30
|
+
<a href="https://oosmetrics.com/repo/neikiri/neiki-editor"><img src="https://api.oosmetrics.com/api/v1/badge/achievement/875222f0-f55c-4209-b894-8bf60b75c590.svg" alt="oosmetrics"/></a>
|
|
31
|
+
<a href="https://oosmetrics.com/repo/neikiri/neiki-editor"><img src="https://api.oosmetrics.com/api/v1/badge/achievement/71eabb82-6f56-4dc3-bb41-e82a5f8cf939.svg" alt="oosmetrics"/></a>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src="preview.png" alt="Neiki's Editor" width="900">
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
**Live version:** [https://neiki.eu/editor](https://neiki.eu/editor)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 💡 Why Neiki's Editor?
|
|
46
|
+
|
|
47
|
+
Most WYSIWYG editors either pull in a tree of dependencies or force you into a heavyweight framework. Neiki's Editor is a **single file with zero dependencies** — drop one `<script>` tag into any page and you get 30+ formatting tools, drag-and-drop blocks, image resizing, a plugin API, and full i18n out of the box. It stays tiny enough for a quick prototype yet powerful enough for a production CMS, so you spend time writing content instead of wrestling with your editor.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
## 📦 Installation
|
|
51
|
+
|
|
52
|
+
Add this single line — CSS is included automatically, always the **latest version**:
|
|
53
|
+
|
|
54
|
+
```html
|
|
55
|
+
<script src="https://cdn.neiki.eu/neiki-editor/neiki-editor.min.js"></script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
<details>
|
|
59
|
+
<summary><b>📋 More installation options</b> (pinned version, separate CSS/JS, jsDelivr, npm, self-hosted)</summary>
|
|
60
|
+
<br>
|
|
61
|
+
|
|
62
|
+
#### Pin a specific version
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<script src="https://cdn.neiki.eu/neiki-editor/2.9.0/neiki-editor.min.js"></script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### Load CSS and JS separately
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<!-- Latest -->
|
|
72
|
+
<link rel="stylesheet" href="https://cdn.neiki.eu/neiki-editor/neiki-editor.css">
|
|
73
|
+
<script src="https://cdn.neiki.eu/neiki-editor/neiki-editor.js"></script>
|
|
74
|
+
|
|
75
|
+
<!-- Or pinned -->
|
|
76
|
+
<link rel="stylesheet" href="https://cdn.neiki.eu/neiki-editor/2.9.0/neiki-editor.css">
|
|
77
|
+
<script src="https://cdn.neiki.eu/neiki-editor/2.9.0/neiki-editor.js"></script>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Alternative CDN — jsDelivr
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<!-- Latest -->
|
|
84
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.min.js"></script>
|
|
85
|
+
|
|
86
|
+
<!-- Pinned -->
|
|
87
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@2.9.0/dist/neiki-editor.min.js"></script>
|
|
88
|
+
|
|
89
|
+
<!-- Separate files (latest) -->
|
|
90
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.css">
|
|
91
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.js"></script>
|
|
92
|
+
|
|
93
|
+
<!-- Separate files (pinned) -->
|
|
94
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@2.9.0/dist/neiki-editor.css">
|
|
95
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@2.9.0/dist/neiki-editor.js"></script>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Package Manager
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm install neiki-editor
|
|
102
|
+
# or
|
|
103
|
+
yarn add neiki-editor
|
|
104
|
+
# or
|
|
105
|
+
pnpm add neiki-editor
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Self-hosted
|
|
109
|
+
|
|
110
|
+
```html
|
|
111
|
+
<script src="path/to/neiki-editor.min.js"></script>
|
|
112
|
+
|
|
113
|
+
<!-- Or separate files -->
|
|
114
|
+
<link rel="stylesheet" href="path/to/neiki-editor.css">
|
|
115
|
+
<script src="path/to/neiki-editor.js"></script>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
</details>
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 🚀 Quick Start
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<textarea id="editor"></textarea>
|
|
126
|
+
|
|
127
|
+
<script>
|
|
128
|
+
const editor = new NeikiEditor('#editor');
|
|
129
|
+
</script>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
That's it — zero config required. The editor replaces the `<textarea>` with a full-featured WYSIWYG editor.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## ⚙️ Configuration
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
const editor = new NeikiEditor('#editor', {
|
|
140
|
+
placeholder: 'Start typing...',
|
|
141
|
+
minHeight: 300,
|
|
142
|
+
maxHeight: 600,
|
|
143
|
+
autofocus: false,
|
|
144
|
+
spellcheck: true,
|
|
145
|
+
readonly: false,
|
|
146
|
+
theme: 'light', // 'light' or 'dark'
|
|
147
|
+
language: 'en', // 'en', 'cs', or custom via addTranslation()
|
|
148
|
+
translations: null, // custom translation keys (merged with built-in)
|
|
149
|
+
toolbar: [
|
|
150
|
+
'viewCode', 'undo', 'redo', 'findReplace', '|',
|
|
151
|
+
'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'removeFormat', '|',
|
|
152
|
+
'heading', 'fontFamily', 'fontSize', '|',
|
|
153
|
+
'foreColor', 'backColor', '|',
|
|
154
|
+
'alignLeft', 'alignCenter', 'alignRight', 'alignJustify', '|',
|
|
155
|
+
'indent', 'outdent', '|',
|
|
156
|
+
'bulletList', 'numberedList', 'blockquote', 'horizontalRule', '|',
|
|
157
|
+
'insertDropdown', '|',
|
|
158
|
+
'moreMenu'
|
|
159
|
+
],
|
|
160
|
+
onChange: function(content, editor) {
|
|
161
|
+
console.log('Content changed:', content);
|
|
162
|
+
},
|
|
163
|
+
onSave: function(content, editor) {
|
|
164
|
+
console.log('Save triggered:', content);
|
|
165
|
+
},
|
|
166
|
+
onReady: function(editor) {
|
|
167
|
+
console.log('Editor is ready!');
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Configuration Options
|
|
173
|
+
|
|
174
|
+
| Option | Type | Default | Description |
|
|
175
|
+
|--------|------|---------|-------------|
|
|
176
|
+
| `placeholder` | `string` | `'Start typing...'` | Placeholder text when editor is empty |
|
|
177
|
+
| `minHeight` | `number` | `300` | Minimum height in pixels |
|
|
178
|
+
| `maxHeight` | `number\|null` | `null` | Maximum height in pixels (enables scroll) |
|
|
179
|
+
| `autofocus` | `boolean` | `false` | Focus editor on initialization |
|
|
180
|
+
| `spellcheck` | `boolean` | `true` | Enable browser spellcheck |
|
|
181
|
+
| `readonly` | `boolean` | `false` | Make editor read-only |
|
|
182
|
+
| `theme` | `string` | `'light'` | `'light'` or `'dark'` |
|
|
183
|
+
| `language` | `string` | `'en'` | UI language — `en`, `cs`, `zh`, `es`, `de`, `fr`, `pt`, `ja` |
|
|
184
|
+
| `translations` | `object\|null` | `null` | Custom translation keys (merged with built-in) |
|
|
185
|
+
| `toolbar` | `array` | *(see above)* | Toolbar button configuration |
|
|
186
|
+
| `onChange` | `function\|null` | `null` | Callback on content change |
|
|
187
|
+
| `onSave` | `function\|null` | `null` | Callback on save (triggered by Ctrl+S or More menu → Save) |
|
|
188
|
+
| `onFocus` | `function\|null` | `null` | Callback when editor gains focus |
|
|
189
|
+
| `onBlur` | `function\|null` | `null` | Callback when editor loses focus |
|
|
190
|
+
| `onReady` | `function\|null` | `null` | Callback when editor is ready |
|
|
191
|
+
| `showHelp` | `boolean` | `true` | Show Help button in More menu (⋯) |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 🔧 Toolbar Buttons
|
|
196
|
+
|
|
197
|
+
Use the `toolbar` array to customize which buttons appear and in what order. Use `'|'` for a visual separator between groups. Groups of buttons between separators wrap as whole units on smaller screens.
|
|
198
|
+
|
|
199
|
+
### Text Formatting
|
|
200
|
+
|
|
201
|
+
| Button | Description |
|
|
202
|
+
|--------|-------------|
|
|
203
|
+
| `bold` | Bold text (**Ctrl+B**) |
|
|
204
|
+
| `italic` | Italic text (**Ctrl+I**) |
|
|
205
|
+
| `underline` | Underline text (**Ctrl+U**) |
|
|
206
|
+
| `strikethrough` | Strikethrough text |
|
|
207
|
+
| `subscript` | Subscript text |
|
|
208
|
+
| `superscript` | Superscript text |
|
|
209
|
+
| `removeFormat` | Remove all formatting |
|
|
210
|
+
|
|
211
|
+
> **Note:** When no text is selected, formatting commands (including Remove Formatting) automatically expand to the word at the cursor position.
|
|
212
|
+
|
|
213
|
+
### Text Style
|
|
214
|
+
|
|
215
|
+
| Button | Type | Description |
|
|
216
|
+
|--------|------|-------------|
|
|
217
|
+
| `heading` | Select | Paragraph, H1, H2, H3, H4, H5, H6. Defaults to Paragraph. |
|
|
218
|
+
| `fontSize` | Widget | Font size widget with **[−]** / **[+]** buttons, text input, and dropdown presets: 8, 9, 10, 11, 12, 14, 18, 24, 30, 36, 48, 60, 72, 96 |
|
|
219
|
+
| `fontFamily` | Select | Sans Serif (Arial), Serif (Georgia), Monospace (Consolas), Cursive (Comic Sans MS) |
|
|
220
|
+
| `foreColor` | Color Picker | Text color — palette, native color input, hex code input |
|
|
221
|
+
| `backColor` | Color Picker | Background color — palette, native color input, hex code input |
|
|
222
|
+
|
|
223
|
+
### Alignment & Lists
|
|
224
|
+
|
|
225
|
+
| Button | Description |
|
|
226
|
+
|--------|-------------|
|
|
227
|
+
| `alignLeft` | Align text left |
|
|
228
|
+
| `alignCenter` | Center text |
|
|
229
|
+
| `alignRight` | Align text right |
|
|
230
|
+
| `alignJustify` | Justify text |
|
|
231
|
+
| `bulletList` | Unordered list |
|
|
232
|
+
| `numberedList` | Ordered list |
|
|
233
|
+
| `indent` | Increase indent |
|
|
234
|
+
| `outdent` | Decrease indent |
|
|
235
|
+
|
|
236
|
+
### Insert Dropdown
|
|
237
|
+
|
|
238
|
+
The `insertDropdown` toolbar item renders a single **Insert** button that opens a dropdown containing:
|
|
239
|
+
|
|
240
|
+
| Item | Description |
|
|
241
|
+
|------|-------------|
|
|
242
|
+
| **Link** | Insert/edit hyperlink (**Ctrl+K**) |
|
|
243
|
+
| **Image** | Insert image (URL or file upload → base64) |
|
|
244
|
+
| **Table** | Insert table with custom rows/columns |
|
|
245
|
+
| **Emoji** | Emoji picker (100+ emojis) |
|
|
246
|
+
| **Symbol** | Special characters (©, ®, €, π, Ω, arrows, etc.) |
|
|
247
|
+
|
|
248
|
+
You can still use `link`, `image`, `table`, `emoji`, `specialChars` as standalone toolbar buttons if preferred.
|
|
249
|
+
|
|
250
|
+
### More Menu
|
|
251
|
+
|
|
252
|
+
The `moreMenu` toolbar item renders a **⋯** button (pushed to the right) that opens a dropdown containing:
|
|
253
|
+
|
|
254
|
+
| Item | Description |
|
|
255
|
+
|------|-------------|
|
|
256
|
+
| **Save** | Trigger the `onSave` callback |
|
|
257
|
+
| **Preview** | Open a document preview modal |
|
|
258
|
+
| **Download** | Download content as an HTML file |
|
|
259
|
+
| **Print** | Print editor content |
|
|
260
|
+
| **Autosave** | Toggle autosave to localStorage |
|
|
261
|
+
| **Clear all** | Clear all editor content |
|
|
262
|
+
| **Toggle Theme** | Switch between light/dark theme |
|
|
263
|
+
| **Fullscreen** | Toggle fullscreen mode |
|
|
264
|
+
| **Help** | Show help modal with author, version, and links (configurable via `showHelp`) |
|
|
265
|
+
|
|
266
|
+
### Standalone Tools
|
|
267
|
+
|
|
268
|
+
| Button | Description |
|
|
269
|
+
|--------|-------------|
|
|
270
|
+
| `undo` | Undo (**Ctrl+Z**) |
|
|
271
|
+
| `redo` | Redo (**Ctrl+Y** / **Ctrl+Shift+Z**) |
|
|
272
|
+
| `findReplace` | Find & Replace with regex support |
|
|
273
|
+
| `viewCode` | Toggle HTML source editor |
|
|
274
|
+
| `blockquote` | Block quote |
|
|
275
|
+
| `horizontalRule` | Horizontal line |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 🎨 Themes
|
|
280
|
+
|
|
281
|
+
Neiki's Editor ships with **Light** and **Dark** themes.
|
|
282
|
+
|
|
283
|
+
### Set theme on init:
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
const editor = new NeikiEditor('#editor', {
|
|
287
|
+
theme: 'dark'
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Toggle theme at runtime:
|
|
292
|
+
|
|
293
|
+
Use the **Toggle Theme** item in the More menu (⋯), or toggle programmatically:
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
editor.toggleTheme();
|
|
297
|
+
// or set a specific theme:
|
|
298
|
+
editor.setTheme('dark');
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The selected theme persists across page reloads via `localStorage`.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 🌍 Localization (i18n)
|
|
306
|
+
|
|
307
|
+
Neiki's Editor supports multiple UI languages. Built-in:
|
|
308
|
+
|
|
309
|
+
- **English** (`en`) — default
|
|
310
|
+
- **Czech** (`cs`)
|
|
311
|
+
- **Chinese** (`zh`)
|
|
312
|
+
- **Spanish** (`es`)
|
|
313
|
+
- **German** (`de`)
|
|
314
|
+
- **French** (`fr`)
|
|
315
|
+
- **Portuguese** (`pt`)
|
|
316
|
+
- **Japanese** (`ja`)
|
|
317
|
+
|
|
318
|
+
### Set language on init:
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
const editor = new NeikiEditor('#editor', {
|
|
322
|
+
language: 'cs' // Czech UI
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Custom translations
|
|
327
|
+
|
|
328
|
+
Add your own language or override existing translations using the static method:
|
|
329
|
+
|
|
330
|
+
```javascript
|
|
331
|
+
NeikiEditor.addTranslation('de', {
|
|
332
|
+
'toolbar.bold': 'Fett (Strg+B)',
|
|
333
|
+
'toolbar.italic': 'Kursiv (Strg+I)',
|
|
334
|
+
'toolbar.undo': 'Rückgängig (Strg+Z)',
|
|
335
|
+
// only override what you need — English is the fallback
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const editor = new NeikiEditor('#editor', { language: 'de' });
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Or pass translations directly in config:
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
const editor = new NeikiEditor('#editor', {
|
|
345
|
+
language: 'de',
|
|
346
|
+
translations: {
|
|
347
|
+
de: {
|
|
348
|
+
'toolbar.bold': 'Fett (Strg+B)',
|
|
349
|
+
'toolbar.italic': 'Kursiv (Strg+I)',
|
|
350
|
+
// ...
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
All toolbar tooltips, modal dialogs, status bar texts, and system messages are translatable.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## 💾 Autosave
|
|
361
|
+
|
|
362
|
+
Autosave is accessible from the **More menu** (⋯) in the default toolbar. When activated:
|
|
363
|
+
|
|
364
|
+
- Content is saved to `localStorage` on every content change (debounced)
|
|
365
|
+
- The status bar shows "Autosaving..." / "Saved locally"
|
|
366
|
+
- Content is restored on page reload **only when autosave was enabled**
|
|
367
|
+
|
|
368
|
+
> **Note:** For production use (CMS, blog, etc.), use the `onSave` callback or `onChange` callback to save content to your database instead.
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 📋 API Methods
|
|
373
|
+
|
|
374
|
+
### Content
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
editor.getContent(); // Get HTML content
|
|
378
|
+
editor.setContent('<p>Hello</p>'); // Set HTML content
|
|
379
|
+
editor.getText(); // Get plain text content
|
|
380
|
+
editor.isEmpty(); // Check if editor is empty
|
|
381
|
+
|
|
382
|
+
editor.getHTML(); // Alias for getContent()
|
|
383
|
+
editor.setHTML(html); // Alias for setContent()
|
|
384
|
+
|
|
385
|
+
editor.getJSON(); // Get structured JSON representation
|
|
386
|
+
editor.setJSON(json); // Set content from JSON
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Editor Control
|
|
390
|
+
|
|
391
|
+
```javascript
|
|
392
|
+
editor.focus(); // Focus the editor
|
|
393
|
+
editor.blur(); // Blur the editor
|
|
394
|
+
editor.enable(); // Enable editing
|
|
395
|
+
editor.disable(); // Disable editing (read-only)
|
|
396
|
+
editor.destroy(); // Remove editor, restore original element
|
|
397
|
+
editor.toggleFullscreen(); // Toggle fullscreen mode
|
|
398
|
+
editor.toggleTheme(); // Toggle light/dark theme
|
|
399
|
+
editor.setTheme('dark'); // Set a specific theme
|
|
400
|
+
editor.triggerSave(); // Trigger onSave callback
|
|
401
|
+
editor.previewContent(); // Open preview modal
|
|
402
|
+
editor.downloadContent(); // Download content as HTML file
|
|
403
|
+
editor.clearAll(); // Clear all content
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Localization
|
|
407
|
+
|
|
408
|
+
```javascript
|
|
409
|
+
NeikiEditor.addTranslation('de', { ... }); // Add/override translations (static)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Command Execution
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
editor.execCommand('bold'); // Execute a command
|
|
416
|
+
editor.insertHTML('<span>Hello</span>'); // Insert HTML at cursor
|
|
417
|
+
editor.wrapSelection('mark', { class: 'highlight' }); // Wrap selection
|
|
418
|
+
editor.unwrapSelection('mark'); // Unwrap selection
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Selection
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
editor.getSelection(); // Get current Selection object
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## 🔌 Plugin API
|
|
430
|
+
|
|
431
|
+
Extend the editor with custom plugins:
|
|
432
|
+
|
|
433
|
+
```javascript
|
|
434
|
+
NeikiEditor.registerPlugin({
|
|
435
|
+
name: 'word-counter-alert',
|
|
436
|
+
icon: '<svg viewBox="0 0 24 24">...</svg>', // optional toolbar button
|
|
437
|
+
tooltip: 'Show Word Count',
|
|
438
|
+
action: function(editor) {
|
|
439
|
+
const text = editor.getContent().replace(/<[^>]*>/g, '');
|
|
440
|
+
const words = text.trim().split(/\s+/).filter(Boolean).length;
|
|
441
|
+
alert('Word count: ' + words);
|
|
442
|
+
},
|
|
443
|
+
init: function(editor) {
|
|
444
|
+
// Called once when editor initializes (optional)
|
|
445
|
+
console.log('Plugin initialized!');
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Plugin Properties
|
|
451
|
+
|
|
452
|
+
| Property | Type | Required | Description |
|
|
453
|
+
|----------|------|----------|-------------|
|
|
454
|
+
| `name` | `string` | ✅ | Unique plugin identifier |
|
|
455
|
+
| `icon` | `string` | ❌ | SVG icon for toolbar button |
|
|
456
|
+
| `tooltip` | `string` | ❌ | Button tooltip text |
|
|
457
|
+
| `action` | `function` | ❌ | Called when toolbar button is clicked |
|
|
458
|
+
| `init` | `function` | ❌ | Called once during editor initialization |
|
|
459
|
+
|
|
460
|
+
### List Registered Plugins
|
|
461
|
+
|
|
462
|
+
```javascript
|
|
463
|
+
NeikiEditor.getPlugins(); // Returns array of registered plugins
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## 📊 Table Features
|
|
469
|
+
|
|
470
|
+
Insert tables via the toolbar button with configurable rows, columns, and optional header row.
|
|
471
|
+
|
|
472
|
+
### Table Context Menu
|
|
473
|
+
|
|
474
|
+
Right-click on any table cell to access:
|
|
475
|
+
|
|
476
|
+
- **Insert Row Above / Below**
|
|
477
|
+
- **Insert Column Left / Right**
|
|
478
|
+
- **Delete Row / Column / Table**
|
|
479
|
+
- **Merge Cells** — merge selected cells horizontally
|
|
480
|
+
- **Split Cell** — split a previously merged cell
|
|
481
|
+
|
|
482
|
+
### Column Resize
|
|
483
|
+
|
|
484
|
+
Hover near any column border to reveal a **drag handle**. Drag to resize adjacent column widths. The table uses fixed layout during resize for precise control.
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## 🖼️ Image Support
|
|
489
|
+
|
|
490
|
+
### Insert via URL
|
|
491
|
+
|
|
492
|
+
Click the **Image** toolbar button and paste a URL.
|
|
493
|
+
|
|
494
|
+
### Upload from File
|
|
495
|
+
|
|
496
|
+
The Image dialog includes a file upload input. Selected images are converted to **base64** and embedded directly in the content.
|
|
497
|
+
|
|
498
|
+
### Drag & Drop
|
|
499
|
+
|
|
500
|
+
Drag image files directly into the editor content area. Images are automatically converted to base64 and inserted at the drop position.
|
|
501
|
+
|
|
502
|
+
### Resize Images
|
|
503
|
+
|
|
504
|
+
Click any image in the editor to select it — **resize handles** appear on all four corners. Drag any handle to resize while maintaining aspect ratio. A live **size label** (width × height) is displayed below the image during resizing.
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## 🔍 Find & Replace
|
|
509
|
+
|
|
510
|
+
Open with the toolbar button or implement via the modal API.
|
|
511
|
+
|
|
512
|
+
Features:
|
|
513
|
+
- **Case-sensitive** search toggle
|
|
514
|
+
- **Regular expression** support
|
|
515
|
+
- **Find Next** — navigate through matches with highlighting
|
|
516
|
+
- **Replace** — replace current match
|
|
517
|
+
- **Replace All** — replace all matches at once
|
|
518
|
+
|
|
519
|
+
---
|
|
520
|
+
|
|
521
|
+
## ✏️ Floating Toolbar
|
|
522
|
+
|
|
523
|
+
When you select text in the editor, a floating toolbar appears above the selection with quick access to:
|
|
524
|
+
|
|
525
|
+
- **Move Block Up / Down** — reorder the current content block (left side)
|
|
526
|
+
- **Bold, Italic, Underline, Strikethrough** — quick formatting
|
|
527
|
+
- **Insert Link**
|
|
528
|
+
|
|
529
|
+
The toolbar follows the selection and disappears when the selection is cleared.
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## 🔀 Block Drag & Drop
|
|
534
|
+
|
|
535
|
+
Hover over any content block (paragraph, heading, table, image, list, etc.) to reveal a **grip handle** (⠿) on the left side. Drag to reorder blocks within the editor. A ghost preview and drop placeholder guide the drop position.
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## 🖨️ Print
|
|
540
|
+
|
|
541
|
+
Click the **Print** button to open the browser print dialog with the editor content formatted for printing.
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## ⌨️ Keyboard Shortcuts
|
|
546
|
+
|
|
547
|
+
| Shortcut | Action |
|
|
548
|
+
|----------|--------|
|
|
549
|
+
| **Ctrl+B** | Bold |
|
|
550
|
+
| **Ctrl+I** | Italic |
|
|
551
|
+
| **Ctrl+U** | Underline |
|
|
552
|
+
| **Ctrl+K** | Insert Link |
|
|
553
|
+
| **Ctrl+S** | Save (triggers `onSave` callback) |
|
|
554
|
+
| **Ctrl+Z** | Undo |
|
|
555
|
+
| **Ctrl+Y** / **Ctrl+Shift+Z** | Redo |
|
|
556
|
+
| **Tab** | Indent |
|
|
557
|
+
| **Shift+Tab** | Outdent |
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 📐 Status Bar
|
|
562
|
+
|
|
563
|
+
The editor includes a status bar at the bottom displaying:
|
|
564
|
+
|
|
565
|
+
- **Left side:** Word count and character count
|
|
566
|
+
- **Right side:** Autosave status (when enabled) and current block type (p, h1, h2, etc.)
|
|
567
|
+
|
|
568
|
+
---
|
|
569
|
+
|
|
570
|
+
## 🔗 Integration Examples
|
|
571
|
+
|
|
572
|
+
### PHP Helper (Recommended)
|
|
573
|
+
|
|
574
|
+
Neiki's Editor includes a PHP integration helper (`php/neiki-editor.php`) that provides asset loading, editor rendering, and HTML sanitization:
|
|
575
|
+
|
|
576
|
+
```php
|
|
577
|
+
<?php require_once 'php/neiki-editor.php'; ?>
|
|
578
|
+
<!DOCTYPE html>
|
|
579
|
+
<html>
|
|
580
|
+
<head>
|
|
581
|
+
<?= NeikiEditor::assets() ?>
|
|
582
|
+
</head>
|
|
583
|
+
<body>
|
|
584
|
+
<form method="POST" action="save.php">
|
|
585
|
+
<?= NeikiEditor::render('content', $article->content, [
|
|
586
|
+
'minHeight' => 400,
|
|
587
|
+
'placeholder' => 'Write your article...'
|
|
588
|
+
]) ?>
|
|
589
|
+
<button type="submit">Save</button>
|
|
590
|
+
</form>
|
|
591
|
+
</body>
|
|
592
|
+
</html>
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
```php
|
|
596
|
+
// save.php — sanitize before saving to database
|
|
597
|
+
require_once 'php/neiki-editor.php';
|
|
598
|
+
$clean = NeikiEditor::sanitize($_POST['content']);
|
|
599
|
+
$db->save($clean);
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### PHP Helper Methods
|
|
603
|
+
|
|
604
|
+
| Method | Description |
|
|
605
|
+
|--------|-------------|
|
|
606
|
+
| `NeikiEditor::assets()` | Output CSS & JS tags (CDN). Call once per page. |
|
|
607
|
+
| `NeikiEditor::assets(true, '/path/to/dist')` | Use local files instead of CDN. |
|
|
608
|
+
| `NeikiEditor::render($id, $content, $options)` | Render textarea + init script. |
|
|
609
|
+
| `NeikiEditor::sanitize($html)` | Strip dangerous tags/attributes before DB save. |
|
|
610
|
+
|
|
611
|
+
### PHP Form (Manual)
|
|
612
|
+
|
|
613
|
+
```php
|
|
614
|
+
<form method="POST" action="save.php">
|
|
615
|
+
<textarea id="editor" name="content"><?= htmlspecialchars($article->content) ?></textarea>
|
|
616
|
+
<button type="submit">Save</button>
|
|
617
|
+
</form>
|
|
618
|
+
|
|
619
|
+
<script>
|
|
620
|
+
const editor = new NeikiEditor('#editor');
|
|
621
|
+
</script>
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
### AJAX Save
|
|
625
|
+
|
|
626
|
+
```javascript
|
|
627
|
+
const editor = new NeikiEditor('#editor', {
|
|
628
|
+
onChange: debounce(function(content) {
|
|
629
|
+
fetch('/api/save', {
|
|
630
|
+
method: 'POST',
|
|
631
|
+
headers: { 'Content-Type': 'application/json' },
|
|
632
|
+
body: JSON.stringify({ content })
|
|
633
|
+
});
|
|
634
|
+
}, 2000)
|
|
635
|
+
});
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### Vue.js
|
|
639
|
+
|
|
640
|
+
```vue
|
|
641
|
+
<template>
|
|
642
|
+
<textarea ref="editor"></textarea>
|
|
643
|
+
</template>
|
|
644
|
+
|
|
645
|
+
<script>
|
|
646
|
+
export default {
|
|
647
|
+
mounted() {
|
|
648
|
+
this.editor = new NeikiEditor(this.$refs.editor, {
|
|
649
|
+
onChange: (content) => {
|
|
650
|
+
this.$emit('update:modelValue', content);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
},
|
|
654
|
+
beforeUnmount() {
|
|
655
|
+
this.editor.destroy();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
</script>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### React
|
|
662
|
+
|
|
663
|
+
```jsx
|
|
664
|
+
import { useEffect, useRef } from 'react';
|
|
665
|
+
|
|
666
|
+
function NeikiEditorComponent({ value, onChange }) {
|
|
667
|
+
const ref = useRef(null);
|
|
668
|
+
const editorRef = useRef(null);
|
|
669
|
+
|
|
670
|
+
useEffect(() => {
|
|
671
|
+
editorRef.current = new NeikiEditor(ref.current, {
|
|
672
|
+
onChange: (content) => onChange?.(content)
|
|
673
|
+
});
|
|
674
|
+
return () => editorRef.current?.destroy();
|
|
675
|
+
}, []);
|
|
676
|
+
|
|
677
|
+
return <textarea ref={ref} defaultValue={value} />;
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## 🌐 Browser Support
|
|
684
|
+
|
|
685
|
+
| Browser | Support |
|
|
686
|
+
|---------|---------|
|
|
687
|
+
| Chrome | ✅ Latest |
|
|
688
|
+
| Firefox | ✅ Latest |
|
|
689
|
+
| Safari | ✅ Latest |
|
|
690
|
+
| Edge | ✅ Latest |
|
|
691
|
+
| Opera | ✅ Latest |
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
## 📁 File Structure
|
|
696
|
+
|
|
697
|
+
```
|
|
698
|
+
neiki-editor/
|
|
699
|
+
├── dist/
|
|
700
|
+
│ ├── neiki-editor.min.js # Minified editor + embedded CSS (recommended)
|
|
701
|
+
│ ├── neiki-editor.min.css # Minified styles
|
|
702
|
+
│ ├── neiki-editor.js # Editor core (unminified)
|
|
703
|
+
│ └── neiki-editor.css # Editor styles (unminified)
|
|
704
|
+
├── demo/
|
|
705
|
+
│ └── index.html # Interactive demo page
|
|
706
|
+
│ └── logo.png # Demo logo
|
|
707
|
+
├── php/
|
|
708
|
+
│ └── neiki-editor.php # PHP integration helper
|
|
709
|
+
├── logo.png
|
|
710
|
+
├── package.json
|
|
711
|
+
├── README.md
|
|
712
|
+
├── LICENSE
|
|
713
|
+
├── CHANGELOG.md
|
|
714
|
+
├── CONTRIBUTING.md
|
|
715
|
+
├── CODE_OF_CONDUCT.md
|
|
716
|
+
└── SECURITY.md
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## 📄 License
|
|
722
|
+
|
|
723
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
<p align="center">
|
|
728
|
+
Made with ❤️ for the web community
|
|
729
|
+
</p>
|