@editora/light-code-editor 1.0.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.
@@ -0,0 +1,1116 @@
1
+ class m {
2
+ constructor(e = "") {
3
+ this._lines = [], this._version = 0, this.setText(e);
4
+ }
5
+ // Get line at index
6
+ getLine(e) {
7
+ return this._lines[e] || "";
8
+ }
9
+ // Get all lines
10
+ getLines() {
11
+ return [...this._lines];
12
+ }
13
+ // Get total number of lines
14
+ getLineCount() {
15
+ return this._lines.length;
16
+ }
17
+ // Get total text content
18
+ getText() {
19
+ return this._lines.join(`
20
+ `);
21
+ }
22
+ // Set entire text content
23
+ setText(e) {
24
+ this._lines = e.split(`
25
+ `), this._version++;
26
+ }
27
+ // Get text in a range
28
+ getTextInRange(e) {
29
+ if (e.start.line === e.end.line)
30
+ return this.getLine(e.start.line).substring(e.start.column, e.end.column);
31
+ const t = [];
32
+ t.push(this.getLine(e.start.line).substring(e.start.column));
33
+ for (let n = e.start.line + 1; n < e.end.line; n++)
34
+ t.push(this.getLine(n));
35
+ return e.end.line < this.getLineCount() && t.push(this.getLine(e.end.line).substring(0, e.end.column)), t.join(`
36
+ `);
37
+ }
38
+ // Replace text in range
39
+ replaceRange(e, t) {
40
+ const n = this.getTextInRange(e);
41
+ if (e.start.line === e.end.line) {
42
+ const i = this.getLine(e.start.line), s = i.substring(0, e.start.column) + t + i.substring(e.end.column);
43
+ this._lines[e.start.line] = s;
44
+ } else {
45
+ const i = this.getLine(e.start.line), s = this.getLine(e.end.line), o = i.substring(0, e.start.column) + t, h = s.substring(e.end.column), r = t.split(`
46
+ `);
47
+ r[0] = o + r[0], r[r.length - 1] = r[r.length - 1] + h, this._lines.splice(e.start.line, e.end.line - e.start.line + 1, ...r);
48
+ }
49
+ return this._version++, { range: e, text: t, oldText: n };
50
+ }
51
+ // Insert text at position
52
+ insertText(e, t) {
53
+ const n = { start: e, end: e };
54
+ return this.replaceRange(n, t);
55
+ }
56
+ // Delete text in range
57
+ deleteRange(e) {
58
+ return this.replaceRange(e, "");
59
+ }
60
+ // Convert position to offset
61
+ positionToOffset(e) {
62
+ let t = 0;
63
+ for (let n = 0; n < e.line; n++)
64
+ t += this.getLine(n).length + 1;
65
+ return t += e.column, t;
66
+ }
67
+ // Convert offset to position
68
+ offsetToPosition(e) {
69
+ let t = e;
70
+ for (let n = 0; n < this.getLineCount(); n++) {
71
+ const i = this.getLine(n).length;
72
+ if (t <= i)
73
+ return { line: n, column: t };
74
+ t -= i + 1;
75
+ }
76
+ return {
77
+ line: this.getLineCount() - 1,
78
+ column: this.getLine(this.getLineCount() - 1).length
79
+ };
80
+ }
81
+ // Validate position
82
+ isValidPosition(e) {
83
+ return !(e.line < 0 || e.line >= this.getLineCount() || e.column < 0 || e.column > this.getLine(e.line).length);
84
+ }
85
+ // Validate range
86
+ isValidRange(e) {
87
+ return this.isValidPosition(e.start) && this.isValidPosition(e.end);
88
+ }
89
+ // Get version for change tracking
90
+ getVersion() {
91
+ return this._version;
92
+ }
93
+ // Clone the model
94
+ clone() {
95
+ const e = new m();
96
+ return e._lines = [...this._lines], e._version = this._version, e;
97
+ }
98
+ }
99
+ class p {
100
+ constructor(e) {
101
+ this.gutterWidth = 50, this.lineHeight = 21, this.container = e, this.createDOM();
102
+ }
103
+ createDOM() {
104
+ this.container.innerHTML = "";
105
+ const e = document.createElement("div");
106
+ e.style.cssText = `
107
+ position: relative;
108
+ display: flex;
109
+ width: 100%;
110
+ height: 100%;
111
+ background: var(--editor-background, #1e1e1e);
112
+ color: var(--editor-foreground, #f8f9fa);
113
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
114
+ font-size: 14px;
115
+ line-height: ${this.lineHeight}px;
116
+ overflow: hidden;
117
+ `, this.lineNumbersElement = document.createElement("div"), this.lineNumbersElement.style.cssText = `
118
+ position: sticky;
119
+ left: 0;
120
+ top: 0;
121
+ width: ${this.gutterWidth}px;
122
+ background: var(--editor-gutter-background, #252526);
123
+ color: var(--editor-gutter-foreground, #858585);
124
+ padding: 0;
125
+ text-align: right;
126
+ border-right: 1px solid var(--editor-gutter-border, #3e3e42);
127
+ user-select: none;
128
+ overflow: hidden;
129
+ z-index: 1;
130
+ `, this.contentElement = document.createElement("div"), this.contentElement.style.cssText = `
131
+ flex: 1;
132
+ padding: 0;
133
+ background: transparent;
134
+ border: none;
135
+ outline: none;
136
+ white-space: pre;
137
+ overflow-x: auto;
138
+ overflow-y: auto;
139
+ min-height: 400px;
140
+ font-family: inherit;
141
+ font-size: inherit;
142
+ line-height: inherit;
143
+ color: inherit;
144
+ tab-size: 2;
145
+ -moz-tab-size: 2;
146
+ `, this.contentElement.contentEditable = "true", this.contentElement.spellcheck = !1, e.appendChild(this.lineNumbersElement), e.appendChild(this.contentElement), this.container.appendChild(e), this.updateLineNumbers(1);
147
+ }
148
+ // Update line numbers
149
+ updateLineNumbers(e) {
150
+ const t = Math.max(e, 20), n = Array.from({ length: t }, (i, s) => s + 1);
151
+ this.lineNumbersElement.innerHTML = n.map((i) => `<div style="height: ${this.lineHeight}px; line-height: ${this.lineHeight}px; padding-right: 12px;">${i}</div>`).join("");
152
+ }
153
+ // Get content element
154
+ getContentElement() {
155
+ return this.contentElement;
156
+ }
157
+ // Get line numbers element
158
+ getLineNumbersElement() {
159
+ return this.lineNumbersElement;
160
+ }
161
+ // Get text content
162
+ getText() {
163
+ return this.contentElement.textContent || "";
164
+ }
165
+ // Set text content
166
+ setText(e) {
167
+ this.contentElement.textContent = e;
168
+ const t = e.split(`
169
+ `).length;
170
+ this.updateLineNumbers(t);
171
+ }
172
+ // Get cursor position from DOM selection
173
+ getCursorPosition() {
174
+ const e = window.getSelection();
175
+ if (!e || e.rangeCount === 0)
176
+ return { line: 0, column: 0 };
177
+ const t = e.getRangeAt(0), n = t.cloneRange();
178
+ n.selectNodeContents(this.contentElement), n.setEnd(t.endContainer, t.endOffset);
179
+ const s = n.toString().split(`
180
+ `);
181
+ return {
182
+ line: s.length - 1,
183
+ column: s[s.length - 1].length
184
+ };
185
+ }
186
+ // Set cursor position
187
+ setCursorPosition(e) {
188
+ const n = this.getText().split(`
189
+ `), i = Math.min(e.line, n.length - 1), s = Math.min(e.column, n[i]?.length || 0);
190
+ let o = 0;
191
+ for (let g = 0; g < i; g++)
192
+ o += n[g].length + 1;
193
+ o += s;
194
+ const h = document.createRange(), r = window.getSelection();
195
+ let l = 0, c = null, a = 0;
196
+ const u = document.createTreeWalker(
197
+ this.contentElement,
198
+ NodeFilter.SHOW_TEXT,
199
+ null
200
+ );
201
+ let f;
202
+ for (; f = u.nextNode(); ) {
203
+ const g = f.textContent?.length || 0;
204
+ if (l + g >= o) {
205
+ c = f, a = o - l;
206
+ break;
207
+ }
208
+ l += g;
209
+ }
210
+ if (c)
211
+ try {
212
+ h.setStart(c, a), h.setEnd(c, a), r?.removeAllRanges(), r?.addRange(h);
213
+ } catch (g) {
214
+ console.warn("Could not set cursor position:", g);
215
+ }
216
+ }
217
+ // Get selection range
218
+ getSelectionRange() {
219
+ const e = window.getSelection();
220
+ if (!e || e.rangeCount === 0 || e.isCollapsed)
221
+ return;
222
+ const t = e.getRangeAt(0), n = t.cloneRange();
223
+ n.selectNodeContents(this.contentElement), n.setEnd(t.startContainer, t.startOffset);
224
+ const s = n.toString().split(`
225
+ `), o = t.cloneRange();
226
+ o.selectNodeContents(this.contentElement), o.setEnd(t.endContainer, t.endOffset);
227
+ const r = o.toString().split(`
228
+ `);
229
+ return {
230
+ start: {
231
+ line: s.length - 1,
232
+ column: s[s.length - 1].length
233
+ },
234
+ end: {
235
+ line: r.length - 1,
236
+ column: r[r.length - 1].length
237
+ }
238
+ };
239
+ }
240
+ // Set selection range
241
+ setSelectionRange(e) {
242
+ this.setCursorPosition(e.start);
243
+ }
244
+ // Focus the editor
245
+ focus() {
246
+ this.contentElement.focus();
247
+ }
248
+ // Blur the editor
249
+ blur() {
250
+ this.contentElement.blur();
251
+ }
252
+ // Set read-only mode
253
+ setReadOnly(e) {
254
+ this.contentElement.contentEditable = e ? "false" : "true";
255
+ }
256
+ // Apply theme
257
+ applyTheme(e) {
258
+ Object.entries(e).forEach(([t, n]) => {
259
+ this.container.style.setProperty(`--${t}`, n);
260
+ });
261
+ }
262
+ // Scroll to position
263
+ scrollToPosition(e) {
264
+ const t = this.lineNumbersElement.children[e.line];
265
+ t && t.scrollIntoView({ block: "center", behavior: "smooth" });
266
+ }
267
+ // Get scroll position
268
+ getScrollTop() {
269
+ return this.contentElement.scrollTop;
270
+ }
271
+ // Set scroll position
272
+ setScrollTop(e) {
273
+ this.contentElement.scrollTop = e, this.lineNumbersElement.scrollTop = e;
274
+ }
275
+ // Destroy the view
276
+ destroy() {
277
+ this.container && this.container.parentNode && this.container.parentNode.removeChild(this.container);
278
+ }
279
+ }
280
+ class x {
281
+ constructor(e, t = {}) {
282
+ this.extensions = /* @__PURE__ */ new Map(), this.commands = /* @__PURE__ */ new Map(), this.eventListeners = /* @__PURE__ */ new Map(), this.folds = [], this.currentTheme = "default", this.isDestroyed = !1, this.config = {
283
+ value: "",
284
+ theme: "default",
285
+ readOnly: !1,
286
+ tabSize: 2,
287
+ lineWrapping: !1,
288
+ lineNumbers: !0,
289
+ ...t
290
+ }, this.textModel = new m(this.config.value), this.view = new p(e), this.view.setText(this.textModel.getText()), this.view.setReadOnly(this.config.readOnly || !1), this.setupEventHandlers(), this.config.extensions && this.config.extensions.forEach((n) => this.addExtension(n)), this.setTheme(this.config.theme);
291
+ }
292
+ // Public accessors for extensions
293
+ getTextModel() {
294
+ return this.textModel;
295
+ }
296
+ getView() {
297
+ return this.view;
298
+ }
299
+ getConfig() {
300
+ return { ...this.config };
301
+ }
302
+ // Get keymap extension if available
303
+ getKeymapExtension() {
304
+ return this.extensions.get("keymap");
305
+ }
306
+ // Setup DOM event handlers
307
+ setupEventHandlers() {
308
+ const e = this.view.getContentElement();
309
+ e.addEventListener("input", () => {
310
+ const t = this.view.getText(), n = this.textModel.getText();
311
+ t !== n && (this.textModel.setText(t), this.emit("change", [{ range: this.getFullRange(), text: t, oldText: n }]), this.updateLineNumbers());
312
+ }), e.addEventListener("selectionchange", () => {
313
+ const t = this.getCursor(), n = this.getSelection();
314
+ this.emit("cursor", t), n && this.emit("selection", n);
315
+ }), e.addEventListener("keydown", (t) => {
316
+ this.emit("keydown", t);
317
+ for (const n of this.extensions.values())
318
+ if (n.onKeyDown && n.onKeyDown(t) === !1) {
319
+ t.preventDefault(), t.stopPropagation();
320
+ return;
321
+ }
322
+ }), e.addEventListener("mousedown", (t) => {
323
+ this.emit("mousedown", t);
324
+ for (const n of this.extensions.values())
325
+ if (n.onMouseDown && n.onMouseDown(t) === !1) {
326
+ t.preventDefault(), t.stopPropagation();
327
+ return;
328
+ }
329
+ }), e.addEventListener("focus", () => {
330
+ this.emit("focus");
331
+ }), e.addEventListener("blur", () => {
332
+ this.emit("blur");
333
+ });
334
+ }
335
+ // Update line numbers display
336
+ updateLineNumbers() {
337
+ const e = this.textModel.getLineCount();
338
+ this.view.updateLineNumbers(e);
339
+ }
340
+ // Get full range of document
341
+ getFullRange() {
342
+ return {
343
+ start: { line: 0, column: 0 },
344
+ end: {
345
+ line: this.textModel.getLineCount() - 1,
346
+ column: this.textModel.getLine(this.textModel.getLineCount() - 1).length
347
+ }
348
+ };
349
+ }
350
+ // Emit events to listeners
351
+ emit(e, ...t) {
352
+ const n = this.eventListeners.get(e);
353
+ n && n.forEach((i) => i(...t));
354
+ }
355
+ // State management
356
+ getValue() {
357
+ return this.textModel.getText();
358
+ }
359
+ setValue(e) {
360
+ this.textModel.setText(e), this.view.setText(e), this.updateLineNumbers(), this.emit("change", [{ range: this.getFullRange(), text: e, oldText: this.getValue() }]);
361
+ }
362
+ getState() {
363
+ return {
364
+ text: this.getValue(),
365
+ cursor: this.getCursor(),
366
+ selection: this.getSelection(),
367
+ readOnly: this.config.readOnly || !1,
368
+ theme: this.currentTheme
369
+ };
370
+ }
371
+ // Cursor & Selection
372
+ getCursor() {
373
+ const e = this.view.getCursorPosition();
374
+ return {
375
+ position: e,
376
+ anchor: e
377
+ // For now, cursor and anchor are the same
378
+ };
379
+ }
380
+ setCursor(e) {
381
+ this.view.setCursorPosition(e), this.emit("cursor", this.getCursor());
382
+ }
383
+ getSelection() {
384
+ return this.view.getSelectionRange();
385
+ }
386
+ setSelection(e) {
387
+ this.view.setSelectionRange(e), this.emit("selection", e);
388
+ }
389
+ // Configuration
390
+ setTheme(e) {
391
+ this.currentTheme = e;
392
+ const t = {
393
+ "editor-background": e === "dark" ? "#1e1e1e" : "#ffffff",
394
+ "editor-foreground": e === "dark" ? "#f8f9fa" : "#1a1a1a",
395
+ "editor-gutter-background": e === "dark" ? "#252526" : "#f8f9fa",
396
+ "editor-gutter-foreground": e === "dark" ? "#858585" : "#666666",
397
+ "editor-gutter-border": e === "dark" ? "#3e3e42" : "#e1e5e9"
398
+ };
399
+ this.view.applyTheme(t);
400
+ }
401
+ setReadOnly(e) {
402
+ this.config.readOnly = e, this.view.setReadOnly(e);
403
+ }
404
+ // Extensions & Commands
405
+ addExtension(e) {
406
+ if (this.extensions.has(e.name))
407
+ throw new Error(`Extension '${e.name}' already exists`);
408
+ this.extensions.set(e.name, e), e.setup(this);
409
+ }
410
+ removeExtension(e) {
411
+ const t = this.extensions.get(e);
412
+ t && t.destroy && t.destroy(), this.extensions.delete(e);
413
+ }
414
+ executeCommand(e, ...t) {
415
+ const n = this.commands.get(e);
416
+ n ? n(this, ...t) : console.warn(`Command '${e}' not found`);
417
+ }
418
+ // Register a command
419
+ registerCommand(e, t) {
420
+ this.commands.set(e, t);
421
+ }
422
+ // Search & Navigation
423
+ search(e, t = {}) {
424
+ const n = {
425
+ caseSensitive: !1,
426
+ regex: !1,
427
+ ...t
428
+ }, i = [], s = this.getValue();
429
+ s.split(`
430
+ `);
431
+ let o = n.caseSensitive ? s : s.toLowerCase(), h = n.caseSensitive ? e : e.toLowerCase();
432
+ if (n.regex) {
433
+ const r = new RegExp(h, n.caseSensitive ? "g" : "gi");
434
+ let l;
435
+ for (; (l = r.exec(o)) !== null; ) {
436
+ const c = this.textModel.offsetToPosition(l.index), a = this.textModel.offsetToPosition(l.index + l[0].length);
437
+ i.push({
438
+ range: { start: c, end: a },
439
+ match: l[0]
440
+ });
441
+ }
442
+ } else {
443
+ let r = 0, l = o.indexOf(h, r);
444
+ for (; l !== -1; ) {
445
+ const c = l + e.length, a = this.textModel.offsetToPosition(l), u = this.textModel.offsetToPosition(c);
446
+ i.push({
447
+ range: { start: a, end: u },
448
+ match: s.substring(l, c)
449
+ }), r = c, l = o.indexOf(h, r);
450
+ }
451
+ }
452
+ return i;
453
+ }
454
+ replace(e, t) {
455
+ const n = this.textModel.replaceRange(e, t);
456
+ this.view.setText(this.getValue()), this.emit("change", [n]);
457
+ }
458
+ replaceAll(e, t, n = {}) {
459
+ const i = this.search(e, n);
460
+ let s = 0;
461
+ for (let o = i.length - 1; o >= 0; o--)
462
+ this.replace(i[o].range, t), s++;
463
+ return s;
464
+ }
465
+ // Folding (basic implementation)
466
+ fold(e) {
467
+ const t = {
468
+ start: e.start,
469
+ end: e.end,
470
+ collapsed: !0,
471
+ level: 0
472
+ };
473
+ this.folds.push(t);
474
+ }
475
+ unfold(e) {
476
+ this.folds = this.folds.filter(
477
+ (t) => !(t.start.line === e.start.line && t.end.line === e.end.line)
478
+ );
479
+ }
480
+ getFolds() {
481
+ return [...this.folds];
482
+ }
483
+ // Utilities
484
+ focus() {
485
+ this.view.focus();
486
+ }
487
+ blur() {
488
+ this.view.blur();
489
+ }
490
+ destroy() {
491
+ if (!this.isDestroyed) {
492
+ this.isDestroyed = !0;
493
+ for (const e of this.extensions.values())
494
+ e.destroy && e.destroy();
495
+ this.extensions.clear(), this.view.destroy(), this.commands.clear(), this.eventListeners.clear();
496
+ }
497
+ }
498
+ // Events
499
+ on(e, t) {
500
+ this.eventListeners.has(e) || this.eventListeners.set(e, []), this.eventListeners.get(e).push(t);
501
+ }
502
+ off(e, t) {
503
+ if (!this.eventListeners.has(e)) return;
504
+ const n = this.eventListeners.get(e);
505
+ if (t) {
506
+ const i = n.indexOf(t);
507
+ i !== -1 && n.splice(i, 1);
508
+ } else
509
+ n.length = 0;
510
+ }
511
+ }
512
+ class y {
513
+ constructor(e) {
514
+ this.name = "keymap", this.editor = null, this.keymap = {}, this.isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0, this.keymap = e || this.getDefaultKeymap();
515
+ }
516
+ setup(e) {
517
+ this.editor = e, e.on("keydown", (t) => this.handleKeyDown(t));
518
+ }
519
+ handleKeyDown(e) {
520
+ if (!this.editor) return;
521
+ const t = this.findMatchingBinding(e);
522
+ if (t)
523
+ return this.editor.executeCommand(t.command), e.preventDefault(), e.stopPropagation(), !1;
524
+ }
525
+ findMatchingBinding(e) {
526
+ const { key: t, ctrlKey: n, altKey: i, shiftKey: s, metaKey: o } = e, h = t.toLowerCase(), r = this.keymap[h];
527
+ if (!r) return null;
528
+ for (const l of r)
529
+ if ((l.ctrlKey === n || !l.ctrlKey && !n) && (l.altKey === i || !l.altKey && !i) && (l.shiftKey === s || !l.shiftKey && !s) && (l.metaKey === o || !l.metaKey && !o))
530
+ return l;
531
+ return null;
532
+ }
533
+ getDefaultKeymap() {
534
+ const e = {};
535
+ return this.addBinding(e, "f", { ctrlKey: !this.isMac, metaKey: this.isMac }, "find"), this.addBinding(e, "h", { ctrlKey: !this.isMac, metaKey: this.isMac }, "replace"), this.addBinding(e, "f3", {}, "findNext"), this.addBinding(e, "f3", { shiftKey: !0 }, "findPrev"), this.addBinding(e, "g", { ctrlKey: !this.isMac, metaKey: this.isMac }, "findNext"), this.addBinding(e, "[", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "fold"), this.addBinding(e, "]", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "unfold"), this.addBinding(e, "s", { ctrlKey: !this.isMac, metaKey: this.isMac }, "save"), this.addBinding(e, "z", { ctrlKey: !this.isMac, metaKey: this.isMac }, "undo"), this.addBinding(e, "y", { ctrlKey: !this.isMac, metaKey: this.isMac }, "redo"), this.addBinding(e, "z", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "redo"), this.addBinding(e, "t", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "toggleTheme"), e;
536
+ }
537
+ addBinding(e, t, n, i) {
538
+ const s = t.toLowerCase();
539
+ e[s] || (e[s] = []), e[s].push({
540
+ key: s,
541
+ command: i,
542
+ ...n
543
+ });
544
+ }
545
+ // Public API for customizing keymap
546
+ setKeymap(e) {
547
+ this.keymap = { ...e };
548
+ }
549
+ addKeyBinding(e) {
550
+ const t = e.key.toLowerCase();
551
+ this.keymap[t] || (this.keymap[t] = []), this.keymap[t] = this.keymap[t].filter((n) => n.command !== e.command), this.keymap[t].push({
552
+ ...e,
553
+ key: t
554
+ });
555
+ }
556
+ removeKeyBinding(e, t) {
557
+ const n = e.toLowerCase();
558
+ t ? this.keymap[n] && (this.keymap[n] = this.keymap[n].filter((i) => i.command !== t), this.keymap[n].length === 0 && delete this.keymap[n]) : delete this.keymap[n];
559
+ }
560
+ getKeymap() {
561
+ return { ...this.keymap };
562
+ }
563
+ getBindingsForCommand(e) {
564
+ const t = [];
565
+ for (const n in this.keymap)
566
+ for (const i of this.keymap[n])
567
+ i.command === e && t.push({ ...i });
568
+ return t;
569
+ }
570
+ getPlatformInfo() {
571
+ return {
572
+ isMac: this.isMac,
573
+ platform: navigator.platform
574
+ };
575
+ }
576
+ destroy() {
577
+ this.keymap = {}, this.editor = null;
578
+ }
579
+ }
580
+ class b {
581
+ constructor() {
582
+ this.name = "line-numbers", this.editor = null, this.lineNumbersElement = null, this.isEnabled = !0;
583
+ }
584
+ setup(e) {
585
+ this.editor = e, this.createLineNumbers(), e.registerCommand("toggleLineNumbers", () => {
586
+ this.toggle();
587
+ }), e.on("change", () => {
588
+ this.updateLineNumbers();
589
+ }), this.updateLineNumbers();
590
+ }
591
+ createLineNumbers() {
592
+ if (!this.editor) return;
593
+ const e = this.editor.getView();
594
+ if (!e.container) return;
595
+ this.lineNumbersElement = document.createElement("div"), this.lineNumbersElement.style.cssText = `
596
+ position: absolute;
597
+ left: 0;
598
+ top: 0;
599
+ bottom: 0;
600
+ width: 50px;
601
+ background: var(--editor-gutter-background, #252526);
602
+ color: var(--editor-gutter-foreground, #858585);
603
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
604
+ font-size: 14px;
605
+ line-height: 21px;
606
+ padding: 0;
607
+ text-align: right;
608
+ border-right: 1px solid var(--editor-gutter-border, #3e3e42);
609
+ user-select: none;
610
+ overflow: hidden;
611
+ z-index: 1;
612
+ pointer-events: none;
613
+ `;
614
+ const n = e.getContentElement();
615
+ n && n.parentNode && (n.parentNode.insertBefore(this.lineNumbersElement, n), n.style.marginLeft = "60px");
616
+ }
617
+ updateLineNumbers() {
618
+ if (!this.lineNumbersElement || !this.editor || !this.isEnabled) return;
619
+ const e = this.editor.getValue().split(`
620
+ `).length, t = Array.from({ length: Math.max(e, 20) }, (n, i) => i + 1);
621
+ this.lineNumbersElement.innerHTML = t.map((n) => `<div style="height: 21px; line-height: 21px; padding-right: 12px;">${n}</div>`).join("");
622
+ }
623
+ toggle() {
624
+ this.isEnabled = !this.isEnabled, this.lineNumbersElement && (this.lineNumbersElement.style.display = this.isEnabled ? "block" : "none");
625
+ const e = this.editor.getView().getContentElement();
626
+ e && (e.style.marginLeft = this.isEnabled ? "60px" : "0"), this.updateLineNumbers();
627
+ }
628
+ destroy() {
629
+ this.lineNumbersElement && this.lineNumbersElement.parentNode && this.lineNumbersElement.parentNode.removeChild(this.lineNumbersElement), this.lineNumbersElement = null, this.editor = null;
630
+ }
631
+ }
632
+ class v {
633
+ constructor() {
634
+ this.name = "theme", this.editor = null, this.currentTheme = "dark";
635
+ }
636
+ setup(e) {
637
+ this.editor = e, e.registerCommand("setTheme", (t) => {
638
+ this.setTheme(t);
639
+ }), e.registerCommand("toggleTheme", () => {
640
+ this.toggleTheme();
641
+ }), this.setTheme(this.currentTheme);
642
+ }
643
+ setTheme(e) {
644
+ this.editor && (this.currentTheme = e, this.editor.setTheme(e));
645
+ }
646
+ toggleTheme() {
647
+ const e = this.currentTheme === "dark" ? "light" : "dark";
648
+ this.setTheme(e);
649
+ }
650
+ getCurrentTheme() {
651
+ return this.currentTheme;
652
+ }
653
+ destroy() {
654
+ this.editor = null;
655
+ }
656
+ }
657
+ class E {
658
+ constructor() {
659
+ this.name = "read-only", this.editor = null, this.isReadOnly = !1;
660
+ }
661
+ setup(e) {
662
+ this.editor = e, e.registerCommand("setReadOnly", (t) => {
663
+ this.setReadOnly(t);
664
+ }), e.registerCommand("toggleReadOnly", () => {
665
+ this.toggleReadOnly();
666
+ }), e.on("keydown", (t) => {
667
+ if (t.ctrlKey && t.key === "r")
668
+ return t.preventDefault(), this.toggleReadOnly(), !1;
669
+ });
670
+ }
671
+ setReadOnly(e) {
672
+ this.editor && (this.isReadOnly = e, this.editor.setReadOnly(e));
673
+ }
674
+ toggleReadOnly() {
675
+ this.setReadOnly(!this.isReadOnly);
676
+ }
677
+ isCurrentlyReadOnly() {
678
+ return this.isReadOnly;
679
+ }
680
+ destroy() {
681
+ this.editor = null;
682
+ }
683
+ }
684
+ class w {
685
+ constructor() {
686
+ this.name = "search", this.editor = null, this.searchUI = null, this.isVisible = !1, this.currentResults = [], this.currentIndex = -1;
687
+ }
688
+ setup(e) {
689
+ this.editor = e, e.registerCommand("find", () => {
690
+ this.showSearch();
691
+ }), e.registerCommand("findNext", () => {
692
+ this.findNext();
693
+ }), e.registerCommand("findPrev", () => {
694
+ this.findPrev();
695
+ }), e.registerCommand("replace", () => {
696
+ this.showReplace();
697
+ }), e.registerCommand("replaceAll", (t, n) => {
698
+ this.replaceAll(t, n);
699
+ });
700
+ }
701
+ showSearch() {
702
+ if (this.editor && (this.searchUI || this.createSearchUI(), this.isVisible = !0, this.searchUI)) {
703
+ this.searchUI.style.display = "block";
704
+ const e = this.searchUI.querySelector("input");
705
+ e && (e.focus(), e.select());
706
+ }
707
+ }
708
+ showReplace() {
709
+ this.showSearch();
710
+ const e = this.searchUI?.querySelector(".search-replace-input");
711
+ e && (e.style.display = "block", e.focus());
712
+ const t = this.searchUI?.querySelector(".search-status");
713
+ t && (t.textContent = "Replace mode - Enter to replace, Shift+Enter to replace all");
714
+ }
715
+ hideSearch() {
716
+ this.isVisible = !1, this.searchUI && (this.searchUI.style.display = "none"), this.clearHighlights();
717
+ }
718
+ createSearchUI() {
719
+ if (!this.editor) return;
720
+ const e = document.querySelector(".rte-source-editor-modal");
721
+ if (!e) return;
722
+ this.searchUI = document.createElement("div"), this.searchUI.style.cssText = `
723
+ position: absolute;
724
+ top: 10px;
725
+ right: 10px;
726
+ background: var(--editor-background, #1e1e1e);
727
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
728
+ border-radius: 4px;
729
+ padding: 8px;
730
+ z-index: 1000;
731
+ display: none;
732
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
733
+ min-width: 250px;
734
+ `, this.searchUI.innerHTML = `
735
+ <div style="display: flex; align-items: center; gap: 4px; margin-bottom: 4px;">
736
+ <input type="text" placeholder="Find..." style="
737
+ flex: 1;
738
+ padding: 4px 8px;
739
+ background: var(--editor-gutter-background, #252526);
740
+ color: var(--editor-foreground, #f8f9fa);
741
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
742
+ border-radius: 3px;
743
+ font-size: 12px;
744
+ outline: none;
745
+ " />
746
+ <button class="search-prev" style="
747
+ padding: 2px 6px;
748
+ background: var(--editor-gutter-background, #252526);
749
+ color: var(--editor-gutter-foreground, #858585);
750
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
751
+ border-radius: 3px;
752
+ cursor: pointer;
753
+ font-size: 11px;
754
+ ">↑</button>
755
+ <button class="search-next" style="
756
+ padding: 2px 6px;
757
+ background: var(--editor-gutter-background, #252526);
758
+ color: var(--editor-gutter-foreground, #858585);
759
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
760
+ border-radius: 3px;
761
+ cursor: pointer;
762
+ font-size: 11px;
763
+ ">↓</button>
764
+ <button class="search-close" style="
765
+ padding: 2px 6px;
766
+ background: var(--editor-gutter-background, #252526);
767
+ color: var(--editor-gutter-foreground, #858585);
768
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
769
+ border-radius: 3px;
770
+ cursor: pointer;
771
+ font-size: 11px;
772
+ ">×</button>
773
+ </div>
774
+ <div class="search-status" style="
775
+ font-size: 11px;
776
+ color: var(--editor-gutter-foreground, #858585);
777
+ text-align: center;
778
+ "></div>
779
+ <input type="text" class="search-replace-input" placeholder="Replace with..." style="
780
+ width: 100%;
781
+ padding: 4px 8px;
782
+ background: var(--editor-gutter-background, #252526);
783
+ color: var(--editor-foreground, #f8f9fa);
784
+ border: 1px solid var(--editor-gutter-border, #3e3e42);
785
+ border-radius: 3px;
786
+ font-size: 12px;
787
+ outline: none;
788
+ display: none;
789
+ margin-top: 4px;
790
+ " />
791
+ `;
792
+ const t = this.searchUI.querySelector("input"), n = this.searchUI.querySelector(".search-replace-input"), i = this.searchUI.querySelector(".search-prev"), s = this.searchUI.querySelector(".search-next"), o = this.searchUI.querySelector(".search-close");
793
+ t.addEventListener("input", () => {
794
+ this.performSearch(t.value);
795
+ }), t.addEventListener("keydown", (h) => {
796
+ h.key === "Enter" && (h.preventDefault(), h.shiftKey ? this.findPrev() : this.findNext());
797
+ }), n.addEventListener("keydown", (h) => {
798
+ h.key === "Enter" && (h.preventDefault(), h.shiftKey ? this.replaceAll(t.value, n.value) : this.replaceCurrent(t.value, n.value));
799
+ }), i.addEventListener("click", () => this.findPrev()), s.addEventListener("click", () => this.findNext()), o.addEventListener("click", () => this.hideSearch()), e.appendChild(this.searchUI);
800
+ }
801
+ performSearch(e) {
802
+ if (!this.editor || !e.trim()) {
803
+ this.clearHighlights(), this.updateStatus("");
804
+ return;
805
+ }
806
+ const t = this.editor.getValue(), n = [];
807
+ let i = t.toLowerCase().indexOf(e.toLowerCase());
808
+ for (; i !== -1; ) {
809
+ const s = this.getPositionFromOffset(t, i), o = this.getPositionFromOffset(t, i + e.length);
810
+ n.push({
811
+ range: { start: s, end: o },
812
+ match: t.substring(i, i + e.length)
813
+ }), i = t.toLowerCase().indexOf(e.toLowerCase(), i + 1);
814
+ }
815
+ this.currentResults = n, this.currentIndex = this.currentResults.length > 0 ? 0 : -1, this.updateHighlights(), this.updateStatus(`${this.currentResults.length} matches`);
816
+ }
817
+ getPositionFromOffset(e, t) {
818
+ const n = e.substring(0, t).split(`
819
+ `), i = n.length - 1, s = n[n.length - 1].length;
820
+ return { line: i, column: s };
821
+ }
822
+ findNext() {
823
+ this.currentResults.length !== 0 && (this.currentIndex = (this.currentIndex + 1) % this.currentResults.length, this.updateHighlights());
824
+ }
825
+ findPrev() {
826
+ this.currentResults.length !== 0 && (this.currentIndex = this.currentIndex <= 0 ? this.currentResults.length - 1 : this.currentIndex - 1, this.updateHighlights());
827
+ }
828
+ replaceCurrent(e, t) {
829
+ if (!this.editor || !e.trim() || this.currentIndex === -1) return;
830
+ const n = this.currentResults[this.currentIndex];
831
+ if (!n) return;
832
+ const i = this.editor.getValue(), s = this.getOffsetFromPosition(i, n.range.start), o = i.substring(0, s), h = i.substring(s + e.length), r = o + t + h;
833
+ this.editor.setValue(r), this.performSearch(e), this.updateStatus("Replaced current occurrence");
834
+ }
835
+ replaceAll(e, t) {
836
+ if (!this.editor || !e.trim()) return;
837
+ let n = this.editor.getValue(), i = 0, s = n.toLowerCase().indexOf(e.toLowerCase());
838
+ for (; s !== -1; )
839
+ n = n.substring(0, s) + t + n.substring(s + e.length), i++, s = n.toLowerCase().indexOf(e.toLowerCase(), s + t.length);
840
+ i > 0 && (this.editor.setValue(n), this.updateStatus(`Replaced ${i} occurrences`));
841
+ }
842
+ getOffsetFromPosition(e, t) {
843
+ const n = e.split(`
844
+ `);
845
+ let i = 0;
846
+ for (let s = 0; s < t.line; s++)
847
+ i += n[s].length + 1;
848
+ return i += t.column, i;
849
+ }
850
+ updateHighlights() {
851
+ this.clearHighlights(), !(this.currentResults.length === 0 || this.currentIndex === -1) && (this.currentResults[this.currentIndex], this.updateStatus(`${this.currentResults.length} matches (showing ${this.currentIndex + 1}/${this.currentResults.length})`));
852
+ }
853
+ clearHighlights() {
854
+ }
855
+ updateStatus(e) {
856
+ const t = this.searchUI?.querySelector(".search-status");
857
+ t && (t.textContent = e);
858
+ }
859
+ destroy() {
860
+ this.searchUI && this.searchUI.parentNode && this.searchUI.parentNode.removeChild(this.searchUI), this.searchUI = null, this.editor = null;
861
+ }
862
+ }
863
+ class k {
864
+ constructor() {
865
+ this.name = "bracket-matching", this.editor = null, this.bracketPairs = {
866
+ "(": ")",
867
+ "[": "]",
868
+ "{": "}",
869
+ "<": ">"
870
+ }, this.reverseBracketPairs = {
871
+ ")": "(",
872
+ "]": "[",
873
+ "}": "{",
874
+ ">": "<"
875
+ }, this.currentMatch = null;
876
+ }
877
+ setup(e) {
878
+ this.editor = e, e.on("cursor", () => {
879
+ this.updateBracketMatching();
880
+ }), e.on("change", () => {
881
+ this.updateBracketMatching();
882
+ });
883
+ }
884
+ updateBracketMatching() {
885
+ if (!this.editor) return;
886
+ const e = this.editor.getCursor(), t = this.editor.getValue();
887
+ this.clearBracketHighlighting();
888
+ const n = this.getBracketAtPosition(t, e.position);
889
+ if (!n) return;
890
+ const i = this.findMatchingBracket(t, n);
891
+ i && (this.currentMatch = i, this.highlightBrackets(i));
892
+ }
893
+ getBracketAtPosition(e, t) {
894
+ const n = e.split(`
895
+ `);
896
+ if (t.line >= n.length) return null;
897
+ const i = n[t.line];
898
+ if (t.column >= i.length) return null;
899
+ const s = i[t.column];
900
+ return this.bracketPairs[s] || this.reverseBracketPairs[s] ? { char: s, position: t } : null;
901
+ }
902
+ findMatchingBracket(e, t) {
903
+ const n = e.split(`
904
+ `), i = t.position.line, s = t.position.column, o = t.char;
905
+ return this.bracketPairs[o] ? this.findClosingBracket(e, n, i, s, o) : this.reverseBracketPairs[o] ? this.findOpeningBracket(e, n, i, s, o) : null;
906
+ }
907
+ findClosingBracket(e, t, n, i, s) {
908
+ const o = this.bracketPairs[s];
909
+ let h = 0;
910
+ for (let r = n; r < t.length; r++) {
911
+ const l = t[r], c = r === n ? i : 0;
912
+ for (let a = c; a < l.length; a++) {
913
+ const u = l[a];
914
+ if (u === s)
915
+ h++;
916
+ else if (u === o && (h--, h === 0))
917
+ return {
918
+ open: { start: { line: n, column: i }, end: { line: n, column: i + 1 } },
919
+ close: { start: { line: r, column: a }, end: { line: r, column: a + 1 } },
920
+ type: s
921
+ };
922
+ }
923
+ }
924
+ return null;
925
+ }
926
+ findOpeningBracket(e, t, n, i, s) {
927
+ const o = this.reverseBracketPairs[s];
928
+ let h = 0;
929
+ for (let r = n; r >= 0; r--) {
930
+ const l = t[r], c = r === n ? i : l.length - 1;
931
+ for (let a = c; a >= 0; a--) {
932
+ const u = l[a];
933
+ if (u === s)
934
+ h++;
935
+ else if (u === o && (h--, h === 0))
936
+ return {
937
+ open: { start: { line: r, column: a }, end: { line: r, column: a + 1 } },
938
+ close: { start: { line: n, column: i }, end: { line: n, column: i + 1 } },
939
+ type: o
940
+ };
941
+ }
942
+ }
943
+ return null;
944
+ }
945
+ highlightBrackets(e) {
946
+ console.log("Bracket match found:", e);
947
+ }
948
+ clearBracketHighlighting() {
949
+ this.currentMatch = null;
950
+ }
951
+ getCurrentMatch() {
952
+ return this.currentMatch;
953
+ }
954
+ destroy() {
955
+ this.clearBracketHighlighting(), this.editor = null;
956
+ }
957
+ }
958
+ class C {
959
+ constructor() {
960
+ this.name = "code-folding", this.editor = null, this.foldIndicators = [], this.foldingUI = null;
961
+ }
962
+ setup(e) {
963
+ this.editor = e, e.registerCommand("fold", () => {
964
+ console.log("Fold command executed - folding not yet implemented"), this.foldAtCursor();
965
+ }), e.registerCommand("unfold", () => {
966
+ console.log("Unfold command executed - unfolding not yet implemented"), this.unfoldAtCursor();
967
+ }), e.registerCommand("foldAll", () => {
968
+ console.log("Fold all command executed - folding not yet implemented"), this.foldAll();
969
+ }), e.registerCommand("unfoldAll", () => {
970
+ console.log("Unfold all command executed - unfolding not yet implemented"), this.unfoldAll();
971
+ }), e.on("change", () => {
972
+ this.updateFoldIndicators();
973
+ }), this.createFoldingUI(), this.updateFoldIndicators();
974
+ }
975
+ createFoldingUI() {
976
+ if (!this.editor) return;
977
+ const e = document.querySelector(".rte-source-editor-modal");
978
+ e && (this.foldingUI = document.createElement("div"), this.foldingUI.style.cssText = `
979
+ position: absolute;
980
+ left: 40px;
981
+ top: 0;
982
+ bottom: 0;
983
+ width: 20px;
984
+ pointer-events: none;
985
+ z-index: 2;
986
+ `, e.appendChild(this.foldingUI));
987
+ }
988
+ updateFoldIndicators() {
989
+ if (!this.editor || !this.foldingUI) return;
990
+ this.foldingUI.innerHTML = "", this.foldIndicators = [];
991
+ const t = this.editor.getValue().split(`
992
+ `);
993
+ this.findFoldableLines(t).forEach((i) => {
994
+ this.createFoldIndicator(i);
995
+ });
996
+ }
997
+ findFoldableLines(e) {
998
+ const t = [];
999
+ for (let n = 0; n < e.length; n++) {
1000
+ const i = e[n].trim();
1001
+ (i.startsWith("{") || i.startsWith("function") || i.startsWith("class") || i.startsWith("if") || i.includes("=>") || i.startsWith("for") || i.startsWith("while") || i.startsWith("try")) && t.push(n);
1002
+ }
1003
+ return t;
1004
+ }
1005
+ createFoldIndicator(e) {
1006
+ if (!this.foldingUI) return;
1007
+ const t = document.createElement("div");
1008
+ t.style.cssText = `
1009
+ position: absolute;
1010
+ left: 0;
1011
+ top: ${e * 21}px;
1012
+ width: 20px;
1013
+ height: 21px;
1014
+ display: flex;
1015
+ align-items: center;
1016
+ justify-content: center;
1017
+ cursor: pointer;
1018
+ pointer-events: auto;
1019
+ color: var(--editor-gutter-foreground, #858585);
1020
+ font-size: 10px;
1021
+ user-select: none;
1022
+ `, t.innerHTML = "▶", t.title = "Code folding not yet implemented - click shows fold indicators", t.addEventListener("click", () => {
1023
+ console.log(`Fold toggle clicked at line ${e} - implementation pending`);
1024
+ }), this.foldingUI.appendChild(t), this.foldIndicators.push(t);
1025
+ }
1026
+ foldAtCursor() {
1027
+ console.log("foldAtCursor called - implementation pending");
1028
+ }
1029
+ unfoldAtCursor() {
1030
+ console.log("unfoldAtCursor called - implementation pending");
1031
+ }
1032
+ foldAll() {
1033
+ console.log("foldAll called - implementation pending");
1034
+ }
1035
+ unfoldAll() {
1036
+ console.log("unfoldAll called - implementation pending");
1037
+ }
1038
+ destroy() {
1039
+ this.foldingUI && this.foldingUI.parentNode && this.foldingUI.parentNode.removeChild(this.foldingUI), this.foldingUI = null, this.foldIndicators = [], this.editor = null;
1040
+ }
1041
+ }
1042
+ class L {
1043
+ constructor() {
1044
+ this.name = "syntax-highlighting", this.editor = null, this.currentTheme = "dark";
1045
+ }
1046
+ setup(e) {
1047
+ this.editor = e, console.log("SyntaxHighlightingExtension: Isolated extension loaded - ready for use");
1048
+ }
1049
+ // Extension provides methods that can be called by the editor
1050
+ setTheme(e) {
1051
+ this.currentTheme = e, console.log(`SyntaxHighlightingExtension: Theme changed to ${e}`);
1052
+ }
1053
+ // Method to get syntax highlighting colors for a given theme
1054
+ getSyntaxColors() {
1055
+ return this.currentTheme === "dark" ? {
1056
+ tag: "#569cd6",
1057
+ // Blue
1058
+ comment: "#6a9955",
1059
+ // Green
1060
+ attrValue: "#ce9178",
1061
+ // Orange
1062
+ text: "#d4d4d4"
1063
+ // Light gray
1064
+ } : {
1065
+ tag: "#0000ff",
1066
+ // Blue
1067
+ comment: "#008000",
1068
+ // Green
1069
+ attrValue: "#a31515",
1070
+ // Red
1071
+ text: "#000000"
1072
+ // Black
1073
+ };
1074
+ }
1075
+ // Method to parse and highlight HTML content (returns highlighted HTML string)
1076
+ highlightHTML(e) {
1077
+ const t = this.getSyntaxColors();
1078
+ let n = e;
1079
+ return n = n.replace(
1080
+ /(<\/?[\w:-]+(?:\s[^>]*?)?\/?>)/g,
1081
+ `<span style="color: ${t.tag};">$1</span>`
1082
+ ), n = n.replace(
1083
+ /(<!--[\s\S]*?-->)/g,
1084
+ `<span style="color: ${t.comment};">$1</span>`
1085
+ ), n = n.replace(
1086
+ /("[^"]*"|'[^']*')/g,
1087
+ `<span style="color: ${t.attrValue};">$1</span>`
1088
+ ), n;
1089
+ }
1090
+ // Method to check if content contains syntax that should be highlighted
1091
+ shouldHighlight(e) {
1092
+ return /<\/?[\w:-]+|<!--/.test(e);
1093
+ }
1094
+ destroy() {
1095
+ this.editor = null, console.log("SyntaxHighlightingExtension: Extension destroyed");
1096
+ }
1097
+ }
1098
+ function T(d, e) {
1099
+ const t = { ...e };
1100
+ return t.extensions || (t.extensions = []), t.extensions.some((i) => i.name === "keymap") || t.extensions.unshift(new y(t.keymap)), new x(d, t);
1101
+ }
1102
+ export {
1103
+ k as BracketMatchingExtension,
1104
+ C as CodeFoldingExtension,
1105
+ x as EditorCore,
1106
+ y as KeymapExtension,
1107
+ b as LineNumbersExtension,
1108
+ E as ReadOnlyExtension,
1109
+ w as SearchExtension,
1110
+ L as SyntaxHighlightingExtension,
1111
+ m as TextModel,
1112
+ v as ThemeExtension,
1113
+ p as View,
1114
+ T as createEditor,
1115
+ x as default
1116
+ };