@pfmcodes/caret 0.1.1 → 0.1.2
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 +22 -22
- package/commonjs/editor.js +272 -0
- package/commonjs/index.js +10 -0
- package/commonjs/languages.js +97 -0
- package/commonjs/theme.js +18 -0
- package/esm/editor.js +69 -19
- package/esm/languages.js +54 -3
- package/package.json +2 -2
- package/types/editor.d.ts +156 -16
- package/types/language-utils.d.ts +428 -0
- package/types/languages.d.ts +128 -13
- package/types/types.d.ts +347 -0
package/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Caret
|
|
2
2
|
|
|
3
|
-
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://github.com/PFMCODES/lexius-edior)
|
|
5
|
+
[](https://github.com/pfmcodes/lexius-editor)
|
|
6
|
+
[](https://github.com/pfmcodes/lexius-editor)
|
|
7
7
|
|
|
8
|
-
A lightweight, feature-rich code editor with real-time syntax highlighting and custom caret rendering. Built with vanilla JavaScript and powered by Highlight.js,
|
|
8
|
+
A lightweight, feature-rich code editor with real-time syntax highlighting and custom caret rendering. Built with vanilla JavaScript and powered by Highlight.js, caret delivers a smooth coding experience with professional-grade features.
|
|
9
9
|
|
|
10
10
|
## ✨ Features
|
|
11
11
|
|
|
12
12
|
- 🎨 **Live Syntax Highlighting** - Real-time code highlighting powered by Highlight.js
|
|
13
|
-
- 🖱️ **Custom Caret** - Smooth, pixel-perfect
|
|
13
|
+
- 🖱️ **Custom Caret** - Smooth, pixel-perfect Caret positioning and rendering
|
|
14
14
|
- 🔢 **Line Numbers** - Built-in line counter with dynamic updates
|
|
15
15
|
- ⌨️ **Smart Indentation** - Tab/Shift+Tab support for indenting/unindenting code blocks
|
|
16
16
|
- 🎭 **Theme Support** - Multiple syntax highlighting themes (light/dark modes)
|
|
@@ -34,19 +34,19 @@ A lightweight, feature-rich code editor with real-time syntax highlighting and c
|
|
|
34
34
|
### NPM
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
npm install caret
|
|
37
|
+
npm install @pfmcodes/caret
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
### Yarn
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
yarn add caret
|
|
43
|
+
yarn add @pfmcodes/caret
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
### PNPM
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
|
-
pnpm add caret
|
|
49
|
+
pnpm add @pfmcodes/caret
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
## 🏁 Quick Start
|
|
@@ -66,7 +66,7 @@ pnpm add caret
|
|
|
66
66
|
<div id="editor"></div>
|
|
67
67
|
|
|
68
68
|
<script type="module">
|
|
69
|
-
import editor from './node_modules/caret/esm/index.js';
|
|
69
|
+
import editor from './node_modules/@pfmcodes/caret/esm/index.js';
|
|
70
70
|
|
|
71
71
|
const instance = await editor.createEditor(
|
|
72
72
|
document.getElementById('editor'),
|
|
@@ -84,7 +84,7 @@ pnpm add caret
|
|
|
84
84
|
### ES Module Import
|
|
85
85
|
|
|
86
86
|
```javascript
|
|
87
|
-
import editor from 'caret
|
|
87
|
+
import editor from '@pfmcodes/caret';
|
|
88
88
|
|
|
89
89
|
// Create editor instance
|
|
90
90
|
const editorInstance = await editor.createEditor(
|
|
@@ -116,7 +116,7 @@ caret/
|
|
|
116
116
|
### JavaScript Editor
|
|
117
117
|
|
|
118
118
|
```javascript
|
|
119
|
-
import editor from 'caret
|
|
119
|
+
import editor from '@pfmcodes/caret';
|
|
120
120
|
|
|
121
121
|
const jsEditor = await editor.createEditor(
|
|
122
122
|
document.getElementById('js-editor'),
|
|
@@ -193,7 +193,7 @@ The editor comes with default styles that you can override:
|
|
|
193
193
|
line-height: 1.6;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
/* Customize the
|
|
196
|
+
/* Customize the Caret */
|
|
197
197
|
#Caret-caret {
|
|
198
198
|
background: #00ff00 !important;
|
|
199
199
|
width: 3px !important;
|
|
@@ -244,7 +244,7 @@ editorInstance.setLanguage('python');
|
|
|
244
244
|
The editor automatically:
|
|
245
245
|
- Updates syntax highlighting as you type
|
|
246
246
|
- Adjusts line numbers dynamically
|
|
247
|
-
- Maintains
|
|
247
|
+
- Maintains Caret position accurately
|
|
248
248
|
- Synchronizes all visual components
|
|
249
249
|
|
|
250
250
|
### Configuration Options
|
|
@@ -329,7 +329,7 @@ Line numbers are automatically generated and synchronized with your code.
|
|
|
329
329
|
- **Shift + Tab** - Unindent selected lines
|
|
330
330
|
|
|
331
331
|
#### Custom Caret
|
|
332
|
-
The editor features a custom-rendered
|
|
332
|
+
The editor features a custom-rendered Caret that adapts to your theme (light/dark).
|
|
333
333
|
|
|
334
334
|
#### Synchronized Scrolling
|
|
335
335
|
All editor components (code, highlights, line numbers) scroll together smoothly.
|
|
@@ -460,7 +460,7 @@ Caret uses a clever layering technique:
|
|
|
460
460
|
|
|
461
461
|
1. **Textarea Layer** - Handles user input and cursor management
|
|
462
462
|
2. **Pre/Code Layer** - Displays syntax-highlighted code (overlay)
|
|
463
|
-
3. **Custom Caret** - Renders a styled
|
|
463
|
+
3. **Custom Caret** - Renders a styled Caret in the correct position
|
|
464
464
|
4. **Line Numbers** - Dynamically generated and synchronized
|
|
465
465
|
|
|
466
466
|
The editor synchronizes all layers during:
|
|
@@ -494,10 +494,10 @@ Contributions are welcome! Please follow these steps:
|
|
|
494
494
|
|
|
495
495
|
```bash
|
|
496
496
|
# Clone the repository
|
|
497
|
-
git clone https://github.com/
|
|
497
|
+
git clone https://github.com/pfmcodes/lexius-editor.git
|
|
498
498
|
|
|
499
499
|
# Navigate to the directory
|
|
500
|
-
cd
|
|
500
|
+
cd lexius-editor
|
|
501
501
|
|
|
502
502
|
# Install dependencies
|
|
503
503
|
npm install
|
|
@@ -521,13 +521,13 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
|
521
521
|
|
|
522
522
|
## 📞 Support
|
|
523
523
|
|
|
524
|
-
- **Issues**: [GitHub Issues](https://github.com/
|
|
525
|
-
- **Discussions**: [GitHub Discussions](https://github.com/
|
|
524
|
+
- **Issues**: [GitHub Issues](https://github.com/pfmcodes/lexius-editor/issues)
|
|
525
|
+
- **Discussions**: [GitHub Discussions](https://github.com/pfmcodes/lexius-editor/discussions)
|
|
526
526
|
|
|
527
527
|
## 🔗 Links
|
|
528
528
|
|
|
529
|
-
- [GitHub Repository](https://github.com/
|
|
530
|
-
- [NPM Package](https://www.npmjs.com/package/caret) *(if published)*
|
|
529
|
+
- [GitHub Repository](https://github.com/pfmcodes/lexius-editor)
|
|
530
|
+
- [NPM Package](https://www.npmjs.com/package/@pfmcodes/caret) *(if published)*
|
|
531
531
|
|
|
532
532
|
---
|
|
533
533
|
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
const hljs = require("../highlight.js/es/core.js"); // Use default export
|
|
2
|
+
const languages = require("./languages.js");
|
|
3
|
+
|
|
4
|
+
languages.init();
|
|
5
|
+
|
|
6
|
+
async function createEditor(editor, data) {
|
|
7
|
+
const editor1 = document.createElement("textarea");
|
|
8
|
+
const highlighted = document.createElement("pre");
|
|
9
|
+
const caret = document.createElement("div");
|
|
10
|
+
const measureCanvas = document.createElement("canvas");
|
|
11
|
+
const measureCtx = measureCanvas.getContext("2d");
|
|
12
|
+
const isDark = data.theme && (data.theme.includes("dark") || data.theme.includes("night"));
|
|
13
|
+
const caretColor = isDark ? "#fff" : "#7116d8";
|
|
14
|
+
const lineColor = isDark ? "#fff" : "#000";
|
|
15
|
+
const lineCounter = document.createElement("div");
|
|
16
|
+
|
|
17
|
+
editor1.id = "Caret-textarea";
|
|
18
|
+
highlighted.id = "Caret-highlighted";
|
|
19
|
+
caret.id = "Caret-caret";
|
|
20
|
+
lineCounter.id = "Caret-lineCounter";
|
|
21
|
+
let code = data.value || "";
|
|
22
|
+
let language = data.language;
|
|
23
|
+
let theme = data.theme;
|
|
24
|
+
if (!languages.registeredlanguages.includee(language)) {
|
|
25
|
+
languages.registerlanguage(language);
|
|
26
|
+
}
|
|
27
|
+
if (theme) {
|
|
28
|
+
let themeLink = document.getElementById("Caret-theme")
|
|
29
|
+
if (!themeLink) {
|
|
30
|
+
const link = document.createElement("link");
|
|
31
|
+
link.rel = "stylesheet";
|
|
32
|
+
link.id = "Caret-theme";
|
|
33
|
+
link.href = `./highlight.js/styles/${theme}.css`;
|
|
34
|
+
document.head.appendChild(link);
|
|
35
|
+
} else {
|
|
36
|
+
themeLink.href = `./highlight.js/styles/${theme}.css`;
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
let themeLink = document.getElementById("Caret-theme");
|
|
40
|
+
if (!themeLink) {
|
|
41
|
+
const link = document.createElement("link");
|
|
42
|
+
link.rel = "stylesheet";
|
|
43
|
+
link.id = "Caret-theme";
|
|
44
|
+
link.href = `./highlight.js/styles/hybrid.css`;
|
|
45
|
+
document.head.appendChild(link);
|
|
46
|
+
} else {
|
|
47
|
+
themeLink.href = `./highlight.js/styles/hybrid.css`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
editor1.spellcheck = false;
|
|
51
|
+
editor1.autocapitalize = "off";
|
|
52
|
+
editor1.autocomplete = "off";
|
|
53
|
+
editor1.autocorrect = "off";
|
|
54
|
+
editor.style = "position: relative; width: 600px; height: 300px; overflow: hidden; /* 👈 CRITICAL */ font-size: 14px;"
|
|
55
|
+
if (code) {
|
|
56
|
+
editor1.value = code;
|
|
57
|
+
editor1.style.paddingTop = "-9px";
|
|
58
|
+
highlighted.innerHTML = hljs.highlight(code, { language: language }).value;
|
|
59
|
+
}
|
|
60
|
+
const keyDown = (e) => {
|
|
61
|
+
if (e.key !== "Tab") return;
|
|
62
|
+
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
|
|
65
|
+
const value = editor1.value;
|
|
66
|
+
const start = editor1.selectionStart;
|
|
67
|
+
const end = editor1.selectionEnd;
|
|
68
|
+
|
|
69
|
+
const indent = " ";
|
|
70
|
+
|
|
71
|
+
// Find line start & end
|
|
72
|
+
const lineStart = value.lastIndexOf("\n", start - 1) + 1;
|
|
73
|
+
const lineEnd = value.indexOf("\n", end);
|
|
74
|
+
const finalLineEnd = lineEnd === -1 ? value.length : lineEnd;
|
|
75
|
+
|
|
76
|
+
const block = value.slice(lineStart, finalLineEnd);
|
|
77
|
+
const lines = block.split("\n");
|
|
78
|
+
|
|
79
|
+
let newLines;
|
|
80
|
+
let delta = 0;
|
|
81
|
+
|
|
82
|
+
if (e.shiftKey) {
|
|
83
|
+
// UNINDENT
|
|
84
|
+
newLines = lines.map(line => {
|
|
85
|
+
if (line.startsWith(indent)) {
|
|
86
|
+
delta -= indent.length;
|
|
87
|
+
return line.slice(indent.length);
|
|
88
|
+
}
|
|
89
|
+
if (line.startsWith("\t")) {
|
|
90
|
+
delta -= 1;
|
|
91
|
+
return line.slice(1);
|
|
92
|
+
}
|
|
93
|
+
return line;
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
// INDENT
|
|
97
|
+
newLines = lines.map(line => indent + line);
|
|
98
|
+
delta = indent.length;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const newBlock = newLines.join("\n");
|
|
102
|
+
|
|
103
|
+
editor1.value =
|
|
104
|
+
value.slice(0, lineStart) +
|
|
105
|
+
newBlock +
|
|
106
|
+
value.slice(finalLineEnd);
|
|
107
|
+
|
|
108
|
+
// Fix selection
|
|
109
|
+
editor1.selectionStart = start + delta;
|
|
110
|
+
editor1.selectionEnd =
|
|
111
|
+
end + delta * newLines.length;
|
|
112
|
+
|
|
113
|
+
highlighted.innerHTML = hljs.highlight(editor1.value, { language }).value;
|
|
114
|
+
updateLineNumbers();
|
|
115
|
+
updateCaret();
|
|
116
|
+
}
|
|
117
|
+
editor1.addEventListener("keydown", keyDown);
|
|
118
|
+
editor.appendChild(lineCounter);
|
|
119
|
+
editor.appendChild(highlighted);
|
|
120
|
+
editor.appendChild(editor1);
|
|
121
|
+
editor.appendChild(caret);
|
|
122
|
+
|
|
123
|
+
function updateFontMetrics() {
|
|
124
|
+
const style = getComputedStyle(editor1);
|
|
125
|
+
measureCtx.font = `${style.fontSize} ${style.fontFamily}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function updateLineNumbers() {
|
|
129
|
+
const lineCount = editor1.value.split("\n").length;
|
|
130
|
+
|
|
131
|
+
let html = "";
|
|
132
|
+
for (let i = 1; i <= lineCount; i++) {
|
|
133
|
+
html += `<div class="Caret-lineCounter-number" style="color: ${lineColor}">${i}</div>`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
lineCounter.innerHTML = html;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
function getFontMetrics() {
|
|
141
|
+
const metrics = measureCtx.measureText("Mg");
|
|
142
|
+
return {
|
|
143
|
+
ascent: metrics.actualBoundingBoxAscent,
|
|
144
|
+
descent: metrics.actualBoundingBoxDescent,
|
|
145
|
+
height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const focus = () => {
|
|
149
|
+
caret.style.opacity = "1";
|
|
150
|
+
caret.style.background = caretColor;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
editor1.addEventListener("focus", focus);
|
|
154
|
+
|
|
155
|
+
const blur = () => {
|
|
156
|
+
caret.style.opacity = "0";
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
editor1.addEventListener("blur", blur);
|
|
160
|
+
|
|
161
|
+
function updateCaret() {
|
|
162
|
+
const start = editor1.selectionStart;
|
|
163
|
+
const text = editor1.value.slice(0, start);
|
|
164
|
+
|
|
165
|
+
const lines = text.split("\n");
|
|
166
|
+
const lineIndex = lines.length - 1;
|
|
167
|
+
const lineText = lines[lineIndex].replace(/\t/g, " ");
|
|
168
|
+
|
|
169
|
+
const style = getComputedStyle(editor1);
|
|
170
|
+
const paddingLeft = parseFloat(style.paddingLeft);
|
|
171
|
+
const paddingTop = parseFloat(style.paddingTop);
|
|
172
|
+
const lineHeight = parseFloat(style.lineHeight);
|
|
173
|
+
|
|
174
|
+
updateFontMetrics();
|
|
175
|
+
const metrics = measureCtx.measureText("Mg");
|
|
176
|
+
const ascent = metrics.actualBoundingBoxAscent;
|
|
177
|
+
|
|
178
|
+
caret.style.left =
|
|
179
|
+
paddingLeft + measureCtx.measureText(lineText).width + "px";
|
|
180
|
+
caret.style.top =
|
|
181
|
+
-9 +
|
|
182
|
+
paddingTop +
|
|
183
|
+
lineIndex * lineHeight +
|
|
184
|
+
(lineHeight - ascent) +
|
|
185
|
+
"px";
|
|
186
|
+
|
|
187
|
+
caret.style.height = `${lineHeight}px`;
|
|
188
|
+
}
|
|
189
|
+
const input = () => {
|
|
190
|
+
caret.style.opacity = "1";
|
|
191
|
+
highlighted.innerHTML = hljs.highlight(editor1.value, { language: language }).value;
|
|
192
|
+
updateLineNumbers();
|
|
193
|
+
updateCaret();
|
|
194
|
+
};
|
|
195
|
+
editor1.addEventListener("input", input);
|
|
196
|
+
const scroll = () => {
|
|
197
|
+
const x = -editor1.scrollLeft;
|
|
198
|
+
const y = -editor1.scrollTop;
|
|
199
|
+
|
|
200
|
+
highlighted.style.transform = `translate(${x}px, ${y}px)`;
|
|
201
|
+
caret.style.transform = `translate(${x}px, ${y}px)`;
|
|
202
|
+
lineCounter.style.transform = `translateY(${y}px)`;
|
|
203
|
+
};
|
|
204
|
+
editor1.addEventListener("scroll", scroll);
|
|
205
|
+
|
|
206
|
+
updateFontMetrics();
|
|
207
|
+
getFontMetrics();
|
|
208
|
+
|
|
209
|
+
editor1.addEventListener("click", updateCaret);
|
|
210
|
+
editor1.addEventListener("keyup", updateCaret);
|
|
211
|
+
|
|
212
|
+
// Initial caret position
|
|
213
|
+
updateLineNumbers();
|
|
214
|
+
updateCaret();
|
|
215
|
+
|
|
216
|
+
// Focus the editor
|
|
217
|
+
editor1.focus();
|
|
218
|
+
function destroy() {
|
|
219
|
+
editor1.removeEventListener('click', updateCaret);
|
|
220
|
+
editor1.removeEventListener('keyup', updateCaret);
|
|
221
|
+
editor1.removeEventListener('scroll', scroll);
|
|
222
|
+
editor1.removeEventListener('keydown', keyDown);
|
|
223
|
+
editor.innerHTML = "";
|
|
224
|
+
}
|
|
225
|
+
function refresh() {
|
|
226
|
+
highlighted.innerHTML = hljs.highlight(editor1.value, { language }).value;
|
|
227
|
+
updateLineNumbers();
|
|
228
|
+
updateCaret();
|
|
229
|
+
}
|
|
230
|
+
function getValue() {
|
|
231
|
+
return editor1.value;
|
|
232
|
+
}
|
|
233
|
+
function setValue(i) {
|
|
234
|
+
editor1.value = i;
|
|
235
|
+
refresh();
|
|
236
|
+
}
|
|
237
|
+
function setLanguage(l) {
|
|
238
|
+
language = l;
|
|
239
|
+
if (!languages.registeredlanguages.includee(language)) {
|
|
240
|
+
languages.registerlanguage(language);
|
|
241
|
+
}
|
|
242
|
+
refresh();
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
getValue,
|
|
246
|
+
setValue,
|
|
247
|
+
focus,
|
|
248
|
+
setLanguage,
|
|
249
|
+
destroy
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const editor = {
|
|
254
|
+
createEditor
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
module.exports = editor;
|
|
258
|
+
|
|
259
|
+
/*
|
|
260
|
+
|
|
261
|
+
createEditor: creates the main editor, using html Elements like, textarea and etc.
|
|
262
|
+
refresh: refreshs the editor
|
|
263
|
+
getValue: return the current value from the editor
|
|
264
|
+
setValue: sets a certain value to the editor's value
|
|
265
|
+
focus: focusses the editor
|
|
266
|
+
destroy: destroys and removeEventListeners
|
|
267
|
+
updateCaret: updates the caret positon, height and other metrics using math
|
|
268
|
+
updateLineNumbers: just add new line numbers
|
|
269
|
+
getFontMetrics: returns back the font's metrics like height
|
|
270
|
+
updateFontMetrics: update the fontMetrics
|
|
271
|
+
|
|
272
|
+
*/
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const javascript = require("../highlight.js/es/languages/javascript.js");
|
|
2
|
+
const xml = require("../highlight.js/es/languages/xml.js");
|
|
3
|
+
const css = require("../highlight.js/es/languages/css.js");
|
|
4
|
+
const python = require("../highlight.js/es/languages/python.js");
|
|
5
|
+
const java = require("../highlight.js/es/languages/java.js");
|
|
6
|
+
const csharp = require("../highlight.js/es/languages/csharp.js");
|
|
7
|
+
const cpp = require("../highlight.js/es/languages/cpp.js");
|
|
8
|
+
const ruby = require("../highlight.js/es/languages/ruby.js");
|
|
9
|
+
const php = require("../highlight.js/es/languages/php.js");
|
|
10
|
+
const go = require("../highlight.js/es/languages/go.js");
|
|
11
|
+
const c = require("../highlight.js/es/languages/c.js");
|
|
12
|
+
const rust = require("../highlight.js/es/languages/rust.js");
|
|
13
|
+
const kotlin = require("../highlight.js/es/languages/kotlin.js");
|
|
14
|
+
const swift = require("../highlight.js/es/languages/swift.js");
|
|
15
|
+
const typescript = require("../highlight.js/es/languages/typescript.js");
|
|
16
|
+
const json = require("../highlight.js/es/languages/json.js");
|
|
17
|
+
const bash = require("../highlight.js/es/languages/bash.js");
|
|
18
|
+
const plaintext = require("../highlight.js/es/languages/plaintext.js");
|
|
19
|
+
const hljs = require("../highlight.js/es/core.js");
|
|
20
|
+
|
|
21
|
+
let registeredLanguages = [];
|
|
22
|
+
|
|
23
|
+
function init() {
|
|
24
|
+
// Register all languages
|
|
25
|
+
hljs.registerLanguage("javascript", javascript);
|
|
26
|
+
hljs.registerLanguage("xml", xml);
|
|
27
|
+
hljs.registerLanguage("css", css);
|
|
28
|
+
hljs.registerLanguage("html", xml);
|
|
29
|
+
hljs.registerLanguage("python", python);
|
|
30
|
+
hljs.registerLanguage("java", java);
|
|
31
|
+
hljs.registerLanguage("csharp", csharp);
|
|
32
|
+
hljs.registerLanguage("cpp", cpp);
|
|
33
|
+
hljs.registerLanguage("ruby", ruby);
|
|
34
|
+
hljs.registerLanguage("php", php);
|
|
35
|
+
hljs.registerLanguage("go", go);
|
|
36
|
+
hljs.registerLanguage("c", c);
|
|
37
|
+
hljs.registerLanguage("rust", rust);
|
|
38
|
+
hljs.registerLanguage("kotlin", kotlin);
|
|
39
|
+
hljs.registerLanguage("swift", swift);
|
|
40
|
+
hljs.registerLanguage("typescript", typescript);
|
|
41
|
+
hljs.registerLanguage("json", json);
|
|
42
|
+
hljs.registerLanguage("bash", bash);
|
|
43
|
+
hljs.registerLanguage("shell", bash);
|
|
44
|
+
hljs.registerLanguage("sh", bash);
|
|
45
|
+
hljs.registerLanguage("plaintext", plaintext);
|
|
46
|
+
registeredLanguages = [
|
|
47
|
+
"javascript",
|
|
48
|
+
"js",
|
|
49
|
+
"xml",
|
|
50
|
+
"html",
|
|
51
|
+
"svg",
|
|
52
|
+
"python",
|
|
53
|
+
"java",
|
|
54
|
+
"csharp",
|
|
55
|
+
"cpp",
|
|
56
|
+
"ruby",
|
|
57
|
+
"php",
|
|
58
|
+
"go",
|
|
59
|
+
"c",
|
|
60
|
+
"rust",
|
|
61
|
+
"kotlin",
|
|
62
|
+
"swift",
|
|
63
|
+
"typescript",
|
|
64
|
+
"json",
|
|
65
|
+
"bash",
|
|
66
|
+
"shell",
|
|
67
|
+
"sh",
|
|
68
|
+
"plaintext"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function registerLanguage(name, definition) {
|
|
73
|
+
hljs.registerLanguage(name, definition);
|
|
74
|
+
if (!registeredLanguages.includes(name)) {
|
|
75
|
+
registeredLanguages.push(name);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const languages = {
|
|
80
|
+
init,
|
|
81
|
+
registeredLanguages,
|
|
82
|
+
registerLanguage,
|
|
83
|
+
hljs
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = languages;
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
|
|
90
|
+
registeredLannguage: added for the editor.js can check if the langauge provided already is regsitered or not
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
init: just registers some languages and updates the registeredLangauges variable
|
|
94
|
+
|
|
95
|
+
registerLanguage: just registers a language
|
|
96
|
+
|
|
97
|
+
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function setTheme(name) {
|
|
2
|
+
const link = document.getElementById("Caret-theme");
|
|
3
|
+
link.href = `./highlight.js/styles/${name}.css`;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function removeTheme() {
|
|
7
|
+
const link = document.getElementById("Caret-theme");
|
|
8
|
+
if (link) {
|
|
9
|
+
link.parentNode.removeChild(link);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const theme = {
|
|
14
|
+
removeTheme,
|
|
15
|
+
setTheme
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = theme;
|
package/esm/editor.js
CHANGED
|
@@ -21,6 +21,10 @@ async function createEditor(editor, data) {
|
|
|
21
21
|
let code = data.value || "";
|
|
22
22
|
let language = data.language;
|
|
23
23
|
let theme = data.theme;
|
|
24
|
+
if (!languages.registeredLanguages.includee(language)) {
|
|
25
|
+
languages.registerLanguage(language);
|
|
26
|
+
language.registeredLanguages.push(language);
|
|
27
|
+
}
|
|
24
28
|
if (theme) {
|
|
25
29
|
let themeLink = document.getElementById("Caret-theme")
|
|
26
30
|
if (!themeLink) {
|
|
@@ -54,7 +58,7 @@ async function createEditor(editor, data) {
|
|
|
54
58
|
editor1.style.paddingTop = "-9px";
|
|
55
59
|
highlighted.innerHTML = hljs.highlight(code, { language: language }).value;
|
|
56
60
|
}
|
|
57
|
-
|
|
61
|
+
const keyDown = (e) => {
|
|
58
62
|
if (e.key !== "Tab") return;
|
|
59
63
|
|
|
60
64
|
e.preventDefault();
|
|
@@ -110,7 +114,8 @@ async function createEditor(editor, data) {
|
|
|
110
114
|
highlighted.innerHTML = hljs.highlight(editor1.value, { language }).value;
|
|
111
115
|
updateLineNumbers();
|
|
112
116
|
updateCaret();
|
|
113
|
-
}
|
|
117
|
+
}
|
|
118
|
+
editor1.addEventListener("keydown", keyDown);
|
|
114
119
|
editor.appendChild(lineCounter);
|
|
115
120
|
editor.appendChild(highlighted);
|
|
116
121
|
editor.appendChild(editor1);
|
|
@@ -141,15 +146,18 @@ async function createEditor(editor, data) {
|
|
|
141
146
|
height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
|
142
147
|
};
|
|
143
148
|
}
|
|
144
|
-
|
|
145
|
-
editor1.addEventListener("focus", () => {
|
|
149
|
+
const focus = () => {
|
|
146
150
|
caret.style.opacity = "1";
|
|
147
151
|
caret.style.background = caretColor;
|
|
148
|
-
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
editor1.addEventListener("focus", focus);
|
|
149
155
|
|
|
150
|
-
|
|
156
|
+
const blur = () => {
|
|
151
157
|
caret.style.opacity = "0";
|
|
152
|
-
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
editor1.addEventListener("blur", blur);
|
|
153
161
|
|
|
154
162
|
function updateCaret() {
|
|
155
163
|
const start = editor1.selectionStart;
|
|
@@ -179,22 +187,22 @@ async function createEditor(editor, data) {
|
|
|
179
187
|
|
|
180
188
|
caret.style.height = `${lineHeight}px`;
|
|
181
189
|
}
|
|
182
|
-
|
|
183
|
-
editor1.addEventListener("input", () => {
|
|
190
|
+
const input = () => {
|
|
184
191
|
caret.style.opacity = "1";
|
|
185
192
|
highlighted.innerHTML = hljs.highlight(editor1.value, { language: language }).value;
|
|
186
193
|
updateLineNumbers();
|
|
187
194
|
updateCaret();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
};
|
|
196
|
+
editor1.addEventListener("input", input);
|
|
197
|
+
const scroll = () => {
|
|
191
198
|
const x = -editor1.scrollLeft;
|
|
192
199
|
const y = -editor1.scrollTop;
|
|
193
200
|
|
|
194
201
|
highlighted.style.transform = `translate(${x}px, ${y}px)`;
|
|
195
202
|
caret.style.transform = `translate(${x}px, ${y}px)`;
|
|
196
203
|
lineCounter.style.transform = `translateY(${y}px)`;
|
|
197
|
-
}
|
|
204
|
+
};
|
|
205
|
+
editor1.addEventListener("scroll", scroll);
|
|
198
206
|
|
|
199
207
|
updateFontMetrics();
|
|
200
208
|
getFontMetrics();
|
|
@@ -208,12 +216,39 @@ async function createEditor(editor, data) {
|
|
|
208
216
|
|
|
209
217
|
// Focus the editor
|
|
210
218
|
editor1.focus();
|
|
219
|
+
function destroy() {
|
|
220
|
+
editor1.removeEventListener('click', updateCaret);
|
|
221
|
+
editor1.removeEventListener('keyup', updateCaret);
|
|
222
|
+
editor1.removeEventListener('scroll', scroll);
|
|
223
|
+
editor1.removeEventListener('keydown', keyDown);
|
|
224
|
+
editor.innerHTML = "";
|
|
225
|
+
}
|
|
226
|
+
function refresh() {
|
|
227
|
+
highlighted.innerHTML = hljs.highlight(editor1.value, { language }).value;
|
|
228
|
+
updateLineNumbers();
|
|
229
|
+
updateCaret();
|
|
230
|
+
}
|
|
231
|
+
function getValue() {
|
|
232
|
+
return editor1.value;
|
|
233
|
+
}
|
|
234
|
+
function setValue(i) {
|
|
235
|
+
editor1.value = i;
|
|
236
|
+
refresh();
|
|
237
|
+
}
|
|
238
|
+
function setLanguage(l) {
|
|
239
|
+
language = l;
|
|
240
|
+
if (!languages.registeredLanguages.includee(language)) {
|
|
241
|
+
languages.registerLanguage(language);
|
|
242
|
+
language.registeredLanguages.push(language);
|
|
243
|
+
}
|
|
244
|
+
refresh();
|
|
245
|
+
}
|
|
211
246
|
return {
|
|
212
|
-
getValue
|
|
213
|
-
setValue
|
|
214
|
-
focus
|
|
215
|
-
setLanguage
|
|
216
|
-
destroy
|
|
247
|
+
getValue,
|
|
248
|
+
setValue,
|
|
249
|
+
focus,
|
|
250
|
+
setLanguage,
|
|
251
|
+
destroy
|
|
217
252
|
};
|
|
218
253
|
}
|
|
219
254
|
|
|
@@ -221,4 +256,19 @@ const editor = {
|
|
|
221
256
|
createEditor
|
|
222
257
|
};
|
|
223
258
|
|
|
224
|
-
export default editor;
|
|
259
|
+
export default editor;
|
|
260
|
+
|
|
261
|
+
/*
|
|
262
|
+
|
|
263
|
+
createEditor: creates the main editor, using html Elements like, textarea and etc.
|
|
264
|
+
refresh: refreshs the editor
|
|
265
|
+
getValue: return the current value from the editor
|
|
266
|
+
setValue: sets a certain value to the editor's value
|
|
267
|
+
focus: focusses the editor
|
|
268
|
+
destroy: destroys and removeEventListeners
|
|
269
|
+
updateCaret: updates the caret positon, height and other metrics using math
|
|
270
|
+
updateLineNumbers: just add new line numbers
|
|
271
|
+
getFontMetrics: returns back the font's metrics like height
|
|
272
|
+
updateFontMetrics: update the fontMetrics
|
|
273
|
+
|
|
274
|
+
*/
|