overtype 1.1.7 → 1.2.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OverType v1.1.7
2
+ * OverType v1.2.0
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
- const levelClasses = ["h1", "h2", "h3"];
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(/^((?:&nbsp;)*)([-*])\s(.+)$/, (match, indent, marker, content) => {
89
- return `${indent}<span class="syntax-marker">${marker}</span> ${content}`;
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(/^((?:&nbsp;)*)(\d+\.)\s(.+)$/, (match, indent, marker, content) => {
99
- return `${indent}<span class="syntax-marker">${marker}</span> ${content}`;
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">](</span><span class="syntax-marker link-url">${url}</span><span class="syntax-marker">)</span></a>`;
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
- return parsedLines.join("");
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(/&nbsp;/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>(?:&nbsp;)*<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>(?:&nbsp;)*<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(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/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
@@ -1323,6 +1438,7 @@ function generateStyles(options = {}) {
1323
1438
  const {
1324
1439
  fontSize = "14px",
1325
1440
  lineHeight = 1.6,
1441
+ /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
1326
1442
  fontFamily = '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
1327
1443
  padding = "20px",
1328
1444
  theme = null,
@@ -1342,11 +1458,44 @@ function generateStyles(options = {}) {
1342
1458
  const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : "";
1343
1459
  return `
1344
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 */
1345
1491
  .overtype-container {
1346
1492
  display: grid !important;
1347
1493
  grid-template-rows: auto 1fr auto !important;
1348
1494
  width: 100% !important;
1349
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;
1350
1499
  ${themeVars ? `
1351
1500
  /* Theme Variables */
1352
1501
  ${themeVars}` : ""}
@@ -1365,20 +1514,21 @@ function generateStyles(options = {}) {
1365
1514
  }
1366
1515
 
1367
1516
  .overtype-wrapper {
1368
- position: relative !important;
1517
+ position: relative !important; /* Override reset - needed for absolute children */
1369
1518
  width: 100% !important;
1370
1519
  height: 100% !important; /* Take full height of grid cell */
1371
1520
  min-height: 60px !important; /* Minimum usable height */
1372
1521
  overflow: hidden !important;
1373
1522
  background: var(--bg-secondary, #ffffff) !important;
1374
1523
  grid-row: 2 !important; /* Always second row in grid */
1524
+ z-index: 1; /* Below toolbar and dropdown */
1375
1525
  }
1376
1526
 
1377
1527
  /* Critical alignment styles - must be identical for both layers */
1378
1528
  .overtype-wrapper .overtype-input,
1379
1529
  .overtype-wrapper .overtype-preview {
1380
1530
  /* Positioning - must be identical */
1381
- position: absolute !important;
1531
+ position: absolute !important; /* Override reset - required for overlay */
1382
1532
  top: 0 !important;
1383
1533
  left: 0 !important;
1384
1534
  width: 100% !important;
@@ -1386,7 +1536,6 @@ function generateStyles(options = {}) {
1386
1536
 
1387
1537
  /* Font properties - any difference breaks alignment */
1388
1538
  font-family: ${fontFamily} !important;
1389
- font-synthesis: none !important; /* no faux bold/italic width drift */
1390
1539
  font-variant-ligatures: none !important; /* keep metrics stable for code */
1391
1540
  font-size: var(--instance-font-size, ${fontSize}) !important;
1392
1541
  line-height: var(--instance-line-height, ${lineHeight}) !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: none !important;
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: none !important;
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 {
@@ -1782,6 +1989,231 @@ function generateStyles(options = {}) {
1782
1989
  margin: 0 2px;
1783
1990
  }
1784
1991
  }
1992
+
1993
+ /* Plain mode - hide preview and show textarea text */
1994
+ .overtype-container.plain-mode .overtype-preview {
1995
+ display: none !important;
1996
+ }
1997
+
1998
+ .overtype-container.plain-mode .overtype-input {
1999
+ color: var(--text, #0d3b66) !important;
2000
+ /* Use system font stack for better plain text readability */
2001
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
2002
+ "Helvetica Neue", Arial, sans-serif !important;
2003
+ }
2004
+
2005
+ /* Ensure textarea remains transparent in overlay mode */
2006
+ .overtype-container:not(.plain-mode) .overtype-input {
2007
+ color: transparent !important;
2008
+ }
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
+ }
1785
2217
 
1786
2218
  ${mobileStyles}
1787
2219
  `;
@@ -1845,6 +2277,10 @@ var taskListIcon = `<svg viewBox="0 0 18 18">
1845
2277
  <rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="13" width="3" height="3" rx="0.5"></rect>
1846
2278
  <polyline stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" points="2.65 9.5 3.5 10.5 5 8.5"></polyline>
1847
2279
  </svg>`;
2280
+ var eyeIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2281
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" fill="none"></path>
2282
+ <circle cx="12" cy="12" r="3" fill="none"></circle>
2283
+ </svg>`;
1848
2284
 
1849
2285
  // src/toolbar.js
1850
2286
  var Toolbar = class {
@@ -1876,7 +2312,9 @@ var Toolbar = class {
1876
2312
  { separator: true },
1877
2313
  { name: "bulletList", icon: bulletListIcon, title: "Bullet List", action: "toggleBulletList" },
1878
2314
  { name: "orderedList", icon: orderedListIcon, title: "Numbered List", action: "toggleNumberedList" },
1879
- { name: "taskList", icon: taskListIcon, title: "Task List", action: "toggleTaskList" }
2315
+ { name: "taskList", icon: taskListIcon, title: "Task List", action: "toggleTaskList" },
2316
+ { separator: true },
2317
+ { name: "viewMode", icon: eyeIcon, title: "View mode", action: "toggle-view-menu", hasDropdown: true }
1880
2318
  ];
1881
2319
  buttonConfig.forEach((config) => {
1882
2320
  if (config.separator) {
@@ -1908,19 +2346,29 @@ var Toolbar = class {
1908
2346
  button.setAttribute("aria-label", config.title);
1909
2347
  button.setAttribute("data-action", config.action);
1910
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
+ }
1911
2355
  button.addEventListener("click", (e) => {
1912
2356
  e.preventDefault();
1913
- this.handleAction(config.action);
2357
+ this.handleAction(config.action, button);
1914
2358
  });
1915
2359
  return button;
1916
2360
  }
1917
2361
  /**
1918
2362
  * Handle toolbar button actions
1919
2363
  */
1920
- async handleAction(action) {
2364
+ async handleAction(action, button) {
1921
2365
  const textarea = this.editor.textarea;
1922
2366
  if (!textarea)
1923
2367
  return;
2368
+ if (action === "toggle-view-menu") {
2369
+ this.toggleViewDropdown(button);
2370
+ return;
2371
+ }
1924
2372
  textarea.focus();
1925
2373
  try {
1926
2374
  switch (action) {
@@ -1957,6 +2405,10 @@ var Toolbar = class {
1957
2405
  case "toggleTaskList":
1958
2406
  toggleTaskList(textarea);
1959
2407
  break;
2408
+ case "toggle-plain":
2409
+ const isPlain = this.editor.container.classList.contains("plain-mode");
2410
+ this.editor.showPlainTextarea(!isPlain);
2411
+ break;
1960
2412
  }
1961
2413
  textarea.dispatchEvent(new Event("input", { bubbles: true }));
1962
2414
  } catch (error) {
@@ -2005,6 +2457,9 @@ var Toolbar = class {
2005
2457
  case "h3":
2006
2458
  isActive = activeFormats.includes("header-3");
2007
2459
  break;
2460
+ case "togglePlain":
2461
+ isActive = !this.editor.container.classList.contains("plain-mode");
2462
+ break;
2008
2463
  }
2009
2464
  button.classList.toggle("active", isActive);
2010
2465
  button.setAttribute("aria-pressed", isActive.toString());
@@ -2012,11 +2467,102 @@ var Toolbar = class {
2012
2467
  } catch (error) {
2013
2468
  }
2014
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
+ }
2015
2558
  /**
2016
2559
  * Destroy toolbar
2017
2560
  */
2018
2561
  destroy() {
2019
2562
  if (this.container) {
2563
+ if (this.handleDocumentClick) {
2564
+ document.removeEventListener("click", this.handleDocumentClick);
2565
+ }
2020
2566
  this.container.remove();
2021
2567
  this.container = null;
2022
2568
  this.buttons = {};
@@ -2253,7 +2799,8 @@ var _OverType = class _OverType {
2253
2799
  // Typography
2254
2800
  fontSize: "14px",
2255
2801
  lineHeight: 1.6,
2256
- fontFamily: "ui-monospace, 'SFMono-Regular', 'Menlo', 'Consolas', 'Liberation Mono', monospace",
2802
+ /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
2803
+ fontFamily: '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
2257
2804
  padding: "16px",
2258
2805
  // Mobile styles
2259
2806
  mobile: {
@@ -2602,6 +3149,26 @@ var _OverType = class _OverType {
2602
3149
  this._updateAutoHeight();
2603
3150
  }
2604
3151
  }
3152
+ /**
3153
+ * Get the rendered HTML of the current content
3154
+ * @param {boolean} processForPreview - If true, post-processes HTML for preview mode (consolidates lists/code blocks)
3155
+ * @returns {string} Rendered HTML
3156
+ */
3157
+ getRenderedHTML(processForPreview = false) {
3158
+ const markdown = this.getValue();
3159
+ let html = MarkdownParser.parse(markdown);
3160
+ if (processForPreview) {
3161
+ html = MarkdownParser.postProcessHTML(html);
3162
+ }
3163
+ return html;
3164
+ }
3165
+ /**
3166
+ * Get the current preview element's HTML
3167
+ * @returns {string} Current preview HTML (as displayed)
3168
+ */
3169
+ getPreviewHTML() {
3170
+ return this.preview.innerHTML;
3171
+ }
2605
3172
  /**
2606
3173
  * Focus the editor
2607
3174
  */
@@ -2731,6 +3298,39 @@ var _OverType = class _OverType {
2731
3298
  this.statsBar = null;
2732
3299
  }
2733
3300
  }
3301
+ /**
3302
+ * Show or hide the plain textarea (toggle overlay visibility)
3303
+ * @param {boolean} show - true to show plain textarea (hide overlay), false to show overlay
3304
+ * @returns {boolean} Current plain textarea state
3305
+ */
3306
+ showPlainTextarea(show) {
3307
+ if (show) {
3308
+ this.container.classList.add("plain-mode");
3309
+ } else {
3310
+ this.container.classList.remove("plain-mode");
3311
+ }
3312
+ if (this.toolbar) {
3313
+ const toggleBtn = this.container.querySelector('[data-action="toggle-plain"]');
3314
+ if (toggleBtn) {
3315
+ toggleBtn.classList.toggle("active", !show);
3316
+ toggleBtn.title = show ? "Show markdown preview" : "Show plain textarea";
3317
+ }
3318
+ }
3319
+ return show;
3320
+ }
3321
+ /**
3322
+ * Show/hide preview mode
3323
+ * @param {boolean} show - Show preview mode if true, edit mode if false
3324
+ * @returns {boolean} Current preview mode state
3325
+ */
3326
+ showPreviewMode(show) {
3327
+ if (show) {
3328
+ this.container.classList.add("preview-mode");
3329
+ } else {
3330
+ this.container.classList.remove("preview-mode");
3331
+ }
3332
+ return show;
3333
+ }
2734
3334
  /**
2735
3335
  * Destroy the editor instance
2736
3336
  */
@@ -2887,6 +3487,9 @@ OverType.ShortcutsManager = ShortcutsManager;
2887
3487
  OverType.themes = { solar, cave: getTheme("cave") };
2888
3488
  OverType.getTheme = getTheme;
2889
3489
  OverType.currentTheme = solar;
3490
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
3491
+ window.OverType = OverType;
3492
+ }
2890
3493
  var overtype_default = OverType;
2891
3494
  export {
2892
3495
  OverType,