overtype 2.0.5 → 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 +117 -6
- package/dist/overtype-webcomponent.esm.js.map +2 -2
- package/dist/overtype-webcomponent.js +117 -6
- package/dist/overtype-webcomponent.js.map +2 -2
- package/dist/overtype-webcomponent.min.js +42 -42
- package/dist/overtype.cjs +117 -6
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.esm.js +117 -6
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +120 -6
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +15 -12
- package/package.json +5 -3
- package/src/overtype.js +81 -4
- package/src/parser.js +30 -6
- package/src/toolbar.js +28 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v2.0.
|
|
2
|
+
* OverType v2.0.6
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author David Miranda
|
|
@@ -50,6 +50,24 @@ var OverTypeEditor = (() => {
|
|
|
50
50
|
static setCodeHighlighter(highlighter) {
|
|
51
51
|
this.codeHighlighter = highlighter;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Set custom syntax processor function
|
|
55
|
+
* @param {Function|null} processor - Function that takes (html) and returns modified HTML
|
|
56
|
+
*/
|
|
57
|
+
static setCustomSyntax(processor) {
|
|
58
|
+
this.customSyntax = processor;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Apply custom syntax processor to parsed HTML
|
|
62
|
+
* @param {string} html - Parsed HTML line
|
|
63
|
+
* @returns {string} HTML with custom syntax applied
|
|
64
|
+
*/
|
|
65
|
+
static applyCustomSyntax(html) {
|
|
66
|
+
if (this.customSyntax) {
|
|
67
|
+
return this.customSyntax(html);
|
|
68
|
+
}
|
|
69
|
+
return html;
|
|
70
|
+
}
|
|
53
71
|
/**
|
|
54
72
|
* Escape HTML special characters
|
|
55
73
|
* @param {string} text - Raw text to escape
|
|
@@ -114,7 +132,7 @@ var OverTypeEditor = (() => {
|
|
|
114
132
|
* @returns {string} Parsed bullet list item
|
|
115
133
|
*/
|
|
116
134
|
static parseBulletList(html) {
|
|
117
|
-
return html.replace(/^((?: )*)([
|
|
135
|
+
return html.replace(/^((?: )*)([-*+])\s(.+)$/, (match, indent, marker, content) => {
|
|
118
136
|
return `${indent}<li class="bullet-list"><span class="syntax-marker">${marker} </span>${content}</li>`;
|
|
119
137
|
});
|
|
120
138
|
}
|
|
@@ -173,7 +191,7 @@ var OverTypeEditor = (() => {
|
|
|
173
191
|
* @returns {string} HTML with italic styling
|
|
174
192
|
*/
|
|
175
193
|
static parseItalic(html) {
|
|
176
|
-
html = html.replace(new RegExp("(
|
|
194
|
+
html = html.replace(new RegExp("(?<![\\*>])\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)", "g"), '<em><span class="syntax-marker">*</span>$1<span class="syntax-marker">*</span></em>');
|
|
177
195
|
html = html.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?<!_)_(?!_)(?=\\s|$)", "g"), '<em><span class="syntax-marker">_</span>$1<span class="syntax-marker">_</span></em>');
|
|
178
196
|
return html;
|
|
179
197
|
}
|
|
@@ -388,14 +406,14 @@ var OverTypeEditor = (() => {
|
|
|
388
406
|
const codeFenceRegex = /^```[^`]*$/;
|
|
389
407
|
if (codeFenceRegex.test(line)) {
|
|
390
408
|
inCodeBlock = !inCodeBlock;
|
|
391
|
-
return this.parseLine(line, isPreviewMode);
|
|
409
|
+
return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));
|
|
392
410
|
}
|
|
393
411
|
if (inCodeBlock) {
|
|
394
412
|
const escaped = this.escapeHtml(line);
|
|
395
413
|
const indented = this.preserveIndentation(escaped, line);
|
|
396
414
|
return `<div>${indented || " "}</div>`;
|
|
397
415
|
}
|
|
398
|
-
return this.parseLine(line, isPreviewMode);
|
|
416
|
+
return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));
|
|
399
417
|
});
|
|
400
418
|
const html = parsedLines.join("");
|
|
401
419
|
return this.postProcessHTML(html, instanceHighlighter);
|
|
@@ -727,6 +745,8 @@ var OverTypeEditor = (() => {
|
|
|
727
745
|
__publicField(MarkdownParser, "linkIndex", 0);
|
|
728
746
|
// Global code highlighter function
|
|
729
747
|
__publicField(MarkdownParser, "codeHighlighter", null);
|
|
748
|
+
// Custom syntax processor function
|
|
749
|
+
__publicField(MarkdownParser, "customSyntax", null);
|
|
730
750
|
/**
|
|
731
751
|
* List pattern definitions
|
|
732
752
|
*/
|
|
@@ -2785,6 +2805,28 @@ ${blockSuffix}` : suffix;
|
|
|
2785
2805
|
button.addEventListener("click", button._clickHandler);
|
|
2786
2806
|
return button;
|
|
2787
2807
|
}
|
|
2808
|
+
/**
|
|
2809
|
+
* Handle button action programmatically (used by keyboard shortcuts)
|
|
2810
|
+
* @param {Object} buttonConfig - Button configuration object with action function
|
|
2811
|
+
*/
|
|
2812
|
+
async handleAction(buttonConfig) {
|
|
2813
|
+
this.editor.textarea.focus();
|
|
2814
|
+
try {
|
|
2815
|
+
if (buttonConfig.action) {
|
|
2816
|
+
await buttonConfig.action({
|
|
2817
|
+
editor: this.editor,
|
|
2818
|
+
getValue: () => this.editor.getValue(),
|
|
2819
|
+
setValue: (value) => this.editor.setValue(value),
|
|
2820
|
+
event: null
|
|
2821
|
+
});
|
|
2822
|
+
}
|
|
2823
|
+
} catch (error) {
|
|
2824
|
+
console.error(`Action "${buttonConfig.name}" error:`, error);
|
|
2825
|
+
this.editor.wrapper.dispatchEvent(new CustomEvent("button-error", {
|
|
2826
|
+
detail: { buttonName: buttonConfig.name, error }
|
|
2827
|
+
}));
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2788
2830
|
/**
|
|
2789
2831
|
* Sanitize SVG to prevent XSS
|
|
2790
2832
|
*/
|
|
@@ -3723,10 +3765,13 @@ ${blockSuffix}` : suffix;
|
|
|
3723
3765
|
*/
|
|
3724
3766
|
handleKeydown(event) {
|
|
3725
3767
|
if (event.key === "Tab") {
|
|
3726
|
-
event.preventDefault();
|
|
3727
3768
|
const start = this.textarea.selectionStart;
|
|
3728
3769
|
const end = this.textarea.selectionEnd;
|
|
3729
3770
|
const value = this.textarea.value;
|
|
3771
|
+
if (event.shiftKey && start === end) {
|
|
3772
|
+
return;
|
|
3773
|
+
}
|
|
3774
|
+
event.preventDefault();
|
|
3730
3775
|
if (start !== end && event.shiftKey) {
|
|
3731
3776
|
const before = value.substring(0, start);
|
|
3732
3777
|
const selection = value.substring(start, end);
|
|
@@ -4082,6 +4127,8 @@ ${blockSuffix}` : suffix;
|
|
|
4082
4127
|
this.statsBar.className = "overtype-stats";
|
|
4083
4128
|
this.container.appendChild(this.statsBar);
|
|
4084
4129
|
this._updateStats();
|
|
4130
|
+
} else if (show && this.statsBar) {
|
|
4131
|
+
this._updateStats();
|
|
4085
4132
|
} else if (!show && this.statsBar) {
|
|
4086
4133
|
this.statsBar.remove();
|
|
4087
4134
|
this.statsBar = null;
|
|
@@ -4150,6 +4197,44 @@ ${blockSuffix}` : suffix;
|
|
|
4150
4197
|
static init(target, options = {}) {
|
|
4151
4198
|
return new _OverType(target, options);
|
|
4152
4199
|
}
|
|
4200
|
+
/**
|
|
4201
|
+
* Initialize editors with options from data-ot-* attributes
|
|
4202
|
+
* @param {string} selector - CSS selector for target elements
|
|
4203
|
+
* @param {Object} defaults - Default options (data attrs override these)
|
|
4204
|
+
* @returns {Array<OverType>} Array of OverType instances
|
|
4205
|
+
* @example
|
|
4206
|
+
* // HTML: <div class="editor" data-ot-toolbar="true" data-ot-theme="cave"></div>
|
|
4207
|
+
* OverType.initFromData('.editor', { fontSize: '14px' });
|
|
4208
|
+
*/
|
|
4209
|
+
static initFromData(selector, defaults = {}) {
|
|
4210
|
+
const elements = document.querySelectorAll(selector);
|
|
4211
|
+
return Array.from(elements).map((el) => {
|
|
4212
|
+
const options = { ...defaults };
|
|
4213
|
+
for (const attr of el.attributes) {
|
|
4214
|
+
if (attr.name.startsWith("data-ot-")) {
|
|
4215
|
+
const kebab = attr.name.slice(8);
|
|
4216
|
+
const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
4217
|
+
options[key] = _OverType._parseDataValue(attr.value);
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
return new _OverType(el, options);
|
|
4221
|
+
});
|
|
4222
|
+
}
|
|
4223
|
+
/**
|
|
4224
|
+
* Parse a data attribute value to the appropriate type
|
|
4225
|
+
* @private
|
|
4226
|
+
*/
|
|
4227
|
+
static _parseDataValue(value) {
|
|
4228
|
+
if (value === "true")
|
|
4229
|
+
return true;
|
|
4230
|
+
if (value === "false")
|
|
4231
|
+
return false;
|
|
4232
|
+
if (value === "null")
|
|
4233
|
+
return null;
|
|
4234
|
+
if (value !== "" && !isNaN(Number(value)))
|
|
4235
|
+
return Number(value);
|
|
4236
|
+
return value;
|
|
4237
|
+
}
|
|
4153
4238
|
/**
|
|
4154
4239
|
* Get instance from element
|
|
4155
4240
|
* @param {Element} element - DOM element
|
|
@@ -4250,6 +4335,32 @@ ${blockSuffix}` : suffix;
|
|
|
4250
4335
|
}
|
|
4251
4336
|
});
|
|
4252
4337
|
}
|
|
4338
|
+
/**
|
|
4339
|
+
* Set custom syntax processor for extending markdown parsing
|
|
4340
|
+
* @param {Function|null} processor - Function that takes (html) and returns modified HTML
|
|
4341
|
+
* @example
|
|
4342
|
+
* OverType.setCustomSyntax((html) => {
|
|
4343
|
+
* // Highlight footnote references [^1]
|
|
4344
|
+
* return html.replace(/\[\^(\w+)\]/g, '<span class="footnote-ref">$&</span>');
|
|
4345
|
+
* });
|
|
4346
|
+
*/
|
|
4347
|
+
static setCustomSyntax(processor) {
|
|
4348
|
+
MarkdownParser.setCustomSyntax(processor);
|
|
4349
|
+
document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => {
|
|
4350
|
+
const instance = wrapper._instance;
|
|
4351
|
+
if (instance && instance.updatePreview) {
|
|
4352
|
+
instance.updatePreview();
|
|
4353
|
+
}
|
|
4354
|
+
});
|
|
4355
|
+
document.querySelectorAll("overtype-editor").forEach((webComponent) => {
|
|
4356
|
+
if (typeof webComponent.getEditor === "function") {
|
|
4357
|
+
const instance = webComponent.getEditor();
|
|
4358
|
+
if (instance && instance.updatePreview) {
|
|
4359
|
+
instance.updatePreview();
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
});
|
|
4363
|
+
}
|
|
4253
4364
|
/**
|
|
4254
4365
|
* Initialize global event listeners
|
|
4255
4366
|
*/
|