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.
package/dist/overtype.js CHANGED
@@ -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
@@ -78,8 +78,7 @@ var OverType = (() => {
78
78
  static parseHeader(html) {
79
79
  return html.replace(/^(#{1,3})\s(.+)$/, (match, hashes, content) => {
80
80
  const level = hashes.length;
81
- const levelClasses = ["h1", "h2", "h3"];
82
- return `<span class="header ${levelClasses[level - 1]}"><span class="syntax-marker">${hashes}</span> ${content}</span>`;
81
+ return `<h${level}><span class="syntax-marker">${hashes} </span>${content}</h${level}>`;
83
82
  });
84
83
  }
85
84
  /**
@@ -110,7 +109,7 @@ var OverType = (() => {
110
109
  */
111
110
  static parseBulletList(html) {
112
111
  return html.replace(/^((?:&nbsp;)*)([-*])\s(.+)$/, (match, indent, marker, content) => {
113
- return `${indent}<span class="syntax-marker">${marker}</span> ${content}`;
112
+ return `${indent}<li class="bullet-list"><span class="syntax-marker">${marker} </span>${content}</li>`;
114
113
  });
115
114
  }
116
115
  /**
@@ -120,7 +119,7 @@ var OverType = (() => {
120
119
  */
121
120
  static parseNumberedList(html) {
122
121
  return html.replace(/^((?:&nbsp;)*)(\d+\.)\s(.+)$/, (match, indent, marker, content) => {
123
- return `${indent}<span class="syntax-marker">${marker}</span> ${content}`;
122
+ return `${indent}<li class="ordered-list"><span class="syntax-marker">${marker} </span>${content}</li>`;
124
123
  });
125
124
  }
126
125
  /**
@@ -195,7 +194,7 @@ var OverType = (() => {
195
194
  return html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => {
196
195
  const anchorName = `--link-${this.linkIndex++}`;
197
196
  const safeUrl = this.sanitizeUrl(url);
198
- 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>`;
197
+ return `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker url-part">](${url})</span></a>`;
199
198
  });
200
199
  }
201
200
  /**
@@ -266,7 +265,123 @@ var OverType = (() => {
266
265
  }
267
266
  return this.parseLine(line);
268
267
  });
269
- return parsedLines.join("");
268
+ const html = parsedLines.join("");
269
+ return this.postProcessHTML(html);
270
+ }
271
+ /**
272
+ * Post-process HTML to consolidate lists and code blocks
273
+ * @param {string} html - HTML to post-process
274
+ * @returns {string} Post-processed HTML with consolidated lists and code blocks
275
+ */
276
+ static postProcessHTML(html) {
277
+ if (typeof document === "undefined" || !document) {
278
+ return this.postProcessHTMLManual(html);
279
+ }
280
+ const container = document.createElement("div");
281
+ container.innerHTML = html;
282
+ let currentList = null;
283
+ let listType = null;
284
+ let currentCodeBlock = null;
285
+ let inCodeBlock = false;
286
+ const children = Array.from(container.children);
287
+ for (let i = 0; i < children.length; i++) {
288
+ const child = children[i];
289
+ if (!child.parentNode)
290
+ continue;
291
+ const codeFence = child.querySelector(".code-fence");
292
+ if (codeFence) {
293
+ const fenceText = codeFence.textContent;
294
+ if (fenceText.startsWith("```")) {
295
+ if (!inCodeBlock) {
296
+ inCodeBlock = true;
297
+ currentCodeBlock = document.createElement("pre");
298
+ const codeElement = document.createElement("code");
299
+ currentCodeBlock.appendChild(codeElement);
300
+ currentCodeBlock.className = "code-block";
301
+ const lang = fenceText.slice(3).trim();
302
+ if (lang) {
303
+ codeElement.className = `language-${lang}`;
304
+ }
305
+ container.insertBefore(currentCodeBlock, child);
306
+ child.remove();
307
+ continue;
308
+ } else {
309
+ inCodeBlock = false;
310
+ currentCodeBlock = null;
311
+ child.remove();
312
+ continue;
313
+ }
314
+ }
315
+ }
316
+ if (inCodeBlock && currentCodeBlock && child.tagName === "DIV" && !child.querySelector(".code-fence")) {
317
+ const codeElement = currentCodeBlock.querySelector("code");
318
+ if (codeElement.textContent.length > 0) {
319
+ codeElement.textContent += "\n";
320
+ }
321
+ const lineText = child.innerHTML.replace(/&nbsp;/g, " ").replace(/<[^>]*>/g, "");
322
+ codeElement.textContent += lineText;
323
+ child.remove();
324
+ continue;
325
+ }
326
+ let listItem = null;
327
+ if (child.tagName === "DIV") {
328
+ listItem = child.querySelector("li");
329
+ }
330
+ if (listItem) {
331
+ const isBullet = listItem.classList.contains("bullet-list");
332
+ const isOrdered = listItem.classList.contains("ordered-list");
333
+ if (!isBullet && !isOrdered) {
334
+ currentList = null;
335
+ listType = null;
336
+ continue;
337
+ }
338
+ const newType = isBullet ? "ul" : "ol";
339
+ if (!currentList || listType !== newType) {
340
+ currentList = document.createElement(newType);
341
+ container.insertBefore(currentList, child);
342
+ listType = newType;
343
+ }
344
+ currentList.appendChild(listItem);
345
+ child.remove();
346
+ } else {
347
+ currentList = null;
348
+ listType = null;
349
+ }
350
+ }
351
+ return container.innerHTML;
352
+ }
353
+ /**
354
+ * Manual post-processing for Node.js environments (without DOM)
355
+ * @param {string} html - HTML to post-process
356
+ * @returns {string} Post-processed HTML
357
+ */
358
+ static postProcessHTMLManual(html) {
359
+ let processed = html;
360
+ processed = processed.replace(/((?:<div>(?:&nbsp;)*<li class="bullet-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
361
+ const items = match.match(/<li class="bullet-list">.*?<\/li>/gs) || [];
362
+ if (items.length > 0) {
363
+ return "<ul>" + items.join("") + "</ul>";
364
+ }
365
+ return match;
366
+ });
367
+ processed = processed.replace(/((?:<div>(?:&nbsp;)*<li class="ordered-list">.*?<\/li><\/div>\s*)+)/gs, (match) => {
368
+ const items = match.match(/<li class="ordered-list">.*?<\/li>/gs) || [];
369
+ if (items.length > 0) {
370
+ return "<ol>" + items.join("") + "</ol>";
371
+ }
372
+ return match;
373
+ });
374
+ const codeBlockRegex = /<div><span class="code-fence">```([^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">```<\/span><\/div>/gs;
375
+ processed = processed.replace(codeBlockRegex, (match, lang, content) => {
376
+ const lines = content.match(/<div>(.*?)<\/div>/gs) || [];
377
+ const codeContent = lines.map((line) => {
378
+ 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, "&");
379
+ return text;
380
+ }).join("\n");
381
+ const langClass = lang ? ` class="language-${lang.trim()}"` : "";
382
+ return `<pre class="code-block"><code${langClass}>${this.escapeHtml(codeContent)}</code></pre>`;
383
+ });
384
+ return processed;
270
385
  }
271
386
  };
272
387
  // Track link index for anchor naming
@@ -1347,6 +1462,7 @@ ${blockSuffix}` : suffix;
1347
1462
  const {
1348
1463
  fontSize = "14px",
1349
1464
  lineHeight = 1.6,
1465
+ /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
1350
1466
  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',
1351
1467
  padding = "20px",
1352
1468
  theme = null,
@@ -1366,11 +1482,44 @@ ${blockSuffix}` : suffix;
1366
1482
  const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : "";
1367
1483
  return `
1368
1484
  /* OverType Editor Styles */
1485
+
1486
+ /* Middle-ground CSS Reset - Prevent parent styles from leaking in */
1487
+ .overtype-container * {
1488
+ /* Box model - these commonly leak */
1489
+ margin: 0 !important;
1490
+ padding: 0 !important;
1491
+ border: 0 !important;
1492
+
1493
+ /* Layout - these can break our layout */
1494
+ /* Don't reset position - it breaks dropdowns */
1495
+ float: none !important;
1496
+ clear: none !important;
1497
+
1498
+ /* Typography - only reset decorative aspects */
1499
+ text-decoration: none !important;
1500
+ text-transform: none !important;
1501
+ letter-spacing: normal !important;
1502
+
1503
+ /* Visual effects that can interfere */
1504
+ box-shadow: none !important;
1505
+ text-shadow: none !important;
1506
+
1507
+ /* Ensure box-sizing is consistent */
1508
+ box-sizing: border-box !important;
1509
+
1510
+ /* Keep inheritance for these */
1511
+ /* font-family, color, line-height, font-size - inherit */
1512
+ }
1513
+
1514
+ /* Container base styles after reset */
1369
1515
  .overtype-container {
1370
1516
  display: grid !important;
1371
1517
  grid-template-rows: auto 1fr auto !important;
1372
1518
  width: 100% !important;
1373
1519
  height: 100% !important;
1520
+ position: relative !important; /* Override reset - needed for absolute children */
1521
+ overflow: visible !important; /* Allow dropdown to overflow container */
1522
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
1374
1523
  ${themeVars ? `
1375
1524
  /* Theme Variables */
1376
1525
  ${themeVars}` : ""}
@@ -1389,20 +1538,21 @@ ${blockSuffix}` : suffix;
1389
1538
  }
