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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OverType v1.1.8
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
- 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
@@ -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: 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 {
@@ -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: "togglePlain", icon: eyeIcon, title: "Show plain textarea", action: "toggle-plain" }
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
- this.textarea.value = before + outdented + after;
2587
- this.textarea.selectionStart = start;
2588
- this.textarea.selectionEnd = start + outdented.length;
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
- this.textarea.value = before + indented + after;
2596
- this.textarea.selectionStart = start;
2597
- this.textarea.selectionEnd = start + indented.length;
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
- this.textarea.value = value.substring(0, start) + " " + value.substring(end);
2600
- this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
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,