overtype 2.3.9 → 2.3.10
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 +72 -8
- package/dist/overtype-webcomponent.esm.js +57 -3
- package/dist/overtype-webcomponent.esm.js.map +2 -2
- package/dist/overtype-webcomponent.js +57 -3
- package/dist/overtype-webcomponent.js.map +2 -2
- package/dist/overtype-webcomponent.min.js +17 -17
- package/dist/overtype.cjs +57 -3
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.d.ts +1 -0
- package/dist/overtype.esm.js +57 -3
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +57 -3
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +9 -9
- package/package.json +1 -1
- package/src/overtype.d.ts +1 -0
- package/src/overtype.js +53 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OverType
|
|
2
2
|
|
|
3
|
-
A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~
|
|
3
|
+
A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~111KB minified with all features.
|
|
4
4
|
|
|
5
5
|
## Live Examples
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ A lightweight markdown editor library with perfect WYSIWYG alignment using an in
|
|
|
19
19
|
- ⌨️ **Keyboard shortcuts** - Common markdown shortcuts (Cmd/Ctrl+B for bold, etc.)
|
|
20
20
|
- 📱 **Mobile optimized** - Responsive design with mobile-specific styles
|
|
21
21
|
- 🔄 **DOM persistence aware** - Recovers from existing DOM (perfect for HyperClay and similar platforms)
|
|
22
|
-
- 🚀 **Lightweight** - ~
|
|
22
|
+
- 🚀 **Lightweight** - ~111KB minified
|
|
23
23
|
- 🎯 **Optional toolbar** - Clean, minimal toolbar with all essential formatting
|
|
24
24
|
- ✨ **Smart shortcuts** - Keyboard shortcuts with selection preservation
|
|
25
25
|
- 📝 **Smart list continuation** - GitHub-style automatic list continuation on Enter
|
|
@@ -35,7 +35,7 @@ We overlap an invisible textarea on top of styled output, giving the illusion of
|
|
|
35
35
|
|
|
36
36
|
| Feature | OverType | HyperMD | Milkdown | TUI Editor | EasyMDE |
|
|
37
37
|
|---------|----------|---------|----------|------------|---------|
|
|
38
|
-
| **Size** | ~
|
|
38
|
+
| **Size** | ~111KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB |
|
|
39
39
|
| **Dependencies** | Bundled | CodeMirror | ProseMirror + plugins | Multiple libs | CodeMirror |
|
|
40
40
|
| **Setup** | Single file | Complex config | Build step required | Complex config | Moderate |
|
|
41
41
|
| **Approach** | Invisible textarea | ContentEditable | ContentEditable | ContentEditable | CodeMirror |
|
|
@@ -145,6 +145,24 @@ const [editor] = new OverType('#editor', {
|
|
|
145
145
|
// orderedList, taskList, quote, separator, viewMode
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
+
**Driving formatting from your own UI:**
|
|
149
|
+
|
|
150
|
+
OverType re-exports the bundled `markdown-actions` library so you can build a fully custom toolbar (or any UI) without installing or bundling `markdown-actions` separately:
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
import OverType, { markdownActions } from 'overtype';
|
|
154
|
+
|
|
155
|
+
const [editor] = new OverType('#editor');
|
|
156
|
+
|
|
157
|
+
// Apply formatting to the editor's textarea directly
|
|
158
|
+
document.querySelector('#bold-btn').addEventListener('click', () => {
|
|
159
|
+
markdownActions.toggleBold(editor.textarea);
|
|
160
|
+
editor.textarea.focus();
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Available actions include `toggleBold`, `toggleItalic`, `toggleCode`, `insertLink`, `toggleBulletList`, `toggleNumberedList`, `toggleQuote`, `toggleTaskList`, `insertHeader`, `toggleH1`/`H2`/`H3`, `getActiveFormats`, `hasFormat`, `expandSelection`, and `applyCustomFormat`. The same namespace is available as `window.markdownActions` and `OverType.markdownActions` in script-tag builds.
|
|
165
|
+
|
|
148
166
|
See [examples/custom-toolbar.html](examples/custom-toolbar.html) for complete examples.
|
|
149
167
|
|
|
150
168
|
### View Modes
|
|
@@ -236,6 +254,38 @@ document.querySelector('form').addEventListener('submit', (e) => {
|
|
|
236
254
|
});
|
|
237
255
|
```
|
|
238
256
|
|
|
257
|
+
### File Uploads
|
|
258
|
+
|
|
259
|
+
OverType handles paste and drop of files when `fileUpload` is configured. You upload to your own backend in `onInsertFile` and return the markdown to insert. When that markdown link is later removed from the editor, `onRemoveFile` fires so you can clean up the backend file.
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
const [editor] = new OverType('#editor', {
|
|
263
|
+
fileUpload: {
|
|
264
|
+
enabled: true,
|
|
265
|
+
maxSize: 10 * 1024 * 1024, // 10MB
|
|
266
|
+
mimeTypes: ['image/png', 'image/jpeg'], // optional whitelist; empty = accept all
|
|
267
|
+
batch: false, // true = one onInsertFile call per drop
|
|
268
|
+
|
|
269
|
+
// Upload to your backend, return the markdown link to insert
|
|
270
|
+
onInsertFile: async (file) => {
|
|
271
|
+
const { url } = await uploadToBackend(file);
|
|
272
|
+
const isImage = file.type.startsWith('image/');
|
|
273
|
+
return isImage ? `` : `[${file.name}](${url})`;
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
// Optional: fires when an inserted link is removed from the editor.
|
|
277
|
+
// Useful for deleting orphaned files from storage.
|
|
278
|
+
onRemoveFile: ({ url, filename, file }) => {
|
|
279
|
+
fetch(`/api/files/${encodeURIComponent(url)}`, { method: 'DELETE' });
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`onRemoveFile` only fires for URLs that OverType originally inserted via `onInsertFile`. URL edits, manual paste of an existing link, or programmatic edits to non-tracked URLs do not trigger it.
|
|
286
|
+
|
|
287
|
+
See [examples/file-upload.html](website/examples/file-upload.html) for a complete working demo.
|
|
288
|
+
|
|
239
289
|
### Custom Theme
|
|
240
290
|
|
|
241
291
|
```javascript
|
|
@@ -476,7 +526,19 @@ new OverType(target, options)
|
|
|
476
526
|
|
|
477
527
|
// Callbacks
|
|
478
528
|
onChange: (value, instance) => {},
|
|
479
|
-
onKeydown: (event, instance) => {}
|
|
529
|
+
onKeydown: (event, instance) => {},
|
|
530
|
+
onFocus: (event, instance) => {},
|
|
531
|
+
onBlur: (event, instance) => {},
|
|
532
|
+
|
|
533
|
+
// File upload (paste/drop) — see "File Uploads" section below
|
|
534
|
+
fileUpload: {
|
|
535
|
+
enabled: true,
|
|
536
|
+
maxSize: 10 * 1024 * 1024, // bytes (default 10MB)
|
|
537
|
+
mimeTypes: [], // empty = accept all
|
|
538
|
+
batch: false, // single onInsertFile call per drop
|
|
539
|
+
onInsertFile: async (file) => `[${file.name}](url)`, // required: return inserted markdown
|
|
540
|
+
onRemoveFile: ({ url, filename, file }) => {} // fires when an inserted link is removed
|
|
541
|
+
}
|
|
480
542
|
}
|
|
481
543
|
```
|
|
482
544
|
|
|
@@ -554,10 +616,12 @@ OverType.init(target, options)
|
|
|
554
616
|
|
|
555
617
|
// Initialize with per-element config via data-ot-* attributes
|
|
556
618
|
// Uses kebab-case: data-ot-show-stats="true" → showStats: true
|
|
619
|
+
// Accepts a selector, Element, NodeList, or Array of elements
|
|
557
620
|
OverType.initFromData('.editor', { /* defaults */ })
|
|
558
621
|
|
|
559
|
-
// Get instance from
|
|
560
|
-
|
|
622
|
+
// Get instance from a selector, Element, NodeList, or Array
|
|
623
|
+
// Returns the instance for the first matching element
|
|
624
|
+
OverType.getInstance(target)
|
|
561
625
|
|
|
562
626
|
// Destroy all instances
|
|
563
627
|
OverType.destroyAll()
|
|
@@ -763,7 +827,7 @@ Uses kebab-case attributes that convert to camelCase options (e.g., `data-ot-sho
|
|
|
763
827
|
|
|
764
828
|
**Supported:** `toolbar`, `theme`, `value`, `placeholder`, `autofocus`, `auto-resize`, `min-height`, `max-height`, `font-size`, `line-height`, `show-stats`, `smart-lists`, `show-active-line-raw`
|
|
765
829
|
|
|
766
|
-
**Not supported (use JS):** `toolbarButtons`, `textareaProps`, `onChange`, `onKeydown`, `statsFormatter`, `codeHighlighter`, `colors`, `mobile`
|
|
830
|
+
**Not supported (use JS):** `toolbarButtons`, `textareaProps`, `onChange`, `onKeydown`, `onFocus`, `onBlur`, `statsFormatter`, `codeHighlighter`, `colors`, `mobile`
|
|
767
831
|
|
|
768
832
|
## Contributors
|
|
769
833
|
|
|
@@ -776,7 +840,7 @@ Special thanks to:
|
|
|
776
840
|
- [Lyric Wai](https://github.com/lyricat) - Fixed double-escaping of links ([#64](https://github.com/panphora/overtype/pull/64)), shared code block alignment fix ([#65](https://github.com/panphora/overtype/issues/65))
|
|
777
841
|
- [kozi](https://github.com/kozi) - Reported Firefox link tooltip bug ([#68](https://github.com/panphora/overtype/issues/68)), toolbar positioning ([#69](https://github.com/panphora/overtype/issues/69)), theme CSS variable issues ([#70](https://github.com/panphora/overtype/issues/70), [#71](https://github.com/panphora/overtype/issues/71))
|
|
778
842
|
- [1951FDG](https://github.com/1951FDG) - Reported unordered list rendering bug ([#74](https://github.com/panphora/overtype/issues/74)), suggested showStats() API improvement ([#77](https://github.com/panphora/overtype/issues/77)), reported placeholder CSS regression ([#102](https://github.com/panphora/overtype/issues/102))
|
|
779
|
-
- [nodesocket](https://github.com/nodesocket) - Reported toolbarButtons export issues ([#73](https://github.com/panphora/overtype/issues/73), [#78](https://github.com/panphora/overtype/issues/78)), suggested image toolbar button ([#89](https://github.com/panphora/overtype/issues/89)), reported custom theme stats bar styling ([#101](https://github.com/panphora/overtype/issues/101))
|
|
843
|
+
- [nodesocket](https://github.com/nodesocket) - Reported toolbarButtons export issues ([#73](https://github.com/panphora/overtype/issues/73), [#78](https://github.com/panphora/overtype/issues/78)), suggested image toolbar button ([#89](https://github.com/panphora/overtype/issues/89)), reported custom theme stats bar styling ([#101](https://github.com/panphora/overtype/issues/101)), suggested onRemoveFile callback ([#104](https://github.com/panphora/overtype/issues/104))
|
|
780
844
|
- [Travis Bell](https://github.com/travisbell) - Reported keyboard shortcuts bug in ESM build ([#80](https://github.com/panphora/overtype/issues/80))
|
|
781
845
|
- [fab2713](https://github.com/fab2713) - Reported italic rendering in lists ([#81](https://github.com/panphora/overtype/issues/81)), reinit maxHeight ([#82](https://github.com/panphora/overtype/issues/82)), placeholder visibility ([#83](https://github.com/panphora/overtype/issues/83)), suggested auto theme ([#84](https://github.com/panphora/overtype/issues/84)), relative URL prefix ([#85](https://github.com/panphora/overtype/issues/85)), minification improvements ([#94](https://github.com/panphora/overtype/issues/94))
|
|
782
846
|
- [oooo-ps](https://github.com/oooo-ps) - Reported remote script loading issue ([#86](https://github.com/panphora/overtype/issues/86))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v2.3.
|
|
2
|
+
* OverType v2.3.10
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author David Miranda
|
|
@@ -5172,6 +5172,7 @@ var _OverType = class _OverType {
|
|
|
5172
5172
|
return;
|
|
5173
5173
|
}
|
|
5174
5174
|
this._fileUploadCounter = 0;
|
|
5175
|
+
this._uploadedFiles = /* @__PURE__ */ new Map();
|
|
5175
5176
|
this._boundHandleFilePaste = this._handleFilePaste.bind(this);
|
|
5176
5177
|
this._boundHandleFileDrop = this._handleFileDrop.bind(this);
|
|
5177
5178
|
this._boundHandleDragOver = this._handleDragOver.bind(this);
|
|
@@ -5180,6 +5181,53 @@ var _OverType = class _OverType {
|
|
|
5180
5181
|
this.textarea.addEventListener("dragover", this._boundHandleDragOver);
|
|
5181
5182
|
this.fileUploadInitialized = true;
|
|
5182
5183
|
}
|
|
5184
|
+
/**
|
|
5185
|
+
* Extract URLs from markdown link syntax: [text](url) or .
|
|
5186
|
+
* @private
|
|
5187
|
+
*/
|
|
5188
|
+
_extractMarkdownUrls(text) {
|
|
5189
|
+
const urls = [];
|
|
5190
|
+
const re = /!?\[[^\]]*\]\(([^)\s]+)/g;
|
|
5191
|
+
let m;
|
|
5192
|
+
while ((m = re.exec(text)) !== null)
|
|
5193
|
+
urls.push(m[1]);
|
|
5194
|
+
return urls;
|
|
5195
|
+
}
|
|
5196
|
+
/**
|
|
5197
|
+
* Track URLs that were just inserted, pairing each with the source File.
|
|
5198
|
+
* If multiple URLs appear in one inserted block, all get associated with
|
|
5199
|
+
* the same file (rare; happens if onInsertFile returns several links).
|
|
5200
|
+
* @private
|
|
5201
|
+
*/
|
|
5202
|
+
_trackInsertedUrls(insertedText, file) {
|
|
5203
|
+
if (!this._uploadedFiles || !file || !insertedText)
|
|
5204
|
+
return;
|
|
5205
|
+
for (const url of this._extractMarkdownUrls(insertedText)) {
|
|
5206
|
+
this._uploadedFiles.set(url, { filename: file.name, file });
|
|
5207
|
+
}
|
|
5208
|
+
}
|
|
5209
|
+
/**
|
|
5210
|
+
* Diff the tracked-URL set against the current value and fire
|
|
5211
|
+
* fileUpload.onRemoveFile for any URL no longer present.
|
|
5212
|
+
* @private
|
|
5213
|
+
*/
|
|
5214
|
+
_checkForRemovedUploads() {
|
|
5215
|
+
var _a;
|
|
5216
|
+
if (!this._uploadedFiles || this._uploadedFiles.size === 0)
|
|
5217
|
+
return;
|
|
5218
|
+
const cb = (_a = this.options.fileUpload) == null ? void 0 : _a.onRemoveFile;
|
|
5219
|
+
const value = this.textarea.value;
|
|
5220
|
+
const removed = [];
|
|
5221
|
+
for (const [url, info] of this._uploadedFiles) {
|
|
5222
|
+
if (!value.includes(url))
|
|
5223
|
+
removed.push({ url, info });
|
|
5224
|
+
}
|
|
5225
|
+
for (const { url, info } of removed) {
|
|
5226
|
+
this._uploadedFiles.delete(url);
|
|
5227
|
+
if (cb)
|
|
5228
|
+
cb({ url, filename: info.filename, file: info.file });
|
|
5229
|
+
}
|
|
5230
|
+
}
|
|
5183
5231
|
_handleFilePaste(e) {
|
|
5184
5232
|
var _a, _b;
|
|
5185
5233
|
if (!((_b = (_a = e == null ? void 0 : e.clipboardData) == null ? void 0 : _a.files) == null ? void 0 : _b.length))
|
|
@@ -5212,6 +5260,7 @@ var _OverType = class _OverType {
|
|
|
5212
5260
|
}
|
|
5213
5261
|
this.options.fileUpload.onInsertFile(file).then((text) => {
|
|
5214
5262
|
this.textarea.value = this.textarea.value.replace(placeholder, text);
|
|
5263
|
+
this._trackInsertedUrls(text, file);
|
|
5215
5264
|
this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
5216
5265
|
}, (error) => {
|
|
5217
5266
|
console.error("OverType: File upload failed", error);
|
|
@@ -5224,6 +5273,7 @@ var _OverType = class _OverType {
|
|
|
5224
5273
|
const texts = Array.isArray(result) ? result : [result];
|
|
5225
5274
|
texts.forEach((text, index) => {
|
|
5226
5275
|
this.textarea.value = this.textarea.value.replace(files[index].placeholder, text);
|
|
5276
|
+
this._trackInsertedUrls(text, files[index].file);
|
|
5227
5277
|
});
|
|
5228
5278
|
this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
5229
5279
|
}, (error) => {
|
|
@@ -5245,6 +5295,7 @@ var _OverType = class _OverType {
|
|
|
5245
5295
|
this._boundHandleFilePaste = null;
|
|
5246
5296
|
this._boundHandleFileDrop = null;
|
|
5247
5297
|
this._boundHandleDragOver = null;
|
|
5298
|
+
this._uploadedFiles = null;
|
|
5248
5299
|
this.fileUploadInitialized = false;
|
|
5249
5300
|
}
|
|
5250
5301
|
insertAtCursor(text) {
|
|
@@ -5289,9 +5340,12 @@ var _OverType = class _OverType {
|
|
|
5289
5340
|
* @private
|
|
5290
5341
|
*/
|
|
5291
5342
|
_notifyChange() {
|
|
5292
|
-
if (!this.
|
|
5343
|
+
if (!this.initialized)
|
|
5293
5344
|
return;
|
|
5294
|
-
this.
|
|
5345
|
+
this._checkForRemovedUploads();
|
|
5346
|
+
if (this.options.onChange) {
|
|
5347
|
+
this.options.onChange(this.textarea.value, this);
|
|
5348
|
+
}
|
|
5295
5349
|
}
|
|
5296
5350
|
/**
|
|
5297
5351
|
* Apply background styling to code blocks
|