1390
1539
 
1391
1540
  .overtype-wrapper {
1392
- position: relative !important;
1541
+ position: relative !important; /* Override reset - needed for absolute children */
1393
1542
  width: 100% !important;
1394
1543
  height: 100% !important; /* Take full height of grid cell */
1395
1544
  min-height: 60px !important; /* Minimum usable height */
1396
1545
  overflow: hidden !important;
1397
1546
  background: var(--bg-secondary, #ffffff) !important;
1398
1547
  grid-row: 2 !important; /* Always second row in grid */
1548
+ z-index: 1; /* Below toolbar and dropdown */
1399
1549
  }
1400
1550
 
1401
1551
  /* Critical alignment styles - must be identical for both layers */
1402
1552
  .overtype-wrapper .overtype-input,
1403
1553
  .overtype-wrapper .overtype-preview {
1404
1554
  /* Positioning - must be identical */
1405
- position: absolute !important;
1555
+ position: absolute !important; /* Override reset - required for overlay */
1406
1556
  top: 0 !important;
1407
1557
  left: 0 !important;
1408
1558
  width: 100% !important;
@@ -1410,7 +1560,6 @@ ${blockSuffix}` : suffix;
1410
1560
 
1411
1561
  /* Font properties - any difference breaks alignment */
1412
1562
  font-family: ${fontFamily} !important;
1413
- font-synthesis: none !important; /* no faux bold/italic width drift */
1414
1563
  font-variant-ligatures: none !important; /* keep metrics stable for code */
1415
1564
  font-size: var(--instance-font-size, ${fontSize}) !important;
1416
1565
  line-height: var(--instance-line-height, ${lineHeight}) !important;
@@ -1470,7 +1619,7 @@ ${blockSuffix}` : suffix;
1470
1619
  /* Overflow */
1471
1620
  overflow-y: auto !important;
1472
1621
  overflow-x: auto !important;
1473
- overscroll-behavior: none !important;
1622
+ /* overscroll-behavior removed to allow scroll-through to parent */
1474
1623
  scrollbar-width: auto !important;
1475
1624
  scrollbar-gutter: auto !important;
1476
1625
 
@@ -1558,6 +1707,45 @@ ${blockSuffix}` : suffix;
1558
1707
  color: var(--h3, #3d8a51) !important;
1559
1708
  }
1560
1709
 
1710
+ /* Semantic headers - flatten in edit mode */
1711
+ .overtype-wrapper .overtype-preview h1,
1712
+ .overtype-wrapper .overtype-preview h2,
1713
+ .overtype-wrapper .overtype-preview h3 {
1714
+ font-size: inherit !important;
1715
+ font-weight: bold !important;
1716
+ margin: 0 !important;
1717
+ padding: 0 !important;
1718
+ display: inline !important;
1719
+ line-height: inherit !important;
1720
+ }
1721
+
1722
+ /* Header colors for semantic headers */
1723
+ .overtype-wrapper .overtype-preview h1 {
1724
+ color: var(--h1, #f95738) !important;
1725
+ }
1726
+ .overtype-wrapper .overtype-preview h2 {
1727
+ color: var(--h2, #ee964b) !important;
1728
+ }
1729
+ .overtype-wrapper .overtype-preview h3 {
1730
+ color: var(--h3, #3d8a51) !important;
1731
+ }
1732
+
1733
+ /* Lists - remove styling in edit mode */
1734
+ .overtype-wrapper .overtype-preview ul,
1735
+ .overtype-wrapper .overtype-preview ol {
1736
+ list-style: none !important;
1737
+ margin: 0 !important;
1738
+ padding: 0 !important;
1739
+ display: block !important; /* Lists need to be block for line breaks */
1740
+ }
1741
+
1742
+ .overtype-wrapper .overtype-preview li {
1743
+ display: block !important; /* Each item on its own line */
1744
+ margin: 0 !important;
1745
+ padding: 0 !important;
1746
+ /* Don't set list-style here - let ul/ol control it */
1747
+ }
1748
+
1561
1749
  /* Bold text */
1562
1750
  .overtype-wrapper .overtype-preview strong {
1563
1751
  color: var(--strong, #ee964b) !important;
@@ -1584,17 +1772,23 @@ ${blockSuffix}` : suffix;
1584
1772
  font-weight: normal !important;
1585
1773
  }
1586
1774
 
1587
- /* Code blocks */
1775
+ /* Code blocks - consolidated pre blocks */
1588
1776
  .overtype-wrapper .overtype-preview pre {
1589
- background: #1e1e1e !important;
1590
1777
  padding: 0 !important;
1591
1778
  margin: 0 !important;
1592
1779
  border-radius: 4px !important;
1593
1780
  overflow-x: auto !important;
1594
1781
  }
1782
+
1783
+ /* Code block styling in normal mode - yellow background */
1784
+ .overtype-wrapper .overtype-preview pre.code-block {
1785
+ background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
1786
+ }
1595
1787
 
1788
+ /* Code inside pre blocks - remove background */
1596
1789
  .overtype-wrapper .overtype-preview pre code {
1597
- background: none !important;
1790
+ background: transparent !important;
1791
+ color: var(--code, #0d3b66) !important;
1598
1792
  }
1599
1793
 
1600
1794
  /* Blockquotes */
@@ -1625,11 +1819,6 @@ ${blockSuffix}` : suffix;
1625
1819
  padding: 0 !important;
1626
1820
  }
1627
1821
 
1628
- .overtype-wrapper .overtype-preview li {
1629
- margin: 0 !important;
1630
- padding: 0 !important;
1631
- list-style: none !important;
1632
- }
1633
1822
 
1634
1823
  /* Horizontal rules */
1635
1824
  .overtype-wrapper .overtype-preview hr {
@@ -1728,13 +1917,31 @@ ${blockSuffix}` : suffix;
1728
1917
  display: flex;
1729
1918
  align-items: center;
1730
1919
  gap: 4px;
1731
- padding: 8px;
1732
- background: var(--toolbar-bg, var(--bg-primary, #f8f9fa));
1733
- overflow-x: auto;
1920
+ padding: 8px !important; /* Override reset */
1921
+ background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */
1922
+ overflow-x: auto !important; /* Allow horizontal scrolling */
1923
+ overflow-y: hidden !important; /* Hide vertical overflow */
1734
1924
  -webkit-overflow-scrolling: touch;
1735
1925
  flex-shrink: 0;
1736
1926
  height: auto !important;
1737
1927
  grid-row: 1 !important; /* Always first row in grid */
1928
+ position: relative !important; /* Override reset */
1929
+ z-index: 100; /* Ensure toolbar is above wrapper */
1930
+ scrollbar-width: thin; /* Thin scrollbar on Firefox */
1931
+ }
1932
+
1933
+ /* Thin scrollbar styling */
1934
+ .overtype-toolbar::-webkit-scrollbar {
1935
+ height: 4px;
1936
+ }
1937
+
1938
+ .overtype-toolbar::-webkit-scrollbar-track {
1939
+ background: transparent;
1940
+ }
1941
+
1942
+ .overtype-toolbar::-webkit-scrollbar-thumb {
1943
+ background: rgba(0, 0, 0, 0.2);
1944
+ border-radius: 2px;
1738
1945
  }
1739
1946
 
1740
1947
  .overtype-toolbar-button {
@@ -1806,6 +2013,231 @@ ${blockSuffix}` : suffix;
1806
2013
  margin: 0 2px;
1807
2014
  }
1808
2015
  }
2016
+
2017
+ /* Plain mode - hide preview and show textarea text */
2018
+ .overtype-container.plain-mode .overtype-preview {
2019
+ display: none !important;
2020
+ }
2021
+
2022
+ .overtype-container.plain-mode .overtype-input {
2023
+ color: var(--text, #0d3b66) !important;
2024
+ /* Use system font stack for better plain text readability */
2025
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
2026
+ "Helvetica Neue", Arial, sans-serif !important;
2027
+ }
2028
+
2029
+ /* Ensure textarea remains transparent in overlay mode */
2030
+ .overtype-container:not(.plain-mode) .overtype-input {
2031
+ color: transparent !important;
2032
+ }
2033
+
2034
+ /* Dropdown menu styles */
2035
+ .overtype-toolbar-button {
2036
+ position: relative !important; /* Override reset - needed for dropdown */
2037
+ }
2038
+
2039
+ .overtype-toolbar-button.dropdown-active {
2040
+ background: var(--toolbar-active, var(--hover-bg, #f0f0f0));
2041
+ }
2042
+
2043
+ .overtype-dropdown-menu {
2044
+ position: fixed !important; /* Fixed positioning relative to viewport */
2045
+ background: var(--bg-secondary, white) !important; /* Override reset */
2046
+ border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */
2047
+ border-radius: 6px;
2048
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */
2049
+ z-index: 10000; /* Very high z-index to ensure visibility */
2050
+ min-width: 150px;
2051
+ padding: 4px 0 !important; /* Override reset */
2052
+ /* Position will be set via JavaScript based on button position */
2053
+ }
2054
+
2055
+ .overtype-dropdown-item {
2056
+ display: flex;
2057
+ align-items: center;
2058
+ width: 100%;
2059
+ padding: 8px 12px;
2060
+ border: none;
2061
+ background: none;
2062
+ text-align: left;
2063
+ cursor: pointer;
2064
+ font-size: 14px;
2065
+ color: var(--text, #333);
2066
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
2067
+ }
2068
+
2069
+ .overtype-dropdown-item:hover {
2070
+ background: var(--hover-bg, #f0f0f0);
2071
+ }
2072
+
2073
+ .overtype-dropdown-item.active {
2074
+ font-weight: 600;
2075
+ }
2076
+
2077
+ .overtype-dropdown-check {
2078
+ width: 16px;
2079
+ margin-right: 8px;
2080
+ color: var(--h1, #007bff);
2081
+ }
2082
+
2083
+ /* Preview mode styles */
2084
+ .overtype-container.preview-mode .overtype-input {
2085
+ display: none !important;
2086
+ }
2087
+
2088
+ .overtype-container.preview-mode .overtype-preview {
2089
+ pointer-events: auto !important;
2090
+ user-select: text !important;
2091
+ cursor: text !important;
2092
+ }
2093
+
2094
+ /* Hide syntax markers in preview mode */
2095
+ .overtype-container.preview-mode .syntax-marker {
2096
+ display: none !important;
2097
+ }
2098
+
2099
+ /* Hide URL part of links in preview mode - extra specificity */
2100
+ .overtype-container.preview-mode .syntax-marker.url-part,
2101
+ .overtype-container.preview-mode .url-part {
2102
+ display: none !important;
2103
+ }
2104
+
2105
+ /* Hide all syntax markers inside links too */
2106
+ .overtype-container.preview-mode a .syntax-marker {
2107
+ display: none !important;
2108
+ }
2109
+
2110
+ /* Headers - restore proper sizing in preview mode */
2111
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h1,
2112
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h2,
2113
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h3 {
2114
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
2115
+ font-weight: 600 !important;
2116
+ margin: 0 !important;
2117
+ display: block !important;
2118
+ color: inherit !important; /* Use parent text color */
2119
+ line-height: 1 !important; /* Tight line height for headings */
2120
+ }
2121
+
2122
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h1 {
2123
+ font-size: 2em !important;
2124
+ }
2125
+
2126
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h2 {
2127
+ font-size: 1.5em !important;
2128
+ }
2129
+
2130
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview h3 {
2131
+ font-size: 1.17em !important;
2132
+ }
2133
+
2134
+ /* Lists - restore list styling in preview mode */
2135
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview ul {
2136
+ display: block !important;
2137
+ list-style: disc !important;
2138
+ padding-left: 2em !important;
2139
+ margin: 1em 0 !important;
2140
+ }
2141
+
2142
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview ol {
2143
+ display: block !important;
2144
+ list-style: decimal !important;
2145
+ padding-left: 2em !important;
2146
+ margin: 1em 0 !important;
2147
+ }
2148
+
2149
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview li {
2150
+ display: list-item !important;
2151
+ margin: 0 !important;
2152
+ padding: 0 !important;
2153
+ }
2154
+
2155
+ /* Links - make clickable in preview mode */
2156
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview a {
2157
+ pointer-events: auto !important;
2158
+ cursor: pointer !important;
2159
+ color: var(--link, #0066cc) !important;
2160
+ text-decoration: underline !important;
2161
+ }
2162
+
2163
+ /* Code blocks - proper pre/code styling in preview mode */
2164
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview pre.code-block {
2165
+ background: #2d2d2d !important;
2166
+ color: #f8f8f2 !important;
2167
+ padding: 1.2em !important;
2168
+ border-radius: 3px !important;
2169
+ overflow-x: auto !important;
2170
+ margin: 0 !important;
2171
+ display: block !important;
2172
+ }
2173
+
2174
+ /* Cave theme code block background in preview mode */
2175
+ .overtype-container[data-theme="cave"].preview-mode .overtype-wrapper .overtype-preview pre.code-block {
2176
+ background: #11171F !important;
2177
+ }
2178
+
2179
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview pre.code-block code {
2180
+ background: transparent !important;
2181
+ color: inherit !important;
2182
+ padding: 0 !important;
2183
+ font-family: ${fontFamily} !important;
2184
+ font-size: 0.9em !important;
2185
+ line-height: 1.4 !important;
2186
+ }
2187
+
2188
+ /* Hide old code block lines and fences in preview mode */
2189
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview .code-block-line {
2190
+ display: none !important;
2191
+ }
2192
+
2193
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview .code-fence {
2194
+ display: none !important;
2195
+ }
2196
+
2197
+ /* Blockquotes - enhanced styling in preview mode */
2198
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview .blockquote {
2199
+ display: block !important;
2200
+ border-left: 4px solid var(--blockquote, #ddd) !important;
2201
+ padding-left: 1em !important;
2202
+ margin: 1em 0 !important;
2203
+ font-style: italic !important;
2204
+ }
2205
+
2206
+ /* Typography improvements in preview mode */
2207
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview {
2208
+ font-family: Georgia, 'Times New Roman', serif !important;
2209
+ font-size: 16px !important;
2210
+ line-height: 1.8 !important;
2211
+ color: var(--text, #333) !important; /* Consistent text color */
2212
+ }
2213
+
2214
+ /* Inline code in preview mode - keep monospace */
2215
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview code {
2216
+ font-family: ${fontFamily} !important;
2217
+ font-size: 0.9em !important;
2218
+ background: rgba(135, 131, 120, 0.15) !important;
2219
+ padding: 0.2em 0.4em !important;
2220
+ border-radius: 3px !important;
2221
+ }
2222
+
2223
+ /* Strong and em elements in preview mode */
2224
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview strong {
2225
+ font-weight: 700 !important;
2226
+ color: inherit !important; /* Use parent text color */
2227
+ }
2228
+
2229
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview em {
2230
+ font-style: italic !important;
2231
+ color: inherit !important; /* Use parent text color */
2232
+ }
2233
+
2234
+ /* HR in preview mode */
2235
+ .overtype-container.preview-mode .overtype-wrapper .overtype-preview .hr-marker {
2236
+ display: block !important;
2237
+ border-top: 2px solid var(--hr, #ddd) !important;
2238
+ text-indent: -9999px !important;
2239
+ height: 2px !important;
2240
+ }
1809
2241
 
1810
2242
  ${mobileStyles}
1811
2243
  `;
@@ -1869,6 +2301,10 @@ ${blockSuffix}` : suffix;
1869
2301
  <rect stroke="currentColor" fill="none" stroke-width="1.5" x="2" y="13" width="3" height="3" rx="0.5"></rect>
1870
2302
  <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>
1871
2303
  </svg>`;
2304
+ var eyeIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2305
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" fill="none"></path>
2306
+ <circle cx="12" cy="12" r="3" fill="none"></circle>
2307
+ </svg>`;
1872
2308
 
1873
2309
  // src/toolbar.js
1874
2310
  var Toolbar = class {
@@ -1900,7 +2336,9 @@ ${blockSuffix}` : suffix;
1900
2336
  { separator: true },
1901
2337
  { name: "bulletList", icon: bulletListIcon, title: "Bullet List", action: "toggleBulletList" },
1902
2338
  { name: "orderedList", icon: orderedListIcon, title: "Numbered List", action: "toggleNumberedList" },
1903
- { name: "taskList", icon: taskListIcon, title: "Task List", action: "toggleTaskList" }
2339
+ { name: "taskList", icon: taskListIcon, title: "Task List", action: "toggleTaskList" },
2340
+ { separator: true },
2341
+ { name: "viewMode", icon: eyeIcon, title: "View mode", action: "toggle-view-menu", hasDropdown: true }
1904
2342
  ];
1905
2343
  buttonConfig.forEach((config) => {
1906
2344
  if (config.separator) {
@@ -1932,19 +2370,29 @@ ${blockSuffix}` : suffix;
1932
2370
  button.setAttribute("aria-label", config.title);
1933
2371
  button.setAttribute("data-action", config.action);
1934
2372
  button.innerHTML = config.icon;
2373
+ if (config.hasDropdown) {
2374
+ button.classList.add("has-dropdown");
2375
+ if (config.name === "viewMode") {
2376
+ this.viewModeButton = button;
2377
+ }
2378
+ }
1935
2379
  button.addEventListener("click", (e) => {
1936
2380
  e.preventDefault();
1937
- this.handleAction(config.action);
2381
+ this.handleAction(config.action, button);
1938
2382
  });
1939
2383
  return button;
1940
2384
  }
1941
2385
  /**
1942
2386
  * Handle toolbar button actions
1943
2387
  */
1944
- async handleAction(action) {
2388
+ async handleAction(action, button) {
1945
2389
  const textarea = this.editor.textarea;
1946
2390
  if (!textarea)
1947
2391
  return;
2392
+ if (action === "toggle-view-menu") {
2393
+ this.toggleViewDropdown(button);
2394
+ return;
2395
+ }
1948
2396
  textarea.focus();
1949
2397
  try {
1950
2398
  switch (action) {
@@ -1981,6 +2429,10 @@ ${blockSuffix}` : suffix;
1981
2429
  case "toggleTaskList":
1982
2430
  toggleTaskList(textarea);
1983
2431
  break;
2432
+ case "toggle-plain":
2433
+ const isPlain = this.editor.container.classList.contains("plain-mode");
2434
+ this.editor.showPlainTextarea(!isPlain);
2435
+ break;
1984
2436
  }
1985
2437
  textarea.dispatchEvent(new Event("input", { bubbles: true }));
1986
2438
  } catch (error) {
@@ -2029,6 +2481,9 @@ ${blockSuffix}` : suffix;
2029
2481
  case "h3":
2030
2482
  isActive = activeFormats.includes("header-3");
2031
2483
  break;
2484
+ case "togglePlain":
2485
+ isActive = !this.editor.container.classList.contains("plain-mode");
2486
+ break;
2032
2487
  }
2033
2488
  button.classList.toggle("active", isActive);
2034
2489
  button.setAttribute("aria-pressed", isActive.toString());
@@ -2036,11 +2491,102 @@ ${blockSuffix}` : suffix;
2036
2491
  } catch (error) {
2037
2492
  }
2038
2493
  }
2494
+ /**
2495
+ * Toggle view mode dropdown menu
2496
+ */
2497
+ toggleViewDropdown(button) {
2498
+ const existingDropdown = document.querySelector(".overtype-dropdown-menu");
2499
+ if (existingDropdown) {
2500
+ existingDropdown.remove();
2501
+ button.classList.remove("dropdown-active");
2502
+ document.removeEventListener("click", this.handleDocumentClick);
2503
+ return;
2504
+ }
2505
+ const dropdown = this.createViewDropdown();
2506
+ const rect = button.getBoundingClientRect();
2507
+ dropdown.style.top = `${rect.bottom + 4}px`;
2508
+ dropdown.style.left = `${rect.left}px`;
2509
+ document.body.appendChild(dropdown);
2510
+ button.classList.add("dropdown-active");
2511
+ this.handleDocumentClick = (e) => {
2512
+ if (!button.contains(e.target) && !dropdown.contains(e.target)) {
2513
+ dropdown.remove();
2514
+ button.classList.remove("dropdown-active");
2515
+ document.removeEventListener("click", this.handleDocumentClick);
2516
+ }
2517
+ };
2518
+ setTimeout(() => {
2519
+ document.addEventListener("click", this.handleDocumentClick);
2520
+ }, 0);
2521
+ }
2522
+ /**
2523
+ * Create view mode dropdown menu
2524
+ */
2525
+ createViewDropdown() {
2526
+ const dropdown = document.createElement("div");
2527
+ dropdown.className = "overtype-dropdown-menu";
2528
+ const isPlain = this.editor.container.classList.contains("plain-mode");
2529
+ const isPreview = this.editor.container.classList.contains("preview-mode");
2530
+ const currentMode = isPreview ? "preview" : isPlain ? "plain" : "normal";
2531
+ const modes = [
2532
+ { id: "normal", label: "Normal Edit", icon: "\u2713" },
2533
+ { id: "plain", label: "Plain Textarea", icon: "\u2713" },
2534
+ { id: "preview", label: "Preview Mode", icon: "\u2713" }
2535
+ ];
2536
+ modes.forEach((mode) => {
2537
+ const item = document.createElement("button");
2538
+ item.className = "overtype-dropdown-item";
2539
+ item.type = "button";
2540
+ const check = document.createElement("span");
2541
+ check.className = "overtype-dropdown-check";
2542
+ check.textContent = currentMode === mode.id ? mode.icon : "";
2543
+ const label = document.createElement("span");
2544
+ label.textContent = mode.label;
2545
+ item.appendChild(check);
2546
+ item.appendChild(label);
2547
+ if (currentMode === mode.id) {
2548
+ item.classList.add("active");
2549
+ }
2550
+ item.addEventListener("click", (e) => {
2551
+ e.stopPropagation();
2552
+ this.setViewMode(mode.id);
2553
+ dropdown.remove();
2554
+ this.viewModeButton.classList.remove("dropdown-active");
2555
+ document.removeEventListener("click", this.handleDocumentClick);
2556
+ });
2557
+ dropdown.appendChild(item);
2558
+ });
2559
+ return dropdown;
2560
+ }
2561
+ /**
2562
+ * Set view mode
2563
+ */
2564
+ setViewMode(mode) {
2565
+ this.editor.container.classList.remove("plain-mode", "preview-mode");
2566
+ switch (mode) {
2567
+ case "plain":
2568
+ this.editor.showPlainTextarea(true);
2569
+ break;
2570
+ case "preview":
2571
+ this.editor.showPreviewMode(true);
2572
+ break;
2573
+ case "normal":
2574
+ default:
2575
+ this.editor.showPlainTextarea(false);
2576
+ if (typeof this.editor.showPreviewMode === "function") {
2577
+ this.editor.showPreviewMode(false);
2578
+ }
2579
+ break;
2580
+ }
2581
+ }
2039
2582
  /**
2040
2583
  * Destroy toolbar
2041
2584
  */
2042
2585
  destroy() {
2043
2586
  if (this.container) {
2587
+ if (this.handleDocumentClick) {
2588
+ document.removeEventListener("click", this.handleDocumentClick);
2589
+ }
2044
2590
  this.container.remove();
2045
2591
  this.container = null;
2046
2592
  this.buttons = {};
@@ -2277,7 +2823,8 @@ ${blockSuffix}` : suffix;
2277
2823
  // Typography
2278
2824
  fontSize: "14px",
2279
2825
  lineHeight: 1.6,
2280
- fontFamily: "ui-monospace, 'SFMono-Regular', 'Menlo', 'Consolas', 'Liberation Mono', monospace",
2826
+ /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
2827
+ 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',
2281
2828
  padding: "16px",
2282
2829
  // Mobile styles
2283
2830
  mobile: {
@@ -2626,6 +3173,26 @@ ${blockSuffix}` : suffix;
2626
3173
  this._updateAutoHeight();
2627
3174
  }
2628
3175
  }
3176
+ /**
3177
+ * Get the rendered HTML of the current content
3178
+ * @param {boolean} processForPreview - If true, post-processes HTML for preview mode (consolidates lists/code blocks)
3179
+ * @returns {string} Rendered HTML
3180
+ */
3181
+ getRenderedHTML(processForPreview = false) {
3182
+ const markdown = this.getValue();
3183
+ let html = MarkdownParser.parse(markdown);
3184
+ if (processForPreview) {
3185
+ html = MarkdownParser.postProcessHTML(html);
3186
+ }
3187
+ return html;
3188
+ }
3189
+ /**
3190
+ * Get the current preview element's HTML
3191
+ * @returns {string} Current preview HTML (as displayed)
3192
+ */
3193
+ getPreviewHTML() {
3194
+ return this.preview.innerHTML;
3195
+ }
2629
3196
  /**
2630
3197
  * Focus the editor
2631
3198
  */
@@ -2755,6 +3322,39 @@ ${blockSuffix}` : suffix;
2755
3322
  this.statsBar = null;
2756
3323
  }
2757
3324
  }
3325
+ /**
3326
+ * Show or hide the plain textarea (toggle overlay visibility)
3327
+ * @param {boolean} show - true to show plain textarea (hide overlay), false to show overlay
3328
+ * @returns {boolean} Current plain textarea state
3329
+ */
3330
+ showPlainTextarea(show) {
3331
+ if (show) {
3332
+ this.container.classList.add("plain-mode");
3333
+ } else {
3334
+ this.container.classList.remove("plain-mode");
3335
+ }
3336
+ if (this.toolbar) {
3337
+ const toggleBtn = this.container.querySelector('[data-action="toggle-plain"]');
3338
+ if (toggleBtn) {
3339
+ toggleBtn.classList.toggle("active", !show);
3340
+ toggleBtn.title = show ? "Show markdown preview" : "Show plain textarea";
3341
+ }
3342
+ }
3343
+ return show;
3344
+ }
3345
+ /**
3346
+ * Show/hide preview mode
3347
+ * @param {boolean} show - Show preview mode if true, edit mode if false
3348
+ * @returns {boolean} Current preview mode state
3349
+ */
3350
+ showPreviewMode(show) {
3351
+ if (show) {
3352
+ this.container.classList.add("preview-mode");
3353
+ } else {
3354
+ this.container.classList.remove("preview-mode");
3355
+ }
3356
+ return show;
3357
+ }
2758
3358
  /**
2759
3359
  * Destroy the editor instance
2760
3360
  */
@@ -2911,6 +3511,9 @@ ${blockSuffix}` : suffix;
2911
3511
  OverType.themes = { solar, cave: getTheme("cave") };
2912
3512
  OverType.getTheme = getTheme;
2913
3513
  OverType.currentTheme = solar;
3514
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
3515
+ window.OverType = OverType;
3516
+ }
2914
3517
  var overtype_default = OverType;
2915
3518
  return __toCommonJS(overtype_exports);
2916
3519
  })();
@@ -2919,5 +3522,4 @@ ${blockSuffix}` : suffix;
2919
3522
  * @version 1.0.0
2920
3523
  * @license MIT
2921
3524
  */
2922
- window.OverType = OverType.OverType || OverType.default || OverType;
2923
3525
  //# sourceMappingURL=overtype.js.map