overtype 2.0.6 → 2.1.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 +34 -3
- package/dist/overtype-webcomponent.esm.js +88 -2
- package/dist/overtype-webcomponent.esm.js.map +2 -2
- package/dist/overtype-webcomponent.js +88 -2
- package/dist/overtype-webcomponent.js.map +2 -2
- package/dist/overtype-webcomponent.min.js +40 -40
- package/dist/overtype.cjs +88 -2
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.esm.js +88 -2
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +90 -3
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +11 -10
- package/package.json +5 -3
- package/src/overtype.js +73 -1
- package/src/parser.js +25 -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. ~94KB 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** - ~94KB 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** | ~94KB | 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 |
|
|
@@ -537,11 +537,22 @@ OverType.setTheme('solar', { h1: '#custom' }) // Override specific colors
|
|
|
537
537
|
OverType.setCodeHighlighter((code, lang) => highlightedHTML)
|
|
538
538
|
OverType.setCodeHighlighter(null) // Disable global highlighting
|
|
539
539
|
|
|
540
|
+
// Extend parsing with custom syntax (footnotes, directives, etc.)
|
|
541
|
+
// IMPORTANT: You must maintain 1-to-1 character alignment - wrap text, don't change it
|
|
542
|
+
// See: https://panphora.github.io/overtype/examples/custom-syntax.html
|
|
543
|
+
OverType.setCustomSyntax((html) => {
|
|
544
|
+
return html.replace(/\[\^(\w+)\]/g, '<span class="footnote">$&</span>');
|
|
545
|
+
})
|
|
546
|
+
|
|
540
547
|
// Note: Instance methods override global settings
|
|
541
548
|
|
|
542
549
|
// Initialize multiple editors (same as constructor)
|
|
543
550
|
OverType.init(target, options)
|
|
544
551
|
|
|
552
|
+
// Initialize with per-element config via data-ot-* attributes
|
|
553
|
+
// Uses kebab-case: data-ot-show-stats="true" → showStats: true
|
|
554
|
+
OverType.initFromData('.editor', { /* defaults */ })
|
|
555
|
+
|
|
545
556
|
// Get instance from element
|
|
546
557
|
OverType.getInstance(element)
|
|
547
558
|
|
|
@@ -731,6 +742,26 @@ OverType uses a unique invisible textarea overlay approach:
|
|
|
731
742
|
- Textarea content drives everything
|
|
732
743
|
- One-way data flow: textarea → parser → preview
|
|
733
744
|
|
|
745
|
+
## Data Attribute Configuration
|
|
746
|
+
|
|
747
|
+
Use `OverType.initFromData()` to configure multiple editors via HTML data attributes:
|
|
748
|
+
|
|
749
|
+
```html
|
|
750
|
+
<div class="editor" data-ot-toolbar="true" data-ot-theme="cave"></div>
|
|
751
|
+
<div class="editor" data-ot-auto-resize="true" data-ot-min-height="200px"></div>
|
|
752
|
+
<div class="editor" data-ot-show-stats="true" data-ot-placeholder="Write here..."></div>
|
|
753
|
+
|
|
754
|
+
<script>
|
|
755
|
+
OverType.initFromData('.editor', { fontSize: '14px' }); // defaults
|
|
756
|
+
</script>
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Uses kebab-case attributes that convert to camelCase options (e.g., `data-ot-show-stats` → `showStats`).
|
|
760
|
+
|
|
761
|
+
**Supported:** `toolbar`, `theme`, `value`, `placeholder`, `autofocus`, `auto-resize`, `min-height`, `max-height`, `font-size`, `line-height`, `show-stats`, `smart-lists`, `show-active-line-raw`
|
|
762
|
+
|
|
763
|
+
**Not supported (use JS):** `toolbarButtons`, `textareaProps`, `onChange`, `onKeydown`, `statsFormatter`, `codeHighlighter`, `colors`, `mobile`
|
|
764
|
+
|
|
734
765
|
## Contributors
|
|
735
766
|
|
|
736
767
|
Special thanks to:
|
|
@@ -27,6 +27,24 @@ var MarkdownParser = class {
|
|
|
27
27
|
static setCodeHighlighter(highlighter) {
|
|
28
28
|
this.codeHighlighter = highlighter;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Set custom syntax processor function
|
|
32
|
+
* @param {Function|null} processor - Function that takes (html) and returns modified HTML
|
|
33
|
+
*/
|
|
34
|
+
static setCustomSyntax(processor) {
|
|
35
|
+
this.customSyntax = processor;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Apply custom syntax processor to parsed HTML
|
|
39
|
+
* @param {string} html - Parsed HTML line
|
|
40
|
+
* @returns {string} HTML with custom syntax applied
|
|
41
|
+
*/
|
|
42
|
+
static applyCustomSyntax(html) {
|
|
43
|
+
if (this.customSyntax) {
|
|
44
|
+
return this.customSyntax(html);
|
|
45
|
+
}
|
|
46
|
+
return html;
|
|
47
|
+
}
|
|
30
48
|
/**
|
|
31
49
|
* Escape HTML special characters
|
|
32
50
|
* @param {string} text - Raw text to escape
|
|
@@ -365,14 +383,14 @@ var MarkdownParser = class {
|
|
|
365
383
|
const codeFenceRegex = /^```[^`]*$/;
|
|
366
384
|
if (codeFenceRegex.test(line)) {
|
|
367
385
|
inCodeBlock = !inCodeBlock;
|
|
368
|
-
return this.parseLine(line, isPreviewMode);
|
|
386
|
+
return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));
|
|
369
387
|
}
|
|
370
388
|
if (inCodeBlock) {
|
|
371
389
|
const escaped = this.escapeHtml(line);
|
|
372
390
|
const indented = this.preserveIndentation(escaped, line);
|
|
373
391
|
return `<div>${indented || " "}</div>`;
|
|
374
392
|
}
|
|
375
|
-
return this.parseLine(line, isPreviewMode);
|
|
393
|
+
return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));
|
|
376
394
|
});
|
|
377
395
|
const html = parsedLines.join("");
|
|
378
396
|
return this.postProcessHTML(html, instanceHighlighter);
|
|
@@ -704,6 +722,8 @@ var MarkdownParser = class {
|
|
|
704
722
|
__publicField(MarkdownParser, "linkIndex", 0);
|
|
705
723
|
// Global code highlighter function
|
|
706
724
|
__publicField(MarkdownParser, "codeHighlighter", null);
|
|
725
|
+
// Custom syntax processor function
|
|
726
|
+
__publicField(MarkdownParser, "customSyntax", null);
|
|
707
727
|
/**
|
|
708
728
|
* List pattern definitions
|
|
709
729
|
*/
|
|
@@ -4084,6 +4104,8 @@ var _OverType = class _OverType {
|
|
|
4084
4104
|
this.statsBar.className = "overtype-stats";
|
|
4085
4105
|
this.container.appendChild(this.statsBar);
|
|
4086
4106
|
this._updateStats();
|
|
4107
|
+
} else if (show && this.statsBar) {
|
|
4108
|
+
this._updateStats();
|
|
4087
4109
|
} else if (!show && this.statsBar) {
|
|
4088
4110
|
this.statsBar.remove();
|
|
4089
4111
|
this.statsBar = null;
|
|
@@ -4152,6 +4174,44 @@ var _OverType = class _OverType {
|
|
|
4152
4174
|
static init(target, options = {}) {
|
|
4153
4175
|
return new _OverType(target, options);
|
|
4154
4176
|
}
|
|
4177
|
+
/**
|
|
4178
|
+
* Initialize editors with options from data-ot-* attributes
|
|
4179
|
+
* @param {string} selector - CSS selector for target elements
|
|
4180
|
+
* @param {Object} defaults - Default options (data attrs override these)
|
|
4181
|
+
* @returns {Array<OverType>} Array of OverType instances
|
|
4182
|
+
* @example
|
|
4183
|
+
* // HTML: <div class="editor" data-ot-toolbar="true" data-ot-theme="cave"></div>
|
|
4184
|
+
* OverType.initFromData('.editor', { fontSize: '14px' });
|
|
4185
|
+
*/
|
|
4186
|
+
static initFromData(selector, defaults = {}) {
|
|
4187
|
+
const elements = document.querySelectorAll(selector);
|
|
4188
|
+
return Array.from(elements).map((el) => {
|
|
4189
|
+
const options = { ...defaults };
|
|
4190
|
+
for (const attr of el.attributes) {
|
|
4191
|
+
if (attr.name.startsWith("data-ot-")) {
|
|
4192
|
+
const kebab = attr.name.slice(8);
|
|
4193
|
+
const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
4194
|
+
options[key] = _OverType._parseDataValue(attr.value);
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
return new _OverType(el, options);
|
|
4198
|
+
});
|
|
4199
|
+
}
|
|
4200
|
+
/**
|
|
4201
|
+
* Parse a data attribute value to the appropriate type
|
|
4202
|
+
* @private
|
|
4203
|
+
*/
|
|
4204
|
+
static _parseDataValue(value) {
|
|
4205
|
+
if (value === "true")
|
|
4206
|
+
return true;
|
|
4207
|
+
if (value === "false")
|
|
4208
|
+
return false;
|
|
4209
|
+
if (value === "null")
|
|
4210
|
+
return null;
|
|
4211
|
+
if (value !== "" && !isNaN(Number(value)))
|
|
4212
|
+
return Number(value);
|
|
4213
|
+
return value;
|
|
4214
|
+
}
|
|
4155
4215
|
/**
|
|
4156
4216
|
* Get instance from element
|
|
4157
4217
|
* @param {Element} element - DOM element
|
|
@@ -4252,6 +4312,32 @@ var _OverType = class _OverType {
|
|
|
4252
4312
|
}
|
|
4253
4313
|
});
|
|
4254
4314
|
}
|
|
4315
|
+
/**
|
|
4316
|
+
* Set custom syntax processor for extending markdown parsing
|
|
4317
|
+
* @param {Function|null} processor - Function that takes (html) and returns modified HTML
|
|
4318
|
+
* @example
|
|
4319
|
+
* OverType.setCustomSyntax((html) => {
|
|
4320
|
+
* // Highlight footnote references [^1]
|
|
4321
|
+
* return html.replace(/\[\^(\w+)\]/g, '<span class="footnote-ref">$&</span>');
|
|
4322
|
+
* });
|
|
4323
|
+
*/
|
|
4324
|
+
static setCustomSyntax(processor) {
|
|
4325
|
+
MarkdownParser.setCustomSyntax(processor);
|
|
4326
|
+
document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => {
|
|
4327
|
+
const instance = wrapper._instance;
|
|
4328
|
+
if (instance && instance.updatePreview) {
|
|
4329
|
+
instance.updatePreview();
|
|
4330
|
+
}
|
|
4331
|
+
});
|
|
4332
|
+
document.querySelectorAll("overtype-editor").forEach((webComponent) => {
|
|
4333
|
+
if (typeof webComponent.getEditor === "function") {
|
|
4334
|
+
const instance = webComponent.getEditor();
|
|
4335
|
+
if (instance && instance.updatePreview) {
|
|
4336
|
+
instance.updatePreview();
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
});
|
|
4340
|
+
}
|
|
4255
4341
|
/**
|
|
4256
4342
|
* Initialize global event listeners
|
|
4257
4343
|
*/
|