@pfmcodes/caret 0.2.5 → 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 +18 -11
- package/{esm/editor.js → editor.js} +1 -1
- package/{esm/index.js → index.js} +1 -1
- package/package.json +8 -8
- package/commonjs/editor.js +0 -469
- package/commonjs/index.js +0 -10
- package/commonjs/languages.js +0 -102
- package/commonjs/theme.js +0 -18
- /package/{esm/languages.js → langauges.js} +0 -0
- /package/{esm/theme.js → theme.js} +0 -0
package/README.md
CHANGED
|
@@ -33,6 +33,11 @@ A lightweight, feature-rich code editor with real-time syntax highlighting and c
|
|
|
33
33
|
|
|
34
34
|
## What's-New?
|
|
35
35
|
|
|
36
|
+
### v0.2.6
|
|
37
|
+
|
|
38
|
+
- CommonJs support has been removed to reduce package size
|
|
39
|
+
|
|
40
|
+
### v0.2.5
|
|
36
41
|
- Multiple editor instances support
|
|
37
42
|
- Word-aware line wrapping
|
|
38
43
|
- Fixed language re-registration bug
|
|
@@ -75,7 +80,7 @@ pnpm add @pfmcodes/caret
|
|
|
75
80
|
<div id="editor"></div>
|
|
76
81
|
|
|
77
82
|
<script type="module">
|
|
78
|
-
import editor from './node_modules/@pfmcodes/caret/
|
|
83
|
+
import editor from './node_modules/@pfmcodes/caret/index.js';
|
|
79
84
|
|
|
80
85
|
const instance = await editor.editor.createEditor(
|
|
81
86
|
document.getElementById('editor'),
|
|
@@ -93,7 +98,7 @@ pnpm add @pfmcodes/caret
|
|
|
93
98
|
### ES Module Import
|
|
94
99
|
|
|
95
100
|
```javascript
|
|
96
|
-
import editor from './node_modules/@pfmcodes/caret/
|
|
101
|
+
import editor from './node_modules/@pfmcodes/caret/index.js';
|
|
97
102
|
|
|
98
103
|
// Create editor instance
|
|
99
104
|
const editorInstance = await editor.editor.createEditor(
|
|
@@ -110,14 +115,17 @@ const editorInstance = await editor.editor.createEditor(
|
|
|
110
115
|
|
|
111
116
|
```
|
|
112
117
|
caret/
|
|
113
|
-
├──
|
|
114
|
-
├── highlight.js/ # Syntax highlighting support
|
|
115
|
-
├── types/ # TypeScript type definitions
|
|
116
|
-
├── index.css # Core styles
|
|
117
|
-
├── package.json # Package configuration
|
|
118
|
+
├── types/ # TypeScript type definitions
|
|
118
119
|
├── .gitignore # Git ignore rules
|
|
119
120
|
├── .npmignore # NPM ignore rules
|
|
120
|
-
|
|
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
|
|
121
129
|
```
|
|
122
130
|
|
|
123
131
|
## Usage
|
|
@@ -125,8 +133,7 @@ caret/
|
|
|
125
133
|
### JavaScript Editor
|
|
126
134
|
|
|
127
135
|
```javascript
|
|
128
|
-
import editor from './node_modules/@pfmcodes/caret/
|
|
129
|
-
|
|
136
|
+
import editor from './node_modules/@pfmcodes/caret/index.js';
|
|
130
137
|
const jsEditor = await editor.editor.createEditor(
|
|
131
138
|
document.getElementById('js-editor'),
|
|
132
139
|
{
|
|
@@ -407,7 +414,7 @@ Here's a complete working example:
|
|
|
407
414
|
<div id="editor"></div>
|
|
408
415
|
|
|
409
416
|
<script type="module">
|
|
410
|
-
import editor from './node_modules/@pfmcodes/caret/
|
|
417
|
+
import editor from './node_modules/@pfmcodes/caret/index.js';
|
|
411
418
|
|
|
412
419
|
// Initialize editor
|
|
413
420
|
const editorInstance = await editor.editor.createEditor(
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pfmcodes/caret",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "The official code editor engine for lexius",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./index.js",
|
|
7
7
|
"types": "./types/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./types/index.d.ts",
|
|
11
|
-
"
|
|
12
|
-
"require": "./commonjs/index.js"
|
|
11
|
+
"default": "./index.js"
|
|
13
12
|
},
|
|
14
|
-
"./
|
|
15
|
-
"./
|
|
13
|
+
"./editor": "./esm/index.js",
|
|
14
|
+
"./langauges": "./langauges.js",
|
|
15
|
+
"./theme": "./theme.js"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"author": "PFMCODES",
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"bugs": {
|
|
38
|
-
"url": "https://github.com/PFMCODES/
|
|
38
|
+
"url": "https://github.com/PFMCODES/Caret/issues"
|
|
39
39
|
},
|
|
40
|
-
"homepage": "https://github.com/PFMCODES/
|
|
40
|
+
"homepage": "https://github.com/PFMCODES/Caret#readme"
|
|
41
41
|
}
|
package/commonjs/editor.js
DELETED
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
const hljs = require("https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js"); // Use default export
|
|
2
|
-
const languages = require("./languages.js");
|
|
3
|
-
|
|
4
|
-
languages.init();
|
|
5
|
-
let numberWrappedCode = 0;
|
|
6
|
-
|
|
7
|
-
async function createEditor(editor, data) {
|
|
8
|
-
const editor1 = document.createElement("textarea");
|
|
9
|
-
const highlighted = document.createElement("pre");
|
|
10
|
-
const caret = document.createElement("div");
|
|
11
|
-
const measureCanvas = document.createElement("canvas");
|
|
12
|
-
const measureCtx = measureCanvas.getContext("2d");
|
|
13
|
-
const isDark = data.theme && (data.theme.includes("dark") || data.theme.includes("night"));
|
|
14
|
-
const caretColor = isDark ? "#fff" : "#7116d8";
|
|
15
|
-
const lineColor = isDark ? "#fff" : "#000";
|
|
16
|
-
const lineCounter = document.createElement("div");
|
|
17
|
-
|
|
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");
|
|
31
|
-
editor1.style.backgroundColor = isDark ? "#222" : "#fff";
|
|
32
|
-
let code = data.value || "";
|
|
33
|
-
let language = data.language;
|
|
34
|
-
let theme = data.theme;
|
|
35
|
-
let lock = data.readOnly || false;
|
|
36
|
-
if (lock) {
|
|
37
|
-
editor1.readOnly = true;
|
|
38
|
-
}
|
|
39
|
-
if (!languages.registeredLanguages.includes(language)) {
|
|
40
|
-
const mod = await import(`https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/${language}.js`);
|
|
41
|
-
languages.registerLanguage(language, mod.default);
|
|
42
|
-
languages.registeredLanguages.push(language);
|
|
43
|
-
}
|
|
44
|
-
if (theme) {
|
|
45
|
-
let themeLink = document.getElementById("Caret-theme")
|
|
46
|
-
if (!themeLink) {
|
|
47
|
-
const link = document.createElement("link");
|
|
48
|
-
link.rel = "stylesheet";
|
|
49
|
-
link.id = "Caret-theme";
|
|
50
|
-
link.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/${theme}.css`;
|
|
51
|
-
document.head.appendChild(link);
|
|
52
|
-
} else {
|
|
53
|
-
themeLink.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/${theme}.css`;
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
let themeLink = document.getElementById("Caret-theme");
|
|
57
|
-
if (!themeLink) {
|
|
58
|
-
const link = document.createElement("link");
|
|
59
|
-
link.rel = "stylesheet";
|
|
60
|
-
link.id = "Caret-theme";
|
|
61
|
-
link.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/hybrid.css`;
|
|
62
|
-
document.head.appendChild(link);
|
|
63
|
-
} else {
|
|
64
|
-
themeLink.href = `./highlight.js/styles/hybrid.css`;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
editor1.spellcheck = false;
|
|
68
|
-
editor1.autocapitalize = "off";
|
|
69
|
-
editor1.autocomplete = "off";
|
|
70
|
-
editor1.autocorrect = "off";
|
|
71
|
-
editor.style = "position: relative; width: 600px; height: 300px; overflow: hidden; /* 👈 CRITICAL */ font-size: 14px;"
|
|
72
|
-
if (code && editor && editor1 && language && highlighted) {
|
|
73
|
-
editor1.style.paddingTop = "-9px";
|
|
74
|
-
editor1.value = data.value;
|
|
75
|
-
highlighted.innerHTML = await _render(data.value, language, editor1);
|
|
76
|
-
}
|
|
77
|
-
const keyDown = async (e) => {
|
|
78
|
-
if (e.key !== "Tab") return;
|
|
79
|
-
|
|
80
|
-
e.preventDefault();
|
|
81
|
-
|
|
82
|
-
const value = editor1.value;
|
|
83
|
-
const start = editor1.selectionStart;
|
|
84
|
-
const end = editor1.selectionEnd;
|
|
85
|
-
|
|
86
|
-
const indent = " ";
|
|
87
|
-
|
|
88
|
-
// Find line start & end
|
|
89
|
-
const lineStart = value.lastIndexOf("\n", start - 1) + 1;
|
|
90
|
-
const lineEnd = value.indexOf("\n", end);
|
|
91
|
-
const finalLineEnd = lineEnd === -1 ? value.length : lineEnd;
|
|
92
|
-
|
|
93
|
-
const block = value.slice(lineStart, finalLineEnd);
|
|
94
|
-
const lines = block.split("\n");
|
|
95
|
-
|
|
96
|
-
let newLines;
|
|
97
|
-
let delta = 0;
|
|
98
|
-
|
|
99
|
-
if (e.shiftKey) {
|
|
100
|
-
// UNINDENT
|
|
101
|
-
newLines = lines.map(line => {
|
|
102
|
-
if (line.startsWith(indent)) {
|
|
103
|
-
delta -= indent.length;
|
|
104
|
-
return line.slice(indent.length);
|
|
105
|
-
}
|
|
106
|
-
if (line.startsWith("\t")) {
|
|
107
|
-
delta -= 1;
|
|
108
|
-
return line.slice(1);
|
|
109
|
-
}
|
|
110
|
-
return line;
|
|
111
|
-
});
|
|
112
|
-
} else {
|
|
113
|
-
// INDENT
|
|
114
|
-
newLines = lines.map(line => indent + line);
|
|
115
|
-
delta = indent.length;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const newBlock = newLines.join("\n");
|
|
119
|
-
|
|
120
|
-
editor1.value =
|
|
121
|
-
value.slice(0, lineStart) +
|
|
122
|
-
newBlock +
|
|
123
|
-
value.slice(finalLineEnd);
|
|
124
|
-
|
|
125
|
-
// Fix selection
|
|
126
|
-
editor1.selectionStart = start + delta;
|
|
127
|
-
editor1.selectionEnd =
|
|
128
|
-
end + delta * newLines.length;
|
|
129
|
-
|
|
130
|
-
highlighted.innerHTML = await _render(editor1.value, language, editor1);
|
|
131
|
-
updateLineNumbers();
|
|
132
|
-
updateCaret();
|
|
133
|
-
}
|
|
134
|
-
editor1.addEventListener("keydown", keyDown);
|
|
135
|
-
editor.appendChild(lineCounter);
|
|
136
|
-
editor.appendChild(highlighted);
|
|
137
|
-
editor.appendChild(editor1);
|
|
138
|
-
editor.appendChild(caret);
|
|
139
|
-
|
|
140
|
-
function updateFontMetrics() {
|
|
141
|
-
const style = getComputedStyle(editor1);
|
|
142
|
-
measureCtx.font = `${style.fontSize} ${style.fontFamily}`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function updateLineNumbers() {
|
|
146
|
-
const lines = editor1.value.split("\n");
|
|
147
|
-
const wrapMap = getWrapMap(editor1.value, 71);
|
|
148
|
-
|
|
149
|
-
let html = "";
|
|
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
|
-
});
|
|
155
|
-
|
|
156
|
-
lineCounter.innerHTML = html;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
highlighted.style.paddingTop = "12px"
|
|
160
|
-
|
|
161
|
-
function getFontMetrics() {
|
|
162
|
-
const metrics = measureCtx.measureText("Mg");
|
|
163
|
-
return {
|
|
164
|
-
ascent: metrics.actualBoundingBoxAscent,
|
|
165
|
-
descent: metrics.actualBoundingBoxDescent,
|
|
166
|
-
height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
const focus = () => {
|
|
170
|
-
caret.style.opacity = "1";
|
|
171
|
-
caret.style.background = caretColor;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
editor1.addEventListener("focus", focus);
|
|
175
|
-
|
|
176
|
-
const blur = () => {
|
|
177
|
-
caret.style.opacity = "0";
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
editor1.addEventListener("blur", blur);
|
|
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
|
-
|
|
204
|
-
function updateCaret() {
|
|
205
|
-
const start = editor1.selectionStart;
|
|
206
|
-
const text = editor1.value.slice(0, start);
|
|
207
|
-
|
|
208
|
-
const lines = text.split("\n");
|
|
209
|
-
const lineIndex = lines.length - 1;
|
|
210
|
-
const currentLineText = lines[lineIndex].replace(/\t/g, " ");
|
|
211
|
-
|
|
212
|
-
const style = getComputedStyle(editor1);
|
|
213
|
-
const paddingLeft = parseFloat(style.paddingLeft);
|
|
214
|
-
const paddingTop = parseFloat(style.paddingTop);
|
|
215
|
-
const lineHeight = parseFloat(style.lineHeight) || 20;
|
|
216
|
-
|
|
217
|
-
updateFontMetrics();
|
|
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;
|
|
232
|
-
|
|
233
|
-
totalVisualRows += row;
|
|
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";
|
|
244
|
-
caret.style.height = `${lineHeight - 5}px`;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const input = async () => {
|
|
248
|
-
caret.style.opacity = "1";
|
|
249
|
-
highlighted.innerHTML = await _render(editor1.value, language, editor1);
|
|
250
|
-
updateLineNumbers();
|
|
251
|
-
updateCaret();
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const onDidChangeModelContent = (fn) => {
|
|
255
|
-
editor1.addEventListener("input", fn)
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
editor1.addEventListener("input", input);
|
|
259
|
-
const scroll = async () => {
|
|
260
|
-
const x = -editor1.scrollLeft;
|
|
261
|
-
const y = -editor1.scrollTop;
|
|
262
|
-
highlighted.innerHTML = await _render(editor1.value, language, editor1);
|
|
263
|
-
highlighted.style.transform = `translateY(${y}px)`;
|
|
264
|
-
caret.style.transform = `translateY(${y}px)`;
|
|
265
|
-
lineCounter.style.transform = `translateY(${y}px)`;
|
|
266
|
-
};
|
|
267
|
-
editor1.addEventListener("scroll", scroll);
|
|
268
|
-
|
|
269
|
-
updateFontMetrics();
|
|
270
|
-
getFontMetrics();
|
|
271
|
-
|
|
272
|
-
editor1.addEventListener("click", updateCaret);
|
|
273
|
-
editor1.addEventListener("keyup", updateCaret);
|
|
274
|
-
|
|
275
|
-
// Initial caret position
|
|
276
|
-
updateLineNumbers();
|
|
277
|
-
updateCaret();
|
|
278
|
-
|
|
279
|
-
// Focus the editor
|
|
280
|
-
editor1.focus();
|
|
281
|
-
function destroy() {
|
|
282
|
-
editor1.removeEventListener('click', updateCaret);
|
|
283
|
-
editor1.removeEventListener('keyup', updateCaret);
|
|
284
|
-
editor1.removeEventListener('scroll', scroll);
|
|
285
|
-
editor1.removeEventListener('keydown', keyDown);
|
|
286
|
-
editor.innerHTML = "";
|
|
287
|
-
}
|
|
288
|
-
async function refresh() {
|
|
289
|
-
highlighted.innerHTML = await _render(editor1.value, language, editor1);
|
|
290
|
-
updateLineNumbers();
|
|
291
|
-
updateCaret();
|
|
292
|
-
}
|
|
293
|
-
function getValue() {
|
|
294
|
-
return editor1.value;
|
|
295
|
-
}
|
|
296
|
-
function setValue(i) {
|
|
297
|
-
editor1.value = i;
|
|
298
|
-
refresh();
|
|
299
|
-
}
|
|
300
|
-
async function setLanguage(l) {
|
|
301
|
-
if (!languages.registeredLanguages.includes(l)) {
|
|
302
|
-
if (l === "html" || l === "svg") {
|
|
303
|
-
language = "xml";
|
|
304
|
-
l = "xml";
|
|
305
|
-
}
|
|
306
|
-
const mod = await import(`https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/languages/${l}.js`);
|
|
307
|
-
languages.registerLanguage(l, mod)
|
|
308
|
-
}
|
|
309
|
-
language = l;
|
|
310
|
-
refresh();
|
|
311
|
-
}
|
|
312
|
-
return {
|
|
313
|
-
getValue,
|
|
314
|
-
setValue,
|
|
315
|
-
focus,
|
|
316
|
-
setLanguage,
|
|
317
|
-
destroy,
|
|
318
|
-
onDidChangeModelContent,
|
|
319
|
-
};
|
|
320
|
-
}
|
|
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
|
-
|
|
399
|
-
function escapeHtml(str) {
|
|
400
|
-
return str
|
|
401
|
-
.replace(/&/g, "&")
|
|
402
|
-
.replace(/</g, "<")
|
|
403
|
-
.replace(/>/g, ">");
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
async function _render(code, language, editor) {
|
|
407
|
-
// If no editor context provided, just highlight everything (initial load)
|
|
408
|
-
if (!editor) {
|
|
409
|
-
return hljs.highlight(code, { language }).value;
|
|
410
|
-
}
|
|
411
|
-
const scrollTop = editor.scrollTop;
|
|
412
|
-
const scrollBottom = scrollTop + editor.clientHeight;
|
|
413
|
-
const style = getComputedStyle(editor);
|
|
414
|
-
const lineHeight = parseFloat(style.lineHeight);
|
|
415
|
-
|
|
416
|
-
// Calculate visible line range
|
|
417
|
-
const startLine = Math.floor(scrollTop / lineHeight);
|
|
418
|
-
const endLine = Math.ceil(scrollBottom / lineHeight);
|
|
419
|
-
|
|
420
|
-
const lines = code.split("\n");
|
|
421
|
-
|
|
422
|
-
// Add buffer (render extra lines above/below for smooth scrolling)
|
|
423
|
-
const bufferLines = 10;
|
|
424
|
-
const visibleStart = Math.max(0, startLine - bufferLines) || 0;
|
|
425
|
-
const visibleEnd = Math.min(lines.length, endLine + bufferLines) || 0;
|
|
426
|
-
|
|
427
|
-
// Split into three sections
|
|
428
|
-
const beforeLines = lines.slice(0, visibleStart);
|
|
429
|
-
const visibleLines = lines.slice(visibleStart, visibleEnd);
|
|
430
|
-
const afterLines = lines.slice(visibleEnd);
|
|
431
|
-
|
|
432
|
-
// Only highlight visible portion
|
|
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;
|
|
441
|
-
// Plain text for non-visible areas (no highlighting = faster)
|
|
442
|
-
if (highlightedVisible.trim() === "") {
|
|
443
|
-
return hljs.highlight(escapeHtml(code), { language }).value;
|
|
444
|
-
}
|
|
445
|
-
const beforeHTML = "\n".repeat(beforeLines.length);
|
|
446
|
-
const afterHTML = "\n".repeat(afterLines.length);
|
|
447
|
-
return beforeHTML + highlightedVisible + afterHTML;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
const editor = {
|
|
451
|
-
createEditor
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
module.exports = editor;
|
|
455
|
-
|
|
456
|
-
/*
|
|
457
|
-
|
|
458
|
-
createEditor: creates the main editor, using html Elements like, textarea and etc.
|
|
459
|
-
refresh: refreshs the editor
|
|
460
|
-
getValue: return the current value from the editor
|
|
461
|
-
setValue: sets a certain value to the editor's value
|
|
462
|
-
focus: focusses the editor
|
|
463
|
-
destroy: destroys and removeEventListeners
|
|
464
|
-
updateCaret: updates the caret positon, height and other metrics using math
|
|
465
|
-
updateLineNumbers: just add new line numbers
|
|
466
|
-
getFontMetrics: returns back the font's metrics like height
|
|
467
|
-
updateFontMetrics: update the fontMetrics
|
|
468
|
-
|
|
469
|
-
*/
|
package/commonjs/index.js
DELETED
package/commonjs/languages.js
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
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
|
-
|
|
21
|
-
let registeredLanguages = [];
|
|
22
|
-
|
|
23
|
-
function init() {
|
|
24
|
-
// Register all languages
|
|
25
|
-
hljs.registerLanguage("javascript", javascript);
|
|
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" });
|
|
33
|
-
hljs.registerLanguage("css", css);
|
|
34
|
-
hljs.registerLanguage("python", python);
|
|
35
|
-
hljs.registerLanguage("java", java);
|
|
36
|
-
hljs.registerLanguage("csharp", csharp);
|
|
37
|
-
hljs.registerLanguage("cpp", cpp);
|
|
38
|
-
hljs.registerLanguage("ruby", ruby);
|
|
39
|
-
hljs.registerLanguage("php", php);
|
|
40
|
-
hljs.registerLanguage("go", go);
|
|
41
|
-
hljs.registerLanguage("c", c);
|
|
42
|
-
hljs.registerLanguage("rust", rust);
|
|
43
|
-
hljs.registerLanguage("kotlin", kotlin);
|
|
44
|
-
hljs.registerLanguage("swift", swift);
|
|
45
|
-
hljs.registerLanguage("json", json);
|
|
46
|
-
hljs.registerLanguage("bash", bash);
|
|
47
|
-
hljs.registerLanguage("shell", bash);
|
|
48
|
-
hljs.registerLanguage("sh", bash);
|
|
49
|
-
hljs.registerLanguage("plaintext", plaintext);
|
|
50
|
-
registeredLanguages = [
|
|
51
|
-
"javascript",
|
|
52
|
-
"js",
|
|
53
|
-
'jsx',
|
|
54
|
-
"xml",
|
|
55
|
-
"html",
|
|
56
|
-
"svg",
|
|
57
|
-
"python",
|
|
58
|
-
"java",
|
|
59
|
-
"csharp",
|
|
60
|
-
"cpp",
|
|
61
|
-
"ruby",
|
|
62
|
-
"php",
|
|
63
|
-
"go",
|
|
64
|
-
"c",
|
|
65
|
-
"rust",
|
|
66
|
-
"kotlin",
|
|
67
|
-
"swift",
|
|
68
|
-
"typescript",
|
|
69
|
-
"json",
|
|
70
|
-
"bash",
|
|
71
|
-
"shell",
|
|
72
|
-
"sh",
|
|
73
|
-
"plaintext"
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function registerLanguage(name, definition) {
|
|
78
|
-
hljs.registerLanguage(name, definition);
|
|
79
|
-
if (!registeredLanguages.includes(name)) {
|
|
80
|
-
registeredLanguages.push(name);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const languages = {
|
|
85
|
-
init,
|
|
86
|
-
registeredLanguages,
|
|
87
|
-
registerLanguage,
|
|
88
|
-
hljs
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
module.exports = languages;
|
|
92
|
-
|
|
93
|
-
/*
|
|
94
|
-
|
|
95
|
-
registeredLannguage: added for the editor.js can check if the langauge provided already is regsitered or not
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
init: just registers some languages and updates the registeredLangauges variable
|
|
99
|
-
|
|
100
|
-
registerLanguage: just registers a language
|
|
101
|
-
|
|
102
|
-
*/
|
package/commonjs/theme.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
function setTheme(name) {
|
|
2
|
-
const link = document.getElementById("Caret-theme");
|
|
3
|
-
link.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/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;
|
|
File without changes
|
|
File without changes
|