@pfmcodes/caret 0.2.5 → 0.2.7

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,6 +33,14 @@ 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.7
37
+ - another cleanup but this time, with file optimizations and updated comments at the end of each containing short summaries of each function and variables(only some important variables)
38
+
39
+ ### v0.2.6
40
+
41
+ - CommonJs support has been removed to reduce package size
42
+
43
+ ### v0.2.5
36
44
  - Multiple editor instances support
37
45
  - Word-aware line wrapping
38
46
  - Fixed language re-registration bug
@@ -75,7 +83,7 @@ pnpm add @pfmcodes/caret
75
83
  <div id="editor"></div>
76
84
 
77
85
  <script type="module">
78
- import editor from './node_modules/@pfmcodes/caret/esm/index.js';
86
+ import editor from './node_modules/@pfmcodes/caret/index.js';
79
87
 
80
88
  const instance = await editor.editor.createEditor(
81
89
  document.getElementById('editor'),
@@ -93,7 +101,7 @@ pnpm add @pfmcodes/caret
93
101
  ### ES Module Import
94
102
 
95
103
  ```javascript
96
- import editor from './node_modules/@pfmcodes/caret/esm/index.js';
104
+ import editor from './node_modules/@pfmcodes/caret/index.js';
97
105
 
98
106
  // Create editor instance
99
107
  const editorInstance = await editor.editor.createEditor(
@@ -110,14 +118,17 @@ const editorInstance = await editor.editor.createEditor(
110
118
 
111
119
  ```
112
120
  caret/
113
- ├── esm/ # ES Module builds
114
- ├── highlight.js/ # Syntax highlighting support
115
- ├── types/ # TypeScript type definitions
116
- ├── index.css # Core styles
117
- ├── package.json # Package configuration
121
+ ├── types/ # TypeScript type definitions
118
122
  ├── .gitignore # Git ignore rules
119
123
  ├── .npmignore # NPM ignore rules
120
- └── LICENSE # MIT License
124
+ ├── editor.js # main editor file essential for ui
125
+ ├── index.css # Core styles
126
+ ├── index.js # Main file
127
+ ├── langauges.js # handles langauge related tasks
128
+ ├── LICENSE # MIT License
129
+ ├── package.json # Package configuration
130
+ ├── README.md # The file containing instructions and help
131
+ └── theme.js # handles theme related tasks
121
132
  ```
122
133
 
123
134
  ## Usage
@@ -125,8 +136,7 @@ caret/
125
136
  ### JavaScript Editor
126
137
 
127
138
  ```javascript
128
- import editor from './node_modules/@pfmcodes/caret/esm/index.js'; // auto link to commonjs version
129
-
139
+ import editor from './node_modules/@pfmcodes/caret/index.js';
130
140
  const jsEditor = await editor.editor.createEditor(
131
141
  document.getElementById('js-editor'),
132
142
  {
@@ -407,7 +417,7 @@ Here's a complete working example:
407
417
  <div id="editor"></div>
408
418
 
409
419
  <script type="module">
410
- import editor from './node_modules/@pfmcodes/caret/esm/index.js';
420
+ import editor from './node_modules/@pfmcodes/caret/index.js';
411
421
 
412
422
  // Initialize editor
413
423
  const editorInstance = await editor.editor.createEditor(
@@ -1,5 +1,5 @@
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
5
  let numberWrappedCode = 0;
@@ -453,16 +453,24 @@ const editor = {
453
453
 
454
454
  export default editor;
455
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
456
+ /*
457
+ createEditor(editor, data): creates the main editor using HTML elements like textarea, pre, div etc.
458
+ Returns an object with the following methods:
459
+ getValue() -> returns the current value from the editor
460
+ setValue(val) -> sets a value to the editor
461
+ focus() -> focuses the editor
462
+ setLanguage(lang) -> changes the syntax highlighting language
463
+ destroy() -> destroys the editor and removes all event listeners
464
+ onDidChangeModelContent(fn) -> fires a callback whenever the editor content changes
465
+
466
+ Internal functions:
467
+ _render(code, language, editor) -> virtual renderer, only highlights visible lines for performance
468
+ wrapCode(code, wrapAt) -> wraps long lines at word boundaries
469
+ getWrapMap(code, wrapAt) -> returns an array mapping each line to its visual line count
470
+ escapeHtml(str) -> escapes HTML special characters
471
+ updateCaret() -> updates the caret position using canvas font metrics
472
+ updateLineNumbers() -> re-renders line numbers, accounting for wrapped lines
473
+ updateFontMetrics() -> updates the canvas font to match the textarea's computed style
474
+ getFontMetrics() -> returns ascent, descent and height of the current font
475
+ getVisualRow(text, wrapAt) -> returns which visual row and remaining text the caret is on
468
476
  */
package/index.js ADDED
@@ -0,0 +1,22 @@
1
+ import editor from "./editor.js";
2
+ import theme from "./theme.js";
3
+ import language from "./langauges.js";
4
+
5
+ const Caret = {
6
+ editor,
7
+ theme,
8
+ language
9
+ }
10
+ export default Caret;
11
+
12
+ /*
13
+ Caret.editor:
14
+ createEditor() -> backbone of caret, handles ui and abstractions
15
+ Caret.theme:
16
+ setTheme() -> changes the current highlight.js theme
17
+ Caret.langauge:
18
+ init() -> initializes default avaible languages
19
+ registerLanguage() -> registers a new languages
20
+ registeredLangauges[List]: has all the langauges registered
21
+ hljs: the highlight.js module
22
+ */
@@ -22,31 +22,31 @@ let registeredLanguages = [];
22
22
 
23
23
  function init() {
24
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);
25
+ registerLanguage("javascript", javascript);
26
+ registerLanguage("xml", xml);
27
+ registerLanguage("typescript", typescript);
28
+ registerAliases(["jsx"], { languageName: "javascript" });
29
+ registerAliases(["js"], { languageName: "javascript" });
30
+ registerAliases(["ts"], { languageName: "typescript" });
31
+ registerAliases(["html"], { languageName: "xml" });
32
+ registerAliases(["svg"], { languageName: "xml" });
33
+ registerLanguage("css", css);
34
+ registerLanguage("python", python);
35
+ registerLanguage("java", java);
36
+ registerLanguage("csharp", csharp);
37
+ registerLanguage("cpp", cpp);
38
+ registerLanguage("ruby", ruby);
39
+ registerLanguage("php", php);
40
+ registerLanguage("go", go);
41
+ registerLanguage("c", c);
42
+ registerLanguage("rust", rust);
43
+ registerLanguage("kotlin", kotlin);
44
+ registerLanguage("swift", swift);
45
+ registerLanguage("json", json);
46
+ registerLanguage("bash", bash);
47
+ registerLanguage("shell", bash);
48
+ registerLanguage("sh", bash);
49
+ registerLanguage("plaintext", plaintext);
50
50
  registeredLanguages.push(
51
51
  "javascript", "js",
52
52
  "xml", "html", "svg",
@@ -70,9 +70,13 @@ function init() {
70
70
  }
71
71
 
72
72
  function registerLanguage(name, definition) {
73
- hljs.registerLanguage(name, definition);
74
73
  if (!registeredLanguages.includes(name)) {
74
+ hljs.registerLanguage(name, definition);
75
75
  registeredLanguages.push(name);
76
+ return;
77
+ } else {
78
+ console.warn(`Caret: Language ${name} already registered, aborting`);
79
+ return;
76
80
  }
77
81
  }
78
82
 
@@ -86,12 +90,7 @@ const languages = {
86
90
  export default languages;
87
91
 
88
92
  /*
89
-
90
93
  registeredLannguage: added for the editor.js can check if the langauge provided already is regsitered or not
91
-
92
-
93
94
  init: just registers some languages and updates the registeredLangauges variable
94
-
95
95
  registerLanguage: just registers a language
96
-
97
96
  */
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@pfmcodes/caret",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "The official code editor engine for lexius",
5
5
  "type": "module",
6
- "main": "./esm/index.js",
6
+ "main": "./index.js",
7
7
  "types": "./types/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./types/index.d.ts",
11
- "import": "./esm/index.js",
12
- "require": "./commonjs/index.js"
11
+ "default": "./index.js"
13
12
  },
14
- "./commonjs": "./commonjs/index.js",
15
- "./esm": "./esm/index.js"
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/lexius-editor/issues"
38
+ "url": "https://github.com/PFMCODES/Caret/issues"
39
39
  },
40
- "homepage": "https://github.com/PFMCODES/lexius-editor#readme"
40
+ "homepage": "https://github.com/PFMCODES/Caret#readme"
41
41
  }
package/theme.js ADDED
@@ -0,0 +1,14 @@
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
+ const theme = {
7
+ setTheme
8
+ }
9
+
10
+ export default theme;
11
+
12
+ /*
13
+ setTheme() -> changes the current highlight.js theme
14
+ */
package/types/editor.ts CHANGED
@@ -1,5 +1,6 @@
1
+ // @ts-ignore
1
2
  import hljs from "https://esm.sh/@pfmcodes/highlight.js@1.0.0/es/core.js"; // Use default export
2
- import languages from "./languages.ts";
3
+ import languages from "./langauges.ts";
3
4
 
4
5
  languages.init();
5
6
 
@@ -49,6 +50,7 @@ async function createEditor(editor: HTMLElement, data: any) {
49
50
  link.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/${theme}.css`;
50
51
  document.head.appendChild(link);
51
52
  } else {
53
+ // @ts-ignore
52
54
  themeLink.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/${theme}.css`;
53
55
  }
54
56
  } else {
@@ -60,6 +62,7 @@ async function createEditor(editor: HTMLElement, data: any) {
60
62
  link.href = `https://esm.sh/@pfmcodes/highlight.js@1.0.0/styles/hybrid.css`;
61
63
  document.head.appendChild(link);
62
64
  } else {
65
+ // @ts-ignore
63
66
  themeLink.href = `./highlight.js/styles/hybrid.css`;
64
67
  }
65
68
  }
@@ -455,16 +458,24 @@ const editor = {
455
458
 
456
459
  export default editor;
457
460
 
458
- /*
459
-
460
- createEditor: creates the main editor, using html Elements like, textarea and etc.
461
- refresh: refreshs the editor
462
- getValue: return the current value from the editor
463
- setValue: sets a certain value to the editor's value
464
- focus: focusses the editor
465
- destroy: destroys and removeEventListeners
466
- updateCaret: updates the caret positon, height and other metrics using math
467
- updateLineNumbers: just add new line numbers
468
- getFontMetrics: returns back the font's metrics like height
469
- updateFontMetrics: update the fontMetrics
461
+ /*
462
+ createEditor(editor, data): creates the main editor using HTML elements like textarea, pre, div etc.
463
+ Returns an object with the following methods:
464
+ getValue() -> returns the current value from the editor
465
+ setValue(val) -> sets a value to the editor
466
+ focus() -> focuses the editor
467
+ setLanguage(lang) -> changes the syntax highlighting language
468
+ destroy() -> destroys the editor and removes all event listeners
469
+ onDidChangeModelContent(fn) -> fires a callback whenever the editor content changes
470
+
471
+ Internal functions:
472
+ _render(code, language, editor) -> virtual renderer, only highlights visible lines for performance
473
+ wrapCode(code, wrapAt) -> wraps long lines at word boundaries
474
+ getWrapMap(code, wrapAt) -> returns an array mapping each line to its visual line count
475
+ escapeHtml(str) -> escapes HTML special characters
476
+ updateCaret() -> updates the caret position using canvas font metrics
477
+ updateLineNumbers() -> re-renders line numbers, accounting for wrapped lines
478
+ updateFontMetrics() -> updates the canvas font to match the textarea's computed style
479
+ getFontMetrics() -> returns ascent, descent and height of the current font
480
+ getVisualRow(text, wrapAt) -> returns which visual row and remaining text the caret is on
470
481
  */
package/types/index.d.ts CHANGED
@@ -32,3 +32,15 @@ declare module "@pfmcodes/caret" {
32
32
 
33
33
  export default Caret;
34
34
  }
35
+
36
+ /*
37
+ Caret.editor:
38
+ createEditor() -> backbone of caret, handles ui and abstractions
39
+ Caret.theme:
40
+ setTheme() -> changes the current highlight.js theme
41
+ Caret.langauge:
42
+ init() -> initializes default avaible languages
43
+ registerLanguage() -> registers a new languages
44
+ registeredLangauges[List]: has all the langauges registered
45
+ hljs: the highlight.js module
46
+ */
package/types/index.ts CHANGED
@@ -1,10 +1,22 @@
1
1
  import editor from "./editor.ts";
2
2
  import theme from "./theme.ts";
3
- import language from "./languages.ts";
3
+ import language from "./langauges.ts";
4
4
 
5
5
  const Caret = {
6
6
  editor,
7
7
  theme,
8
8
  language
9
9
  }
10
- export default Caret;
10
+ export default Caret;
11
+
12
+ /*
13
+ Caret.editor:
14
+ createEditor() -> backbone of caret, handles ui and abstractions
15
+ Caret.theme:
16
+ setTheme() -> changes the current highlight.js theme
17
+ Caret.langauge:
18
+ init() -> initializes default avaible languages
19
+ registerLanguage() -> registers a new languages
20
+ registeredLangauges[List]: has all the langauges registered
21
+ hljs: the highlight.js module
22
+ */
package/types/theme.ts CHANGED
@@ -3,16 +3,12 @@ function setTheme(name: string) {
3
3
  link.href = `./highlight.js/styles/${name}.css`;
4
4
  }
5
5
 
6
- function removeTheme() {
7
- const link = document.getElementById("Caret-theme") as HTMLLinkElement;
8
- if (link && link.parentNode) {
9
- link.parentNode.removeChild(link);
10
- }
11
- }
12
-
13
6
  const theme = {
14
- removeTheme,
15
7
  setTheme
16
8
  }
17
9
 
18
- export default theme;
10
+ export default theme;
11
+
12
+ /*
13
+ setTheme() -> changes the current highlight.js theme
14
+ */
@@ -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, "&amp;")
402
- .replace(/</g, "&lt;")
403
- .replace(/>/g, "&gt;");
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
@@ -1,10 +0,0 @@
1
- const editor = require("./editor.js");
2
- const theme = require("./theme.js");
3
- const language = require("./languages.js");
4
-
5
- const Caret = {
6
- editor,
7
- theme,
8
- language
9
- }
10
- module.exports = Caret;
@@ -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;
package/esm/index.js DELETED
@@ -1,10 +0,0 @@
1
- import editor from "./editor.js";
2
- import theme from "./theme.js";
3
- import language from "./languages.js";
4
-
5
- const Caret = {
6
- editor,
7
- theme,
8
- language
9
- }
10
- export default Caret;
package/esm/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
- export default theme;
@@ -1,4 +0,0 @@
1
- declare module "https://esm.sh/@pfmcodes/highlight.js@1.0.0/*" {
2
- const mod: any;
3
- export default mod;
4
- }
File without changes