overtype 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/overtype.esm.js +131 -30
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +131 -30
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +63 -54
- package/package.json +1 -1
- package/src/overtype.js +147 -13
- package/src/parser.js +3 -1
- package/src/styles.js +29 -20
package/src/overtype.js
CHANGED
|
@@ -144,8 +144,14 @@ class OverType {
|
|
|
144
144
|
lineHeight: 1.5
|
|
145
145
|
},
|
|
146
146
|
|
|
147
|
+
// Native textarea properties
|
|
148
|
+
textareaProps: {},
|
|
149
|
+
|
|
147
150
|
// Behavior
|
|
148
151
|
autofocus: false,
|
|
152
|
+
autoResize: false, // Auto-expand height with content
|
|
153
|
+
minHeight: '100px', // Minimum height for autoResize mode
|
|
154
|
+
maxHeight: null, // Maximum height for autoResize mode (null = unlimited)
|
|
149
155
|
placeholder: 'Start typing...',
|
|
150
156
|
value: '',
|
|
151
157
|
|
|
@@ -307,10 +313,6 @@ class OverType {
|
|
|
307
313
|
this.wrapper = document.createElement('div');
|
|
308
314
|
this.wrapper.className = 'overtype-wrapper';
|
|
309
315
|
|
|
310
|
-
// Add stats wrapper class if stats are enabled
|
|
311
|
-
if (this.options.showStats) {
|
|
312
|
-
this.wrapper.classList.add('with-stats');
|
|
313
|
-
}
|
|
314
316
|
|
|
315
317
|
// Apply instance-specific styles via CSS custom properties
|
|
316
318
|
if (this.options.fontSize) {
|
|
@@ -330,6 +332,19 @@ class OverType {
|
|
|
330
332
|
this.textarea.className = 'overtype-input';
|
|
331
333
|
this.textarea.placeholder = this.options.placeholder;
|
|
332
334
|
this._configureTextarea();
|
|
335
|
+
|
|
336
|
+
// Apply any native textarea properties
|
|
337
|
+
if (this.options.textareaProps) {
|
|
338
|
+
Object.entries(this.options.textareaProps).forEach(([key, value]) => {
|
|
339
|
+
if (key === 'className' || key === 'class') {
|
|
340
|
+
this.textarea.className += ' ' + value;
|
|
341
|
+
} else if (key === 'style' && typeof value === 'object') {
|
|
342
|
+
Object.assign(this.textarea.style, value);
|
|
343
|
+
} else {
|
|
344
|
+
this.textarea.setAttribute(key, value);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
333
348
|
|
|
334
349
|
// Create preview div
|
|
335
350
|
this.preview = document.createElement('div');
|
|
@@ -340,19 +355,42 @@ class OverType {
|
|
|
340
355
|
this.wrapper.appendChild(this.textarea);
|
|
341
356
|
this.wrapper.appendChild(this.preview);
|
|
342
357
|
|
|
343
|
-
// Add
|
|
358
|
+
// Add wrapper to container first
|
|
359
|
+
this.container.appendChild(this.wrapper);
|
|
360
|
+
|
|
361
|
+
// Add stats bar at the end (bottom) if enabled
|
|
344
362
|
if (this.options.showStats) {
|
|
345
363
|
this.statsBar = document.createElement('div');
|
|
346
364
|
this.statsBar.className = 'overtype-stats';
|
|
347
|
-
this.
|
|
365
|
+
this.container.appendChild(this.statsBar);
|
|
348
366
|
this._updateStats();
|
|
349
367
|
}
|
|
350
368
|
|
|
351
|
-
// Add wrapper to container
|
|
352
|
-
this.container.appendChild(this.wrapper);
|
|
353
|
-
|
|
354
369
|
// Add container to element
|
|
355
370
|
this.element.appendChild(this.container);
|
|
371
|
+
|
|
372
|
+
// Debug logging
|
|
373
|
+
if (window.location.pathname.includes('demo.html')) {
|
|
374
|
+
console.log('_createDOM completed:', {
|
|
375
|
+
elementId: this.element.id,
|
|
376
|
+
autoResize: this.options.autoResize,
|
|
377
|
+
containerClasses: this.container.className,
|
|
378
|
+
hasStats: !!this.statsBar,
|
|
379
|
+
hasToolbar: this.options.toolbar
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Setup auto-resize if enabled
|
|
384
|
+
if (this.options.autoResize) {
|
|
385
|
+
this._setupAutoResize();
|
|
386
|
+
} else {
|
|
387
|
+
// Ensure auto-resize class is removed if not using auto-resize
|
|
388
|
+
this.container.classList.remove('overtype-auto-resize');
|
|
389
|
+
|
|
390
|
+
if (window.location.pathname.includes('demo.html')) {
|
|
391
|
+
console.log('Removed auto-resize class from:', this.element.id);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
356
394
|
}
|
|
357
395
|
|
|
358
396
|
/**
|
|
@@ -378,6 +416,16 @@ class OverType {
|
|
|
378
416
|
if (this.options.autofocus) {
|
|
379
417
|
this.textarea.focus();
|
|
380
418
|
}
|
|
419
|
+
|
|
420
|
+
// Setup or remove auto-resize
|
|
421
|
+
if (this.options.autoResize) {
|
|
422
|
+
if (!this.container.classList.contains('overtype-auto-resize')) {
|
|
423
|
+
this._setupAutoResize();
|
|
424
|
+
}
|
|
425
|
+
} else {
|
|
426
|
+
// Ensure auto-resize class is removed
|
|
427
|
+
this.container.classList.remove('overtype-auto-resize');
|
|
428
|
+
}
|
|
381
429
|
|
|
382
430
|
// Update preview with initial content
|
|
383
431
|
this.updatePreview();
|
|
@@ -554,6 +602,11 @@ class OverType {
|
|
|
554
602
|
setValue(value) {
|
|
555
603
|
this.textarea.value = value;
|
|
556
604
|
this.updatePreview();
|
|
605
|
+
|
|
606
|
+
// Update height if auto-resize is enabled
|
|
607
|
+
if (this.options.autoResize) {
|
|
608
|
+
this._updateAutoHeight();
|
|
609
|
+
}
|
|
557
610
|
}
|
|
558
611
|
|
|
559
612
|
|
|
@@ -629,6 +682,89 @@ class OverType {
|
|
|
629
682
|
}
|
|
630
683
|
}
|
|
631
684
|
|
|
685
|
+
/**
|
|
686
|
+
* Setup auto-resize functionality
|
|
687
|
+
* @private
|
|
688
|
+
*/
|
|
689
|
+
_setupAutoResize() {
|
|
690
|
+
// Add auto-resize class for styling
|
|
691
|
+
this.container.classList.add('overtype-auto-resize');
|
|
692
|
+
|
|
693
|
+
// Store previous height for comparison
|
|
694
|
+
this.previousHeight = null;
|
|
695
|
+
|
|
696
|
+
// Initial height update
|
|
697
|
+
this._updateAutoHeight();
|
|
698
|
+
|
|
699
|
+
// Listen for input events
|
|
700
|
+
this.textarea.addEventListener('input', () => this._updateAutoHeight());
|
|
701
|
+
|
|
702
|
+
// Listen for window resize
|
|
703
|
+
window.addEventListener('resize', () => this._updateAutoHeight());
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Update height based on scrollHeight
|
|
708
|
+
* @private
|
|
709
|
+
*/
|
|
710
|
+
_updateAutoHeight() {
|
|
711
|
+
if (!this.options.autoResize) return;
|
|
712
|
+
|
|
713
|
+
const textarea = this.textarea;
|
|
714
|
+
const preview = this.preview;
|
|
715
|
+
const wrapper = this.wrapper;
|
|
716
|
+
|
|
717
|
+
// Get computed styles
|
|
718
|
+
const computed = window.getComputedStyle(textarea);
|
|
719
|
+
const paddingTop = parseFloat(computed.paddingTop);
|
|
720
|
+
const paddingBottom = parseFloat(computed.paddingBottom);
|
|
721
|
+
|
|
722
|
+
// Store scroll positions
|
|
723
|
+
const scrollTop = textarea.scrollTop;
|
|
724
|
+
|
|
725
|
+
// Reset height to get accurate scrollHeight
|
|
726
|
+
textarea.style.setProperty('height', 'auto', 'important');
|
|
727
|
+
|
|
728
|
+
// Calculate new height based on scrollHeight
|
|
729
|
+
let newHeight = textarea.scrollHeight;
|
|
730
|
+
|
|
731
|
+
// Apply min height constraint
|
|
732
|
+
if (this.options.minHeight) {
|
|
733
|
+
const minHeight = parseInt(this.options.minHeight);
|
|
734
|
+
newHeight = Math.max(newHeight, minHeight);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Apply max height constraint
|
|
738
|
+
let overflow = 'hidden';
|
|
739
|
+
if (this.options.maxHeight) {
|
|
740
|
+
const maxHeight = parseInt(this.options.maxHeight);
|
|
741
|
+
if (newHeight > maxHeight) {
|
|
742
|
+
newHeight = maxHeight;
|
|
743
|
+
overflow = 'auto';
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Apply the new height to all elements with !important to override base styles
|
|
748
|
+
const heightPx = newHeight + 'px';
|
|
749
|
+
textarea.style.setProperty('height', heightPx, 'important');
|
|
750
|
+
textarea.style.setProperty('overflow-y', overflow, 'important');
|
|
751
|
+
|
|
752
|
+
preview.style.setProperty('height', heightPx, 'important');
|
|
753
|
+
preview.style.setProperty('overflow-y', overflow, 'important');
|
|
754
|
+
|
|
755
|
+
wrapper.style.setProperty('height', heightPx, 'important');
|
|
756
|
+
|
|
757
|
+
// Restore scroll position
|
|
758
|
+
textarea.scrollTop = scrollTop;
|
|
759
|
+
preview.scrollTop = scrollTop;
|
|
760
|
+
|
|
761
|
+
// Track if height changed
|
|
762
|
+
if (this.previousHeight !== newHeight) {
|
|
763
|
+
this.previousHeight = newHeight;
|
|
764
|
+
// Could dispatch a custom event here if needed
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
632
768
|
/**
|
|
633
769
|
* Show or hide stats bar
|
|
634
770
|
* @param {boolean} show - Whether to show stats
|
|
@@ -637,17 +773,15 @@ class OverType {
|
|
|
637
773
|
this.options.showStats = show;
|
|
638
774
|
|
|
639
775
|
if (show && !this.statsBar) {
|
|
640
|
-
// Create stats bar
|
|
776
|
+
// Create stats bar (add to container, not wrapper)
|
|
641
777
|
this.statsBar = document.createElement('div');
|
|
642
778
|
this.statsBar.className = 'overtype-stats';
|
|
643
|
-
this.
|
|
644
|
-
this.wrapper.classList.add('with-stats');
|
|
779
|
+
this.container.appendChild(this.statsBar);
|
|
645
780
|
this._updateStats();
|
|
646
781
|
} else if (!show && this.statsBar) {
|
|
647
782
|
// Remove stats bar
|
|
648
783
|
this.statsBar.remove();
|
|
649
784
|
this.statsBar = null;
|
|
650
|
-
this.wrapper.classList.remove('with-stats');
|
|
651
785
|
}
|
|
652
786
|
}
|
|
653
787
|
|
package/src/parser.js
CHANGED
|
@@ -109,7 +109,9 @@ export class MarkdownParser {
|
|
|
109
109
|
* @returns {string|null} Parsed code fence or null
|
|
110
110
|
*/
|
|
111
111
|
static parseCodeBlock(html) {
|
|
112
|
-
if
|
|
112
|
+
// Only treat as code block if ``` is alone or followed by a language identifier
|
|
113
|
+
// This prevents ```some code``` from being treated as a code fence
|
|
114
|
+
if (html.match(/^```(\s*|\w*)$/)) {
|
|
113
115
|
return `<div><span class="code-fence">${html}</span></div>`;
|
|
114
116
|
}
|
|
115
117
|
return null;
|
package/src/styles.js
CHANGED
|
@@ -14,7 +14,7 @@ export function generateStyles(options = {}) {
|
|
|
14
14
|
const {
|
|
15
15
|
fontSize = '14px',
|
|
16
16
|
lineHeight = 1.6,
|
|
17
|
-
fontFamily = "
|
|
17
|
+
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',
|
|
18
18
|
padding = '20px',
|
|
19
19
|
theme = null,
|
|
20
20
|
mobile = {}
|
|
@@ -41,7 +41,8 @@ export function generateStyles(options = {}) {
|
|
|
41
41
|
return `
|
|
42
42
|
/* OverType Editor Styles */
|
|
43
43
|
.overtype-container {
|
|
44
|
-
|
|
44
|
+
display: grid !important;
|
|
45
|
+
grid-template-rows: auto 1fr auto !important;
|
|
45
46
|
width: 100% !important;
|
|
46
47
|
height: 100% !important;
|
|
47
48
|
${themeVars ? `
|
|
@@ -49,12 +50,26 @@ export function generateStyles(options = {}) {
|
|
|
49
50
|
${themeVars}` : ''}
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
/* Auto-resize mode styles */
|
|
54
|
+
.overtype-container.overtype-auto-resize {
|
|
55
|
+
height: auto !important;
|
|
56
|
+
grid-template-rows: auto auto auto !important;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.overtype-container.overtype-auto-resize .overtype-wrapper {
|
|
60
|
+
height: auto !important;
|
|
61
|
+
min-height: 60px !important;
|
|
62
|
+
overflow: visible !important;
|
|
63
|
+
}
|
|
64
|
+
|
|
52
65
|
.overtype-wrapper {
|
|
53
66
|
position: relative !important;
|
|
54
67
|
width: 100% !important;
|
|
55
|
-
height: 100% !important;
|
|
68
|
+
height: 100% !important; /* Take full height of grid cell */
|
|
69
|
+
min-height: 60px !important; /* Minimum usable height */
|
|
56
70
|
overflow: hidden !important;
|
|
57
71
|
background: var(--bg-secondary, #ffffff) !important;
|
|
72
|
+
grid-row: 2 !important; /* Always second row in grid */
|
|
58
73
|
}
|
|
59
74
|
|
|
60
75
|
/* Critical alignment styles - must be identical for both layers */
|
|
@@ -69,6 +84,8 @@ export function generateStyles(options = {}) {
|
|
|
69
84
|
|
|
70
85
|
/* Font properties - any difference breaks alignment */
|
|
71
86
|
font-family: ${fontFamily} !important;
|
|
87
|
+
font-synthesis: none !important; /* no faux bold/italic width drift */
|
|
88
|
+
font-variant-ligatures: none !important; /* keep metrics stable for code */
|
|
72
89
|
font-size: var(--instance-font-size, ${fontSize}) !important;
|
|
73
90
|
line-height: var(--instance-line-height, ${lineHeight}) !important;
|
|
74
91
|
font-weight: normal !important;
|
|
@@ -335,15 +352,9 @@ export function generateStyles(options = {}) {
|
|
|
335
352
|
}
|
|
336
353
|
|
|
337
354
|
/* Stats bar */
|
|
338
|
-
.overtype-wrapper.with-stats {
|
|
339
|
-
padding-bottom: 40px !important;
|
|
340
|
-
}
|
|
341
355
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
bottom: 0 !important;
|
|
345
|
-
left: 0 !important;
|
|
346
|
-
right: 0 !important;
|
|
356
|
+
/* Stats bar - positioned by grid, not absolute */
|
|
357
|
+
.overtype-stats {
|
|
347
358
|
height: 40px !important;
|
|
348
359
|
padding: 0 20px !important;
|
|
349
360
|
background: #f8f9fa !important;
|
|
@@ -354,24 +365,24 @@ export function generateStyles(options = {}) {
|
|
|
354
365
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
|
|
355
366
|
font-size: 0.85rem !important;
|
|
356
367
|
color: #666 !important;
|
|
357
|
-
|
|
368
|
+
grid-row: 3 !important; /* Always third row in grid */
|
|
358
369
|
}
|
|
359
370
|
|
|
360
371
|
/* Dark theme stats bar */
|
|
361
|
-
.overtype-
|
|
372
|
+
.overtype-container[data-theme="cave"] .overtype-stats {
|
|
362
373
|
background: var(--bg-secondary, #1D2D3E) !important;
|
|
363
374
|
border-top: 1px solid rgba(197, 221, 232, 0.1) !important;
|
|
364
375
|
color: var(--text, #c5dde8) !important;
|
|
365
376
|
}
|
|
366
377
|
|
|
367
|
-
.overtype-
|
|
378
|
+
.overtype-stats .overtype-stat {
|
|
368
379
|
display: flex !important;
|
|
369
380
|
align-items: center !important;
|
|
370
381
|
gap: 5px !important;
|
|
371
382
|
white-space: nowrap !important;
|
|
372
383
|
}
|
|
373
384
|
|
|
374
|
-
.overtype-
|
|
385
|
+
.overtype-stats .live-dot {
|
|
375
386
|
width: 8px !important;
|
|
376
387
|
height: 8px !important;
|
|
377
388
|
background: #4caf50 !important;
|
|
@@ -384,11 +395,6 @@ export function generateStyles(options = {}) {
|
|
|
384
395
|
50% { opacity: 0.6; transform: scale(1.2); }
|
|
385
396
|
}
|
|
386
397
|
|
|
387
|
-
/* Adjust textarea and preview for stats bar */
|
|
388
|
-
.overtype-wrapper.with-stats .overtype-input,
|
|
389
|
-
.overtype-wrapper.with-stats .overtype-preview {
|
|
390
|
-
height: calc(100% - 40px) !important;
|
|
391
|
-
}
|
|
392
398
|
|
|
393
399
|
/* Toolbar Styles */
|
|
394
400
|
.overtype-toolbar {
|
|
@@ -399,6 +405,9 @@ export function generateStyles(options = {}) {
|
|
|
399
405
|
background: var(--toolbar-bg, var(--bg-primary, #f8f9fa));
|
|
400
406
|
overflow-x: auto;
|
|
401
407
|
-webkit-overflow-scrolling: touch;
|
|
408
|
+
flex-shrink: 0;
|
|
409
|
+
height: auto !important;
|
|
410
|
+
grid-row: 1 !important; /* Always first row in grid */
|
|
402
411
|
}
|
|
403
412
|
|
|
404
413
|
.overtype-toolbar-button {
|