overtype 1.1.1 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/overtype.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OverType v1.1.0
2
+ * OverType v1.1.4
3
3
  * A lightweight markdown editor library with perfect WYSIWYG alignment
4
4
  * @license MIT
5
5
  * @author Demo User
@@ -129,7 +129,7 @@ var OverType = (() => {
129
129
  * @returns {string|null} Parsed code fence or null
130
130
  */
131
131
  static parseCodeBlock(html) {
132
- if (html.startsWith("```")) {
132
+ if (html.match(/^```(\s*|\w*)$/)) {
133
133
  return `<div><span class="code-fence">${html}</span></div>`;
134
134
  }
135
135
  return null;
@@ -1318,7 +1318,7 @@ ${blockSuffix}` : suffix;
1318
1318
  const {
1319
1319
  fontSize = "14px",
1320
1320
  lineHeight = 1.6,
1321
- fontFamily = "ui-monospace, 'SFMono-Regular', 'Menlo', 'Consolas', 'Liberation Mono', monospace",
1321
+ 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',
1322
1322
  padding = "20px",
1323
1323
  theme = null,
1324
1324
  mobile = {}
@@ -1338,7 +1338,8 @@ ${blockSuffix}` : suffix;
1338
1338
  return `
1339
1339
  /* OverType Editor Styles */
1340
1340
  .overtype-container {
1341
- position: relative !important;
1341
+ display: grid !important;
1342
+ grid-template-rows: auto 1fr auto !important;
1342
1343
  width: 100% !important;
1343
1344
  height: 100% !important;
1344
1345
  ${themeVars ? `
@@ -1346,12 +1347,26 @@ ${blockSuffix}` : suffix;
1346
1347
  ${themeVars}` : ""}
1347
1348
  }
1348
1349
 
1350
+ /* Auto-resize mode styles */
1351
+ .overtype-container.overtype-auto-resize {
1352
+ height: auto !important;
1353
+ grid-template-rows: auto auto auto !important;
1354
+ }
1355
+
1356
+ .overtype-container.overtype-auto-resize .overtype-wrapper {
1357
+ height: auto !important;
1358
+ min-height: 60px !important;
1359
+ overflow: visible !important;
1360
+ }
1361
+
1349
1362
  .overtype-wrapper {
1350
1363
  position: relative !important;
1351
1364
  width: 100% !important;
1352
- height: 100% !important;
1365
+ height: 100% !important; /* Take full height of grid cell */
1366
+ min-height: 60px !important; /* Minimum usable height */
1353
1367
  overflow: hidden !important;
1354
1368
  background: var(--bg-secondary, #ffffff) !important;
1369
+ grid-row: 2 !important; /* Always second row in grid */
1355
1370
  }
1356
1371
 
1357
1372
  /* Critical alignment styles - must be identical for both layers */
@@ -1366,6 +1381,8 @@ ${blockSuffix}` : suffix;
1366
1381
 
1367
1382
  /* Font properties - any difference breaks alignment */
1368
1383
  font-family: ${fontFamily} !important;
1384
+ font-synthesis: none !important; /* no faux bold/italic width drift */
1385
+ font-variant-ligatures: none !important; /* keep metrics stable for code */
1369
1386
  font-size: var(--instance-font-size, ${fontSize}) !important;
1370
1387
  line-height: var(--instance-line-height, ${lineHeight}) !important;
1371
1388
  font-weight: normal !important;
@@ -1632,15 +1649,9 @@ ${blockSuffix}` : suffix;
1632
1649
  }
1633
1650
 
1634
1651
  /* Stats bar */
1635
- .overtype-wrapper.with-stats {
1636
- padding-bottom: 40px !important;
1637
- }
1638
1652
 
1639
- .overtype-wrapper .overtype-stats {
1640
- position: absolute !important;
1641
- bottom: 0 !important;
1642
- left: 0 !important;
1643
- right: 0 !important;
1653
+ /* Stats bar - positioned by grid, not absolute */
1654
+ .overtype-stats {
1644
1655
  height: 40px !important;
1645
1656
  padding: 0 20px !important;
1646
1657
  background: #f8f9fa !important;
@@ -1651,24 +1662,24 @@ ${blockSuffix}` : suffix;
1651
1662
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
1652
1663
  font-size: 0.85rem !important;
1653
1664
  color: #666 !important;
1654
- z-index: 2 !important;
1665
+ grid-row: 3 !important; /* Always third row in grid */
1655
1666
  }
1656
1667
 
1657
1668
  /* Dark theme stats bar */
1658
- .overtype-wrapper[data-theme="cave"] .overtype-stats {
1669
+ .overtype-container[data-theme="cave"] .overtype-stats {
1659
1670
  background: var(--bg-secondary, #1D2D3E) !important;
1660
1671
  border-top: 1px solid rgba(197, 221, 232, 0.1) !important;
1661
1672
  color: var(--text, #c5dde8) !important;
1662
1673
  }
1663
1674
 
1664
- .overtype-wrapper .overtype-stats .overtype-stat {
1675
+ .overtype-stats .overtype-stat {
1665
1676
  display: flex !important;
1666
1677
  align-items: center !important;
1667
1678
  gap: 5px !important;
1668
1679
  white-space: nowrap !important;
1669
1680
  }
1670
1681
 
1671
- .overtype-wrapper .overtype-stats .live-dot {
1682
+ .overtype-stats .live-dot {
1672
1683
  width: 8px !important;
1673
1684
  height: 8px !important;
1674
1685
  background: #4caf50 !important;
@@ -1681,11 +1692,6 @@ ${blockSuffix}` : suffix;
1681
1692
  50% { opacity: 0.6; transform: scale(1.2); }
1682
1693
  }
1683
1694
 
1684
- /* Adjust textarea and preview for stats bar */
1685
- .overtype-wrapper.with-stats .overtype-input,
1686
- .overtype-wrapper.with-stats .overtype-preview {
1687
- height: calc(100% - 40px) !important;
1688
- }
1689
1695
 
1690
1696
  /* Toolbar Styles */
1691
1697
  .overtype-toolbar {
@@ -1696,6 +1702,9 @@ ${blockSuffix}` : suffix;
1696
1702
  background: var(--toolbar-bg, var(--bg-primary, #f8f9fa));
1697
1703
  overflow-x: auto;
1698
1704
  -webkit-overflow-scrolling: touch;
1705
+ flex-shrink: 0;
1706
+ height: auto !important;
1707
+ grid-row: 1 !important; /* Always first row in grid */
1699
1708
  }
1700
1709
 
1701
1710
  .overtype-toolbar-button {
@@ -2247,8 +2256,16 @@ ${blockSuffix}` : suffix;
2247
2256
  padding: "12px",
2248
2257
  lineHeight: 1.5
2249
2258
  },
2259
+ // Native textarea properties
2260
+ textareaProps: {},
2250
2261
  // Behavior
2251
2262
  autofocus: false,
2263
+ autoResize: false,
2264
+ // Auto-expand height with content
2265
+ minHeight: "100px",
2266
+ // Minimum height for autoResize mode
2267
+ maxHeight: null,
2268
+ // Maximum height for autoResize mode (null = unlimited)
2252
2269
  placeholder: "Start typing...",
2253
2270
  value: "",
2254
2271
  // Callbacks
@@ -2365,9 +2382,6 @@ ${blockSuffix}` : suffix;
2365
2382
  }
2366
2383
  this.wrapper = document.createElement("div");
2367
2384
  this.wrapper.className = "overtype-wrapper";
2368
- if (this.options.showStats) {
2369
- this.wrapper.classList.add("with-stats");
2370
- }
2371
2385
  if (this.options.fontSize) {
2372
2386
  this.wrapper.style.setProperty("--instance-font-size", this.options.fontSize);
2373
2387
  }
@@ -2382,19 +2396,47 @@ ${blockSuffix}` : suffix;
2382
2396
  this.textarea.className = "overtype-input";
2383
2397
  this.textarea.placeholder = this.options.placeholder;
2384
2398
  this._configureTextarea();
2399
+ if (this.options.textareaProps) {
2400
+ Object.entries(this.options.textareaProps).forEach(([key, value]) => {
2401
+ if (key === "className" || key === "class") {
2402
+ this.textarea.className += " " + value;
2403
+ } else if (key === "style" && typeof value === "object") {
2404
+ Object.assign(this.textarea.style, value);
2405
+ } else {
2406
+ this.textarea.setAttribute(key, value);
2407
+ }
2408
+ });
2409
+ }
2385
2410
  this.preview = document.createElement("div");
2386
2411
  this.preview.className = "overtype-preview";
2387
2412
  this.preview.setAttribute("aria-hidden", "true");
2388
2413
  this.wrapper.appendChild(this.textarea);
2389
2414
  this.wrapper.appendChild(this.preview);
2415
+ this.container.appendChild(this.wrapper);
2390
2416
  if (this.options.showStats) {
2391
2417
  this.statsBar = document.createElement("div");
2392
2418
  this.statsBar.className = "overtype-stats";
2393
- this.wrapper.appendChild(this.statsBar);
2419
+ this.container.appendChild(this.statsBar);
2394
2420
  this._updateStats();
2395
2421
  }
2396
- this.container.appendChild(this.wrapper);
2397
2422
  this.element.appendChild(this.container);
2423
+ if (window.location.pathname.includes("demo.html")) {
2424
+ console.log("_createDOM completed:", {
2425
+ elementId: this.element.id,
2426
+ autoResize: this.options.autoResize,
2427
+ containerClasses: this.container.className,
2428
+ hasStats: !!this.statsBar,
2429
+ hasToolbar: this.options.toolbar
2430
+ });
2431
+ }
2432
+ if (this.options.autoResize) {
2433
+ this._setupAutoResize();
2434
+ } else {
2435
+ this.container.classList.remove("overtype-auto-resize");
2436
+ if (window.location.pathname.includes("demo.html")) {
2437
+ console.log("Removed auto-resize class from:", this.element.id);
2438
+ }
2439
+ }
2398
2440
  }
2399
2441
  /**
2400
2442
  * Configure textarea attributes
@@ -2417,6 +2459,13 @@ ${blockSuffix}` : suffix;
2417
2459
  if (this.options.autofocus) {
2418
2460
  this.textarea.focus();
2419
2461
  }
2462
+ if (this.options.autoResize) {
2463
+ if (!this.container.classList.contains("overtype-auto-resize")) {
2464
+ this._setupAutoResize();
2465
+ }
2466
+ } else {
2467
+ this.container.classList.remove("overtype-auto-resize");
2468
+ }
2420
2469
  this.updatePreview();
2421
2470
  }
2422
2471
  /**
@@ -2457,6 +2506,8 @@ ${blockSuffix}` : suffix;
2457
2506
  while (currentDiv && currentDiv !== closeParent) {
2458
2507
  if (currentDiv.tagName === "DIV") {
2459
2508
  currentDiv.classList.add("code-block-line");
2509
+ const plainText = currentDiv.textContent;
2510
+ currentDiv.textContent = plainText;
2460
2511
  }
2461
2512
  currentDiv = currentDiv.nextElementSibling;
2462
2513
  if (!currentDiv)
@@ -2541,6 +2592,9 @@ ${blockSuffix}` : suffix;
2541
2592
  setValue(value) {
2542
2593
  this.textarea.value = value;
2543
2594
  this.updatePreview();
2595
+ if (this.options.autoResize) {
2596
+ this._updateAutoHeight();
2597
+ }
2544
2598
  }
2545
2599
  /**
2546
2600
  * Focus the editor
@@ -2604,6 +2658,57 @@ ${blockSuffix}` : suffix;
2604
2658
  `;
2605
2659
  }
2606
2660
  }
2661
+ /**
2662
+ * Setup auto-resize functionality
2663
+ * @private
2664
+ */
2665
+ _setupAutoResize() {
2666
+ this.container.classList.add("overtype-auto-resize");
2667
+ this.previousHeight = null;
2668
+ this._updateAutoHeight();
2669
+ this.textarea.addEventListener("input", () => this._updateAutoHeight());
2670
+ window.addEventListener("resize", () => this._updateAutoHeight());
2671
+ }
2672
+ /**
2673
+ * Update height based on scrollHeight
2674
+ * @private
2675
+ */
2676
+ _updateAutoHeight() {
2677
+ if (!this.options.autoResize)
2678
+ return;
2679
+ const textarea = this.textarea;
2680
+ const preview = this.preview;
2681
+ const wrapper = this.wrapper;
2682
+ const computed = window.getComputedStyle(textarea);
2683
+ const paddingTop = parseFloat(computed.paddingTop);
2684
+ const paddingBottom = parseFloat(computed.paddingBottom);
2685
+ const scrollTop = textarea.scrollTop;
2686
+ textarea.style.setProperty("height", "auto", "important");
2687
+ let newHeight = textarea.scrollHeight;
2688
+ if (this.options.minHeight) {
2689
+ const minHeight = parseInt(this.options.minHeight);
2690
+ newHeight = Math.max(newHeight, minHeight);
2691
+ }
2692
+ let overflow = "hidden";
2693
+ if (this.options.maxHeight) {
2694
+ const maxHeight = parseInt(this.options.maxHeight);
2695
+ if (newHeight > maxHeight) {
2696
+ newHeight = maxHeight;
2697
+ overflow = "auto";
2698
+ }
2699
+ }
2700
+ const heightPx = newHeight + "px";
2701
+ textarea.style.setProperty("height", heightPx, "important");
2702
+ textarea.style.setProperty("overflow-y", overflow, "important");
2703
+ preview.style.setProperty("height", heightPx, "important");
2704
+ preview.style.setProperty("overflow-y", overflow, "important");
2705
+ wrapper.style.setProperty("height", heightPx, "important");
2706
+ textarea.scrollTop = scrollTop;
2707
+ preview.scrollTop = scrollTop;
2708
+ if (this.previousHeight !== newHeight) {
2709
+ this.previousHeight = newHeight;
2710
+ }
2711
+ }
2607
2712
  /**
2608
2713
  * Show or hide stats bar
2609
2714
  * @param {boolean} show - Whether to show stats
@@ -2613,13 +2718,11 @@ ${blockSuffix}` : suffix;
2613
2718
  if (show && !this.statsBar) {
2614
2719
  this.statsBar = document.createElement("div");
2615
2720
  this.statsBar.className = "overtype-stats";
2616
- this.wrapper.appendChild(this.statsBar);
2617
- this.wrapper.classList.add("with-stats");
2721
+ this.container.appendChild(this.statsBar);
2618
2722
  this._updateStats();
2619
2723
  } else if (!show && this.statsBar) {
2620
2724
  this.statsBar.remove();
2621
2725
  this.statsBar = null;
2622
- this.wrapper.classList.remove("with-stats");
2623
2726
  }
2624
2727
  }
2625
2728
  /**