overtype 1.1.8 → 1.2.1
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 +66 -6
- package/dist/overtype.cjs +3541 -0
- package/dist/overtype.cjs.map +7 -0
- package/dist/overtype.esm.js +598 -32
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +598 -33
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +350 -49
- package/package.json +17 -3
- package/src/overtype.js +83 -11
- package/src/parser.js +176 -7
- package/src/styles.js +314 -14
- package/src/toolbar.js +140 -4
package/dist/overtype.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v1.1
|
|
2
|
+
* OverType v1.2.1
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author Demo User
|
|
@@ -54,8 +54,7 @@ var MarkdownParser = class {
|
|
|
54
54
|
static parseHeader(html) {
|
|
55
55
|
return html.replace(/^(#{1,3})\s(.+)$/, (match, hashes, content) => {
|
|
56
56
|
const level = hashes.length;
|
|
57
|
-
|
|
58
|
-
return `<span class="header ${levelClasses[level - 1]}"><span class="syntax-marker">${hashes}</span> ${content}</span>`;
|
|
57
|
+
return `<h${level}><span class="syntax-marker">${hashes} </span>${content}</h${level}>`;
|
|
59
58
|
});
|
|
60
59
|
}
|
|
61
60
|
/**
|
|
@@ -86,7 +85,7 @@ var MarkdownParser = class {
|
|
|
86
85
|
*/
|
|
87
86
|
static parseBulletList(html) {
|
|
88
87
|
return html.replace(/^((?: )*)([-*])\s(.+)$/, (match, indent, marker, content) => {
|
|
89
|
-
return `${indent}<span class="syntax-marker">${marker}</span
|
|
88
|
+
return `${indent}<li class="bullet-list"><span class="syntax-marker">${marker} </span>${content}</li>`;
|
|
90
89
|
});
|
|
91
90
|
}
|
|
92
91
|
/**
|
|
@@ -96,7 +95,7 @@ var MarkdownParser = class {
|
|
|
96
95
|
*/
|
|
97
96
|
static parseNumberedList(html) {
|
|
98
97
|
return html.replace(/^((?: )*)(\d+\.)\s(.+)$/, (match, indent, marker, content) => {
|
|
99
|
-
return `${indent}<span class="syntax-marker">${marker}</span
|
|
98
|
+
return `${indent}<li class="ordered-list"><span class="syntax-marker">${marker} </span>${content}</li>`;
|
|
100
99
|
});
|
|
101
100
|
}
|
|
102
101
|
/**
|
|
@@ -171,7 +170,7 @@ var MarkdownParser = class {
|
|
|
171
170
|
return html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => {
|
|
172
171
|
const anchorName = `--link-${this.linkIndex++}`;
|
|
173
172
|
const safeUrl = this.sanitizeUrl(url);
|
|
174
|
-
return `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker">](
|
|
173
|
+
return `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker url-part">](${url})</span></a>`;
|
|
175
174
|
});
|
|
176
175
|
}
|
|
177
176
|
/**
|
|
@@ -242,7 +241,123 @@ var MarkdownParser = class {
|
|
|
242
241
|
}
|
|
243
242
|
return this.parseLine(line);
|
|
244
243
|
});
|
|
245
|
-
|
|
244
|
+
const html = parsedLines.join("");
|
|
245
|
+
return this.postProcessHTML(html);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Post-process HTML to consolidate lists and code blocks
|
|
249
|
+
* @param {string} html - HTML to post-process
|
|
250
|
+
* @returns {string} Post-processed HTML with consolidated lists and code blocks
|
|
251
|
+
*/
|
|
252
|
+
static postProcessHTML(html) {
|
|
253
|
+
if (typeof document === "undefined" || !document) {
|
|
254
|
+
return this.postProcessHTMLManual(html);
|
|
255
|
+
}
|
|
256
|
+
const container = document.createElement("div");
|
|
257
|
+
container.innerHTML = html;
|
|
258
|
+
let currentList = null;
|
|
259
|
+
let listType = null;
|
|
260
|
+
let currentCodeBlock = null;
|
|
261
|
+
let inCodeBlock = false;
|
|
262
|
+
const children = Array.from(container.children);
|
|
263
|
+
for (let i = 0; i < children.length; i++) {
|
|
264
|
+
const child = children[i];
|
|
265
|
+
if (!child.parentNode)
|
|
266
|
+
continue;
|
|
267
|
+
const codeFence = child.querySelector(".code-fence");
|
|
268
|
+
if (codeFence) {
|
|
269
|
+
const fenceText = codeFence.textContent;
|
|
270
|
+
if (fenceText.startsWith("```")) {
|
|
271
|
+
if (!inCodeBlock) {
|
|
272
|
+
inCodeBlock = true;
|
|
273
|
+
currentCodeBlock = document.createElement("pre");
|
|
274
|
+
const codeElement = document.createElement("code");
|
|
275
|
+
currentCodeBlock.appendChild(codeElement);
|
|
276
|
+
currentCodeBlock.className = "code-block";
|
|
277
|
+
const lang = fenceText.slice(3).trim();
|
|
278
|
+
if (lang) {
|
|
279
|
+
codeElement.className = `language-${lang}`;
|
|
280
|
+
}
|
|
281
|
+
container.insertBefore(currentCodeBlock, child);
|
|
282
|
+
child.remove();
|
|
283
|
+
continue;
|
|
284
|
+
} else {
|
|
285
|
+
inCodeBlock = false;
|
|
286
|
+
currentCodeBlock = null;
|
|
287
|
+
child.remove();
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (inCodeBlock && currentCodeBlock && child.tagName === "DIV" && !child.querySelector(".code-fence")) {
|
|
293
|
+
const codeElement = currentCodeBlock.querySelector("code");
|
|
294
|
+
if (codeElement.textContent.length > 0) {
|
|
295
|
+
codeElement.textContent += "\n";
|
|
296
|
+
}
|
|
297
|
+
const lineText = child.innerHTML.replace(/ /g, " ").replace(/<[^>]*>/g, "");
|
|
298
|
+
codeElement.textContent += lineText;
|
|
299
|
+
child.remove();
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
let listItem = null;
|
|
303
|
+
if (child.tagName === "DIV") {
|
|
304
|
+
listItem = child.querySelector("li");
|
|
305
|
+
}
|
|
306
|
+
if (listItem) {
|
|
307
|
+
const isBullet = listItem.classList.contains("bullet-list");
|
|
308
|
+
const isOrdered = listItem.classList.contains("ordered-list");
|
|
309
|
+
if (!isBullet && !isOrdered) {
|
|
310
|
+
currentList = null;
|
|
311
|
+
listType = null;
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const newType = isBullet ? "ul" : "ol";
|
|
315
|
+
if (!currentList || listType !== newType) {
|
|
316
|
+
currentList = document.createElement(newType);
|
|
317
|
+
container.insertBefore(currentList, child);
|
|
318
|
+
listType = newType;
|
|
319
|
+
}
|
|
320
|
+
currentList.appendChild(listItem);
|
|
321
|
+
child.remove();
|
|
322
|
+
} else {
|
|
323
|
+
currentList = null;
|
|
324
|
+
listType = null;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return container.innerHTML;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Manual post-processing for Node.js environments (without DOM)
|
|
331
|
+
* @param {string} html - HTML to post-process
|
|
332
|
+
* @returns {string} Post-processed HTML
|
|
333
|
+
*/
|
|
334
|
+
static postProcessHTMLManual(html) {
|
|
335
|
+
let processed = html;
|
|
336
|
+
processed = processed.replace(/((?:<div>(?: )*<li class="bullet-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
|
|
337
|
+
const items = match.match(/<li class="bullet-list">.*?<\/li>/gs) || [];
|
|
338
|
+
if (items.length > 0) {
|
|
339
|
+
return "<ul>" + items.join("") + "</ul>";
|
|
340
|
+
}
|
|
341
|
+
return match;
|
|
342
|
+
});
|
|
343
|
+
processed = processed.replace(/((?:<div>(?: )*<li class="ordered-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
|
|
344
|
+
const items = match.match(/<li class="ordered-list">.*?<\/li>/gs) || [];
|
|
345
|
+
if (items.length > 0) {
|
|
346
|
+
return "<ol>" + items.join("") + "</ol>";
|
|
347
|
+
}
|
|
348
|
+
return match;
|
|
349
|
+
});
|
|
350
|
+
const codeBlockRegex = /<div><span class="code-fence">```([^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">```<\/span><\/div>/gs;
|
|
351
|
+
processed = processed.replace(codeBlockRegex, (match, lang, content) => {
|
|
352
|
+
const lines = content.match(/<div>(.*?)<\/div>/gs) || [];
|
|
353
|
+
const codeContent = lines.map((line) => {
|
|
354
|
+
const text = line.replace(/<div>(.*?)<\/div>/s, "$1").replace(/ /g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
355
|
+
return text;
|
|
356
|
+
}).join("\n");
|
|
357
|
+
const langClass = lang ? ` class="language-${lang.trim()}"` : "";
|
|
358
|
+
return `<pre class="code-block"><code${langClass}>${this.escapeHtml(codeContent)}</code></pre>`;
|
|
359
|
+
});
|
|
360
|
+
return processed;
|
|
246
361
|
}
|
|
247
362
|
};
|
|
248
363
|
// Track link index for anchor naming
|
|
@@ -1343,11 +1458,44 @@ function generateStyles(options = {}) {
|
|
|
1343
1458
|
const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : "";
|
|
1344
1459
|
return `
|
|
1345
1460
|
/* OverType Editor Styles */
|
|
1461
|
+
|
|
1462
|
+
/* Middle-ground CSS Reset - Prevent parent styles from leaking in */
|
|
1463
|
+
.overtype-container * {
|
|
1464
|
+
/* Box model - these commonly leak */
|
|
1465
|
+
margin: 0 !important;
|
|
1466
|
+
padding: 0 !important;
|
|
1467
|
+
border: 0 !important;
|
|
1468
|
+
|
|
1469
|
+
/* Layout - these can break our layout */
|
|
1470
|
+
/* Don't reset position - it breaks dropdowns */
|
|
1471
|
+
float: none !important;
|
|
1472
|
+
clear: none !important;
|
|
1473
|
+
|
|
1474
|
+
/* Typography - only reset decorative aspects */
|
|
1475
|
+
text-decoration: none !important;
|
|
1476
|
+
text-transform: none !important;
|
|
1477
|
+
letter-spacing: normal !important;
|
|
1478
|
+
|
|
1479
|
+
/* Visual effects that can interfere */
|
|
1480
|
+
box-shadow: none !important;
|
|
1481
|
+
text-shadow: none !important;
|
|
1482
|
+
|
|
1483
|
+
/* Ensure box-sizing is consistent */
|
|
1484
|
+
box-sizing: border-box !important;
|
|
1485
|
+
|
|
1486
|
+
/* Keep inheritance for these */
|
|
1487
|
+
/* font-family, color, line-height, font-size - inherit */
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
/* Container base styles after reset */
|
|
1346
1491
|
.overtype-container {
|
|
1347
1492
|
display: grid !important;
|
|
1348
1493
|
grid-template-rows: auto 1fr auto !important;
|
|
1349
1494
|
width: 100% !important;
|
|
1350
1495
|
height: 100% !important;
|
|
1496
|
+
position: relative !important; /* Override reset - needed for absolute children */
|
|
1497
|
+
overflow: visible !important; /* Allow dropdown to overflow container */
|
|
1498
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
1351
1499
|
${themeVars ? `
|
|
1352
1500
|
/* Theme Variables */
|
|
1353
1501
|
${themeVars}` : ""}
|
|
@@ -1366,20 +1514,21 @@ function generateStyles(options = {}) {
|
|
|
1366
1514
|
}
|
|
1367
1515
|
|
|
1368
1516
|
.overtype-wrapper {
|
|
1369
|
-
position: relative !important;
|
|
1517
|
+
position: relative !important; /* Override reset - needed for absolute children */
|
|
1370
1518
|
width: 100% !important;
|
|
1371
1519
|
height: 100% !important; /* Take full height of grid cell */
|
|
1372
1520
|
min-height: 60px !important; /* Minimum usable height */
|
|
1373
1521
|
overflow: hidden !important;
|
|
1374
1522
|
background: var(--bg-secondary, #ffffff) !important;
|
|
1375
1523
|
grid-row: 2 !important; /* Always second row in grid */
|
|
1524
|
+
z-index: 1; /* Below toolbar and dropdown */
|
|
1376
1525
|
}
|
|
1377
1526
|
|
|
1378
1527
|
/* Critical alignment styles - must be identical for both layers */
|
|
1379
1528
|
.overtype-wrapper .overtype-input,
|
|
1380
1529
|
.overtype-wrapper .overtype-preview {
|
|
1381
1530
|
/* Positioning - must be identical */
|
|
1382
|
-
position: absolute !important;
|
|
1531
|
+
position: absolute !important; /* Override reset - required for overlay */
|
|
1383
1532
|
top: 0 !important;
|
|
1384
1533
|
left: 0 !important;
|
|
1385
1534
|
width: 100% !important;
|
|
@@ -1446,7 +1595,7 @@ function generateStyles(options = {}) {
|
|
|
1446
1595
|
/* Overflow */
|
|
1447
1596
|
overflow-y: auto !important;
|
|
1448
1597
|
overflow-x: auto !important;
|
|
1449
|
-
overscroll-behavior
|
|
1598
|
+
/* overscroll-behavior removed to allow scroll-through to parent */
|
|
1450
1599
|
scrollbar-width: auto !important;
|
|
1451
1600
|
scrollbar-gutter: auto !important;
|
|
1452
1601
|
|
|
@@ -1534,6 +1683,45 @@ function generateStyles(options = {}) {
|
|
|
1534
1683
|
color: var(--h3, #3d8a51) !important;
|
|
1535
1684
|
}
|
|
1536
1685
|
|
|
1686
|
+
/* Semantic headers - flatten in edit mode */
|
|
1687
|
+
.overtype-wrapper .overtype-preview h1,
|
|
1688
|
+
.overtype-wrapper .overtype-preview h2,
|
|
1689
|
+
.overtype-wrapper .overtype-preview h3 {
|
|
1690
|
+
font-size: inherit !important;
|
|
1691
|
+
font-weight: bold !important;
|
|
1692
|
+
margin: 0 !important;
|
|
1693
|
+
padding: 0 !important;
|
|
1694
|
+
display: inline !important;
|
|
1695
|
+
line-height: inherit !important;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
/* Header colors for semantic headers */
|
|
1699
|
+
.overtype-wrapper .overtype-preview h1 {
|
|
1700
|
+
color: var(--h1, #f95738) !important;
|
|
1701
|
+
}
|
|
1702
|
+
.overtype-wrapper .overtype-preview h2 {
|
|
1703
|
+
color: var(--h2, #ee964b) !important;
|
|
1704
|
+
}
|
|
1705
|
+
.overtype-wrapper .overtype-preview h3 {
|
|
1706
|
+
color: var(--h3, #3d8a51) !important;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/* Lists - remove styling in edit mode */
|
|
1710
|
+
.overtype-wrapper .overtype-preview ul,
|
|
1711
|
+
.overtype-wrapper .overtype-preview ol {
|
|
1712
|
+
list-style: none !important;
|
|
1713
|
+
margin: 0 !important;
|
|
1714
|
+
padding: 0 !important;
|
|
1715
|
+
display: block !important; /* Lists need to be block for line breaks */
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
.overtype-wrapper .overtype-preview li {
|
|
1719
|
+
display: block !important; /* Each item on its own line */
|
|
1720
|
+
margin: 0 !important;
|
|
1721
|
+
padding: 0 !important;
|
|
1722
|
+
/* Don't set list-style here - let ul/ol control it */
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1537
1725
|
/* Bold text */
|
|
1538
1726
|
.overtype-wrapper .overtype-preview strong {
|
|
1539
1727
|
color: var(--strong, #ee964b) !important;
|
|
@@ -1560,17 +1748,23 @@ function generateStyles(options = {}) {
|
|
|
1560
1748
|
font-weight: normal !important;
|
|
1561
1749
|
}
|
|
1562
1750
|
|
|
1563
|
-
/* Code blocks */
|
|
1751
|
+
/* Code blocks - consolidated pre blocks */
|
|
1564
1752
|
.overtype-wrapper .overtype-preview pre {
|
|
1565
|
-
background: #1e1e1e !important;
|
|
1566
1753
|
padding: 0 !important;
|
|
1567
1754
|
margin: 0 !important;
|
|
1568
1755
|
border-radius: 4px !important;
|
|
1569
1756
|
overflow-x: auto !important;
|
|
1570
1757
|
}
|
|
1758
|
+
|
|
1759
|
+
/* Code block styling in normal mode - yellow background */
|
|
1760
|
+
.overtype-wrapper .overtype-preview pre.code-block {
|
|
1761
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
1762
|
+
}
|
|
1571
1763
|
|
|
1764
|
+
/* Code inside pre blocks - remove background */
|
|
1572
1765
|
.overtype-wrapper .overtype-preview pre code {
|
|
1573
|
-
background:
|
|
1766
|
+
background: transparent !important;
|
|
1767
|
+
color: var(--code, #0d3b66) !important;
|
|
1574
1768
|
}
|
|
1575
1769
|
|
|
1576
1770
|
/* Blockquotes */
|
|
@@ -1601,11 +1795,6 @@ function generateStyles(options = {}) {
|
|
|
1601
1795
|
padding: 0 !important;
|
|
1602
1796
|
}
|
|
1603
1797
|
|
|
1604
|
-
.overtype-wrapper .overtype-preview li {
|
|
1605
|
-
margin: 0 !important;
|
|
1606
|
-
padding: 0 !important;
|
|
1607
|
-
list-style: none !important;
|
|
1608
|
-
}
|
|
1609
1798
|
|
|
1610
1799
|
/* Horizontal rules */
|
|
1611
1800
|
.overtype-wrapper .overtype-preview hr {
|
|
@@ -1704,13 +1893,31 @@ function generateStyles(options = {}) {
|
|
|
1704
1893
|
display: flex;
|
|
1705
1894
|
align-items: center;
|
|
1706
1895
|
gap: 4px;
|
|
1707
|
-
padding: 8px;
|
|
1708
|
-
background: var(--toolbar-bg, var(--bg-primary, #f8f9fa));
|
|
1709
|
-
overflow-x: auto;
|
|
1896
|
+
padding: 8px !important; /* Override reset */
|
|
1897
|
+
background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */
|
|
1898
|
+
overflow-x: auto !important; /* Allow horizontal scrolling */
|
|
1899
|
+
overflow-y: hidden !important; /* Hide vertical overflow */
|
|
1710
1900
|
-webkit-overflow-scrolling: touch;
|
|
1711
1901
|
flex-shrink: 0;
|
|
1712
1902
|
height: auto !important;
|
|
1713
1903
|
grid-row: 1 !important; /* Always first row in grid */
|
|
1904
|
+
position: relative !important; /* Override reset */
|
|
1905
|
+
z-index: 100; /* Ensure toolbar is above wrapper */
|
|
1906
|
+
scrollbar-width: thin; /* Thin scrollbar on Firefox */
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
/* Thin scrollbar styling */
|
|
1910
|
+
.overtype-toolbar::-webkit-scrollbar {
|
|
1911
|
+
height: 4px;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
.overtype-toolbar::-webkit-scrollbar-track {
|
|
1915
|
+
background: transparent;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
.overtype-toolbar::-webkit-scrollbar-thumb {
|
|
1919
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1920
|
+
border-radius: 2px;
|
|
1714
1921
|
}
|
|
1715
1922
|
|
|
1716
1923
|
.overtype-toolbar-button {
|
|
@@ -1800,6 +2007,214 @@ function generateStyles(options = {}) {
|
|
|
1800
2007
|
color: transparent !important;
|
|
1801
2008
|
}
|
|
1802
2009
|
|
|
2010
|
+
/* Dropdown menu styles */
|
|
2011
|
+
.overtype-toolbar-button {
|
|
2012
|
+
position: relative !important; /* Override reset - needed for dropdown */
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
.overtype-toolbar-button.dropdown-active {
|
|
2016
|
+
background: var(--toolbar-active, var(--hover-bg, #f0f0f0));
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
.overtype-dropdown-menu {
|
|
2020
|
+
position: fixed !important; /* Fixed positioning relative to viewport */
|
|
2021
|
+
background: var(--bg-secondary, white) !important; /* Override reset */
|
|
2022
|
+
border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */
|
|
2023
|
+
border-radius: 6px;
|
|
2024
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */
|
|
2025
|
+
z-index: 10000; /* Very high z-index to ensure visibility */
|
|
2026
|
+
min-width: 150px;
|
|
2027
|
+
padding: 4px 0 !important; /* Override reset */
|
|
2028
|
+
/* Position will be set via JavaScript based on button position */
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
.overtype-dropdown-item {
|
|
2032
|
+
display: flex;
|
|
2033
|
+
align-items: center;
|
|
2034
|
+
width: 100%;
|
|
2035
|
+
padding: 8px 12px;
|
|
2036
|
+
border: none;
|
|
2037
|
+
background: none;
|
|
2038
|
+
text-align: left;
|
|
2039
|
+
cursor: pointer;
|
|
2040
|
+
font-size: 14px;
|
|
2041
|
+
color: var(--text, #333);
|
|
2042
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
.overtype-dropdown-item:hover {
|
|
2046
|
+
background: var(--hover-bg, #f0f0f0);
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
.overtype-dropdown-item.active {
|
|
2050
|
+
font-weight: 600;
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
.overtype-dropdown-check {
|
|
2054
|
+
width: 16px;
|
|
2055
|
+
margin-right: 8px;
|
|
2056
|
+
color: var(--h1, #007bff);
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
/* Preview mode styles */
|
|
2060
|
+
.overtype-container.preview-mode .overtype-input {
|
|
2061
|
+
display: none !important;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
.overtype-container.preview-mode .overtype-preview {
|
|
2065
|
+
pointer-events: auto !important;
|
|
2066
|
+
user-select: text !important;
|
|
2067
|
+
cursor: text !important;
|
|
2068
|
+
}
|
|
2069
|
+
|
|
2070
|
+
/* Hide syntax markers in preview mode */
|
|
2071
|
+
.overtype-container.preview-mode .syntax-marker {
|
|
2072
|
+
display: none !important;
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
/* Hide URL part of links in preview mode - extra specificity */
|
|
2076
|
+
.overtype-container.preview-mode .syntax-marker.url-part,
|
|
2077
|
+
.overtype-container.preview-mode .url-part {
|
|
2078
|
+
display: none !important;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
/* Hide all syntax markers inside links too */
|
|
2082
|
+
.overtype-container.preview-mode a .syntax-marker {
|
|
2083
|
+
display: none !important;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/* Headers - restore proper sizing in preview mode */
|
|
2087
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h1,
|
|
2088
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h2,
|
|
2089
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h3 {
|
|
2090
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
|
|
2091
|
+
font-weight: 600 !important;
|
|
2092
|
+
margin: 0 !important;
|
|
2093
|
+
display: block !important;
|
|
2094
|
+
color: inherit !important; /* Use parent text color */
|
|
2095
|
+
line-height: 1 !important; /* Tight line height for headings */
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h1 {
|
|
2099
|
+
font-size: 2em !important;
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h2 {
|
|
2103
|
+
font-size: 1.5em !important;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview h3 {
|
|
2107
|
+
font-size: 1.17em !important;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
/* Lists - restore list styling in preview mode */
|
|
2111
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview ul {
|
|
2112
|
+
display: block !important;
|
|
2113
|
+
list-style: disc !important;
|
|
2114
|
+
padding-left: 2em !important;
|
|
2115
|
+
margin: 1em 0 !important;
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview ol {
|
|
2119
|
+
display: block !important;
|
|
2120
|
+
list-style: decimal !important;
|
|
2121
|
+
padding-left: 2em !important;
|
|
2122
|
+
margin: 1em 0 !important;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview li {
|
|
2126
|
+
display: list-item !important;
|
|
2127
|
+
margin: 0 !important;
|
|
2128
|
+
padding: 0 !important;
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
/* Links - make clickable in preview mode */
|
|
2132
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview a {
|
|
2133
|
+
pointer-events: auto !important;
|
|
2134
|
+
cursor: pointer !important;
|
|
2135
|
+
color: var(--link, #0066cc) !important;
|
|
2136
|
+
text-decoration: underline !important;
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
/* Code blocks - proper pre/code styling in preview mode */
|
|
2140
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview pre.code-block {
|
|
2141
|
+
background: #2d2d2d !important;
|
|
2142
|
+
color: #f8f8f2 !important;
|
|
2143
|
+
padding: 1.2em !important;
|
|
2144
|
+
border-radius: 3px !important;
|
|
2145
|
+
overflow-x: auto !important;
|
|
2146
|
+
margin: 0 !important;
|
|
2147
|
+
display: block !important;
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
/* Cave theme code block background in preview mode */
|
|
2151
|
+
.overtype-container[data-theme="cave"].preview-mode .overtype-wrapper .overtype-preview pre.code-block {
|
|
2152
|
+
background: #11171F !important;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview pre.code-block code {
|
|
2156
|
+
background: transparent !important;
|
|
2157
|
+
color: inherit !important;
|
|
2158
|
+
padding: 0 !important;
|
|
2159
|
+
font-family: ${fontFamily} !important;
|
|
2160
|
+
font-size: 0.9em !important;
|
|
2161
|
+
line-height: 1.4 !important;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
/* Hide old code block lines and fences in preview mode */
|
|
2165
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview .code-block-line {
|
|
2166
|
+
display: none !important;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview .code-fence {
|
|
2170
|
+
display: none !important;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
/* Blockquotes - enhanced styling in preview mode */
|
|
2174
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview .blockquote {
|
|
2175
|
+
display: block !important;
|
|
2176
|
+
border-left: 4px solid var(--blockquote, #ddd) !important;
|
|
2177
|
+
padding-left: 1em !important;
|
|
2178
|
+
margin: 1em 0 !important;
|
|
2179
|
+
font-style: italic !important;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
/* Typography improvements in preview mode */
|
|
2183
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview {
|
|
2184
|
+
font-family: Georgia, 'Times New Roman', serif !important;
|
|
2185
|
+
font-size: 16px !important;
|
|
2186
|
+
line-height: 1.8 !important;
|
|
2187
|
+
color: var(--text, #333) !important; /* Consistent text color */
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
/* Inline code in preview mode - keep monospace */
|
|
2191
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview code {
|
|
2192
|
+
font-family: ${fontFamily} !important;
|
|
2193
|
+
font-size: 0.9em !important;
|
|
2194
|
+
background: rgba(135, 131, 120, 0.15) !important;
|
|
2195
|
+
padding: 0.2em 0.4em !important;
|
|
2196
|
+
border-radius: 3px !important;
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
/* Strong and em elements in preview mode */
|
|
2200
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview strong {
|
|
2201
|
+
font-weight: 700 !important;
|
|
2202
|
+
color: inherit !important; /* Use parent text color */
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview em {
|
|
2206
|
+
font-style: italic !important;
|
|
2207
|
+
color: inherit !important; /* Use parent text color */
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
/* HR in preview mode */
|
|
2211
|
+
.overtype-container.preview-mode .overtype-wrapper .overtype-preview .hr-marker {
|
|
2212
|
+
display: block !important;
|
|
2213
|
+
border-top: 2px solid var(--hr, #ddd) !important;
|
|
2214
|
+
text-indent: -9999px !important;
|
|
2215
|
+
height: 2px !important;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
1803
2218
|
${mobileStyles}
|
|
1804
2219
|
`;
|
|
1805
2220
|
}
|
|
@@ -1899,7 +2314,7 @@ var Toolbar = class {
|
|
|
1899
2314
|
{ name: "orderedList", icon: orderedListIcon, title: "Numbered List", action: "toggleNumberedList" },
|
|
1900
2315
|
{ name: "taskList", icon: taskListIcon, title: "Task List", action: "toggleTaskList" },
|
|
1901
2316
|
{ separator: true },
|
|
1902
|
-
{ name: "
|
|
2317
|
+
{ name: "viewMode", icon: eyeIcon, title: "View mode", action: "toggle-view-menu", hasDropdown: true }
|
|
1903
2318
|
];
|
|
1904
2319
|
buttonConfig.forEach((config) => {
|
|
1905
2320
|
if (config.separator) {
|
|
@@ -1931,19 +2346,29 @@ var Toolbar = class {
|
|
|
1931
2346
|
button.setAttribute("aria-label", config.title);
|
|
1932
2347
|
button.setAttribute("data-action", config.action);
|
|
1933
2348
|
button.innerHTML = config.icon;
|
|
2349
|
+
if (config.hasDropdown) {
|
|
2350
|
+
button.classList.add("has-dropdown");
|
|
2351
|
+
if (config.name === "viewMode") {
|
|
2352
|
+
this.viewModeButton = button;
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
1934
2355
|
button.addEventListener("click", (e) => {
|
|
1935
2356
|
e.preventDefault();
|
|
1936
|
-
this.handleAction(config.action);
|
|
2357
|
+
this.handleAction(config.action, button);
|
|
1937
2358
|
});
|
|
1938
2359
|
return button;
|
|
1939
2360
|
}
|
|
1940
2361
|
/**
|
|
1941
2362
|
* Handle toolbar button actions
|
|
1942
2363
|
*/
|
|
1943
|
-
async handleAction(action) {
|
|
2364
|
+
async handleAction(action, button) {
|
|
1944
2365
|
const textarea = this.editor.textarea;
|
|
1945
2366
|
if (!textarea)
|
|
1946
2367
|
return;
|
|
2368
|
+
if (action === "toggle-view-menu") {
|
|
2369
|
+
this.toggleViewDropdown(button);
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
1947
2372
|
textarea.focus();
|
|
1948
2373
|
try {
|
|
1949
2374
|
switch (action) {
|
|
@@ -2042,11 +2467,102 @@ var Toolbar = class {
|
|
|
2042
2467
|
} catch (error) {
|
|
2043
2468
|
}
|
|
2044
2469
|
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Toggle view mode dropdown menu
|
|
2472
|
+
*/
|
|
2473
|
+
toggleViewDropdown(button) {
|
|
2474
|
+
const existingDropdown = document.querySelector(".overtype-dropdown-menu");
|
|
2475
|
+
if (existingDropdown) {
|
|
2476
|
+
existingDropdown.remove();
|
|
2477
|
+
button.classList.remove("dropdown-active");
|
|
2478
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
const dropdown = this.createViewDropdown();
|
|
2482
|
+
const rect = button.getBoundingClientRect();
|
|
2483
|
+
dropdown.style.top = `${rect.bottom + 4}px`;
|
|
2484
|
+
dropdown.style.left = `${rect.left}px`;
|
|
2485
|
+
document.body.appendChild(dropdown);
|
|
2486
|
+
button.classList.add("dropdown-active");
|
|
2487
|
+
this.handleDocumentClick = (e) => {
|
|
2488
|
+
if (!button.contains(e.target) && !dropdown.contains(e.target)) {
|
|
2489
|
+
dropdown.remove();
|
|
2490
|
+
button.classList.remove("dropdown-active");
|
|
2491
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2494
|
+
setTimeout(() => {
|
|
2495
|
+
document.addEventListener("click", this.handleDocumentClick);
|
|
2496
|
+
}, 0);
|
|
2497
|
+
}
|
|
2498
|
+
/**
|
|
2499
|
+
* Create view mode dropdown menu
|
|
2500
|
+
*/
|
|
2501
|
+
createViewDropdown() {
|
|
2502
|
+
const dropdown = document.createElement("div");
|
|
2503
|
+
dropdown.className = "overtype-dropdown-menu";
|
|
2504
|
+
const isPlain = this.editor.container.classList.contains("plain-mode");
|
|
2505
|
+
const isPreview = this.editor.container.classList.contains("preview-mode");
|
|
2506
|
+
const currentMode = isPreview ? "preview" : isPlain ? "plain" : "normal";
|
|
2507
|
+
const modes = [
|
|
2508
|
+
{ id: "normal", label: "Normal Edit", icon: "\u2713" },
|
|
2509
|
+
{ id: "plain", label: "Plain Textarea", icon: "\u2713" },
|
|
2510
|
+
{ id: "preview", label: "Preview Mode", icon: "\u2713" }
|
|
2511
|
+
];
|
|
2512
|
+
modes.forEach((mode) => {
|
|
2513
|
+
const item = document.createElement("button");
|
|
2514
|
+
item.className = "overtype-dropdown-item";
|
|
2515
|
+
item.type = "button";
|
|
2516
|
+
const check = document.createElement("span");
|
|
2517
|
+
check.className = "overtype-dropdown-check";
|
|
2518
|
+
check.textContent = currentMode === mode.id ? mode.icon : "";
|
|
2519
|
+
const label = document.createElement("span");
|
|
2520
|
+
label.textContent = mode.label;
|
|
2521
|
+
item.appendChild(check);
|
|
2522
|
+
item.appendChild(label);
|
|
2523
|
+
if (currentMode === mode.id) {
|
|
2524
|
+
item.classList.add("active");
|
|
2525
|
+
}
|
|
2526
|
+
item.addEventListener("click", (e) => {
|
|
2527
|
+
e.stopPropagation();
|
|
2528
|
+
this.setViewMode(mode.id);
|
|
2529
|
+
dropdown.remove();
|
|
2530
|
+
this.viewModeButton.classList.remove("dropdown-active");
|
|
2531
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
2532
|
+
});
|
|
2533
|
+
dropdown.appendChild(item);
|
|
2534
|
+
});
|
|
2535
|
+
return dropdown;
|
|
2536
|
+
}
|
|
2537
|
+
/**
|
|
2538
|
+
* Set view mode
|
|
2539
|
+
*/
|
|
2540
|
+
setViewMode(mode) {
|
|
2541
|
+
this.editor.container.classList.remove("plain-mode", "preview-mode");
|
|
2542
|
+
switch (mode) {
|
|
2543
|
+
case "plain":
|
|
2544
|
+
this.editor.showPlainTextarea(true);
|
|
2545
|
+
break;
|
|
2546
|
+
case "preview":
|
|
2547
|
+
this.editor.showPreviewMode(true);
|
|
2548
|
+
break;
|
|
2549
|
+
case "normal":
|
|
2550
|
+
default:
|
|
2551
|
+
this.editor.showPlainTextarea(false);
|
|
2552
|
+
if (typeof this.editor.showPreviewMode === "function") {
|
|
2553
|
+
this.editor.showPreviewMode(false);
|
|
2554
|
+
}
|
|
2555
|
+
break;
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2045
2558
|
/**
|
|
2046
2559
|
* Destroy toolbar
|
|
2047
2560
|
*/
|
|
2048
2561
|
destroy() {
|
|
2049
2562
|
if (this.container) {
|
|
2563
|
+
if (this.handleDocumentClick) {
|
|
2564
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
2565
|
+
}
|
|
2050
2566
|
this.container.remove();
|
|
2051
2567
|
this.container = null;
|
|
2052
2568
|
this.buttons = {};
|
|
@@ -2583,21 +3099,35 @@ var _OverType = class _OverType {
|
|
|
2583
3099
|
const after = value.substring(end);
|
|
2584
3100
|
const lines = selection.split("\n");
|
|
2585
3101
|
const outdented = lines.map((line) => line.replace(/^ /, "")).join("\n");
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
3102
|
+
if (document.execCommand) {
|
|
3103
|
+
this.textarea.setSelectionRange(start, end);
|
|
3104
|
+
document.execCommand("insertText", false, outdented);
|
|
3105
|
+
} else {
|
|
3106
|
+
this.textarea.value = before + outdented + after;
|
|
3107
|
+
this.textarea.selectionStart = start;
|
|
3108
|
+
this.textarea.selectionEnd = start + outdented.length;
|
|
3109
|
+
}
|
|
2589
3110
|
} else if (start !== end) {
|
|
2590
3111
|
const before = value.substring(0, start);
|
|
2591
3112
|
const selection = value.substring(start, end);
|
|
2592
3113
|
const after = value.substring(end);
|
|
2593
3114
|
const lines = selection.split("\n");
|
|
2594
3115
|
const indented = lines.map((line) => " " + line).join("\n");
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
3116
|
+
if (document.execCommand) {
|
|
3117
|
+
this.textarea.setSelectionRange(start, end);
|
|
3118
|
+
document.execCommand("insertText", false, indented);
|
|
3119
|
+
} else {
|
|
3120
|
+
this.textarea.value = before + indented + after;
|
|
3121
|
+
this.textarea.selectionStart = start;
|
|
3122
|
+
this.textarea.selectionEnd = start + indented.length;
|
|
3123
|
+
}
|
|
2598
3124
|
} else {
|
|
2599
|
-
|
|
2600
|
-
|
|
3125
|
+
if (document.execCommand) {
|
|
3126
|
+
document.execCommand("insertText", false, " ");
|
|
3127
|
+
} else {
|
|
3128
|
+
this.textarea.value = value.substring(0, start) + " " + value.substring(end);
|
|
3129
|
+
this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
|
|
3130
|
+
}
|
|
2601
3131
|
}
|
|
2602
3132
|
this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2603
3133
|
return;
|
|
@@ -2633,6 +3163,26 @@ var _OverType = class _OverType {
|
|
|
2633
3163
|
this._updateAutoHeight();
|
|
2634
3164
|
}
|
|
2635
3165
|
}
|
|
3166
|
+
/**
|
|
3167
|
+
* Get the rendered HTML of the current content
|
|
3168
|
+
* @param {boolean} processForPreview - If true, post-processes HTML for preview mode (consolidates lists/code blocks)
|
|
3169
|
+
* @returns {string} Rendered HTML
|
|
3170
|
+
*/
|
|
3171
|
+
getRenderedHTML(processForPreview = false) {
|
|
3172
|
+
const markdown = this.getValue();
|
|
3173
|
+
let html = MarkdownParser.parse(markdown);
|
|
3174
|
+
if (processForPreview) {
|
|
3175
|
+
html = MarkdownParser.postProcessHTML(html);
|
|
3176
|
+
}
|
|
3177
|
+
return html;
|
|
3178
|
+
}
|
|
3179
|
+
/**
|
|
3180
|
+
* Get the current preview element's HTML
|
|
3181
|
+
* @returns {string} Current preview HTML (as displayed)
|
|
3182
|
+
*/
|
|
3183
|
+
getPreviewHTML() {
|
|
3184
|
+
return this.preview.innerHTML;
|
|
3185
|
+
}
|
|
2636
3186
|
/**
|
|
2637
3187
|
* Focus the editor
|
|
2638
3188
|
*/
|
|
@@ -2782,6 +3332,19 @@ var _OverType = class _OverType {
|
|
|
2782
3332
|
}
|
|
2783
3333
|
return show;
|
|
2784
3334
|
}
|
|
3335
|
+
/**
|
|
3336
|
+
* Show/hide preview mode
|
|
3337
|
+
* @param {boolean} show - Show preview mode if true, edit mode if false
|
|
3338
|
+
* @returns {boolean} Current preview mode state
|
|
3339
|
+
*/
|
|
3340
|
+
showPreviewMode(show) {
|
|
3341
|
+
if (show) {
|
|
3342
|
+
this.container.classList.add("preview-mode");
|
|
3343
|
+
} else {
|
|
3344
|
+
this.container.classList.remove("preview-mode");
|
|
3345
|
+
}
|
|
3346
|
+
return show;
|
|
3347
|
+
}
|
|
2785
3348
|
/**
|
|
2786
3349
|
* Destroy the editor instance
|
|
2787
3350
|
*/
|
|
@@ -2938,6 +3501,9 @@ OverType.ShortcutsManager = ShortcutsManager;
|
|
|
2938
3501
|
OverType.themes = { solar, cave: getTheme("cave") };
|
|
2939
3502
|
OverType.getTheme = getTheme;
|
|
2940
3503
|
OverType.currentTheme = solar;
|
|
3504
|
+
if (typeof window !== "undefined" && typeof window.document !== "undefined") {
|
|
3505
|
+
window.OverType = OverType;
|
|
3506
|
+
}
|
|
2941
3507
|
var overtype_default = OverType;
|
|
2942
3508
|
export {
|
|
2943
3509
|
OverType,
|