@editora/light-code-editor 1.0.2 → 1.0.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/dist/index.es.js CHANGED
@@ -1,10 +1,10 @@
1
- class m {
2
- constructor(e = "") {
3
- this._lines = [], this._version = 0, this.setText(e);
1
+ class k {
2
+ constructor(t = "") {
3
+ this._lines = [], this._version = 0, this.setText(t);
4
4
  }
5
5
  // Get line at index
6
- getLine(e) {
7
- return this._lines[e] || "";
6
+ getLine(t) {
7
+ return this._lines[t] || "";
8
8
  }
9
9
  // Get all lines
10
10
  getLines() {
@@ -20,58 +20,58 @@ class m {
20
20
  `);
21
21
  }
22
22
  // Set entire text content
23
- setText(e) {
24
- this._lines = e.split(`
23
+ setText(t) {
24
+ this._lines = t.split(`
25
25
  `), this._version++;
26
26
  }
27
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(`
28
+ getTextInRange(t) {
29
+ if (t.start.line === t.end.line)
30
+ return this.getLine(t.start.line).substring(t.start.column, t.end.column);
31
+ const e = [];
32
+ e.push(this.getLine(t.start.line).substring(t.start.column));
33
+ for (let s = t.start.line + 1; s < t.end.line; s++)
34
+ e.push(this.getLine(s));
35
+ return t.end.line < this.getLineCount() && e.push(this.getLine(t.end.line).substring(0, t.end.column)), e.join(`
36
36
  `);
37
37
  }
38
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;
39
+ replaceRange(t, e) {
40
+ const s = this.getTextInRange(t);
41
+ if (t.start.line === t.end.line) {
42
+ const i = this.getLine(t.start.line), n = i.substring(0, t.start.column) + e + i.substring(t.end.column);
43
+ this._lines[t.start.line] = n;
44
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(`
45
+ const i = this.getLine(t.start.line), n = this.getLine(t.end.line), o = i.substring(0, t.start.column) + e, h = n.substring(t.end.column), r = e.split(`
46
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);
47
+ r[0] = o + r[0], r[r.length - 1] = r[r.length - 1] + h, this._lines.splice(t.start.line, t.end.line - t.start.line + 1, ...r);
48
48
  }
49
- return this._version++, { range: e, text: t, oldText: n };
49
+ return this._version++, { range: t, text: e, oldText: s };
50
50
  }
51
51
  // Insert text at position
52
- insertText(e, t) {
53
- const n = { start: e, end: e };
54
- return this.replaceRange(n, t);
52
+ insertText(t, e) {
53
+ const s = { start: t, end: t };
54
+ return this.replaceRange(s, e);
55
55
  }
56
56
  // Delete text in range
57
- deleteRange(e) {
58
- return this.replaceRange(e, "");
57
+ deleteRange(t) {
58
+ return this.replaceRange(t, "");
59
59
  }
60
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;
61
+ positionToOffset(t) {
62
+ let e = 0;
63
+ for (let s = 0; s < t.line; s++)
64
+ e += this.getLine(s).length + 1;
65
+ return e += t.column, e;
66
66
  }
67
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;
68
+ offsetToPosition(t) {
69
+ let e = t;
70
+ for (let s = 0; s < this.getLineCount(); s++) {
71
+ const i = this.getLine(s).length;
72
+ if (e <= i)
73
+ return { line: s, column: e };
74
+ e -= i + 1;
75
75
  }
76
76
  return {
77
77
  line: this.getLineCount() - 1,
@@ -79,12 +79,12 @@ class m {
79
79
  };
80
80
  }
81
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);
82
+ isValidPosition(t) {
83
+ return !(t.line < 0 || t.line >= this.getLineCount() || t.column < 0 || t.column > this.getLine(t.line).length);
84
84
  }
85
85
  // Validate range
86
- isValidRange(e) {
87
- return this.isValidPosition(e.start) && this.isValidPosition(e.end);
86
+ isValidRange(t) {
87
+ return this.isValidPosition(t.start) && this.isValidPosition(t.end);
88
88
  }
89
89
  // Get version for change tracking
90
90
  getVersion() {
@@ -92,18 +92,18 @@ class m {
92
92
  }
93
93
  // Clone the model
94
94
  clone() {
95
- const e = new m();
96
- return e._lines = [...this._lines], e._version = this._version, e;
95
+ const t = new k();
96
+ return t._lines = [...this._lines], t._version = this._version, t;
97
97
  }
98
98
  }
99
- class p {
100
- constructor(e) {
101
- this.gutterWidth = 50, this.lineHeight = 21, this.container = e, this.createDOM();
99
+ class P {
100
+ constructor(t) {
101
+ this.gutterWidth = 50, this.lineHeight = 21, this.container = t, this.createDOM();
102
102
  }
103
103
  createDOM() {
104
104
  this.container.innerHTML = "";
105
- const e = document.createElement("div");
106
- e.style.cssText = `
105
+ const t = document.createElement("div");
106
+ this.editorContainer = t, t.style.cssText = `
107
107
  position: relative;
108
108
  display: flex;
109
109
  width: 100%;
@@ -113,29 +113,29 @@ class p {
113
113
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
114
114
  font-size: 14px;
115
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;
116
+ /* make the outer container the single scrollable element so gutter and content scroll together */
117
+ overflow: auto;
118
+ `, this.lineNumbersElement = document.createElement("div"), this.lineNumbersElement.setAttribute("data-editor-gutter", "true"), this.lineNumbersElement.style.cssText = `
119
+ display: table-cell;
120
+ vertical-align: top;
121
121
  width: ${this.gutterWidth}px;
122
122
  background: var(--editor-gutter-background, #252526);
123
123
  color: var(--editor-gutter-foreground, #858585);
124
- padding: 0;
124
+ padding: 0 8px 0 0;
125
125
  text-align: right;
126
126
  border-right: 1px solid var(--editor-gutter-border, #3e3e42);
127
127
  user-select: none;
128
- overflow: hidden;
129
128
  z-index: 1;
130
129
  `, this.contentElement = document.createElement("div"), this.contentElement.style.cssText = `
131
- flex: 1;
132
- padding: 0;
130
+ display: table-cell;
131
+ vertical-align: top;
132
+ padding: 0 12px;
133
133
  background: transparent;
134
134
  border: none;
135
135
  outline: none;
136
136
  white-space: pre;
137
137
  overflow-x: auto;
138
- overflow-y: auto;
138
+ overflow-y: visible;
139
139
  min-height: 400px;
140
140
  font-family: inherit;
141
141
  font-size: inherit;
@@ -143,12 +143,14 @@ class p {
143
143
  color: inherit;
144
144
  tab-size: 2;
145
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);
146
+ `, this.contentElement.contentEditable = "true", this.contentElement.spellcheck = !1;
147
+ const e = document.createElement("div");
148
+ e.setAttribute("data-editora-editor", "true"), e.style.cssText = "display: table; table-layout: fixed; width: 100%; height: 100%;", e.appendChild(this.lineNumbersElement), e.appendChild(this.contentElement), t.appendChild(e), this.container.appendChild(t), this.updateLineNumbers(1);
147
149
  }
148
150
  // 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("");
151
+ updateLineNumbers(t) {
152
+ const e = Math.max(t, 20), s = Array.from({ length: e }, (i, n) => n + 1);
153
+ this.lineNumbersElement.innerHTML = s.map((i) => `<div style="height: ${this.lineHeight}px; line-height: ${this.lineHeight}px; padding-right: 12px;">${i}</div>`).join("");
152
154
  }
153
155
  // Get content element
154
156
  getContentElement() {
@@ -163,73 +165,81 @@ class p {
163
165
  return this.contentElement.textContent || "";
164
166
  }
165
167
  // Set text content
166
- setText(e) {
167
- this.contentElement.textContent = e;
168
- const t = e.split(`
168
+ setText(t) {
169
+ this.contentElement.textContent = t;
170
+ const e = t.split(`
169
171
  `).length;
170
- this.updateLineNumbers(t);
172
+ this.updateLineNumbers(e);
173
+ }
174
+ // Set inner HTML (used for syntax highlighted content)
175
+ setHTML(t) {
176
+ const e = /&lt;|&gt;/.test(t), s = /<span\b/i.test(t), i = /<[^>]+>/.test(t);
177
+ e && s ? this.contentElement.innerHTML = t : i && !e ? this.contentElement.textContent = t : this.contentElement.innerHTML = t;
178
+ const o = (this.contentElement.textContent || "").split(`
179
+ `).length;
180
+ this.updateLineNumbers(o);
171
181
  }
172
182
  // Get cursor position from DOM selection
173
183
  getCursorPosition() {
174
- const e = window.getSelection();
175
- if (!e || e.rangeCount === 0)
184
+ const t = window.getSelection();
185
+ if (!t || t.rangeCount === 0)
176
186
  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(`
187
+ const e = t.getRangeAt(0), s = e.cloneRange();
188
+ s.selectNodeContents(this.contentElement), s.setEnd(e.endContainer, e.endOffset);
189
+ const n = s.toString().split(`
180
190
  `);
181
191
  return {
182
- line: s.length - 1,
183
- column: s[s.length - 1].length
192
+ line: n.length - 1,
193
+ column: n[n.length - 1].length
184
194
  };
185
195
  }
186
196
  // 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);
197
+ setCursorPosition(t) {
198
+ const s = this.getText().split(`
199
+ `), i = Math.min(t.line, s.length - 1), n = Math.min(t.column, s[i]?.length || 0);
190
200
  let o = 0;
191
- for (let g = 0; g < i; g++)
192
- o += n[g].length + 1;
193
- o += s;
201
+ for (let a = 0; a < i; a++)
202
+ o += s[a].length + 1;
203
+ o += n;
194
204
  const h = document.createRange(), r = window.getSelection();
195
- let l = 0, c = null, a = 0;
196
- const u = document.createTreeWalker(
205
+ let l = 0, c = null, d = 0;
206
+ const f = document.createTreeWalker(
197
207
  this.contentElement,
198
208
  NodeFilter.SHOW_TEXT,
199
209
  null
200
210
  );
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;
211
+ let g;
212
+ for (; g = f.nextNode(); ) {
213
+ const a = g.textContent?.length || 0;
214
+ if (l + a >= o) {
215
+ c = g, d = o - l;
206
216
  break;
207
217
  }
208
- l += g;
218
+ l += a;
209
219
  }
210
220
  if (c)
211
221
  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);
222
+ h.setStart(c, d), h.setEnd(c, d), r?.removeAllRanges(), r?.addRange(h);
223
+ } catch (a) {
224
+ console.warn("Could not set cursor position:", a);
215
225
  }
216
226
  }
217
227
  // Get selection range
218
228
  getSelectionRange() {
219
- const e = window.getSelection();
220
- if (!e || e.rangeCount === 0 || e.isCollapsed)
229
+ const t = window.getSelection();
230
+ if (!t || t.rangeCount === 0 || t.isCollapsed)
221
231
  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);
232
+ const e = t.getRangeAt(0), s = e.cloneRange();
233
+ s.selectNodeContents(this.contentElement), s.setEnd(e.startContainer, e.startOffset);
234
+ const n = s.toString().split(`
235
+ `), o = e.cloneRange();
236
+ o.selectNodeContents(this.contentElement), o.setEnd(e.endContainer, e.endOffset);
227
237
  const r = o.toString().split(`
228
238
  `);
229
239
  return {
230
240
  start: {
231
- line: s.length - 1,
232
- column: s[s.length - 1].length
241
+ line: n.length - 1,
242
+ column: n[n.length - 1].length
233
243
  },
234
244
  end: {
235
245
  line: r.length - 1,
@@ -238,8 +248,8 @@ class p {
238
248
  };
239
249
  }
240
250
  // Set selection range
241
- setSelectionRange(e) {
242
- this.setCursorPosition(e.start);
251
+ setSelectionRange(t) {
252
+ this.setCursorPosition(t.start);
243
253
  }
244
254
  // Focus the editor
245
255
  focus() {
@@ -250,44 +260,44 @@ class p {
250
260
  this.contentElement.blur();
251
261
  }
252
262
  // Set read-only mode
253
- setReadOnly(e) {
254
- this.contentElement.contentEditable = e ? "false" : "true";
263
+ setReadOnly(t) {
264
+ this.contentElement.contentEditable = t ? "false" : "true";
255
265
  }
256
266
  // Apply theme
257
- applyTheme(e) {
258
- Object.entries(e).forEach(([t, n]) => {
259
- this.container.style.setProperty(`--${t}`, n);
267
+ applyTheme(t) {
268
+ Object.entries(t).forEach(([e, s]) => {
269
+ this.container.style.setProperty(`--${e}`, s);
260
270
  });
261
271
  }
262
272
  // Scroll to position
263
- scrollToPosition(e) {
264
- const t = this.lineNumbersElement.children[e.line];
265
- t && t.scrollIntoView({ block: "center", behavior: "smooth" });
273
+ scrollToPosition(t) {
274
+ const e = this.lineNumbersElement.children[t.line];
275
+ e && e.scrollIntoView({ block: "center", behavior: "smooth" });
266
276
  }
267
277
  // Get scroll position
268
278
  getScrollTop() {
269
- return this.contentElement.scrollTop;
279
+ return this.editorContainer.scrollTop;
270
280
  }
271
281
  // Set scroll position
272
- setScrollTop(e) {
273
- this.contentElement.scrollTop = e, this.lineNumbersElement.scrollTop = e;
282
+ setScrollTop(t) {
283
+ this.editorContainer.scrollTop = t;
274
284
  }
275
285
  // Destroy the view
276
286
  destroy() {
277
- this.container && this.container.parentNode && this.container.parentNode.removeChild(this.container);
287
+ this.container && this.container.parentNode && this.container.parentNode.removeChild(this.container), this._rafId && (cancelAnimationFrame(this._rafId), this._rafId = void 0);
278
288
  }
279
289
  }
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 = {
290
+ class $ {
291
+ constructor(t, e = {}) {
292
+ this.extensions = /* @__PURE__ */ new Map(), this.commands = /* @__PURE__ */ new Map(), this.eventListeners = /* @__PURE__ */ new Map(), this.folds = [], this.currentTheme = "default", this.isDestroyed = !1, this.undoStack = [], this.redoStack = [], this.suppressHistory = !1, this.expectingProgrammaticCursor = !1, this.config = {
283
293
  value: "",
284
294
  theme: "default",
285
295
  readOnly: !1,
286
296
  tabSize: 2,
287
297
  lineWrapping: !1,
288
298
  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);
299
+ ...e
300
+ }, this.textModel = new k(this.config.value), this.view = new P(t), this.setupEventHandlers(), this.config.extensions && this.config.extensions.forEach((s) => this.addExtension(s)), this.setTheme(this.config.theme), this.view.setReadOnly(this.config.readOnly || !1), this.renderTextWithHighlight(this.textModel.getText()), this.registerBuiltInCommands();
291
301
  }
292
302
  // Public accessors for extensions
293
303
  getTextModel() {
@@ -299,43 +309,96 @@ class x {
299
309
  getConfig() {
300
310
  return { ...this.config };
301
311
  }
312
+ // Register built-in editor commands like undo/redo/insertTab
313
+ registerBuiltInCommands() {
314
+ this.registerCommand("undo", () => this.undo()), this.registerCommand("redo", () => this.redo()), this.registerCommand("insertTab", () => this.insertTab()), this.registerCommand("save", () => {
315
+ this.emit("save");
316
+ });
317
+ }
302
318
  // Get keymap extension if available
303
319
  getKeymapExtension() {
304
320
  return this.extensions.get("keymap");
305
321
  }
306
322
  // Setup DOM event handlers
307
323
  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();
324
+ const t = this.view.getContentElement();
325
+ t.addEventListener("input", () => {
326
+ const e = this.view.getText(), s = this.textModel.getText();
327
+ if (e !== s) {
328
+ if (!this.suppressHistory) {
329
+ const i = this.getCursor().position, n = this.textModel.positionToOffset(i), o = this.getSelection();
330
+ let h, r;
331
+ o && (h = this.textModel.positionToOffset(o.start), r = this.textModel.positionToOffset(o.end)), this.undoStack.push({ text: s, cursorOffset: n, anchorOffset: h, focusOffset: r }), this.undoStack.length > 100 && this.undoStack.shift(), this.redoStack.length = 0;
332
+ }
333
+ this.textModel.setText(e), this.highlightTimeout && clearTimeout(this.highlightTimeout), this.highlightTimeout = setTimeout(() => {
334
+ this.renderTextWithHighlight(this.textModel.getText(), !1), this.highlightTimeout = null;
335
+ }, 300), this.updateLineNumbers(), this.emit("change", [{ range: this.getFullRange(), text: e, oldText: s }]);
336
+ }
337
+ }), t.addEventListener("selectionchange", () => {
338
+ const e = this.getCursor(), s = this.getSelection();
339
+ this.emit("cursor", e), s && this.emit("selection", s);
340
+ }), t.addEventListener("keydown", (e) => {
341
+ if (this.emit("keydown", e), e.key === "Tab") {
342
+ this.config.readOnly || this.insertTab(), e.preventDefault(), e.stopPropagation();
343
+ return;
344
+ }
345
+ if (e.key === "Enter") {
346
+ if (!this.config.readOnly) {
347
+ const s = window.getSelection();
348
+ if (s && s.rangeCount > 0) {
349
+ const i = this.getCursor().position, n = this.textModel.positionToOffset(i), o = this.getSelection();
350
+ let h, r;
351
+ o && (h = this.textModel.positionToOffset(o.start), r = this.textModel.positionToOffset(o.end)), this.suppressHistory || (this.undoStack.push({ text: this.textModel.getText(), cursorOffset: n, anchorOffset: h, focusOffset: r }), this.undoStack.length > 100 && this.undoStack.shift(), this.redoStack.length = 0);
352
+ const l = s.getRangeAt(0);
353
+ l.deleteContents();
354
+ const c = document.createTextNode(`
355
+ `);
356
+ l.insertNode(c), l.setStartAfter(c), l.collapse(!0), s.removeAllRanges(), s.addRange(l);
357
+ const d = this.getCursor().position, f = this.textModel.positionToOffset(d), g = this.getSelection();
358
+ let a, u;
359
+ g && (a = this.textModel.positionToOffset(g.start), u = this.textModel.positionToOffset(g.end));
360
+ const p = this.view.getText();
361
+ this.textModel.setText(p), this.highlightTimeout && clearTimeout(this.highlightTimeout), this.highlightTimeout = setTimeout(() => {
362
+ this.renderTextWithHighlight(this.textModel.getText(), !1), requestAnimationFrame(() => {
363
+ try {
364
+ if (g && (a !== void 0 || u !== void 0)) {
365
+ const m = a !== void 0 ? a : f, M = u !== void 0 ? u : f, y = Math.min(m, M), C = Math.max(m, M), w = this.textModel.offsetToPosition(y), v = this.textModel.offsetToPosition(C);
366
+ this.setSelection({ start: w, end: v });
367
+ } else {
368
+ const m = this.textModel.offsetToPosition(f);
369
+ this.setCursor(m);
370
+ }
371
+ } catch {
372
+ }
373
+ }), this.highlightTimeout = null;
374
+ }, 300), this.updateLineNumbers(), this.emit("change", [{ range: this.getFullRange(), text: this.getValue(), oldText: "" }]);
375
+ }
376
+ }
377
+ e.preventDefault(), e.stopPropagation();
378
+ return;
379
+ }
380
+ for (const s of this.extensions.values())
381
+ if (s.onKeyDown && s.onKeyDown(e) === !1) {
382
+ e.preventDefault(), e.stopPropagation();
320
383
  return;
321
384
  }
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();
385
+ }), t.addEventListener("mousedown", (e) => {
386
+ this.emit("mousedown", e);
387
+ for (const s of this.extensions.values())
388
+ if (s.onMouseDown && s.onMouseDown(e) === !1) {
389
+ e.preventDefault(), e.stopPropagation();
327
390
  return;
328
391
  }
329
- }), e.addEventListener("focus", () => {
392
+ }), t.addEventListener("focus", () => {
330
393
  this.emit("focus");
331
- }), e.addEventListener("blur", () => {
394
+ }), t.addEventListener("blur", () => {
332
395
  this.emit("blur");
333
396
  });
334
397
  }
335
398
  // Update line numbers display
336
399
  updateLineNumbers() {
337
- const e = this.textModel.getLineCount();
338
- this.view.updateLineNumbers(e);
400
+ const t = this.textModel.getLineCount();
401
+ this.view.updateLineNumbers(t);
339
402
  }
340
403
  // Get full range of document
341
404
  getFullRange() {
@@ -348,16 +411,17 @@ class x {
348
411
  };
349
412
  }
350
413
  // Emit events to listeners
351
- emit(e, ...t) {
352
- const n = this.eventListeners.get(e);
353
- n && n.forEach((i) => i(...t));
414
+ emit(t, ...e) {
415
+ const s = this.eventListeners.get(t);
416
+ s && s.forEach((i) => i(...e));
354
417
  }
355
418
  // State management
356
419
  getValue() {
357
420
  return this.textModel.getText();
358
421
  }
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() }]);
422
+ setValue(t) {
423
+ const e = this.textModel.getText();
424
+ this.textModel.setText(t), this.renderTextWithHighlight(t, !1), this.updateLineNumbers(), this.emit("change", [{ range: this.getFullRange(), text: t, oldText: e }]);
361
425
  }
362
426
  getState() {
363
427
  return {
@@ -370,111 +434,124 @@ class x {
370
434
  }
371
435
  // Cursor & Selection
372
436
  getCursor() {
373
- const e = this.view.getCursorPosition();
437
+ const t = this.view.getCursorPosition();
374
438
  return {
375
- position: e,
376
- anchor: e
439
+ position: t,
440
+ anchor: t
377
441
  // For now, cursor and anchor are the same
378
442
  };
379
443
  }
380
- setCursor(e) {
381
- this.view.setCursorPosition(e), this.emit("cursor", this.getCursor());
444
+ setCursor(t) {
445
+ this.view.setCursorPosition(t), this.emit("cursor", this.getCursor());
382
446
  }
383
447
  getSelection() {
384
448
  return this.view.getSelectionRange();
385
449
  }
386
- setSelection(e) {
387
- this.view.setSelectionRange(e), this.emit("selection", e);
450
+ setSelection(t) {
451
+ this.view.setSelectionRange(t), this.emit("selection", t);
388
452
  }
389
453
  // 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"
454
+ setTheme(t) {
455
+ this.currentTheme = t;
456
+ const e = {
457
+ "editor-background": t === "dark" ? "#1e1e1e" : "#ffffff",
458
+ "editor-foreground": t === "dark" ? "#f8f9fa" : "#1a1a1a",
459
+ "editor-gutter-background": t === "dark" ? "#252526" : "#f8f9fa",
460
+ "editor-gutter-foreground": t === "dark" ? "#858585" : "#666666",
461
+ "editor-gutter-border": t === "dark" ? "#3e3e42" : "#e1e5e9"
398
462
  };
399
- this.view.applyTheme(t);
463
+ this.view.applyTheme(e);
464
+ const s = this.extensions.get("syntax-highlighting");
465
+ if (s && typeof s.setTheme == "function")
466
+ try {
467
+ s.setTheme(t === "dark" ? "dark" : "light"), this.renderTextWithHighlight(this.textModel.getText());
468
+ } catch (i) {
469
+ console.warn("Error applying theme to syntax-highlighting extension", i);
470
+ }
400
471
  }
401
- setReadOnly(e) {
402
- this.config.readOnly = e, this.view.setReadOnly(e);
472
+ setReadOnly(t) {
473
+ this.config.readOnly = t, this.view.setReadOnly(t);
403
474
  }
404
475
  // 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);
476
+ addExtension(t) {
477
+ if (this.extensions.has(t.name))
478
+ throw new Error(`Extension '${t.name}' already exists`);
479
+ this.extensions.set(t.name, t), t.setup(this), t.name === "syntax-highlighting" && typeof t.highlightHTML == "function" && this.renderTextWithHighlight(this.textModel.getText());
409
480
  }
410
- removeExtension(e) {
411
- const t = this.extensions.get(e);
412
- t && t.destroy && t.destroy(), this.extensions.delete(e);
481
+ removeExtension(t) {
482
+ const e = this.extensions.get(t);
483
+ e && e.destroy && e.destroy(), this.extensions.delete(t);
413
484
  }
414
- executeCommand(e, ...t) {
415
- const n = this.commands.get(e);
416
- n ? n(this, ...t) : console.warn(`Command '${e}' not found`);
485
+ executeCommand(t, ...e) {
486
+ const s = this.commands.get(t);
487
+ s ? s(this, ...e) : console.warn(`Command '${t}' not found`);
417
488
  }
418
489
  // Register a command
419
- registerCommand(e, t) {
420
- this.commands.set(e, t);
490
+ registerCommand(t, e) {
491
+ this.commands.set(t, e);
421
492
  }
422
493
  // Search & Navigation
423
- search(e, t = {}) {
424
- const n = {
494
+ search(t, e = {}) {
495
+ const s = {
425
496
  caseSensitive: !1,
426
497
  regex: !1,
427
- ...t
428
- }, i = [], s = this.getValue();
429
- s.split(`
498
+ ...e
499
+ }, i = [], n = this.getValue();
500
+ n.split(`
430
501
  `);
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");
502
+ let o = s.caseSensitive ? n : n.toLowerCase(), h = s.caseSensitive ? t : t.toLowerCase();
503
+ if (s.regex) {
504
+ const r = new RegExp(h, s.caseSensitive ? "g" : "gi");
434
505
  let l;
435
506
  for (; (l = r.exec(o)) !== null; ) {
436
- const c = this.textModel.offsetToPosition(l.index), a = this.textModel.offsetToPosition(l.index + l[0].length);
507
+ const c = this.textModel.offsetToPosition(l.index), d = this.textModel.offsetToPosition(l.index + l[0].length);
437
508
  i.push({
438
- range: { start: c, end: a },
509
+ range: { start: c, end: d },
439
510
  match: l[0]
440
511
  });
441
512
  }
442
513
  } else {
443
514
  let r = 0, l = o.indexOf(h, r);
444
515
  for (; l !== -1; ) {
445
- const c = l + e.length, a = this.textModel.offsetToPosition(l), u = this.textModel.offsetToPosition(c);
516
+ const c = l + t.length, d = this.textModel.offsetToPosition(l), f = this.textModel.offsetToPosition(c);
446
517
  i.push({
447
- range: { start: a, end: u },
448
- match: s.substring(l, c)
518
+ range: { start: d, end: f },
519
+ match: n.substring(l, c)
449
520
  }), r = c, l = o.indexOf(h, r);
450
521
  }
451
522
  }
452
523
  return i;
453
524
  }
454
- replace(e, t) {
455
- const n = this.textModel.replaceRange(e, t);
456
- this.view.setText(this.getValue()), this.emit("change", [n]);
525
+ replace(t, e) {
526
+ const s = this.getValue();
527
+ if (!this.suppressHistory) {
528
+ const n = this.getCursor().position, o = this.textModel.positionToOffset(n), h = this.getSelection();
529
+ let r, l;
530
+ h && (r = this.textModel.positionToOffset(h.start), l = this.textModel.positionToOffset(h.end)), this.undoStack.push({ text: s, cursorOffset: o, anchorOffset: r, focusOffset: l }), this.undoStack.length > 100 && this.undoStack.shift(), this.redoStack.length = 0;
531
+ }
532
+ const i = this.textModel.replaceRange(t, e);
533
+ this.renderTextWithHighlight(this.getValue(), !1), this.emit("change", [i]);
457
534
  }
458
- replaceAll(e, t, n = {}) {
459
- const i = this.search(e, n);
460
- let s = 0;
535
+ replaceAll(t, e, s = {}) {
536
+ const i = this.search(t, s);
537
+ let n = 0;
461
538
  for (let o = i.length - 1; o >= 0; o--)
462
- this.replace(i[o].range, t), s++;
463
- return s;
539
+ this.replace(i[o].range, e), n++;
540
+ return n;
464
541
  }
465
542
  // Folding (basic implementation)
466
- fold(e) {
467
- const t = {
468
- start: e.start,
469
- end: e.end,
543
+ fold(t) {
544
+ const e = {
545
+ start: t.start,
546
+ end: t.end,
470
547
  collapsed: !0,
471
548
  level: 0
472
549
  };
473
- this.folds.push(t);
550
+ this.folds.push(e);
474
551
  }
475
- unfold(e) {
552
+ unfold(t) {
476
553
  this.folds = this.folds.filter(
477
- (t) => !(t.start.line === e.start.line && t.end.line === e.end.line)
554
+ (e) => !(e.start.line === t.start.line && e.end.line === t.end.line)
478
555
  );
479
556
  }
480
557
  getFolds() {
@@ -487,85 +564,205 @@ class x {
487
564
  blur() {
488
565
  this.view.blur();
489
566
  }
567
+ // Render text using syntax highlighting extension if available
568
+ // If `restoreSelection` is true (default), the method captures current selection/caret
569
+ // and restores it after updating the DOM. Callers that will explicitly set the caret
570
+ // should pass `false` to avoid stomping programmatic cursor changes.
571
+ renderTextWithHighlight(t, e = !0) {
572
+ const s = this.extensions.get("syntax-highlighting");
573
+ if (s && typeof s.highlightHTML == "function")
574
+ try {
575
+ const i = !e && !this.expectingProgrammaticCursor;
576
+ let n, o, h, r;
577
+ if (e || i) {
578
+ n = this.getSelection();
579
+ const c = this.getCursor().position;
580
+ o = this.textModel.positionToOffset(c), n && (h = this.textModel.positionToOffset(n.start), r = this.textModel.positionToOffset(n.end));
581
+ }
582
+ const l = s.highlightHTML(t);
583
+ typeof this.view.setHighlightHTML == "function" ? this.view.setHighlightHTML(l) : this.view.setHTML(l), (e || i) && requestAnimationFrame(() => {
584
+ try {
585
+ if (n && (h !== void 0 || r !== void 0)) {
586
+ const c = h !== void 0 ? h : o, d = r !== void 0 ? r : o, f = Math.min(c, d), g = Math.max(c, d), a = this.textModel.offsetToPosition(f), u = this.textModel.offsetToPosition(g);
587
+ this.view.setSelectionRange({ start: a, end: u });
588
+ } else if (o !== void 0) {
589
+ const c = this.textModel.offsetToPosition(o);
590
+ this.view.setCursorPosition(c);
591
+ }
592
+ } catch {
593
+ }
594
+ });
595
+ return;
596
+ } catch (i) {
597
+ console.warn("Syntax highlighting failed, falling back to plain text", i);
598
+ }
599
+ this.view.setText(t);
600
+ }
490
601
  destroy() {
491
602
  if (!this.isDestroyed) {
492
603
  this.isDestroyed = !0;
493
- for (const e of this.extensions.values())
494
- e.destroy && e.destroy();
604
+ for (const t of this.extensions.values())
605
+ t.destroy && t.destroy();
495
606
  this.extensions.clear(), this.view.destroy(), this.commands.clear(), this.eventListeners.clear();
496
607
  }
497
608
  }
609
+ // History: undo/redo
610
+ undo() {
611
+ if (this.undoStack.length === 0) return;
612
+ const t = this.undoStack.pop(), e = { text: this.getValue(), cursorOffset: this.textModel.positionToOffset(this.getCursor().position) };
613
+ this.redoStack.push(e);
614
+ try {
615
+ this.suppressHistory = !0, this.expectingProgrammaticCursor = !0;
616
+ let s, i;
617
+ typeof t == "string" ? s = t : (s = t.text, i = t.cursorOffset), this.setValue(s), requestAnimationFrame(() => {
618
+ try {
619
+ if (i != null)
620
+ if (typeof t != "string" && (t.anchorOffset !== void 0 || t.focusOffset !== void 0)) {
621
+ const n = t.anchorOffset !== void 0 ? t.anchorOffset : i, o = t.focusOffset !== void 0 ? t.focusOffset : i, h = Math.min(n, o), r = Math.max(n, o), l = this.textModel.offsetToPosition(h), c = this.textModel.offsetToPosition(r);
622
+ this.setSelection({ start: l, end: c });
623
+ } else {
624
+ const n = this.textModel.offsetToPosition(i);
625
+ this.setCursor(n);
626
+ }
627
+ } catch {
628
+ }
629
+ }), setTimeout(() => {
630
+ this.expectingProgrammaticCursor = !1;
631
+ }, 30);
632
+ } finally {
633
+ this.suppressHistory = !1;
634
+ }
635
+ }
636
+ redo() {
637
+ if (this.redoStack.length === 0) return;
638
+ const t = this.redoStack.pop(), e = { text: this.getValue(), cursorOffset: this.textModel.positionToOffset(this.getCursor().position) };
639
+ this.undoStack.push(e);
640
+ try {
641
+ this.suppressHistory = !0, this.expectingProgrammaticCursor = !0;
642
+ let s, i;
643
+ typeof t == "string" ? s = t : (s = t.text, i = t.cursorOffset), this.setValue(s), requestAnimationFrame(() => {
644
+ try {
645
+ if (i != null)
646
+ if (typeof t != "string" && (t.anchorOffset !== void 0 || t.focusOffset !== void 0)) {
647
+ const n = t.anchorOffset !== void 0 ? t.anchorOffset : i, o = t.focusOffset !== void 0 ? t.focusOffset : i, h = Math.min(n, o), r = Math.max(n, o), l = this.textModel.offsetToPosition(h), c = this.textModel.offsetToPosition(r);
648
+ this.setSelection({ start: l, end: c });
649
+ } else {
650
+ const n = this.textModel.offsetToPosition(i);
651
+ this.setCursor(n);
652
+ }
653
+ } catch {
654
+ }
655
+ }), setTimeout(() => {
656
+ this.expectingProgrammaticCursor = !1;
657
+ }, 30);
658
+ } finally {
659
+ this.suppressHistory = !1;
660
+ }
661
+ }
662
+ // Insert a tab character or spaces at current cursor
663
+ insertTab() {
664
+ if (this.config.readOnly) return;
665
+ const t = this.getCursor().position, e = this.textModel.positionToOffset(t), s = " ".repeat(this.config.tabSize || 2), i = this.textModel.insertText(t, s), n = this.textModel.offsetToPosition(this.textModel.positionToOffset(t) + s.length);
666
+ if (!this.suppressHistory) {
667
+ const o = this.getSelection();
668
+ let h, r;
669
+ o && (h = this.textModel.positionToOffset(o.start), r = this.textModel.positionToOffset(o.end)), this.undoStack.push({ text: this.getValue(), cursorOffset: e, anchorOffset: h, focusOffset: r }), this.redoStack.length = 0;
670
+ }
671
+ this.expectingProgrammaticCursor = !0, this.renderTextWithHighlight(this.getValue(), !1), this.setCursor(n), setTimeout(() => {
672
+ this.expectingProgrammaticCursor = !1;
673
+ }, 20), this.emit("change", [i]);
674
+ }
675
+ // Insert a newline at current cursor position
676
+ insertNewLine() {
677
+ if (this.config.readOnly) return;
678
+ const t = this.getCursor().position, e = this.textModel.positionToOffset(t), s = this.textModel.insertText(t, `
679
+ `), i = this.textModel.offsetToPosition(this.textModel.positionToOffset(t) + 1);
680
+ if (!this.suppressHistory) {
681
+ const n = this.getSelection();
682
+ let o, h;
683
+ n && (o = this.textModel.positionToOffset(n.start), h = this.textModel.positionToOffset(n.end)), this.undoStack.push({ text: this.getValue(), cursorOffset: e, anchorOffset: o, focusOffset: h }), this.redoStack.length = 0;
684
+ }
685
+ this.expectingProgrammaticCursor = !0, this.renderTextWithHighlight(this.getValue(), !1), this.setCursor(i), setTimeout(() => {
686
+ this.expectingProgrammaticCursor = !1;
687
+ }, 20), this.emit("change", [s]);
688
+ }
498
689
  // 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);
690
+ on(t, e) {
691
+ this.eventListeners.has(t) || this.eventListeners.set(t, []), this.eventListeners.get(t).push(e);
692
+ }
693
+ off(t, e) {
694
+ if (!this.eventListeners.has(t)) return;
695
+ const s = this.eventListeners.get(t);
696
+ if (e) {
697
+ const i = s.indexOf(e);
698
+ i !== -1 && s.splice(i, 1);
508
699
  } else
509
- n.length = 0;
700
+ s.length = 0;
510
701
  }
511
702
  }
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();
703
+ class H {
704
+ constructor(t) {
705
+ this.name = "keymap", this.editor = null, this.keymap = {}, this.isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0, this.keymap = t || this.getDefaultKeymap();
515
706
  }
516
- setup(e) {
517
- this.editor = e, e.on("keydown", (t) => this.handleKeyDown(t));
707
+ setup(t) {
708
+ this.editor = t;
518
709
  }
519
- handleKeyDown(e) {
710
+ handleKeyDown(t) {
520
711
  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;
712
+ const e = this.findMatchingBinding(t);
713
+ if (e)
714
+ return this.editor.executeCommand(e.command), t.preventDefault(), t.stopPropagation(), !1;
524
715
  }
525
- findMatchingBinding(e) {
526
- const { key: t, ctrlKey: n, altKey: i, shiftKey: s, metaKey: o } = e, h = t.toLowerCase(), r = this.keymap[h];
716
+ findMatchingBinding(t) {
717
+ const { key: e, ctrlKey: s, altKey: i, shiftKey: n, metaKey: o } = t, h = String(e).toLowerCase(), r = this.keymap[h];
527
718
  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))
719
+ for (const l of r) {
720
+ const c = l.ctrlKey === void 0 || l.ctrlKey === s, d = l.altKey === void 0 || l.altKey === i, f = l.shiftKey === void 0 || l.shiftKey === n, g = l.metaKey === void 0 || l.metaKey === o;
721
+ if (c && d && f && g)
530
722
  return l;
723
+ }
531
724
  return null;
532
725
  }
726
+ // Allow EditorCore to call this directly when checking extension.onKeyDown
727
+ onKeyDown(t) {
728
+ return this.handleKeyDown(t);
729
+ }
533
730
  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;
731
+ const t = {};
732
+ return this.addBinding(t, "f", { ctrlKey: !this.isMac, metaKey: this.isMac }, "find"), this.addBinding(t, "h", { ctrlKey: !this.isMac, metaKey: this.isMac }, "replace"), this.addBinding(t, "f3", {}, "findNext"), this.addBinding(t, "f3", { shiftKey: !0 }, "findPrev"), this.addBinding(t, "g", { ctrlKey: !this.isMac, metaKey: this.isMac }, "findNext"), this.addBinding(t, "[", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "fold"), this.addBinding(t, "]", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "unfold"), this.addBinding(t, "s", { ctrlKey: !0 }, "save"), this.addBinding(t, "s", { metaKey: !0 }, "save"), this.addBinding(t, "z", { ctrlKey: !0 }, "undo"), this.addBinding(t, "z", { metaKey: !0 }, "undo"), this.addBinding(t, "y", { ctrlKey: !0 }, "redo"), this.addBinding(t, "y", { metaKey: !0 }, "redo"), this.addBinding(t, "z", { ctrlKey: !0, shiftKey: !0 }, "redo"), this.addBinding(t, "z", { metaKey: !0, shiftKey: !0 }, "redo"), this.addBinding(t, "tab", {}, "insertTab"), this.addBinding(t, "t", { ctrlKey: !this.isMac, metaKey: this.isMac, shiftKey: !0 }, "toggleTheme"), t;
536
733
  }
537
- addBinding(e, t, n, i) {
538
- const s = t.toLowerCase();
539
- e[s] || (e[s] = []), e[s].push({
540
- key: s,
734
+ addBinding(t, e, s, i) {
735
+ const n = e.toLowerCase();
736
+ t[n] || (t[n] = []), t[n].push({
737
+ key: n,
541
738
  command: i,
542
- ...n
739
+ ...s
543
740
  });
544
741
  }
545
742
  // 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
743
+ setKeymap(t) {
744
+ this.keymap = { ...t };
745
+ }
746
+ addKeyBinding(t) {
747
+ const e = t.key.toLowerCase();
748
+ this.keymap[e] || (this.keymap[e] = []), this.keymap[e] = this.keymap[e].filter((s) => s.command !== t.command), this.keymap[e].push({
749
+ ...t,
750
+ key: e
554
751
  });
555
752
  }
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];
753
+ removeKeyBinding(t, e) {
754
+ const s = t.toLowerCase();
755
+ e ? this.keymap[s] && (this.keymap[s] = this.keymap[s].filter((i) => i.command !== e), this.keymap[s].length === 0 && delete this.keymap[s]) : delete this.keymap[s];
559
756
  }
560
757
  getKeymap() {
561
758
  return { ...this.keymap };
562
759
  }
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;
760
+ getBindingsForCommand(t) {
761
+ const e = [];
762
+ for (const s in this.keymap)
763
+ for (const i of this.keymap[s])
764
+ i.command === t && e.push({ ...i });
765
+ return e;
569
766
  }
570
767
  getPlatformInfo() {
571
768
  return {
@@ -577,75 +774,76 @@ class y {
577
774
  this.keymap = {}, this.editor = null;
578
775
  }
579
776
  }
580
- class b {
777
+ class R {
778
+ constructor() {
779
+ this.name = "transaction", this.transactions = [];
780
+ }
781
+ setup(t) {
782
+ t.on("change", (e) => {
783
+ const s = {
784
+ changes: [e],
785
+ selection: t.getSelection(),
786
+ effects: [],
787
+ annotations: []
788
+ };
789
+ this.transactions.push(s);
790
+ });
791
+ }
792
+ getTransactions() {
793
+ return this.transactions;
794
+ }
795
+ destroy() {
796
+ this.transactions = [];
797
+ }
798
+ }
799
+ class N {
581
800
  constructor() {
582
801
  this.name = "line-numbers", this.editor = null, this.lineNumbersElement = null, this.isEnabled = !0;
583
802
  }
584
- setup(e) {
585
- this.editor = e, this.createLineNumbers(), e.registerCommand("toggleLineNumbers", () => {
803
+ setup(t) {
804
+ this.editor = t, this.createLineNumbers(), t.registerCommand("toggleLineNumbers", () => {
586
805
  this.toggle();
587
- }), e.on("change", () => {
806
+ }), t.on("change", () => {
588
807
  this.updateLineNumbers();
589
808
  }), this.updateLineNumbers();
590
809
  }
591
810
  createLineNumbers() {
592
811
  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");
812
+ const e = this.editor.getView().getLineNumbersElement();
813
+ e && (this.lineNumbersElement = e);
616
814
  }
617
815
  updateLineNumbers() {
618
816
  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("");
817
+ const t = this.editor.getValue().split(`
818
+ `).length, e = Array.from({ length: Math.max(t, 20) }, (s, i) => i + 1);
819
+ this.lineNumbersElement.innerHTML = e.map((s) => `<div style="height: 21px; line-height: 21px; padding-right: 12px;">${s}</div>`).join("");
622
820
  }
623
821
  toggle() {
624
822
  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();
823
+ const t = this.editor.getView().getContentElement();
824
+ t && (t.style.marginLeft = this.isEnabled ? "60px" : "0"), this.updateLineNumbers();
627
825
  }
628
826
  destroy() {
629
- this.lineNumbersElement && this.lineNumbersElement.parentNode && this.lineNumbersElement.parentNode.removeChild(this.lineNumbersElement), this.lineNumbersElement = null, this.editor = null;
827
+ this.lineNumbersElement = null, this.editor = null;
630
828
  }
631
829
  }
632
- class v {
830
+ class K {
633
831
  constructor() {
634
832
  this.name = "theme", this.editor = null, this.currentTheme = "dark";
635
833
  }
636
- setup(e) {
637
- this.editor = e, e.registerCommand("setTheme", (t) => {
638
- this.setTheme(t);
639
- }), e.registerCommand("toggleTheme", () => {
834
+ setup(t) {
835
+ this.editor = t, t.registerCommand("setTheme", (e) => {
836
+ this.setTheme(e);
837
+ }), t.registerCommand("toggleTheme", () => {
640
838
  this.toggleTheme();
641
839
  }), this.setTheme(this.currentTheme);
642
840
  }
643
- setTheme(e) {
644
- this.editor && (this.currentTheme = e, this.editor.setTheme(e));
841
+ setTheme(t) {
842
+ this.editor && (this.currentTheme = t, this.editor.setTheme(t));
645
843
  }
646
844
  toggleTheme() {
647
- const e = this.currentTheme === "dark" ? "light" : "dark";
648
- this.setTheme(e);
845
+ const t = this.currentTheme === "dark" ? "light" : "dark";
846
+ this.setTheme(t);
649
847
  }
650
848
  getCurrentTheme() {
651
849
  return this.currentTheme;
@@ -654,22 +852,22 @@ class v {
654
852
  this.editor = null;
655
853
  }
656
854
  }
657
- class E {
855
+ class B {
658
856
  constructor() {
659
857
  this.name = "read-only", this.editor = null, this.isReadOnly = !1;
660
858
  }
661
- setup(e) {
662
- this.editor = e, e.registerCommand("setReadOnly", (t) => {
663
- this.setReadOnly(t);
664
- }), e.registerCommand("toggleReadOnly", () => {
859
+ setup(t) {
860
+ this.editor = t, t.registerCommand("setReadOnly", (e) => {
861
+ this.setReadOnly(e);
862
+ }), t.registerCommand("toggleReadOnly", () => {
665
863
  this.toggleReadOnly();
666
- }), e.on("keydown", (t) => {
667
- if (t.ctrlKey && t.key === "r")
668
- return t.preventDefault(), this.toggleReadOnly(), !1;
864
+ }), t.on("keydown", (e) => {
865
+ if (e.ctrlKey && e.key === "r")
866
+ return e.preventDefault(), this.toggleReadOnly(), !1;
669
867
  });
670
868
  }
671
- setReadOnly(e) {
672
- this.editor && (this.isReadOnly = e, this.editor.setReadOnly(e));
869
+ setReadOnly(t) {
870
+ this.editor && (this.isReadOnly = t, this.editor.setReadOnly(t));
673
871
  }
674
872
  toggleReadOnly() {
675
873
  this.setReadOnly(!this.isReadOnly);
@@ -681,44 +879,44 @@ class E {
681
879
  this.editor = null;
682
880
  }
683
881
  }
684
- class w {
882
+ class V {
685
883
  constructor() {
686
884
  this.name = "search", this.editor = null, this.searchUI = null, this.isVisible = !1, this.currentResults = [], this.currentIndex = -1;
687
885
  }
688
- setup(e) {
689
- this.editor = e, e.registerCommand("find", () => {
886
+ setup(t) {
887
+ this.editor = t, t.registerCommand("find", () => {
690
888
  this.showSearch();
691
- }), e.registerCommand("findNext", () => {
889
+ }), t.registerCommand("findNext", () => {
692
890
  this.findNext();
693
- }), e.registerCommand("findPrev", () => {
891
+ }), t.registerCommand("findPrev", () => {
694
892
  this.findPrev();
695
- }), e.registerCommand("replace", () => {
893
+ }), t.registerCommand("replace", () => {
696
894
  this.showReplace();
697
- }), e.registerCommand("replaceAll", (t, n) => {
698
- this.replaceAll(t, n);
895
+ }), t.registerCommand("replaceAll", (e, s) => {
896
+ this.replaceAll(e, s);
699
897
  });
700
898
  }
701
899
  showSearch() {
702
900
  if (this.editor && (this.searchUI || this.createSearchUI(), this.isVisible = !0, this.searchUI)) {
703
901
  this.searchUI.style.display = "block";
704
- const e = this.searchUI.querySelector("input");
705
- e && (e.focus(), e.select());
902
+ const t = this.searchUI.querySelector("input");
903
+ t && (t.focus(), t.select());
706
904
  }
707
905
  }
708
906
  showReplace() {
709
907
  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");
908
+ const t = this.searchUI?.querySelector(".search-replace-input");
909
+ t && (t.style.display = "block", t.focus());
910
+ const e = this.searchUI?.querySelector(".search-status");
911
+ e && (e.textContent = "Replace mode - Enter to replace, Shift+Enter to replace all");
714
912
  }
715
913
  hideSearch() {
716
914
  this.isVisible = !1, this.searchUI && (this.searchUI.style.display = "none"), this.clearHighlights();
717
915
  }
718
916
  createSearchUI() {
719
917
  if (!this.editor) return;
720
- const e = document.querySelector(".rte-source-editor-modal");
721
- if (!e) return;
918
+ const t = document.querySelector(".rte-source-editor-modal");
919
+ if (!t) return;
722
920
  this.searchUI = document.createElement("div"), this.searchUI.style.cssText = `
723
921
  position: absolute;
724
922
  top: 10px;
@@ -789,35 +987,35 @@ class w {
789
987
  margin-top: 4px;
790
988
  " />
791
989
  `;
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) => {
990
+ const e = this.searchUI.querySelector("input"), s = this.searchUI.querySelector(".search-replace-input"), i = this.searchUI.querySelector(".search-prev"), n = this.searchUI.querySelector(".search-next"), o = this.searchUI.querySelector(".search-close");
991
+ e.addEventListener("input", () => {
992
+ this.performSearch(e.value);
993
+ }), e.addEventListener("keydown", (h) => {
796
994
  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);
995
+ }), s.addEventListener("keydown", (h) => {
996
+ h.key === "Enter" && (h.preventDefault(), h.shiftKey ? this.replaceAll(e.value, s.value) : this.replaceCurrent(e.value, s.value));
997
+ }), i.addEventListener("click", () => this.findPrev()), n.addEventListener("click", () => this.findNext()), o.addEventListener("click", () => this.hideSearch()), t.appendChild(this.searchUI);
800
998
  }
801
- performSearch(e) {
802
- if (!this.editor || !e.trim()) {
999
+ performSearch(t) {
1000
+ if (!this.editor || !t.trim()) {
803
1001
  this.clearHighlights(), this.updateStatus("");
804
1002
  return;
805
1003
  }
806
- const t = this.editor.getValue(), n = [];
807
- let i = t.toLowerCase().indexOf(e.toLowerCase());
1004
+ const e = this.editor.getValue(), s = [];
1005
+ let i = e.toLowerCase().indexOf(t.toLowerCase());
808
1006
  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);
1007
+ const n = this.getPositionFromOffset(e, i), o = this.getPositionFromOffset(e, i + t.length);
1008
+ s.push({
1009
+ range: { start: n, end: o },
1010
+ match: e.substring(i, i + t.length)
1011
+ }), i = e.toLowerCase().indexOf(t.toLowerCase(), i + 1);
814
1012
  }
815
- this.currentResults = n, this.currentIndex = this.currentResults.length > 0 ? 0 : -1, this.updateHighlights(), this.updateStatus(`${this.currentResults.length} matches`);
1013
+ this.currentResults = s, this.currentIndex = this.currentResults.length > 0 ? 0 : -1, this.updateHighlights(), this.updateStatus(`${this.currentResults.length} matches`);
816
1014
  }
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 };
1015
+ getPositionFromOffset(t, e) {
1016
+ const s = t.substring(0, e).split(`
1017
+ `), i = s.length - 1, n = s[s.length - 1].length;
1018
+ return { line: i, column: n };
821
1019
  }
822
1020
  findNext() {
823
1021
  this.currentResults.length !== 0 && (this.currentIndex = (this.currentIndex + 1) % this.currentResults.length, this.updateHighlights());
@@ -825,42 +1023,42 @@ class w {
825
1023
  findPrev() {
826
1024
  this.currentResults.length !== 0 && (this.currentIndex = this.currentIndex <= 0 ? this.currentResults.length - 1 : this.currentIndex - 1, this.updateHighlights());
827
1025
  }
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(`
1026
+ replaceCurrent(t, e) {
1027
+ if (!this.editor || !t.trim() || this.currentIndex === -1) return;
1028
+ const s = this.currentResults[this.currentIndex];
1029
+ if (!s) return;
1030
+ const i = this.editor.getValue(), n = this.getOffsetFromPosition(i, s.range.start), o = i.substring(0, n), h = i.substring(n + t.length), r = o + e + h;
1031
+ this.editor.setValue(r), this.performSearch(t), this.updateStatus("Replaced current occurrence");
1032
+ }
1033
+ replaceAll(t, e) {
1034
+ if (!this.editor || !t.trim()) return;
1035
+ let s = this.editor.getValue(), i = 0, n = s.toLowerCase().indexOf(t.toLowerCase());
1036
+ for (; n !== -1; )
1037
+ s = s.substring(0, n) + e + s.substring(n + t.length), i++, n = s.toLowerCase().indexOf(t.toLowerCase(), n + e.length);
1038
+ i > 0 && (this.editor.setValue(s), this.updateStatus(`Replaced ${i} occurrences`));
1039
+ }
1040
+ getOffsetFromPosition(t, e) {
1041
+ const s = t.split(`
844
1042
  `);
845
1043
  let i = 0;
846
- for (let s = 0; s < t.line; s++)
847
- i += n[s].length + 1;
848
- return i += t.column, i;
1044
+ for (let n = 0; n < e.line; n++)
1045
+ i += s[n].length + 1;
1046
+ return i += e.column, i;
849
1047
  }
850
1048
  updateHighlights() {
851
1049
  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
1050
  }
853
1051
  clearHighlights() {
854
1052
  }
855
- updateStatus(e) {
856
- const t = this.searchUI?.querySelector(".search-status");
857
- t && (t.textContent = e);
1053
+ updateStatus(t) {
1054
+ const e = this.searchUI?.querySelector(".search-status");
1055
+ e && (e.textContent = t);
858
1056
  }
859
1057
  destroy() {
860
1058
  this.searchUI && this.searchUI.parentNode && this.searchUI.parentNode.removeChild(this.searchUI), this.searchUI = null, this.editor = null;
861
1059
  }
862
1060
  }
863
- class k {
1061
+ class A {
864
1062
  constructor() {
865
1063
  this.name = "bracket-matching", this.editor = null, this.bracketPairs = {
866
1064
  "(": ")",
@@ -874,76 +1072,75 @@ class k {
874
1072
  ">": "<"
875
1073
  }, this.currentMatch = null;
876
1074
  }
877
- setup(e) {
878
- this.editor = e, e.on("cursor", () => {
1075
+ setup(t) {
1076
+ this.editor = t, t.on("cursor", () => {
879
1077
  this.updateBracketMatching();
880
- }), e.on("change", () => {
1078
+ }), t.on("change", () => {
881
1079
  this.updateBracketMatching();
882
1080
  });
883
1081
  }
884
1082
  updateBracketMatching() {
885
1083
  if (!this.editor) return;
886
- const e = this.editor.getCursor(), t = this.editor.getValue();
1084
+ const t = this.editor.getCursor(), e = this.editor.getValue();
887
1085
  this.clearBracketHighlighting();
888
- const n = this.getBracketAtPosition(t, e.position);
889
- if (!n) return;
890
- const i = this.findMatchingBracket(t, n);
1086
+ const s = this.getBracketAtPosition(e, t.position);
1087
+ if (!s) return;
1088
+ const i = this.findMatchingBracket(e, s);
891
1089
  i && (this.currentMatch = i, this.highlightBrackets(i));
892
1090
  }
893
- getBracketAtPosition(e, t) {
894
- const n = e.split(`
1091
+ getBracketAtPosition(t, e) {
1092
+ const s = t.split(`
895
1093
  `);
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];
1094
+ if (e.line >= s.length) return null;
1095
+ const i = s[e.line];
1096
+ if (e.column >= i.length) return null;
1097
+ const n = i[e.column];
1098
+ return this.bracketPairs[n] || this.reverseBracketPairs[n] ? { char: n, position: e } : null;
1099
+ }
1100
+ findMatchingBracket(t, e) {
1101
+ const s = t.split(`
1102
+ `), i = e.position.line, n = e.position.column, o = e.char;
1103
+ return this.bracketPairs[o] ? this.findClosingBracket(t, s, i, n, o) : this.reverseBracketPairs[o] ? this.findOpeningBracket(t, s, i, n, o) : null;
1104
+ }
1105
+ findClosingBracket(t, e, s, i, n) {
1106
+ const o = this.bracketPairs[n];
909
1107
  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)
1108
+ for (let r = s; r < e.length; r++) {
1109
+ const l = e[r], c = r === s ? i : 0;
1110
+ for (let d = c; d < l.length; d++) {
1111
+ const f = l[d];
1112
+ if (f === n)
915
1113
  h++;
916
- else if (u === o && (h--, h === 0))
1114
+ else if (f === o && (h--, h === 0))
917
1115
  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
1116
+ open: { start: { line: s, column: i }, end: { line: s, column: i + 1 } },
1117
+ close: { start: { line: r, column: d }, end: { line: r, column: d + 1 } },
1118
+ type: n
921
1119
  };
922
1120
  }
923
1121
  }
924
1122
  return null;
925
1123
  }
926
- findOpeningBracket(e, t, n, i, s) {
927
- const o = this.reverseBracketPairs[s];
1124
+ findOpeningBracket(t, e, s, i, n) {
1125
+ const o = this.reverseBracketPairs[n];
928
1126
  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)
1127
+ for (let r = s; r >= 0; r--) {
1128
+ const l = e[r], c = r === s ? i : l.length - 1;
1129
+ for (let d = c; d >= 0; d--) {
1130
+ const f = l[d];
1131
+ if (f === n)
934
1132
  h++;
935
- else if (u === o && (h--, h === 0))
1133
+ else if (f === o && (h--, h === 0))
936
1134
  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 } },
1135
+ open: { start: { line: r, column: d }, end: { line: r, column: d + 1 } },
1136
+ close: { start: { line: s, column: i }, end: { line: s, column: i + 1 } },
939
1137
  type: o
940
1138
  };
941
1139
  }
942
1140
  }
943
1141
  return null;
944
1142
  }
945
- highlightBrackets(e) {
946
- console.log("Bracket match found:", e);
1143
+ highlightBrackets(t) {
947
1144
  }
948
1145
  clearBracketHighlighting() {
949
1146
  this.currentMatch = null;
@@ -955,27 +1152,27 @@ class k {
955
1152
  this.clearBracketHighlighting(), this.editor = null;
956
1153
  }
957
1154
  }
958
- class C {
1155
+ class U {
959
1156
  constructor() {
960
1157
  this.name = "code-folding", this.editor = null, this.foldIndicators = [], this.foldingUI = null;
961
1158
  }
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", () => {
1159
+ setup(t) {
1160
+ this.editor = t, t.registerCommand("fold", () => {
1161
+ this.foldAtCursor();
1162
+ }), t.registerCommand("unfold", () => {
1163
+ this.unfoldAtCursor();
1164
+ }), t.registerCommand("foldAll", () => {
1165
+ this.foldAll();
1166
+ }), t.registerCommand("unfoldAll", () => {
1167
+ this.unfoldAll();
1168
+ }), t.on("change", () => {
972
1169
  this.updateFoldIndicators();
973
1170
  }), this.createFoldingUI(), this.updateFoldIndicators();
974
1171
  }
975
1172
  createFoldingUI() {
976
1173
  if (!this.editor) return;
977
- const e = document.querySelector(".rte-source-editor-modal");
978
- e && (this.foldingUI = document.createElement("div"), this.foldingUI.style.cssText = `
1174
+ const t = document.querySelector(".rte-source-editor-modal");
1175
+ t && (this.foldingUI = document.createElement("div"), this.foldingUI.style.cssText = `
979
1176
  position: absolute;
980
1177
  left: 40px;
981
1178
  top: 0;
@@ -983,32 +1180,32 @@ class C {
983
1180
  width: 20px;
984
1181
  pointer-events: none;
985
1182
  z-index: 2;
986
- `, e.appendChild(this.foldingUI));
1183
+ `, t.appendChild(this.foldingUI));
987
1184
  }
988
1185
  updateFoldIndicators() {
989
1186
  if (!this.editor || !this.foldingUI) return;
990
1187
  this.foldingUI.innerHTML = "", this.foldIndicators = [];
991
- const t = this.editor.getValue().split(`
1188
+ const e = this.editor.getValue().split(`
992
1189
  `);
993
- this.findFoldableLines(t).forEach((i) => {
1190
+ this.findFoldableLines(e).forEach((i) => {
994
1191
  this.createFoldIndicator(i);
995
1192
  });
996
1193
  }
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);
1194
+ findFoldableLines(t) {
1195
+ const e = [];
1196
+ for (let s = 0; s < t.length; s++) {
1197
+ const i = t[s].trim();
1198
+ (i.startsWith("{") || i.startsWith("function") || i.startsWith("class") || i.startsWith("if") || i.includes("=>") || i.startsWith("for") || i.startsWith("while") || i.startsWith("try")) && e.push(s);
1002
1199
  }
1003
- return t;
1200
+ return e;
1004
1201
  }
1005
- createFoldIndicator(e) {
1202
+ createFoldIndicator(t) {
1006
1203
  if (!this.foldingUI) return;
1007
- const t = document.createElement("div");
1008
- t.style.cssText = `
1204
+ const e = document.createElement("div");
1205
+ e.style.cssText = `
1009
1206
  position: absolute;
1010
1207
  left: 0;
1011
- top: ${e * 21}px;
1208
+ top: ${t * 21}px;
1012
1209
  width: 20px;
1013
1210
  height: 21px;
1014
1211
  display: flex;
@@ -1019,36 +1216,37 @@ class C {
1019
1216
  color: var(--editor-gutter-foreground, #858585);
1020
1217
  font-size: 10px;
1021
1218
  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);
1219
+ `, e.innerHTML = "▶", e.title = "Code folding not yet implemented - click shows fold indicators", e.addEventListener("click", () => {
1220
+ }), this.foldingUI.appendChild(e), this.foldIndicators.push(e);
1025
1221
  }
1026
1222
  foldAtCursor() {
1027
- console.log("foldAtCursor called - implementation pending");
1028
1223
  }
1029
1224
  unfoldAtCursor() {
1030
- console.log("unfoldAtCursor called - implementation pending");
1031
1225
  }
1032
1226
  foldAll() {
1033
- console.log("foldAll called - implementation pending");
1034
1227
  }
1035
1228
  unfoldAll() {
1036
- console.log("unfoldAll called - implementation pending");
1037
1229
  }
1038
1230
  destroy() {
1039
1231
  this.foldingUI && this.foldingUI.parentNode && this.foldingUI.parentNode.removeChild(this.foldingUI), this.foldingUI = null, this.foldIndicators = [], this.editor = null;
1040
1232
  }
1041
1233
  }
1042
- class L {
1234
+ class F {
1043
1235
  constructor() {
1044
- this.name = "syntax-highlighting", this.editor = null, this.currentTheme = "dark";
1236
+ this.name = "syntax-highlighting", this.editor = null, this.currentTheme = "dark", this.currentLanguage = null, this.modes = /* @__PURE__ */ new Map();
1045
1237
  }
1046
- setup(e) {
1047
- this.editor = e, console.log("SyntaxHighlightingExtension: Isolated extension loaded - ready for use");
1238
+ setup(t) {
1239
+ this.editor = t, this.registerMode("html", { name: "html", highlight: (e, s) => this._highlightHTML(e, s) }), this.registerMode("javascript", { name: "javascript", highlight: (e, s) => this._highlightJS(e, s) }), this.registerMode("typescript", { name: "typescript", highlight: (e, s) => this._highlightJS(e, s) }), this.registerMode("php", { name: "php", highlight: (e, s) => this._highlightPHP(e, s) });
1048
1240
  }
1049
1241
  // Extension provides methods that can be called by the editor
1050
- setTheme(e) {
1051
- this.currentTheme = e, console.log(`SyntaxHighlightingExtension: Theme changed to ${e}`);
1242
+ setTheme(t) {
1243
+ this.currentTheme = t;
1244
+ }
1245
+ setLanguage(t) {
1246
+ this.currentLanguage = t;
1247
+ }
1248
+ registerMode(t, e) {
1249
+ this.modes.set(t.toLowerCase(), e);
1052
1250
  }
1053
1251
  // Method to get syntax highlighting colors for a given theme
1054
1252
  getSyntaxColors() {
@@ -1057,60 +1255,204 @@ class L {
1057
1255
  // Blue
1058
1256
  comment: "#6a9955",
1059
1257
  // Green
1258
+ attrName: "#9cdcfe",
1259
+ // Light blue for attribute names
1060
1260
  attrValue: "#ce9178",
1061
- // Orange
1062
- text: "#d4d4d4"
1063
- // Light gray
1261
+ // Orange for attribute values
1262
+ styleProp: "#c586c0",
1263
+ // Purple for CSS property names
1264
+ styleVal: "#dcdcaa",
1265
+ // Yellow-ish for CSS values
1266
+ doctype: "#808080",
1267
+ // Gray for doctype
1268
+ text: "#d4d4d4",
1269
+ // Light gray for normal text
1270
+ keyword: "#c586c0",
1271
+ // JS/PHP keywords (purple)
1272
+ string: "#ce9178",
1273
+ // JS strings
1274
+ number: "#b5cea8",
1275
+ // numbers
1276
+ variable: "#9cdcfe"
1277
+ // php variable color
1064
1278
  } : {
1065
1279
  tag: "#0000ff",
1066
1280
  // Blue
1067
1281
  comment: "#008000",
1068
1282
  // Green
1283
+ attrName: "#001080",
1069
1284
  attrValue: "#a31515",
1070
1285
  // Red
1071
- text: "#000000"
1286
+ styleProp: "#6a00a8",
1287
+ styleVal: "#804000",
1288
+ doctype: "#444444",
1289
+ text: "#000000",
1072
1290
  // Black
1291
+ keyword: "#000080",
1292
+ string: "#a31515",
1293
+ number: "#0086b3",
1294
+ variable: "#001080"
1073
1295
  };
1074
1296
  }
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;
1297
+ // Public API: highlight a source string using the chosen mode (or detect html)
1298
+ highlight(t, e) {
1299
+ const s = this.getSyntaxColors(), i = (e || this.currentLanguage || "html").toLowerCase();
1300
+ return (this.modes.get(i) || this.modes.get("html")).highlight(t, s);
1301
+ }
1302
+ // Backwards-compatible method
1303
+ highlightHTML(t) {
1304
+ return this.highlight(t, "html");
1305
+ }
1306
+ // --- Internal mode implementations ---
1307
+ escapeHTML(t) {
1308
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;").replace(/'/g, "&#39;");
1309
+ }
1310
+ // Robustly unescape common HTML entities, repeating a few times to handle nested encoding like &amp;amp;...
1311
+ unescapeEntitiesRepeated(t) {
1312
+ let e = t || "";
1313
+ for (let s = 0; s < 5; s++) {
1314
+ const i = e;
1315
+ if (e = e.replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'"), e === i) break;
1316
+ }
1317
+ return e;
1318
+ }
1319
+ _highlightHTML(t, e) {
1320
+ const s = e, i = (l) => this.escapeHTML(l);
1321
+ let n = i(t);
1322
+ const o = (l) => {
1323
+ let c = l.replace(/&quot;/g, '"').replace(/&#39;/g, "'");
1324
+ return c = c.replace(/(\/\*[\s\S]*?\*\/)/g, `<span style="color: ${s.comment};">$1</span>`), c = c.replace(/([a-zA-Z-]+)(\s*:\s*)([^;{]+)(;?)/g, (d, f, g, a, u) => {
1325
+ const p = String(a).trim(), m = i(p);
1326
+ return `<span style="color: ${s.styleProp};">${f}</span>${g}<span style="color: ${s.styleVal};">${m}</span>${u}`;
1327
+ }), c;
1328
+ }, h = [];
1329
+ try {
1330
+ t.replace(/<script\b([^>]*)>([\s\S]*?)<\/script>/gi, (l, c, d) => (h.push({ attrs: String(c || ""), inner: String(d || "") }), l));
1331
+ } catch {
1332
+ }
1333
+ let r = 0;
1334
+ return n = n.replace(/(&lt;script\b([^&>]*)&gt;)([\s\S]*?)(&lt;\/script&gt;)/gi, (l, c, d, f, g) => {
1335
+ const a = h[r++]?.inner ?? this.unescapeEntitiesRepeated(f || "");
1336
+ (h[r - 1]?.attrs || d || "").toLowerCase();
1337
+ const u = this._highlightJS(a, s);
1338
+ return `${c}${u}${g}`;
1339
+ }), n = n.replace(/(&lt;style\b[^&]*&gt;)([\s\S]*?)(&lt;\/style&gt;)/gi, (l, c, d, f) => {
1340
+ const g = o(d);
1341
+ return `${c}${g}${f}`;
1342
+ }), n = n.replace(/(&lt;!--[\s\S]*?--&gt;)/g, `<span style="color: ${s.comment};">$1</span>`), n = n.replace(/(&lt;!DOCTYPE[\s\S]*?&gt;)/i, `<span style="color: ${s.doctype};">$1</span>`), n = n.replace(/(&lt;\/?\s*)([^\s&>\/]+)([\s\S]*?)(\/?&gt;)/g, (l, c, d, f, g) => {
1343
+ const a = `<span style="color: ${s.tag};">${d}</span>`;
1344
+ let u = f;
1345
+ return u = u.replace(/([\w:-]+)(\s*=\s*)((&quot;[\s\S]*?&quot;|&#39;[\s\S]*?&#39;|[^\s&>]+))/g, (p, m, M, y) => {
1346
+ const C = String(m).toLowerCase(), w = `<span style="color: ${s.attrName};">${m}</span>`;
1347
+ let v = y, T = "";
1348
+ y.startsWith("&quot;") && y.endsWith("&quot;") ? (v = y.slice(6, -6), T = "&quot;") : y.startsWith("&#39;") && y.endsWith("&#39;") && (v = y.slice(5, -5), T = "&#39;");
1349
+ let b = y;
1350
+ if (C === "style") {
1351
+ const L = v.replace(/([\w-]+)\s*:\s*([^;]+)(;?)/g, (I, S, O, E) => `<span style="color: ${s.styleProp};">${S}</span>:<span style="color: ${s.styleVal};">${O.trim()}</span>${E}`);
1352
+ T ? b = `${T}${L}${T}` : b = L, b = `<span style="color: ${s.attrValue};">${b}</span>`;
1353
+ } else
1354
+ T && (b = `${T}${v}${T}`), b = `<span style="color: ${s.attrValue};">${b}</span>`;
1355
+ return `${w}${M}${b}`;
1356
+ }), `${c}${a}${u}${g}`;
1357
+ }), n;
1358
+ }
1359
+ _highlightJS(t, e) {
1360
+ const s = this.unescapeEntitiesRepeated(t);
1361
+ this.escapeHTML(s);
1362
+ const i = [], n = (g) => {
1363
+ let a = "", u = g;
1364
+ do
1365
+ a = String.fromCharCode(97 + u % 26) + a, u = Math.floor(u / 26) - 1;
1366
+ while (u >= 0);
1367
+ return a || "a";
1368
+ }, o = (g) => `\0${n(g)}\0`, h = (g) => {
1369
+ const a = i.length;
1370
+ return i.push(g), o(a);
1371
+ };
1372
+ let r;
1373
+ const l = /(\/\*[\s\S]*?\*\/)|(\/\/[^\n\r]*)|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`)/g;
1374
+ let c = 0, d = "";
1375
+ for (; r = l.exec(s); ) {
1376
+ const g = r.index;
1377
+ c < g && (d += this.escapeHTML(s.slice(c, g)));
1378
+ const a = r[0];
1379
+ /^\/\*/.test(a) || /^\/\//.test(a) ? d += h(`<span style="color: ${e.comment};">${this.escapeHTML(a)}</span>`) : d += h(`<span style="color: ${e.string};">${this.escapeHTML(a)}</span>`), c = l.lastIndex;
1380
+ }
1381
+ return c < s.length && (d += this.escapeHTML(s.slice(c))), d = d.replace(/\b(0x[0-9a-fA-F]+|\d+\.?\d*|\d*\.\d+)\b/g, (g, a, u) => {
1382
+ const p = d[u - 1] || "", m = d[u + g.length] || "";
1383
+ return p === "&" || p === "#" || m === ";" || m === "#" ? g : `<span style="color: ${e.number};">${g}</span>`;
1384
+ }), d = d.replace(/\b(const|let|var|function|class|if|else|return|for|while|switch|case|break|import|from|export|extends|new|try|catch|finally|throw|await|async|interface|type)\b/g, `<span style="color: ${e.keyword};">$1</span>`), d.replace(/\u0000([a-z]+)\u0000/g, (g, a) => {
1385
+ let u = 0;
1386
+ for (let p = 0; p < a.length; p++)
1387
+ u = u * 26 + (a.charCodeAt(p) - 97 + 1);
1388
+ return u = u - 1, i[u] || "";
1389
+ });
1390
+ }
1391
+ _highlightPHP(t, e) {
1392
+ const s = this.unescapeEntitiesRepeated(t);
1393
+ let i = this.escapeHTML(s);
1394
+ const n = [], o = (a) => {
1395
+ let u = "", p = a;
1396
+ do
1397
+ u = String.fromCharCode(97 + p % 26) + u, p = Math.floor(p / 26) - 1;
1398
+ while (p >= 0);
1399
+ return u || "a";
1400
+ }, h = (a) => {
1401
+ const u = n.length;
1402
+ return n.push(a), `\0${o(u)}\0`;
1403
+ }, r = (a, u) => {
1404
+ const p = i.indexOf(a);
1405
+ return p === -1 ? !1 : (i = i.slice(0, p) + u + i.slice(p + a.length), !0);
1406
+ };
1407
+ let l;
1408
+ const c = /\/\*[\s\S]*?\*\//g, d = /\/\/[^\n\r]*/g, f = /\#([^\n\r]*)/g, g = /("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*')/g;
1409
+ for (; l = c.exec(s); ) {
1410
+ const a = l[0];
1411
+ r(this.escapeHTML(a), h(`<span style="color: ${e.comment};">${this.escapeHTML(a)}</span>`));
1412
+ }
1413
+ for (; l = d.exec(s); ) {
1414
+ const a = l[0];
1415
+ r(this.escapeHTML(a), h(`<span style="color: ${e.comment};">${this.escapeHTML(a)}</span>`));
1416
+ }
1417
+ for (; l = f.exec(s); ) {
1418
+ const a = l[0];
1419
+ r(this.escapeHTML(a), h(`<span style="color: ${e.comment};">${this.escapeHTML(a)}</span>`));
1420
+ }
1421
+ for (; l = g.exec(s); ) {
1422
+ const a = l[0];
1423
+ r(this.escapeHTML(a), h(`<span style="color: ${e.string};">${this.escapeHTML(a)}</span>`));
1424
+ }
1425
+ return i = i.replace(/(\$[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/g, `<span style="color: ${e.variable};">$1</span>`), i = i.replace(/\b(echo|print|function|class|if|else|elseif|foreach|as|return|namespace|use|new|extends|public|protected|private|static)\b/g, `<span style="color: ${e.keyword};">$1</span>`), i = i.replace(/\u0000([a-z]+)\u0000/g, (a, u) => {
1426
+ let p = 0;
1427
+ for (let m = 0; m < u.length; m++)
1428
+ p = p * 26 + (u.charCodeAt(m) - 97 + 1);
1429
+ return p = p - 1, n[p] || "";
1430
+ }), i;
1089
1431
  }
1090
1432
  // Method to check if content contains syntax that should be highlighted
1091
- shouldHighlight(e) {
1092
- return /<\/?[\w:-]+|<!--/.test(e);
1433
+ shouldHighlight(t) {
1434
+ return /<\/?[\w:-]+|<!--/.test(t);
1093
1435
  }
1094
1436
  destroy() {
1095
- this.editor = null, console.log("SyntaxHighlightingExtension: Extension destroyed");
1437
+ this.editor = null, this.modes.clear();
1096
1438
  }
1097
1439
  }
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);
1440
+ function _(x, t) {
1441
+ const e = { ...t };
1442
+ return e.extensions || (e.extensions = []), e.extensions.some((n) => n.name === "keymap") || e.extensions.unshift(new H(e.keymap)), e.extensions.some((n) => n.name === "transaction") || e.extensions.unshift(new R()), new $(x, e);
1101
1443
  }
1102
1444
  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
1445
+ A as BracketMatchingExtension,
1446
+ U as CodeFoldingExtension,
1447
+ $ as EditorCore,
1448
+ H as KeymapExtension,
1449
+ N as LineNumbersExtension,
1450
+ B as ReadOnlyExtension,
1451
+ V as SearchExtension,
1452
+ F as SyntaxHighlightingExtension,
1453
+ k as TextModel,
1454
+ K as ThemeExtension,
1455
+ P as View,
1456
+ _ as createEditor,
1457
+ $ as default
1116
1458
  };