neiki-editor 2.10.1 → 3.0.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 +43 -17
- package/dist/neiki-editor.css +243 -12
- package/dist/neiki-editor.js +759 -128
- 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
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<img src="https://img.shields.io/badge/css-%23663399.svg?style=for-the-badge&logo=css&logoColor=white" alt="CSS">
|
|
12
12
|
<br>
|
|
13
13
|
<img src="https://img.shields.io/badge/License-AGPL--3.0-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-
|
|
14
|
+
<img src="https://img.shields.io/badge/Version-3.0.0-2563EB?style=for-the-badge&logo=semantic-release&logoColor=white&labelColor=000F15&logoWidth=20" alt="Version">
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
@@ -62,7 +62,7 @@ Add this single line — CSS is included automatically, always the **latest vers
|
|
|
62
62
|
#### Pin a specific version
|
|
63
63
|
|
|
64
64
|
```html
|
|
65
|
-
<script src="https://cdn.neikiri.dev/neiki-editor/
|
|
65
|
+
<script src="https://cdn.neikiri.dev/neiki-editor/3.0.0/neiki-editor.min.js"></script>
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
#### Load CSS and JS separately
|
|
@@ -73,8 +73,8 @@ Add this single line — CSS is included automatically, always the **latest vers
|
|
|
73
73
|
<script src="https://cdn.neikiri.dev/neiki-editor/neiki-editor.js"></script>
|
|
74
74
|
|
|
75
75
|
<!-- Or pinned -->
|
|
76
|
-
<link rel="stylesheet" href="https://cdn.neikiri.dev/neiki-editor/
|
|
77
|
-
<script src="https://cdn.neikiri.dev/neiki-editor/
|
|
76
|
+
<link rel="stylesheet" href="https://cdn.neikiri.dev/neiki-editor/3.0.0/neiki-editor.css">
|
|
77
|
+
<script src="https://cdn.neikiri.dev/neiki-editor/3.0.0/neiki-editor.js"></script>
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
#### Alternative CDN — jsDelivr
|
|
@@ -84,15 +84,15 @@ Add this single line — CSS is included automatically, always the **latest vers
|
|
|
84
84
|
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.min.js"></script>
|
|
85
85
|
|
|
86
86
|
<!-- Pinned -->
|
|
87
|
-
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@
|
|
87
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@3.0.0/dist/neiki-editor.min.js"></script>
|
|
88
88
|
|
|
89
89
|
<!-- Separate files (latest) -->
|
|
90
90
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.css">
|
|
91
91
|
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@latest/dist/neiki-editor.js"></script>
|
|
92
92
|
|
|
93
93
|
<!-- Separate files (pinned) -->
|
|
94
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@
|
|
95
|
-
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@
|
|
94
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@3.0.0/dist/neiki-editor.css">
|
|
95
|
+
<script src="https://cdn.jsdelivr.net/gh/neikiri/neiki-editor@3.0.0/dist/neiki-editor.js"></script>
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
#### Package Manager
|
|
@@ -143,7 +143,7 @@ const editor = new NeikiEditor('#editor', {
|
|
|
143
143
|
autofocus: false,
|
|
144
144
|
spellcheck: true,
|
|
145
145
|
readonly: false,
|
|
146
|
-
theme: 'light', // 'light' or 'dark'
|
|
146
|
+
theme: 'light', // 'light', 'dark', 'blue', or 'dark-blue'
|
|
147
147
|
language: 'en', // 'en', 'cs', or custom via addTranslation()
|
|
148
148
|
translations: null, // custom translation keys (merged with built-in)
|
|
149
149
|
autosaveKey: null, // optional custom localStorage scope for autosave
|
|
@@ -181,7 +181,7 @@ const editor = new NeikiEditor('#editor', {
|
|
|
181
181
|
| `autofocus` | `boolean` | `false` | Focus editor on initialization |
|
|
182
182
|
| `spellcheck` | `boolean` | `true` | Enable browser spellcheck |
|
|
183
183
|
| `readonly` | `boolean` | `false` | Make editor read-only |
|
|
184
|
-
| `theme` | `string` | `'light'` | `'light'` or `'dark'` |
|
|
184
|
+
| `theme` | `string` | `'light'` | `'light'`, `'dark'`, `'blue'`, or `'dark-blue'` |
|
|
185
185
|
| `language` | `string` | `'en'` | UI language — `en`, `cs`, `zh`, `es`, `de`, `fr`, `pt`, `ja` |
|
|
186
186
|
| `translations` | `object\|null` | `null` | Custom translation keys (merged with built-in) |
|
|
187
187
|
| `autosaveKey` | `string\|null` | `null` | Custom `localStorage` scope for autosave content and enabled state |
|
|
@@ -193,6 +193,7 @@ const editor = new NeikiEditor('#editor', {
|
|
|
193
193
|
| `onReady` | `function\|null` | `null` | Callback when editor is ready |
|
|
194
194
|
| `showHelp` | `boolean` | `true` | Show Help button in More menu (⋯) |
|
|
195
195
|
| `imageUploadHandler` | `function\|null` | `null` | Async callback `(file) => Promise<url>` for uploading images to a server/CDN instead of base64 |
|
|
196
|
+
| `videoUploadHandler` | `function\|null` | `null` | Async callback `(file) => Promise<url>` for uploading videos to a server/CDN instead of base64 |
|
|
196
197
|
| `customClass` | `string\|null` | `null` | Custom CSS class appended to the editor content area (`neiki-content`) |
|
|
197
198
|
|
|
198
199
|
---
|
|
@@ -247,11 +248,12 @@ The `insertDropdown` toolbar item renders a single **Insert** button that opens
|
|
|
247
248
|
|------|-------------|
|
|
248
249
|
| **Link** | Insert/edit hyperlink (**Ctrl+K**) |
|
|
249
250
|
| **Image** | Insert image (URL or file upload → base64) |
|
|
251
|
+
| **Video** | Insert video (URL or file upload → base64, or via `videoUploadHandler`) |
|
|
250
252
|
| **Table** | Insert table with custom rows/columns |
|
|
251
253
|
| **Emoji** | Emoji picker (100+ emojis) |
|
|
252
254
|
| **Symbol** | Special characters (©, ®, €, π, Ω, arrows, etc.) |
|
|
253
255
|
|
|
254
|
-
You can still use `link`, `image`, `table`, `emoji`, `specialChars` as standalone toolbar buttons if preferred.
|
|
256
|
+
You can still use `link`, `image`, `video`, `table`, `emoji`, `specialChars` as standalone toolbar buttons if preferred.
|
|
255
257
|
|
|
256
258
|
### More Menu
|
|
257
259
|
|
|
@@ -265,7 +267,7 @@ The `moreMenu` toolbar item renders a **⋯** button (pushed to the right) that
|
|
|
265
267
|
| **Print** | Print editor content |
|
|
266
268
|
| **Autosave** | Toggle autosave to localStorage |
|
|
267
269
|
| **Clear all** | Clear all editor content |
|
|
268
|
-
| **
|
|
270
|
+
| **Change theme** | Choose light, dark, blue, or dark-blue from a select |
|
|
269
271
|
| **Fullscreen** | Toggle fullscreen mode |
|
|
270
272
|
| **Help** | Show help modal with author, version, and links (configurable via `showHelp`) |
|
|
271
273
|
|
|
@@ -276,7 +278,7 @@ The `moreMenu` toolbar item renders a **⋯** button (pushed to the right) that
|
|
|
276
278
|
| `undo` | Undo (**Ctrl+Z**) |
|
|
277
279
|
| `redo` | Redo (**Ctrl+Y** / **Ctrl+Shift+Z**) |
|
|
278
280
|
| `findReplace` | Find & Replace with regex support |
|
|
279
|
-
| `viewCode` | Toggle HTML source editor |
|
|
281
|
+
| `viewCode` | Toggle formatted HTML source editor with syntax highlighting |
|
|
280
282
|
| `blockquote` | Block quote (toggles on/off) |
|
|
281
283
|
| `horizontalRule` | Horizontal line |
|
|
282
284
|
|
|
@@ -284,7 +286,7 @@ The `moreMenu` toolbar item renders a **⋯** button (pushed to the right) that
|
|
|
284
286
|
|
|
285
287
|
## 🎨 Themes
|
|
286
288
|
|
|
287
|
-
Neiki's Editor ships with **Light** and **Dark** themes.
|
|
289
|
+
Neiki's Editor ships with **Light**, **Dark**, **Blue**, and **Dark Blue** themes.
|
|
288
290
|
|
|
289
291
|
### Set theme on init:
|
|
290
292
|
|
|
@@ -294,14 +296,16 @@ const editor = new NeikiEditor('#editor', {
|
|
|
294
296
|
});
|
|
295
297
|
```
|
|
296
298
|
|
|
297
|
-
###
|
|
299
|
+
### Change theme at runtime:
|
|
298
300
|
|
|
299
|
-
Use the **
|
|
301
|
+
Use the **Change theme** select in the More menu (⋯), or change themes programmatically:
|
|
300
302
|
|
|
301
303
|
```javascript
|
|
302
304
|
editor.toggleTheme();
|
|
303
305
|
// or set a specific theme:
|
|
304
306
|
editor.setTheme('dark');
|
|
307
|
+
editor.setTheme('blue');
|
|
308
|
+
editor.setTheme('dark-blue');
|
|
305
309
|
```
|
|
306
310
|
|
|
307
311
|
The selected theme persists across page reloads via `localStorage`.
|
|
@@ -410,8 +414,8 @@ editor.enable(); // Enable editing
|
|
|
410
414
|
editor.disable(); // Disable editing (read-only)
|
|
411
415
|
editor.destroy(); // Remove editor, restore original element
|
|
412
416
|
editor.toggleFullscreen(); // Toggle fullscreen mode
|
|
413
|
-
editor.toggleTheme(); //
|
|
414
|
-
editor.setTheme('dark'); // Set a specific theme
|
|
417
|
+
editor.toggleTheme(); // Cycle through built-in themes
|
|
418
|
+
editor.setTheme('dark'); // Set a specific theme ('light', 'dark', 'blue', 'dark-blue')
|
|
415
419
|
editor.triggerSave(); // Trigger onSave callback
|
|
416
420
|
editor.previewContent(); // Open preview modal
|
|
417
421
|
editor.downloadContent(); // Download content as HTML file
|
|
@@ -514,6 +518,8 @@ The Image dialog includes a file upload input. Selected images are converted to
|
|
|
514
518
|
|
|
515
519
|
Drag image files directly into the editor content area. Images are automatically converted to base64 and inserted at the drop position.
|
|
516
520
|
|
|
521
|
+
Selected text can also be dragged to a new position inside the editor. Text, image, and video drags show the same insertion indicator so the drop position is visible before release.
|
|
522
|
+
|
|
517
523
|
### Resize Images
|
|
518
524
|
|
|
519
525
|
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.
|
|
@@ -530,6 +536,26 @@ The floating text-formatting toolbar is automatically hidden when an image is se
|
|
|
530
536
|
|
|
531
537
|
---
|
|
532
538
|
|
|
539
|
+
## 🎬 Video Support
|
|
540
|
+
|
|
541
|
+
Use **Insert → Video** to add a video by URL, by selecting a local video file, or by dragging a video file into the editor. Without `videoUploadHandler`, selected videos are embedded as base64 data URIs. With `videoUploadHandler`, the editor uploads the file through your callback and inserts the returned URL.
|
|
542
|
+
|
|
543
|
+
```javascript
|
|
544
|
+
const editor = new NeikiEditor('#editor', {
|
|
545
|
+
videoUploadHandler: async (file) => {
|
|
546
|
+
const formData = new FormData();
|
|
547
|
+
formData.append('video', file);
|
|
548
|
+
const response = await fetch('/upload-video', { method: 'POST', body: formData });
|
|
549
|
+
const data = await response.json();
|
|
550
|
+
return data.url;
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Inserted videos render as `<video controls>`, are preserved by the built-in sanitizer, and can be resized or repositioned like images.
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
533
559
|
## 🔍 Find & Replace
|
|
534
560
|
|
|
535
561
|
Open with the toolbar button or implement via the modal API.
|
package/dist/neiki-editor.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NeikiEditor - Production-Ready WYSIWYG Rich Text Editor
|
|
3
3
|
* CSS Stylesheet
|
|
4
|
-
* Version:
|
|
4
|
+
* Version: 3.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/* ============================================
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/* Dark Theme */
|
|
41
|
-
.neiki-editor.neiki-dark
|
|
41
|
+
.neiki-editor.neiki-dark,
|
|
42
|
+
.neiki-modal-overlay.neiki-dark {
|
|
42
43
|
--neiki-bg-primary: #1e1e1e;
|
|
43
44
|
--neiki-bg-secondary: #252526;
|
|
44
45
|
--neiki-bg-tertiary: #2d2d30;
|
|
@@ -67,6 +68,68 @@
|
|
|
67
68
|
--neiki-table-border: #3e3e42;
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/* Blue Theme */
|
|
72
|
+
.neiki-editor.neiki-theme-blue,
|
|
73
|
+
.neiki-modal-overlay.neiki-theme-blue {
|
|
74
|
+
--neiki-bg-primary: #f8fbff;
|
|
75
|
+
--neiki-bg-secondary: #eef6ff;
|
|
76
|
+
--neiki-bg-tertiary: #dbeafe;
|
|
77
|
+
--neiki-bg-hover: #bfdbfe;
|
|
78
|
+
--neiki-bg-active: #93c5fd;
|
|
79
|
+
--neiki-border-color: #bfdbfe;
|
|
80
|
+
--neiki-border-color-dark: #60a5fa;
|
|
81
|
+
--neiki-text-primary: #0f172a;
|
|
82
|
+
--neiki-text-secondary: #1e3a8a;
|
|
83
|
+
--neiki-text-muted: #64748b;
|
|
84
|
+
--neiki-accent-color: #2563eb;
|
|
85
|
+
--neiki-accent-hover: #1d4ed8;
|
|
86
|
+
--neiki-danger-color: #dc3545;
|
|
87
|
+
--neiki-success-color: #16803d;
|
|
88
|
+
--neiki-shadow-sm: 0 1px 2px rgba(37, 99, 235, 0.08);
|
|
89
|
+
--neiki-shadow-md: 0 4px 10px rgba(37, 99, 235, 0.12);
|
|
90
|
+
--neiki-shadow-lg: 0 14px 28px rgba(37, 99, 235, 0.16);
|
|
91
|
+
--neiki-editor-bg: #ffffff;
|
|
92
|
+
--neiki-toolbar-bg: #eaf4ff;
|
|
93
|
+
--neiki-statusbar-bg: #eef6ff;
|
|
94
|
+
--neiki-modal-overlay: rgba(15, 23, 42, 0.45);
|
|
95
|
+
--neiki-scrollbar-thumb: #93c5fd;
|
|
96
|
+
--neiki-scrollbar-track: #eff6ff;
|
|
97
|
+
--neiki-selection-bg: #bfdbfe;
|
|
98
|
+
--neiki-highlight-color: #fef08a;
|
|
99
|
+
--neiki-table-border: #bfdbfe;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Dark Blue Theme */
|
|
103
|
+
.neiki-editor.neiki-theme-dark-blue,
|
|
104
|
+
.neiki-modal-overlay.neiki-theme-dark-blue {
|
|
105
|
+
--neiki-bg-primary: #07111f;
|
|
106
|
+
--neiki-bg-secondary: #0b1d33;
|
|
107
|
+
--neiki-bg-tertiary: #102a46;
|
|
108
|
+
--neiki-bg-hover: #173b61;
|
|
109
|
+
--neiki-bg-active: #1d4f82;
|
|
110
|
+
--neiki-border-color: #1f3f63;
|
|
111
|
+
--neiki-border-color-dark: #2f6da5;
|
|
112
|
+
--neiki-text-primary: #e6f1ff;
|
|
113
|
+
--neiki-text-secondary: #b9d7f8;
|
|
114
|
+
--neiki-text-muted: #7ea6cc;
|
|
115
|
+
--neiki-accent-color: #38bdf8;
|
|
116
|
+
--neiki-accent-hover: #0ea5e9;
|
|
117
|
+
--neiki-danger-color: #fb7185;
|
|
118
|
+
--neiki-success-color: #34d399;
|
|
119
|
+
--neiki-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.24);
|
|
120
|
+
--neiki-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.34);
|
|
121
|
+
--neiki-shadow-lg: 0 18px 36px rgba(0, 0, 0, 0.46);
|
|
122
|
+
--neiki-editor-bg: #081827;
|
|
123
|
+
--neiki-toolbar-bg: #0b1d33;
|
|
124
|
+
--neiki-statusbar-bg: #0b1d33;
|
|
125
|
+
--neiki-modal-overlay: rgba(0, 0, 0, 0.72);
|
|
126
|
+
--neiki-scrollbar-thumb: #1d4f82;
|
|
127
|
+
--neiki-scrollbar-track: #07111f;
|
|
128
|
+
--neiki-selection-bg: #164e63;
|
|
129
|
+
--neiki-highlight-color: #854d0e;
|
|
130
|
+
--neiki-table-border: #1f3f63;
|
|
131
|
+
}
|
|
132
|
+
|
|
70
133
|
/* ============================================
|
|
71
134
|
Base Editor Container
|
|
72
135
|
============================================ */
|
|
@@ -229,6 +292,34 @@
|
|
|
229
292
|
box-shadow: 0 0 0 2px rgba(13, 110, 253, 0.15);
|
|
230
293
|
}
|
|
231
294
|
|
|
295
|
+
.neiki-theme-select-wrapper {
|
|
296
|
+
display: inline-flex;
|
|
297
|
+
align-items: center;
|
|
298
|
+
gap: 6px;
|
|
299
|
+
height: 32px;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.neiki-theme-select-icon {
|
|
303
|
+
display: inline-flex;
|
|
304
|
+
align-items: center;
|
|
305
|
+
justify-content: center;
|
|
306
|
+
color: var(--neiki-text-secondary);
|
|
307
|
+
width: 18px;
|
|
308
|
+
height: 18px;
|
|
309
|
+
flex-shrink: 0;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.neiki-theme-select-icon svg {
|
|
313
|
+
width: 16px;
|
|
314
|
+
height: 16px;
|
|
315
|
+
fill: currentColor;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.neiki-theme-select {
|
|
319
|
+
min-width: 116px;
|
|
320
|
+
max-width: 150px;
|
|
321
|
+
}
|
|
322
|
+
|
|
232
323
|
/* Color Picker Button */
|
|
233
324
|
.neiki-color-btn {
|
|
234
325
|
position: relative;
|
|
@@ -307,7 +398,7 @@
|
|
|
307
398
|
}
|
|
308
399
|
|
|
309
400
|
.neiki-content.neiki-drag-over::after {
|
|
310
|
-
content: 'Drop
|
|
401
|
+
content: 'Drop media here';
|
|
311
402
|
position: absolute;
|
|
312
403
|
top: 50%;
|
|
313
404
|
left: 50%;
|
|
@@ -319,6 +410,44 @@
|
|
|
319
410
|
z-index: 10;
|
|
320
411
|
}
|
|
321
412
|
|
|
413
|
+
.neiki-drop-indicator {
|
|
414
|
+
position: absolute;
|
|
415
|
+
width: 3px;
|
|
416
|
+
min-height: 22px;
|
|
417
|
+
background: var(--neiki-accent-color);
|
|
418
|
+
border-radius: 999px;
|
|
419
|
+
box-shadow: 0 0 0 3px rgba(13, 110, 253, 0.18);
|
|
420
|
+
pointer-events: none;
|
|
421
|
+
opacity: 0;
|
|
422
|
+
transform: translateX(-1px);
|
|
423
|
+
transition: opacity 0.08s ease;
|
|
424
|
+
z-index: 80;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.neiki-drop-indicator::before,
|
|
428
|
+
.neiki-drop-indicator::after {
|
|
429
|
+
content: '';
|
|
430
|
+
position: absolute;
|
|
431
|
+
left: 50%;
|
|
432
|
+
width: 9px;
|
|
433
|
+
height: 9px;
|
|
434
|
+
background: var(--neiki-accent-color);
|
|
435
|
+
border-radius: 50%;
|
|
436
|
+
transform: translateX(-50%);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.neiki-drop-indicator::before {
|
|
440
|
+
top: -4px;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.neiki-drop-indicator::after {
|
|
444
|
+
bottom: -4px;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.neiki-drop-indicator.show {
|
|
448
|
+
opacity: 1;
|
|
449
|
+
}
|
|
450
|
+
|
|
322
451
|
/* Focus state for editor container - disabled */
|
|
323
452
|
/* .neiki-editor.neiki-focused removed */
|
|
324
453
|
|
|
@@ -445,6 +574,15 @@
|
|
|
445
574
|
outline-offset: 2px;
|
|
446
575
|
}
|
|
447
576
|
|
|
577
|
+
.neiki-content video {
|
|
578
|
+
display: block;
|
|
579
|
+
max-width: 100%;
|
|
580
|
+
height: auto;
|
|
581
|
+
margin: 0 0 1em 0;
|
|
582
|
+
border-radius: 6px;
|
|
583
|
+
background: #000;
|
|
584
|
+
}
|
|
585
|
+
|
|
448
586
|
/* Search Highlight */
|
|
449
587
|
.neiki-highlight {
|
|
450
588
|
background: var(--neiki-highlight-color);
|
|
@@ -1492,23 +1630,89 @@
|
|
|
1492
1630
|
color: var(--neiki-text-primary);
|
|
1493
1631
|
}
|
|
1494
1632
|
|
|
1495
|
-
.neiki-code-view-
|
|
1633
|
+
.neiki-code-view-editor {
|
|
1634
|
+
position: relative;
|
|
1496
1635
|
flex: 1;
|
|
1497
1636
|
width: 100%;
|
|
1637
|
+
min-height: 0;
|
|
1638
|
+
background: var(--neiki-bg-primary);
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
.neiki-code-view-highlight,
|
|
1642
|
+
.neiki-code-view-textarea {
|
|
1643
|
+
position: absolute;
|
|
1644
|
+
inset: 0;
|
|
1645
|
+
width: 100%;
|
|
1646
|
+
height: 100%;
|
|
1498
1647
|
padding: 16px;
|
|
1499
1648
|
border: none;
|
|
1500
|
-
background: var(--neiki-bg-primary);
|
|
1501
|
-
color: var(--neiki-text-primary);
|
|
1502
1649
|
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
1503
1650
|
font-size: 13px;
|
|
1504
1651
|
line-height: 1.5;
|
|
1652
|
+
tab-size: 2;
|
|
1653
|
+
white-space: pre-wrap;
|
|
1654
|
+
word-break: break-word;
|
|
1655
|
+
overflow: auto;
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
.neiki-code-view-highlight {
|
|
1659
|
+
margin: 0;
|
|
1660
|
+
color: var(--neiki-text-primary);
|
|
1661
|
+
pointer-events: none;
|
|
1662
|
+
user-select: none;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
.neiki-code-view-textarea {
|
|
1666
|
+
background: transparent;
|
|
1667
|
+
color: transparent;
|
|
1668
|
+
caret-color: var(--neiki-text-primary);
|
|
1505
1669
|
resize: none;
|
|
1670
|
+
z-index: 1;
|
|
1506
1671
|
}
|
|
1507
1672
|
|
|
1508
1673
|
.neiki-code-view-textarea:focus {
|
|
1509
1674
|
outline: none;
|
|
1510
1675
|
}
|
|
1511
1676
|
|
|
1677
|
+
.neiki-code-view-textarea::selection {
|
|
1678
|
+
background: var(--neiki-selection-bg);
|
|
1679
|
+
color: transparent;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
.neiki-html-punct {
|
|
1683
|
+
color: var(--neiki-text-muted);
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
.neiki-html-tag {
|
|
1687
|
+
color: #0f74d8;
|
|
1688
|
+
font-weight: 600;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
.neiki-html-attr {
|
|
1692
|
+
color: #9a5b00;
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
.neiki-html-string {
|
|
1696
|
+
color: #16803d;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
.neiki-html-comment {
|
|
1700
|
+
color: var(--neiki-text-muted);
|
|
1701
|
+
font-style: italic;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
.neiki-dark .neiki-html-tag {
|
|
1705
|
+
color: #7dd3fc;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
.neiki-dark .neiki-html-attr {
|
|
1709
|
+
color: #fbbf24;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
.neiki-dark .neiki-html-string {
|
|
1713
|
+
color: #86efac;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1512
1716
|
.neiki-code-view-apply {
|
|
1513
1717
|
width: auto !important;
|
|
1514
1718
|
padding: 0 12px !important;
|
|
@@ -1722,7 +1926,7 @@
|
|
|
1722
1926
|
}
|
|
1723
1927
|
|
|
1724
1928
|
/* ============================================
|
|
1725
|
-
|
|
1929
|
+
Media Resize Handles
|
|
1726
1930
|
============================================ */
|
|
1727
1931
|
.neiki-img-resizable {
|
|
1728
1932
|
display: inline-block;
|
|
@@ -1731,11 +1935,16 @@
|
|
|
1731
1935
|
outline-offset: 2px;
|
|
1732
1936
|
border-radius: 4px;
|
|
1733
1937
|
line-height: 0;
|
|
1938
|
+
user-select: none;
|
|
1939
|
+
-webkit-user-select: none;
|
|
1734
1940
|
}
|
|
1735
1941
|
|
|
1736
|
-
.neiki-img-resizable img
|
|
1942
|
+
.neiki-img-resizable img,
|
|
1943
|
+
.neiki-img-resizable video {
|
|
1737
1944
|
display: block;
|
|
1738
1945
|
max-width: 100%;
|
|
1946
|
+
user-select: none;
|
|
1947
|
+
-webkit-user-select: none;
|
|
1739
1948
|
}
|
|
1740
1949
|
|
|
1741
1950
|
.neiki-img-resize-handle {
|
|
@@ -1785,7 +1994,7 @@
|
|
|
1785
1994
|
}
|
|
1786
1995
|
|
|
1787
1996
|
/* ============================================
|
|
1788
|
-
|
|
1997
|
+
Media Toolbar (replace, delete, drag)
|
|
1789
1998
|
============================================ */
|
|
1790
1999
|
.neiki-img-toolbar {
|
|
1791
2000
|
position: absolute;
|
|
@@ -1801,6 +2010,8 @@
|
|
|
1801
2010
|
box-shadow: var(--neiki-shadow-md);
|
|
1802
2011
|
z-index: 20;
|
|
1803
2012
|
white-space: nowrap;
|
|
2013
|
+
user-select: none;
|
|
2014
|
+
-webkit-user-select: none;
|
|
1804
2015
|
}
|
|
1805
2016
|
|
|
1806
2017
|
.neiki-img-toolbar-btn {
|
|
@@ -1891,7 +2102,7 @@
|
|
|
1891
2102
|
user-select: none;
|
|
1892
2103
|
}
|
|
1893
2104
|
|
|
1894
|
-
.neiki-content:hover .neiki-block-grip {
|
|
2105
|
+
.neiki-content-wrapper:hover .neiki-block-grip {
|
|
1895
2106
|
opacity: 0.5;
|
|
1896
2107
|
}
|
|
1897
2108
|
|
|
@@ -2321,8 +2532,6 @@
|
|
|
2321
2532
|
top: 100%;
|
|
2322
2533
|
right: 0;
|
|
2323
2534
|
z-index: 1000;
|
|
2324
|
-
min-width: 140px;
|
|
2325
|
-
max-width: 170px;
|
|
2326
2535
|
background: var(--neiki-bg-primary);
|
|
2327
2536
|
border: 1px solid var(--neiki-border-color);
|
|
2328
2537
|
border-radius: 6px;
|
|
@@ -2365,6 +2574,28 @@
|
|
|
2365
2574
|
background: rgba(220, 53, 69, 0.1);
|
|
2366
2575
|
}
|
|
2367
2576
|
|
|
2577
|
+
.neiki-theme-menu-item {
|
|
2578
|
+
cursor: default;
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
.neiki-theme-menu-select {
|
|
2582
|
+
min-width: 105px;
|
|
2583
|
+
height: 28px;
|
|
2584
|
+
padding: 0 24px 0 8px;
|
|
2585
|
+
border: 1px solid var(--neiki-border-color);
|
|
2586
|
+
border-radius: 4px;
|
|
2587
|
+
background: var(--neiki-bg-primary);
|
|
2588
|
+
color: var(--neiki-text-primary);
|
|
2589
|
+
font-size: 12px;
|
|
2590
|
+
cursor: pointer;
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
.neiki-theme-menu-select:focus {
|
|
2594
|
+
outline: none;
|
|
2595
|
+
border-color: var(--neiki-accent-color);
|
|
2596
|
+
box-shadow: 0 0 0 2px rgba(13, 110, 253, 0.15);
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2368
2599
|
/* Autosave badge in More menu */
|
|
2369
2600
|
.neiki-autosave-badge {
|
|
2370
2601
|
font-size: 12px;
|