overtype 1.2.3 → 1.2.4
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 +36 -15
- package/dist/overtype.cjs +150 -39
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.d.ts +169 -0
- package/dist/overtype.esm.js +150 -39
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +155 -39
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +84 -68
- package/package.json +4 -2
- package/src/link-tooltip.js +16 -16
- package/src/overtype.d.ts +23 -1
- package/src/overtype.js +22 -12
- package/src/parser.js +127 -68
- package/src/styles.js +16 -8
- package/src/toolbar.js +63 -2
package/dist/overtype.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v1.2.
|
|
2
|
+
* OverType v1.2.4
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author Demo User
|
|
@@ -155,6 +155,17 @@ var OverType = (() => {
|
|
|
155
155
|
html = html.replace(new RegExp("(?<!_)_(?!_)(.+?)(?<!_)_(?!_)", "g"), '<em><span class="syntax-marker">_</span>$1<span class="syntax-marker">_</span></em>');
|
|
156
156
|
return html;
|
|
157
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Parse strikethrough text
|
|
160
|
+
* Supports both single (~) and double (~~) tildes, but rejects 3+ tildes
|
|
161
|
+
* @param {string} html - HTML with potential strikethrough markdown
|
|
162
|
+
* @returns {string} HTML with strikethrough styling
|
|
163
|
+
*/
|
|
164
|
+
static parseStrikethrough(html) {
|
|
165
|
+
html = html.replace(new RegExp("(?<!~)~~(?!~)(.+?)(?<!~)~~(?!~)", "g"), '<del><span class="syntax-marker">~~</span>$1<span class="syntax-marker">~~</span></del>');
|
|
166
|
+
html = html.replace(new RegExp("(?<!~)~(?!~)(.+?)(?<!~)~(?!~)", "g"), '<del><span class="syntax-marker">~</span>$1<span class="syntax-marker">~</span></del>');
|
|
167
|
+
return html;
|
|
168
|
+
}
|
|
158
169
|
/**
|
|
159
170
|
* Parse inline code
|
|
160
171
|
* @param {string} html - HTML with potential code markdown
|
|
@@ -217,6 +228,7 @@ var OverType = (() => {
|
|
|
217
228
|
sanctuaries.set(placeholder, match);
|
|
218
229
|
return placeholder;
|
|
219
230
|
});
|
|
231
|
+
html = this.parseStrikethrough(html);
|
|
220
232
|
html = this.parseBold(html);
|
|
221
233
|
html = this.parseItalic(html);
|
|
222
234
|
sanctuaries.forEach((content, placeholder) => {
|
|
@@ -351,6 +363,17 @@ var OverType = (() => {
|
|
|
351
363
|
container.insertBefore(currentList, child);
|
|
352
364
|
listType = newType;
|
|
353
365
|
}
|
|
366
|
+
const indentationNodes = [];
|
|
367
|
+
for (const node of child.childNodes) {
|
|
368
|
+
if (node.nodeType === 3 && node.textContent.match(/^\u00A0+$/)) {
|
|
369
|
+
indentationNodes.push(node.cloneNode(true));
|
|
370
|
+
} else if (node === listItem) {
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
indentationNodes.forEach((node) => {
|
|
375
|
+
listItem.insertBefore(node, listItem.firstChild);
|
|
376
|
+
});
|
|
354
377
|
currentList.appendChild(listItem);
|
|
355
378
|
child.remove();
|
|
356
379
|
} else {
|
|
@@ -368,15 +391,35 @@ var OverType = (() => {
|
|
|
368
391
|
static postProcessHTMLManual(html) {
|
|
369
392
|
let processed = html;
|
|
370
393
|
processed = processed.replace(/((?:<div>(?: )*<li class="bullet-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
|
|
371
|
-
const
|
|
372
|
-
if (
|
|
394
|
+
const divs = match.match(/<div>(?: )*<li class="bullet-list">.*?<\/li><\/div>/gs) || [];
|
|
395
|
+
if (divs.length > 0) {
|
|
396
|
+
const items = divs.map((div) => {
|
|
397
|
+
const indentMatch = div.match(/<div>((?: )*)<li/);
|
|
398
|
+
const listItemMatch = div.match(/<li class="bullet-list">.*?<\/li>/);
|
|
399
|
+
if (indentMatch && listItemMatch) {
|
|
400
|
+
const indentation = indentMatch[1];
|
|
401
|
+
const listItem = listItemMatch[0];
|
|
402
|
+
return listItem.replace(/<li class="bullet-list">/, `<li class="bullet-list">${indentation}`);
|
|
403
|
+
}
|
|
404
|
+
return listItemMatch ? listItemMatch[0] : "";
|
|
405
|
+
}).filter(Boolean);
|
|
373
406
|
return "<ul>" + items.join("") + "</ul>";
|
|
374
407
|
}
|
|
375
408
|
return match;
|
|
376
409
|
});
|
|
377
410
|
processed = processed.replace(/((?:<div>(?: )*<li class="ordered-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
|
|
378
|
-
const
|
|
379
|
-
if (
|
|
411
|
+
const divs = match.match(/<div>(?: )*<li class="ordered-list">.*?<\/li><\/div>/gs) || [];
|
|
412
|
+
if (divs.length > 0) {
|
|
413
|
+
const items = divs.map((div) => {
|
|
414
|
+
const indentMatch = div.match(/<div>((?: )*)<li/);
|
|
415
|
+
const listItemMatch = div.match(/<li class="ordered-list">.*?<\/li>/);
|
|
416
|
+
if (indentMatch && listItemMatch) {
|
|
417
|
+
const indentation = indentMatch[1];
|
|
418
|
+
const listItem = listItemMatch[0];
|
|
419
|
+
return listItem.replace(/<li class="ordered-list">/, `<li class="ordered-list">${indentation}`);
|
|
420
|
+
}
|
|
421
|
+
return listItemMatch ? listItemMatch[0] : "";
|
|
422
|
+
}).filter(Boolean);
|
|
380
423
|
return "<ol>" + items.join("") + "</ol>";
|
|
381
424
|
}
|
|
382
425
|
return match;
|
|
@@ -1918,6 +1961,14 @@ ${blockSuffix}` : suffix;
|
|
|
1918
1961
|
font-style: italic !important;
|
|
1919
1962
|
}
|
|
1920
1963
|
|
|
1964
|
+
/* Strikethrough text */
|
|
1965
|
+
.overtype-wrapper .overtype-preview del {
|
|
1966
|
+
color: var(--del, #ee964b) !important;
|
|
1967
|
+
text-decoration: line-through !important;
|
|
1968
|
+
text-decoration-color: var(--del, #ee964b) !important;
|
|
1969
|
+
text-decoration-thickness: 1px !important;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1921
1972
|
/* Inline code */
|
|
1922
1973
|
.overtype-wrapper .overtype-preview code {
|
|
1923
1974
|
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
@@ -2061,10 +2112,10 @@ ${blockSuffix}` : suffix;
|
|
|
2061
2112
|
height: 8px !important;
|
|
2062
2113
|
background: #4caf50 !important;
|
|
2063
2114
|
border-radius: 50% !important;
|
|
2064
|
-
animation: pulse 2s infinite !important;
|
|
2115
|
+
animation: overtype-pulse 2s infinite !important;
|
|
2065
2116
|
}
|
|
2066
2117
|
|
|
2067
|
-
@keyframes pulse {
|
|
2118
|
+
@keyframes overtype-pulse {
|
|
2068
2119
|
0%, 100% { opacity: 1; transform: scale(1); }
|
|
2069
2120
|
50% { opacity: 0.6; transform: scale(1.2); }
|
|
2070
2121
|
}
|
|
@@ -2072,19 +2123,19 @@ ${blockSuffix}` : suffix;
|
|
|
2072
2123
|
|
|
2073
2124
|
/* Toolbar Styles */
|
|
2074
2125
|
.overtype-toolbar {
|
|
2075
|
-
display: flex;
|
|
2076
|
-
align-items: center;
|
|
2077
|
-
gap: 4px;
|
|
2126
|
+
display: flex !important;
|
|
2127
|
+
align-items: center !important;
|
|
2128
|
+
gap: 4px !important;
|
|
2078
2129
|
padding: 8px !important; /* Override reset */
|
|
2079
2130
|
background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */
|
|
2080
2131
|
overflow-x: auto !important; /* Allow horizontal scrolling */
|
|
2081
2132
|
overflow-y: hidden !important; /* Hide vertical overflow */
|
|
2082
|
-
-webkit-overflow-scrolling: touch;
|
|
2083
|
-
flex-shrink: 0;
|
|
2133
|
+
-webkit-overflow-scrolling: touch !important;
|
|
2134
|
+
flex-shrink: 0 !important;
|
|
2084
2135
|
height: auto !important;
|
|
2085
2136
|
grid-row: 1 !important; /* Always first row in grid */
|
|
2086
2137
|
position: relative !important; /* Override reset */
|
|
2087
|
-
z-index: 100; /* Ensure toolbar is above wrapper */
|
|
2138
|
+
z-index: 100 !important; /* Ensure toolbar is above wrapper */
|
|
2088
2139
|
scrollbar-width: thin; /* Thin scrollbar on Firefox */
|
|
2089
2140
|
}
|
|
2090
2141
|
|
|
@@ -2466,20 +2517,67 @@ ${blockSuffix}` : suffix;
|
|
|
2466
2517
|
|
|
2467
2518
|
// src/toolbar.js
|
|
2468
2519
|
var Toolbar = class {
|
|
2469
|
-
constructor(editor) {
|
|
2520
|
+
constructor(editor, buttonConfig = null) {
|
|
2470
2521
|
this.editor = editor;
|
|
2471
2522
|
this.container = null;
|
|
2472
2523
|
this.buttons = {};
|
|
2524
|
+
this.buttonConfig = buttonConfig;
|
|
2525
|
+
}
|
|
2526
|
+
/**
|
|
2527
|
+
* Check if cursor/selection is inside a markdown link
|
|
2528
|
+
* @param {HTMLTextAreaElement} textarea - The textarea element
|
|
2529
|
+
* @returns {boolean} True if inside a link
|
|
2530
|
+
*/
|
|
2531
|
+
isInsideLink(textarea) {
|
|
2532
|
+
const value = textarea.value;
|
|
2533
|
+
const start = textarea.selectionStart;
|
|
2534
|
+
const end = textarea.selectionEnd;
|
|
2535
|
+
let insideLink = false;
|
|
2536
|
+
let openBracket = -1;
|
|
2537
|
+
let closeBracket = -1;
|
|
2538
|
+
for (let i = start - 1; i >= 0; i--) {
|
|
2539
|
+
if (value[i] === "[") {
|
|
2540
|
+
openBracket = i;
|
|
2541
|
+
break;
|
|
2542
|
+
}
|
|
2543
|
+
if (value[i] === "\n") {
|
|
2544
|
+
break;
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
if (openBracket >= 0) {
|
|
2548
|
+
for (let i = end; i < value.length - 1; i++) {
|
|
2549
|
+
if (value[i] === "]" && value[i + 1] === "(") {
|
|
2550
|
+
closeBracket = i;
|
|
2551
|
+
break;
|
|
2552
|
+
}
|
|
2553
|
+
if (value[i] === "\n") {
|
|
2554
|
+
break;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
if (openBracket >= 0 && closeBracket >= 0) {
|
|
2559
|
+
for (let i = closeBracket + 2; i < value.length; i++) {
|
|
2560
|
+
if (value[i] === ")") {
|
|
2561
|
+
insideLink = true;
|
|
2562
|
+
break;
|
|
2563
|
+
}
|
|
2564
|
+
if (value[i] === "\n" || value[i] === " ") {
|
|
2565
|
+
break;
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return insideLink;
|
|
2473
2570
|
}
|
|
2474
2571
|
/**
|
|
2475
2572
|
* Create and attach toolbar to editor
|
|
2476
2573
|
*/
|
|
2477
2574
|
create() {
|
|
2575
|
+
var _a;
|
|
2478
2576
|
this.container = document.createElement("div");
|
|
2479
2577
|
this.container.className = "overtype-toolbar";
|
|
2480
2578
|
this.container.setAttribute("role", "toolbar");
|
|
2481
2579
|
this.container.setAttribute("aria-label", "Text formatting");
|
|
2482
|
-
const buttonConfig = [
|
|
2580
|
+
const buttonConfig = (_a = this.buttonConfig) != null ? _a : [
|
|
2483
2581
|
{ name: "bold", icon: boldIcon, title: "Bold (Ctrl+B)", action: "toggleBold" },
|
|
2484
2582
|
{ name: "italic", icon: italicIcon, title: "Italic (Ctrl+I)", action: "toggleItalic" },
|
|
2485
2583
|
{ separator: true },
|
|
@@ -2573,6 +2671,9 @@ ${blockSuffix}` : suffix;
|
|
|
2573
2671
|
insertLink(textarea);
|
|
2574
2672
|
break;
|
|
2575
2673
|
case "toggleCode":
|
|
2674
|
+
if (this.isInsideLink(textarea)) {
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2576
2677
|
toggleCode(textarea);
|
|
2577
2678
|
break;
|
|
2578
2679
|
case "toggleBulletList":
|
|
@@ -2788,29 +2889,29 @@ ${blockSuffix}` : suffix;
|
|
|
2788
2889
|
position: absolute;
|
|
2789
2890
|
position-anchor: var(--target-anchor, --link-0);
|
|
2790
2891
|
position-area: block-end center;
|
|
2791
|
-
margin-top: 8px;
|
|
2892
|
+
margin-top: 8px !important;
|
|
2792
2893
|
|
|
2793
|
-
background: #333;
|
|
2794
|
-
color: white;
|
|
2795
|
-
padding: 6px 10px;
|
|
2796
|
-
border-radius: 16px;
|
|
2797
|
-
font-size: 12px;
|
|
2798
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
2799
|
-
display: none;
|
|
2800
|
-
z-index: 10000;
|
|
2801
|
-
cursor: pointer;
|
|
2802
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
2803
|
-
max-width: 300px;
|
|
2804
|
-
white-space: nowrap;
|
|
2805
|
-
overflow: hidden;
|
|
2806
|
-
text-overflow: ellipsis;
|
|
2894
|
+
background: #333 !important;
|
|
2895
|
+
color: white !important;
|
|
2896
|
+
padding: 6px 10px !important;
|
|
2897
|
+
border-radius: 16px !important;
|
|
2898
|
+
font-size: 12px !important;
|
|
2899
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
|
|
2900
|
+
display: none !important;
|
|
2901
|
+
z-index: 10000 !important;
|
|
2902
|
+
cursor: pointer !important;
|
|
2903
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
|
|
2904
|
+
max-width: 300px !important;
|
|
2905
|
+
white-space: nowrap !important;
|
|
2906
|
+
overflow: hidden !important;
|
|
2907
|
+
text-overflow: ellipsis !important;
|
|
2807
2908
|
|
|
2808
2909
|
position-try: most-width block-end inline-end, flip-inline, block-start center;
|
|
2809
2910
|
position-visibility: anchors-visible;
|
|
2810
2911
|
}
|
|
2811
2912
|
|
|
2812
2913
|
.overtype-link-tooltip.visible {
|
|
2813
|
-
display: flex;
|
|
2914
|
+
display: flex !important;
|
|
2814
2915
|
}
|
|
2815
2916
|
}
|
|
2816
2917
|
`;
|
|
@@ -2958,7 +3059,8 @@ ${blockSuffix}` : suffix;
|
|
|
2958
3059
|
this.shortcuts = new ShortcutsManager(this);
|
|
2959
3060
|
this.linkTooltip = new LinkTooltip(this);
|
|
2960
3061
|
if (this.options.toolbar) {
|
|
2961
|
-
this.toolbar
|
|
3062
|
+
const toolbarButtons = typeof this.options.toolbar === "object" ? this.options.toolbar.buttons : null;
|
|
3063
|
+
this.toolbar = new Toolbar(this, toolbarButtons);
|
|
2962
3064
|
this.toolbar.create();
|
|
2963
3065
|
this.textarea.addEventListener("selectionchange", () => {
|
|
2964
3066
|
this.toolbar.updateButtonStates();
|
|
@@ -3440,24 +3542,36 @@ ${blockSuffix}` : suffix;
|
|
|
3440
3542
|
}
|
|
3441
3543
|
/**
|
|
3442
3544
|
* Get the rendered HTML of the current content
|
|
3443
|
-
* @param {
|
|
3545
|
+
* @param {Object} options - Rendering options
|
|
3546
|
+
* @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes
|
|
3444
3547
|
* @returns {string} Rendered HTML
|
|
3445
3548
|
*/
|
|
3446
|
-
getRenderedHTML(
|
|
3549
|
+
getRenderedHTML(options = {}) {
|
|
3447
3550
|
const markdown = this.getValue();
|
|
3448
3551
|
let html = MarkdownParser.parse(markdown);
|
|
3449
|
-
if (
|
|
3450
|
-
html =
|
|
3552
|
+
if (options.cleanHTML) {
|
|
3553
|
+
html = html.replace(/<span class="syntax-marker[^"]*">.*?<\/span>/g, "");
|
|
3554
|
+
html = html.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g, "");
|
|
3555
|
+
html = html.replace(/\sclass=""/g, "");
|
|
3451
3556
|
}
|
|
3452
3557
|
return html;
|
|
3453
3558
|
}
|
|
3454
3559
|
/**
|
|
3455
3560
|
* Get the current preview element's HTML
|
|
3561
|
+
* This includes all syntax markers and OverType styling
|
|
3456
3562
|
* @returns {string} Current preview HTML (as displayed)
|
|
3457
3563
|
*/
|
|
3458
3564
|
getPreviewHTML() {
|
|
3459
3565
|
return this.preview.innerHTML;
|
|
3460
3566
|
}
|
|
3567
|
+
/**
|
|
3568
|
+
* Get clean HTML without any OverType-specific markup
|
|
3569
|
+
* Useful for exporting to other formats or storage
|
|
3570
|
+
* @returns {string} Clean HTML suitable for export
|
|
3571
|
+
*/
|
|
3572
|
+
getCleanHTML() {
|
|
3573
|
+
return this.getRenderedHTML({ cleanHTML: true });
|
|
3574
|
+
}
|
|
3461
3575
|
/**
|
|
3462
3576
|
* Focus the editor
|
|
3463
3577
|
*/
|
|
@@ -3776,9 +3890,6 @@ ${blockSuffix}` : suffix;
|
|
|
3776
3890
|
OverType.themes = { solar, cave: getTheme("cave") };
|
|
3777
3891
|
OverType.getTheme = getTheme;
|
|
3778
3892
|
OverType.currentTheme = solar;
|
|
3779
|
-
if (typeof window !== "undefined" && typeof window.document !== "undefined") {
|
|
3780
|
-
window.OverType = OverType;
|
|
3781
|
-
}
|
|
3782
3893
|
var overtype_default = OverType;
|
|
3783
3894
|
return __toCommonJS(overtype_exports);
|
|
3784
3895
|
})();
|
|
@@ -3787,4 +3898,9 @@ ${blockSuffix}` : suffix;
|
|
|
3787
3898
|
* @version 1.0.0
|
|
3788
3899
|
* @license MIT
|
|
3789
3900
|
*/
|
|
3901
|
+
|
|
3902
|
+
if (typeof window !== "undefined" && typeof window.document !== "undefined") {
|
|
3903
|
+
window.OverType = OverType.default ? OverType.default : OverType;
|
|
3904
|
+
}
|
|
3905
|
+
|
|
3790
3906
|
//# sourceMappingURL=overtype.js.map
|