@pfmcodes/caret 0.2.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,12 +29,14 @@ A lightweight, feature-rich code editor with real-time syntax highlighting and c
29
29
  - [Customization](#customization)
30
30
  - [Contributing](#contributing)
31
31
  - [License](#license)
32
- - [Performance Notes](#performance-notes)
32
+ - [Perfomance Notes](#performance-notes)
33
33
 
34
34
  ## What's-New?
35
35
 
36
- ### The editor has been optimized like crazy, the editor used to lag at 500 lines not it does not lag until 10k+ lines(x20 performance increase)
37
- ### for more info about the performance check out [this.](#performance-notes)
36
+ - Multiple editor instances support
37
+ - Word-aware line wrapping
38
+ - Fixed language re-registration bug
39
+ - Known issue: custom caret may be 1 character off on original lines of a wrapped line
38
40
 
39
41
  ## Installation
40
42
 
@@ -91,7 +93,7 @@ pnpm add @pfmcodes/caret
91
93
  ### ES Module Import
92
94
 
93
95
  ```javascript
94
- import editor from '@pfmcodes/caret';
96
+ import editor from './node_modules/@pfmcodes/caret/esm/index.js';
95
97
 
96
98
  // Create editor instance
97
99
  const editorInstance = await editor.editor.createEditor(
@@ -123,7 +125,7 @@ caret/
123
125
  ### JavaScript Editor
124
126
 
125
127
  ```javascript
126
- import editor from '@pfmcodes/caret'; // auto link to commonjs version
128
+ import editor from './node_modules/@pfmcodes/caret/esm/index.js'; // auto link to commonjs version
127
129
 
128
130
  const jsEditor = await editor.editor.createEditor(
129
131
  document.getElementById('js-editor'),
@@ -142,7 +144,7 @@ console.log(greet('World'));`,
142
144
  ### Python Editor
143
145
 
144
146
  ```javascript
145
- const pyEditor = await editor.createEditor(
147
+ const pyEditor = await editor.editor.createEditor(
146
148
  document.getElementById('py-editor'),
147
149
  {
148
150
  value: `def fibonacci(n):
@@ -160,7 +162,7 @@ print([fibonacci(i) for i in range(10)])`,
160
162
  ### Empty Editor (Start from Scratch)
161
163
 
162
164
  ```javascript
163
- const emptyEditor = await editor.createEditor(
165
+ const emptyEditor = await editor.editor.createEditor(
164
166
  document.getElementById('empty-editor'),
165
167
  {
166
168
  value: '',
@@ -215,19 +217,19 @@ Caret supports all languages available in Highlight.js:
215
217
 
216
218
  ```javascript
217
219
  // JavaScript
218
- await editor.createEditor(el, { language: 'javascript', ... });
220
+ await editor.editor.createEditor(el, { language: 'javascript', ... });
219
221
 
220
222
  // Python
221
- await editor.createEditor(el, { language: 'python', ... });
223
+ await editor.editor.createEditor(el, { language: 'python', ... });
222
224
 
223
225
  // TypeScript
224
- await editor.createEditor(el, { language: 'typescript', ... });
226
+ await editor.editor.createEditor(el, { language: 'typescript', ... });
225
227
 
226
228
  // HTML
227
- await editor.createEditor(el, { language: 'html', ... });
229
+ await editor.editor.createEditor(el, { language: 'html', ... });
228
230
 
229
231
  // CSS
230
- await editor.createEditor(el, { language: 'css', ... });
232
+ await editor.editor.createEditor(el, { language: 'css', ... });
231
233
 
232
234
  // And many more...
233
235
  ```
@@ -235,7 +237,7 @@ await editor.createEditor(el, { language: 'css', ... });
235
237
  ### Dynamic Language Switching
236
238
 
237
239
  ```javascript
238
- const editorInstance = await editor.createEditor(el, {
240
+ const editorInstance = await editor.editor.createEditor(el, {
239
241
  value: 'console.log("Hello");',
240
242
  language: 'javascript',
241
243
  theme: 'hybrid'
@@ -257,7 +259,7 @@ The editor automatically:
257
259
  ### Configuration Options
258
260
 
259
261
  ```javascript
260
- const editorInstance = await editor.createEditor(
262
+ const editorInstance = await editor.editor.createEditor(
261
263
  containerElement,
262
264
  {
263
265
  // Initial code content
@@ -352,7 +354,7 @@ Here's a complete working example:
352
354
  <meta charset="UTF-8">
353
355
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
354
356
  <title>Caret Demo</title>
355
- <link rel="stylesheet" href="./node_modules/caret/index.css">
357
+ <link rel="stylesheet" href="./index.css">
356
358
  <style>
357
359
  body {
358
360
  font-family: system-ui, -apple-system, sans-serif;
@@ -393,21 +395,22 @@ Here's a complete working example:
393
395
  <h1 style="text-align: center;">Caret Demo</h1>
394
396
 
395
397
  <div class="controls">
396
- <button onclick="changeLanguage('javascript')">JavaScript</button>
397
- <button onclick="changeLanguage('python')">Python</button>
398
- <button onclick="changeLanguage('html')">HTML</button>
399
- <button onclick="changeTheme('monokai')">Monokai</button>
400
- <button onclick="changeTheme('github')">GitHub</button>
401
- <button onclick="getCode()">Get Code</button>
398
+ <button onclick="window.changeLanguage('javascript')">JavaScript</button>
399
+ <button onclick="window.changeLanguage('python')">Python</button>
400
+ <button onclick="window.changeLanguage('html')">HTML</button>
401
+ <button onclick="window.changeTheme('monokai')">Monokai</button>
402
+ <button onclick="window.changeTheme('github-dark')">GitHub</button>
403
+ <button onclick="window.changeTheme('atom-one-dark')">Atom One Dark</button>
404
+ <button onclick="window.getCode()">Get Code</button>
402
405
  </div>
403
406
 
404
407
  <div id="editor"></div>
405
408
 
406
409
  <script type="module">
407
- import editor from './node_modules/caret/esm/index.js';
410
+ import editor from './node_modules/@pfmcodes/caret/esm/index.js';
408
411
 
409
412
  // Initialize editor
410
- const editorInstance = await editor.createEditor(
413
+ const editorInstance = await editor.editor.createEditor(
411
414
  document.getElementById('editor'),
412
415
  {
413
416
  value: `// Welcome to Caret!
@@ -421,7 +424,7 @@ for (let i = 0; i < 10; i++) {
421
424
  console.log(\`F(\${i}) = \${fibonacci(i)}\`);
422
425
  }`,
423
426
  language: 'javascript',
424
- theme: 'atom-one-dark'
427
+ theme: 'tokyo-night-dark'
425
428
  }
426
429
  );
427
430
 
@@ -433,20 +436,7 @@ for (let i = 0; i < 10; i++) {
433
436
  };
434
437
 
435
438
  window.changeTheme = (theme) => {
436
- // Recreate editor with new theme
437
- const currentCode = editorInstance.getValue();
438
- editorInstance.destroy();
439
-
440
- editor.createEditor(
441
- document.getElementById('editor'),
442
- {
443
- value: currentCode,
444
- language: 'javascript',
445
- theme: theme
446
- }
447
- ).then(instance => {
448
- window.editorInstance = instance;
449
- });
439
+ editor.theme.setTheme(theme);
450
440
  };
451
441
 
452
442
  window.getCode = () => {
@@ -480,7 +470,7 @@ The editor synchronizes all layers during:
480
470
  - **Real-time Highlighting**: Uses Highlight.js for fast, accurate syntax highlighting
481
471
  - **Canvas Measurement**: Employs HTML5 Canvas API for precise text width calculations
482
472
  - **Event Optimization**: Efficiently updates only what's necessary on each interaction
483
- - **Heavy Optimization**: previous version(0.1.6) used to handle 500 lines before lagging, with new caret@0.2.0, there's almost 20 times perfomace increase now it can handle 10K+ lines smoothly before lagging(better results in optimized browsers like firfox)
473
+ - **Heavy Optimization**: v0.1.5 used to handle 500 lines before lagging, with new caret@0.2.0 and onwards, there's almost 20 times performance increase now it can handle 10K+ lines smoothly before lagging(better results in optimized browsers like firefox)
484
474
 
485
475
  ### Browser Support
486
476
 
@@ -2,6 +2,7 @@ const hljs = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js");
2
2
  const languages = require("./languages.js");
3
3
 
4
4
  languages.init();
5
+ let numberWrappedCode = 0;
5
6
 
6
7
  async function createEditor(editor, data) {
7
8
  const editor1 = document.createElement("textarea");
@@ -14,18 +15,27 @@ async function createEditor(editor, data) {
14
15
  const lineColor = isDark ? "#fff" : "#000";
15
16
  const lineCounter = document.createElement("div");
16
17
 
17
- editor1.id = "Caret-textarea";
18
- highlighted.id = "Caret-highlighted";
19
- caret.id = "Caret-caret";
20
- lineCounter.id = "Caret-lineCounter";
21
- editor1.className = 'dark';
22
- highlighted.className = 'dark';
23
- caret.className = 'dark';
24
- lineCounter.className = 'dark';
18
+ const i = Math.random().toString(16).slice(2);
19
+ editor1.id = `Caret-textarea-${i}`;
20
+ highlighted.id = `Caret-highlighted-${i}`;
21
+ caret.id = `Caret-caret-${i}`;
22
+ lineCounter.id = `Caret-lineCounter-${i}`;
23
+ editor1.classList.add("Caret-textarea");
24
+ highlighted.classList.add("Caret-highlighted");
25
+ caret.classList.add("Caret-caret");
26
+ lineCounter.classList.add("Caret-lineCounter");
27
+ editor1.classList.add("dark");
28
+ highlighted.classList.add("dark");
29
+ caret.classList.add("dark");
30
+ lineCounter.classList.add("dark");
25
31
  editor1.style.backgroundColor = isDark ? "#222" : "#fff";
26
32
  let code = data.value || "";
27
33
  let language = data.language;
28
34
  let theme = data.theme;
35
+ let lock = data.readOnly || false;
36
+ if (lock) {
37
+ editor1.readOnly = true;
38
+ }
29
39
  if (!languages.registeredLanguages.includes(language)) {
30
40
  const mod = await import(`https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/${language}.js`);
31
41
  languages.registerLanguage(language, mod.default);
@@ -61,7 +71,6 @@ async function createEditor(editor, data) {
61
71
  editor.style = "position: relative; width: 600px; height: 300px; overflow: hidden; /* 👈 CRITICAL */ font-size: 14px;"
62
72
  if (code && editor && editor1 && language && highlighted) {
63
73
  editor1.style.paddingTop = "-9px";
64
- console.log(data.value + " data.value");
65
74
  editor1.value = data.value;
66
75
  highlighted.innerHTML = await _render(data.value, language, editor1);
67
76
  }
@@ -134,12 +143,15 @@ async function createEditor(editor, data) {
134
143
  }
135
144
 
136
145
  function updateLineNumbers() {
137
- const lineCount = editor1.value.split("\n").length;
146
+ const lines = editor1.value.split("\n");
147
+ const wrapMap = getWrapMap(editor1.value, 71);
138
148
 
139
149
  let html = "";
140
- for (let i = 1; i <= lineCount; i++) {
141
- html += `<div class="Caret-lineCounter-number" style="color: ${lineColor}">${i}</div>`;
142
- }
150
+ lines.forEach((line, i) => {
151
+ const visualLines = wrapMap[i] || 1;
152
+ // first visual line gets the number
153
+ html += `<div class="Caret-lineCounter-number" style="color: ${lineColor}; height: calc(1.5em * ${visualLines})">${i + 1}</div>`;
154
+ });
143
155
 
144
156
  lineCounter.innerHTML = html;
145
157
  }
@@ -167,47 +179,89 @@ async function createEditor(editor, data) {
167
179
 
168
180
  editor1.addEventListener("blur", blur);
169
181
 
182
+ function getVisualRow(text, wrapAt) {
183
+ // simulate exactly what wrapCode does, but track caret position
184
+ const words = text.split(" ");
185
+ let currentLine = "";
186
+ let visualRow = 0;
187
+
188
+ for (let w = 0; w < words.length; w++) {
189
+ const word = words[w];
190
+ const isLast = w === words.length - 1;
191
+ const test = currentLine ? currentLine + " " + word : word;
192
+
193
+ if (test.length > wrapAt && currentLine !== "") {
194
+ visualRow++;
195
+ currentLine = word;
196
+ } else {
197
+ currentLine = test;
198
+ }
199
+ }
200
+
201
+ return { row: visualRow, lineText: currentLine };
202
+ }
203
+
170
204
  function updateCaret() {
171
205
  const start = editor1.selectionStart;
172
206
  const text = editor1.value.slice(0, start);
173
207
 
174
208
  const lines = text.split("\n");
175
209
  const lineIndex = lines.length - 1;
176
- const lineText = lines[lineIndex].replace(/\t/g, " ");
210
+ const currentLineText = lines[lineIndex].replace(/\t/g, " ");
177
211
 
178
212
  const style = getComputedStyle(editor1);
179
213
  const paddingLeft = parseFloat(style.paddingLeft);
180
214
  const paddingTop = parseFloat(style.paddingTop);
181
- const lineHeight = parseFloat(style.lineHeight);
215
+ const lineHeight = parseFloat(style.lineHeight) || 20;
182
216
 
183
217
  updateFontMetrics();
184
- const metrics = measureCtx.measureText("Mg");
185
- const ascent = metrics.actualBoundingBoxAscent;
218
+ const ascent = measureCtx.measureText("Mg").actualBoundingBoxAscent;
219
+
220
+ const WRAP_AT = 71;
221
+
222
+ // count visual rows from all previous lines
223
+ let totalVisualRows = 0;
224
+ for (let i = 0; i < lineIndex; i++) {
225
+ const l = lines[i].replace(/\t/g, " ");
226
+ const { row } = getVisualRow(l, WRAP_AT);
227
+ totalVisualRows += row + 1;
228
+ }
229
+
230
+ const { row, lineText } = getVisualRow(currentLineText, WRAP_AT);
231
+ const onWrappedLine = row > 0;
186
232
 
187
- caret.style.left =
188
- paddingLeft + measureCtx.measureText(lineText).width + "px";
189
- caret.style.top =
190
- -9 +
191
- paddingTop +
192
- lineIndex * lineHeight +
193
- (lineHeight - ascent) +
194
- "px";
233
+ totalVisualRows += row;
195
234
 
235
+ if (onWrappedLine) {
236
+ // on wrapped line - X is just the text on this visual row
237
+ caret.style.left = paddingLeft + measureCtx.measureText(lineText).width + "px";
238
+ } else {
239
+ // on original line - X is full line text width
240
+ caret.style.left = paddingLeft + measureCtx.measureText(lineText.trimEnd()).width + "px";
241
+ }
242
+
243
+ caret.style.top = -9 + paddingTop + totalVisualRows * lineHeight + (lineHeight - ascent) + "px";
196
244
  caret.style.height = `${lineHeight - 5}px`;
197
245
  }
246
+
198
247
  const input = async () => {
199
248
  caret.style.opacity = "1";
200
249
  highlighted.innerHTML = await _render(editor1.value, language, editor1);
201
250
  updateLineNumbers();
202
251
  updateCaret();
203
252
  };
253
+
254
+ const onDidChangeModelContent = (fn) => {
255
+ editor1.addEventListener("input", fn)
256
+ }
257
+
204
258
  editor1.addEventListener("input", input);
205
259
  const scroll = async () => {
206
260
  const x = -editor1.scrollLeft;
207
261
  const y = -editor1.scrollTop;
208
262
  highlighted.innerHTML = await _render(editor1.value, language, editor1);
209
- highlighted.style.transform = `translate(${x}px, ${y}px)`;
210
- caret.style.transform = `translate(${x}px, ${y}px)`;
263
+ highlighted.style.transform = `translateY(${y}px)`;
264
+ caret.style.transform = `translateY(${y}px)`;
211
265
  lineCounter.style.transform = `translateY(${y}px)`;
212
266
  };
213
267
  editor1.addEventListener("scroll", scroll);
@@ -250,7 +304,7 @@ async function createEditor(editor, data) {
250
304
  l = "xml";
251
305
  }
252
306
  const mod = await import(`https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/${l}.js`);
253
-
307
+ languages.registerLanguage(l, mod)
254
308
  }
255
309
  language = l;
256
310
  refresh();
@@ -260,10 +314,88 @@ async function createEditor(editor, data) {
260
314
  setValue,
261
315
  focus,
262
316
  setLanguage,
263
- destroy
317
+ destroy,
318
+ onDidChangeModelContent,
264
319
  };
265
320
  }
266
321
 
322
+ function wrapCode(code, wrapAt = 71) {
323
+ return code.split("\n").map(line => {
324
+ if (line.length <= wrapAt) return line;
325
+
326
+ const indent = line.match(/^(\s*)/)[1];
327
+ const words = line.trimStart().split(" ");
328
+ const wrappedLines = [];
329
+ let currentLine = indent; // first line keeps indent
330
+ let isFirstLine = true;
331
+
332
+ for (const word of words) {
333
+ if (word.length > wrapAt) {
334
+ if (currentLine.trim()) {
335
+ wrappedLines.push(currentLine);
336
+ currentLine = "";
337
+ isFirstLine = false;
338
+ }
339
+ for (let i = 0; i < word.length; i += wrapAt) {
340
+ wrappedLines.push(word.slice(i, i + wrapAt));
341
+ }
342
+ continue;
343
+ }
344
+
345
+ const test = currentLine ? currentLine + " " + word : word;
346
+ if (test.length > wrapAt) {
347
+ wrappedLines.push(currentLine);
348
+ currentLine = word; // no indent on continuation lines
349
+ isFirstLine = false;
350
+ } else {
351
+ currentLine = test;
352
+ }
353
+ }
354
+
355
+ if (currentLine) wrappedLines.push(currentLine);
356
+ return wrappedLines.join("\n");
357
+ }).join("\n");
358
+ }
359
+
360
+ function getWrapMap(code, wrapAt = 71) {
361
+ const wrapMap = []; // wrapMap[originalLineIndex] = number of visual lines it produces
362
+
363
+ code.split("\n").forEach((line, i) => {
364
+ if (line.length <= wrapAt) {
365
+ wrapMap[i] = 1; // no wrap, 1 visual line
366
+ return;
367
+ }
368
+
369
+ const indent = line.match(/^(\s*)/)[1];
370
+ const words = line.trimStart().split(" ");
371
+ let currentLine = indent;
372
+ let visualLines = 1;
373
+
374
+ for (const word of words) {
375
+ if (word.length > wrapAt) {
376
+ if (currentLine.trim()) {
377
+ visualLines++;
378
+ currentLine = "";
379
+ }
380
+ visualLines += Math.floor(word.length / wrapAt);
381
+ continue;
382
+ }
383
+
384
+ const test = currentLine ? currentLine + " " + word : word;
385
+ if (test.length > wrapAt) {
386
+ visualLines++;
387
+ currentLine = word;
388
+ } else {
389
+ currentLine = test;
390
+ }
391
+ }
392
+
393
+ wrapMap[i] = visualLines;
394
+ });
395
+
396
+ return wrapMap;
397
+ }
398
+
267
399
  function escapeHtml(str) {
268
400
  return str
269
401
  .replace(/&/g, "&amp;")
@@ -276,7 +408,6 @@ async function _render(code, language, editor) {
276
408
  if (!editor) {
277
409
  return hljs.highlight(code, { language }).value;
278
410
  }
279
-
280
411
  const scrollTop = editor.scrollTop;
281
412
  const scrollBottom = scrollTop + editor.clientHeight;
282
413
  const style = getComputedStyle(editor);
@@ -299,8 +430,14 @@ async function _render(code, language, editor) {
299
430
  const afterLines = lines.slice(visibleEnd);
300
431
 
301
432
  // Only highlight visible portion
302
-
303
- const highlightedVisible = hljs.highlight(visibleLines.join("\n"), { language }).value;
433
+ let wrappedCode;
434
+ if (visibleLines == []) {
435
+ wrappedCode = wrapCode(code, 68);
436
+ }
437
+ else {
438
+ wrappedCode = wrapCode(visibleLines.join("\n"), 71)
439
+ }
440
+ const highlightedVisible = hljs.highlight(wrappedCode, { language }).value;
304
441
  // Plain text for non-visible areas (no highlighting = faster)
305
442
  if (highlightedVisible.trim() === "") {
306
443
  return hljs.highlight(escapeHtml(code), { language }).value;
@@ -1,22 +1,22 @@
1
- const javascript = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/javascript.js");
2
- const xml = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/xml.js");
3
- const css = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/css.js");
4
- const python = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/python.js");
5
- const java = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/java.js");
6
- const csharp = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/csharp.js");
7
- const cpp = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/cpp.js");
8
- const ruby = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/ruby.js");
9
- const php = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/php.js");
10
- const go = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/go.js");
11
- const c = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/c.js");
12
- const rust = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/rust.js");
13
- const kotlin = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/kotlin.js");
14
- const swift = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/swift.js");
15
- const typescript = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/typescript.js");
16
- const json = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/json.js");
17
- const bash = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/bash.js");
18
- const plaintext = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/plaintext.js");
19
- const hljs = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js");
1
+ import javascript from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/javascript.js";
2
+ import xml from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/xml.js";
3
+ import css from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/css.js";
4
+ import python from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/python.js";
5
+ import java from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/java.js";
6
+ import csharp from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/csharp.js";
7
+ import cpp from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/cpp.js";
8
+ import ruby from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/ruby.js";
9
+ import php from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/php.js";
10
+ import go from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/go.js";
11
+ import c from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/c.js";
12
+ import rust from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/rust.js";
13
+ import kotlin from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/kotlin.js";
14
+ import swift from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/swift.js";
15
+ import typescript from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/typescript.js";
16
+ import json from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/json.js";
17
+ import bash from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/bash.js";
18
+ import plaintext from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/plaintext.js";
19
+ import hljs from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js";
20
20
 
21
21
  let registeredLanguages = [];
22
22
 
@@ -24,8 +24,13 @@ function init() {
24
24
  // Register all languages
25
25
  hljs.registerLanguage("javascript", javascript);
26
26
  hljs.registerLanguage("xml", xml);
27
+ hljs.registerLanguage("typescript", typescript);
28
+ hljs.registerAliases(["jsx"], { languageName: "javascript" });
29
+ hljs.registerAliases(["js"], { languageName: "javascript" });
30
+ hljs.registerAliases(["ts"], { languageName: "typescript" });
31
+ hljs.registerAliases(["html"], { languageName: "xml" });
32
+ hljs.registerAliases(["svg"], { languageName: "xml" });
27
33
  hljs.registerLanguage("css", css);
28
- hljs.registerLanguage("html", xml);
29
34
  hljs.registerLanguage("python", python);
30
35
  hljs.registerLanguage("java", java);
31
36
  hljs.registerLanguage("csharp", csharp);
@@ -37,7 +42,6 @@ function init() {
37
42
  hljs.registerLanguage("rust", rust);
38
43
  hljs.registerLanguage("kotlin", kotlin);
39
44
  hljs.registerLanguage("swift", swift);
40
- hljs.registerLanguage("typescript", typescript);
41
45
  hljs.registerLanguage("json", json);
42
46
  hljs.registerLanguage("bash", bash);
43
47
  hljs.registerLanguage("shell", bash);
@@ -46,6 +50,7 @@ function init() {
46
50
  registeredLanguages = [
47
51
  "javascript",
48
52
  "js",
53
+ 'jsx',
49
54
  "xml",
50
55
  "html",
51
56
  "svg",