@pfmcodes/caret 0.2.1 → 0.2.6

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
@@ -33,8 +33,15 @@ A lightweight, feature-rich code editor with real-time syntax highlighting and c
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 perfomace check out [this](#performance-notes) and [this](#performance).
36
+ ### v0.2.6
37
+
38
+ - CommonJs support has been removed to reduce package size
39
+
40
+ ### v0.2.5
41
+ - Multiple editor instances support
42
+ - Word-aware line wrapping
43
+ - Fixed language re-registration bug
44
+ - Known issue: custom caret may be 1 character off on original lines of a wrapped line
38
45
 
39
46
  ## Installation
40
47
 
@@ -73,7 +80,7 @@ pnpm add @pfmcodes/caret
73
80
  <div id="editor"></div>
74
81
 
75
82
  <script type="module">
76
- import editor from './node_modules/@pfmcodes/caret/esm/index.js';
83
+ import editor from './node_modules/@pfmcodes/caret/index.js';
77
84
 
78
85
  const instance = await editor.editor.createEditor(
79
86
  document.getElementById('editor'),
@@ -91,7 +98,7 @@ pnpm add @pfmcodes/caret
91
98
  ### ES Module Import
92
99
 
93
100
  ```javascript
94
- import editor from './node_modules/@pfmcodes/caret/esm/index.js';
101
+ import editor from './node_modules/@pfmcodes/caret/index.js';
95
102
 
96
103
  // Create editor instance
97
104
  const editorInstance = await editor.editor.createEditor(
@@ -108,14 +115,17 @@ const editorInstance = await editor.editor.createEditor(
108
115
 
109
116
  ```
110
117
  caret/
111
- ├── esm/ # ES Module builds
112
- ├── highlight.js/ # Syntax highlighting support
113
- ├── types/ # TypeScript type definitions
114
- ├── index.css # Core styles
115
- ├── package.json # Package configuration
118
+ ├── types/ # TypeScript type definitions
116
119
  ├── .gitignore # Git ignore rules
117
120
  ├── .npmignore # NPM ignore rules
118
- └── LICENSE # MIT License
121
+ ├── editor.js # main editor file essential for ui
122
+ ├── index.css # Core styles
123
+ ├── index.js # Main file
124
+ ├── langauges.js # handles langauge related tasks
125
+ ├── LICENSE # MIT License
126
+ ├── package.json # Package configuration
127
+ ├── README.md # The file containing instructions and help
128
+ └── theme.js # handles theme related tasks
119
129
  ```
120
130
 
121
131
  ## Usage
@@ -123,8 +133,7 @@ caret/
123
133
  ### JavaScript Editor
124
134
 
125
135
  ```javascript
126
- import editor from './node_modules/@pfmcodes/caret/esm/index.js'; // auto link to commonjs version
127
-
136
+ import editor from './node_modules/@pfmcodes/caret/index.js';
128
137
  const jsEditor = await editor.editor.createEditor(
129
138
  document.getElementById('js-editor'),
130
139
  {
@@ -142,7 +151,7 @@ console.log(greet('World'));`,
142
151
  ### Python Editor
143
152
 
144
153
  ```javascript
145
- const pyEditor = await editor.createEditor(
154
+ const pyEditor = await editor.editor.createEditor(
146
155
  document.getElementById('py-editor'),
147
156
  {
148
157
  value: `def fibonacci(n):
@@ -160,7 +169,7 @@ print([fibonacci(i) for i in range(10)])`,
160
169
  ### Empty Editor (Start from Scratch)
161
170
 
162
171
  ```javascript
163
- const emptyEditor = await editor.createEditor(
172
+ const emptyEditor = await editor.editor.createEditor(
164
173
  document.getElementById('empty-editor'),
165
174
  {
166
175
  value: '',
@@ -215,19 +224,19 @@ Caret supports all languages available in Highlight.js:
215
224
 
216
225
  ```javascript
217
226
  // JavaScript
218
- await editor.createEditor(el, { language: 'javascript', ... });
227
+ await editor.editor.createEditor(el, { language: 'javascript', ... });
219
228
 
220
229
  // Python
221
- await editor.createEditor(el, { language: 'python', ... });
230
+ await editor.editor.createEditor(el, { language: 'python', ... });
222
231
 
223
232
  // TypeScript
224
- await editor.createEditor(el, { language: 'typescript', ... });
233
+ await editor.editor.createEditor(el, { language: 'typescript', ... });
225
234
 
226
235
  // HTML
227
- await editor.createEditor(el, { language: 'html', ... });
236
+ await editor.editor.createEditor(el, { language: 'html', ... });
228
237
 
229
238
  // CSS
230
- await editor.createEditor(el, { language: 'css', ... });
239
+ await editor.editor.createEditor(el, { language: 'css', ... });
231
240
 
232
241
  // And many more...
233
242
  ```
@@ -235,7 +244,7 @@ await editor.createEditor(el, { language: 'css', ... });
235
244
  ### Dynamic Language Switching
236
245
 
237
246
  ```javascript
238
- const editorInstance = await editor.createEditor(el, {
247
+ const editorInstance = await editor.editor.createEditor(el, {
239
248
  value: 'console.log("Hello");',
240
249
  language: 'javascript',
241
250
  theme: 'hybrid'
@@ -257,7 +266,7 @@ The editor automatically:
257
266
  ### Configuration Options
258
267
 
259
268
  ```javascript
260
- const editorInstance = await editor.createEditor(
269
+ const editorInstance = await editor.editor.createEditor(
261
270
  containerElement,
262
271
  {
263
272
  // Initial code content
@@ -352,7 +361,7 @@ Here's a complete working example:
352
361
  <meta charset="UTF-8">
353
362
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
354
363
  <title>Caret Demo</title>
355
- <link rel="stylesheet" href="./node_modules/caret/index.css">
364
+ <link rel="stylesheet" href="./index.css">
356
365
  <style>
357
366
  body {
358
367
  font-family: system-ui, -apple-system, sans-serif;
@@ -393,21 +402,22 @@ Here's a complete working example:
393
402
  <h1 style="text-align: center;">Caret Demo</h1>
394
403
 
395
404
  <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>
405
+ <button onclick="window.changeLanguage('javascript')">JavaScript</button>
406
+ <button onclick="window.changeLanguage('python')">Python</button>
407
+ <button onclick="window.changeLanguage('html')">HTML</button>
408
+ <button onclick="window.changeTheme('monokai')">Monokai</button>
409
+ <button onclick="window.changeTheme('github-dark')">GitHub</button>
410
+ <button onclick="window.changeTheme('atom-one-dark')">Atom One Dark</button>
411
+ <button onclick="window.getCode()">Get Code</button>
402
412
  </div>
403
413
 
404
414
  <div id="editor"></div>
405
415
 
406
416
  <script type="module">
407
- import editor from './node_modules/caret/esm/index.js';
417
+ import editor from './node_modules/@pfmcodes/caret/index.js';
408
418
 
409
419
  // Initialize editor
410
- const editorInstance = await editor.createEditor(
420
+ const editorInstance = await editor.editor.createEditor(
411
421
  document.getElementById('editor'),
412
422
  {
413
423
  value: `// Welcome to Caret!
@@ -421,7 +431,7 @@ for (let i = 0; i < 10; i++) {
421
431
  console.log(\`F(\${i}) = \${fibonacci(i)}\`);
422
432
  }`,
423
433
  language: 'javascript',
424
- theme: 'atom-one-dark'
434
+ theme: 'tokyo-night-dark'
425
435
  }
426
436
  );
427
437
 
@@ -433,20 +443,7 @@ for (let i = 0; i < 10; i++) {
433
443
  };
434
444
 
435
445
  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
- });
446
+ editor.theme.setTheme(theme);
450
447
  };
451
448
 
452
449
  window.getCode = () => {
@@ -1,7 +1,8 @@
1
1
  import hljs from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js"; // Use default export
2
- import languages from "./languages.js";
2
+ import languages from "./langauges.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);
@@ -244,13 +298,13 @@ async function createEditor(editor, data) {
244
298
  refresh();
245
299
  }
246
300
  async function setLanguage(l) {
301
+ if (l === "html" || l === "svg") {
302
+ language = "xml";
303
+ l = "xml";
304
+ }
247
305
  if (!languages.registeredLanguages.includes(l)) {
248
- if (l === "html" || l === "svg") {
249
- language = "xml";
250
- l = "xml";
251
- }
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;
package/index.css CHANGED
@@ -1,4 +1,4 @@
1
- #Caret-textarea {
1
+ .Caret-textarea {
2
2
  position: absolute;
3
3
  border: none;
4
4
  inset: 0;
@@ -7,33 +7,40 @@
7
7
  background: transparent;
8
8
  color: transparent;
9
9
  caret-color: #fff;
10
- border: 1px solid #ccc;
11
10
  overflow-x: scroll; /* 👈 ONLY THIS SCROLLS */
12
11
  z-index: 1;
13
- width: 100%;
12
+ width: auto;
13
+ min-width: max-content;
14
14
  }
15
15
 
16
- #Caret-texarea::-webkit-scrollbar {
17
- z-index: 3;
16
+ ::-webkit-scrollbar {
17
+ display: none;
18
+ }
19
+
20
+ .Caret-caret, .Caret-lineCounter, .Caret-textarea {
21
+ overflow: auto;
22
+ overflow-x: auto;
18
23
  }
19
24
 
20
- #Caret-textarea:focus {
25
+ .Caret-textarea:focus {
21
26
  outline: none;
22
27
  }
23
28
 
24
- #Caret-highlighted {
29
+ .Caret-highlighted {
25
30
  position: absolute;
26
31
  top: 0;
27
32
  left: 0;
28
33
  margin: 0;
29
34
  padding: 10px;
30
35
  pointer-events: none;
31
- overflow: hidden; /* 👈 IMPORTANT */
36
+ overflow: visible; /* 👈 IMPORTANT */
32
37
  z-index: 2;
33
38
  white-space: pre;
39
+ min-width: max-content;
40
+ width: auto;
34
41
  }
35
42
 
36
- #Caret-caret {
43
+ .Caret-caret {
37
44
  position: absolute;
38
45
  width: 2px !important; /* 👈 thickness */
39
46
  opacity: 0;
@@ -44,20 +51,20 @@
44
51
  animation: blink 1s step-end infinite;
45
52
  }
46
53
 
47
- #Caret-textarea,
48
- #Caret-highlighted,
49
- #Caret-lineCounter {
54
+ .Caret-textarea,
55
+ .Caret-highlighted,
56
+ .Caret-lineCounter {
50
57
  font: inherit;
51
58
  line-height: inherit;
52
59
  }
53
60
 
54
- #Caret-textarea::selection {
61
+ .Caret-textarea::selection {
55
62
  color: transparent;
56
63
  background-color: rgb(79, 79, 249);
57
64
  }
58
65
 
59
- #Caret-textarea,
60
- #Caret-highlighted {
66
+ .Caret-textarea,
67
+ .Caret-highlighted {
61
68
  font-family: monospace;
62
69
  font-size: 14px;
63
70
  line-height: 1.5;
@@ -65,7 +72,7 @@
65
72
  tab-size: 2;
66
73
  }
67
74
 
68
- #Caret-lineCounter {
75
+ .Caret-lineCounter {
69
76
  position: absolute;
70
77
  top: 0;
71
78
  left: 0;
@@ -74,7 +81,7 @@
74
81
  font-family: monospace;
75
82
  font: 18px;
76
83
  line-height: 1.5;
77
- color: #999;
84
+ color: .999;
78
85
  text-align: right;
79
86
  user-select: none;
80
87
  opacity: 0.7;
@@ -92,12 +99,12 @@
92
99
  50% { opacity: 0; }
93
100
  }
94
101
 
95
- #Caret-caret.dark {
102
+ .Caret-caret.dark {
96
103
  background: #fff0; /* caret color */
97
104
  }
98
- #Caret-highlighted.dark {
105
+ .Caret-highlighted.dark {
99
106
  color: #fff;
100
107
  }
101
- #Caret-lineCounter.dark {
108
+ .Caret-lineCounter.dark {
102
109
  color: #fff;
103
110
  }
@@ -1,6 +1,6 @@
1
1
  import editor from "./editor.js";
2
2
  import theme from "./theme.js";
3
- import language from "./languages.js";
3
+ import language from "./langauges.js";
4
4
 
5
5
  const Caret = {
6
6
  editor,
@@ -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,18 +42,15 @@ 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);
44
48
  hljs.registerLanguage("sh", bash);
45
49
  hljs.registerLanguage("plaintext", plaintext);
46
- registeredLanguages = [
47
- "javascript",
48
- "js",
49
- "xml",
50
- "html",
51
- "svg",
50
+ registeredLanguages.push(
51
+ "javascript", "js",
52
+ "xml", "html", "svg",
53
+ "css",
52
54
  "python",
53
55
  "java",
54
56
  "csharp",
@@ -62,11 +64,9 @@ function init() {
62
64
  "swift",
63
65
  "typescript",
64
66
  "json",
65
- "bash",
66
- "shell",
67
- "sh",
67
+ "bash", "shell", "sh",
68
68
  "plaintext"
69
- ]
69
+ );
70
70
  }
71
71
 
72
72
  function registerLanguage(name, definition) {