juxscript 1.1.45 → 1.1.47
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/index.d.ts.map +1 -1
- package/lib/components/code.d.ts.map +1 -1
- package/lib/components/code.js +4 -8
- package/lib/components/code.ts +6 -11
- package/lib/utils/codeparser.d.ts +44 -3
- package/lib/utils/codeparser.d.ts.map +1 -1
- package/lib/utils/codeparser.js +131 -69
- package/lib/utils/codeparser.ts +151 -77
- package/package.json +1 -1
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAOxD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GAAG;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;IAChD,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAS;gBAE9B,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAYjD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAIhD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAsBtC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKrC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK9B,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IASrC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,aAAa;
|
|
1
|
+
{"version":3,"file":"code.d.ts","sourceRoot":"","sources":["code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAOxD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GAAG;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;IAChD,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAS;gBAE9B,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAYjD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAIhD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI;IAsBtC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAKrC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK9B,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IASrC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0B1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAezB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI;CAgFnE;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAEhE"}
|
package/lib/components/code.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
-
import {
|
|
2
|
+
import { codeParser } from '../utils/codeparser.js'; // ✅ Default import
|
|
3
3
|
// Event definitions
|
|
4
4
|
const TRIGGER_EVENTS = [];
|
|
5
5
|
const CALLBACK_EVENTS = [];
|
|
@@ -68,7 +68,7 @@ export class Code extends BaseComponent {
|
|
|
68
68
|
* Parse code content into individual lines with tokens
|
|
69
69
|
*/
|
|
70
70
|
_parseLines() {
|
|
71
|
-
return
|
|
71
|
+
return codeParser.parse(this.state.content, this.state.language);
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
74
|
* Rebuild all line elements
|
|
@@ -88,10 +88,6 @@ export class Code extends BaseComponent {
|
|
|
88
88
|
const lineEl = this._createLineElement(parsedLine, lineNumber, isHighlighted);
|
|
89
89
|
codeEl.appendChild(lineEl);
|
|
90
90
|
});
|
|
91
|
-
// Re-run Prism if available
|
|
92
|
-
if (window.Prism && this._codeContainer) {
|
|
93
|
-
window.Prism.highlightAllUnder(this._codeContainer);
|
|
94
|
-
}
|
|
95
91
|
}
|
|
96
92
|
/**
|
|
97
93
|
* Create a single line element with parsed tokens
|
|
@@ -113,7 +109,7 @@ export class Code extends BaseComponent {
|
|
|
113
109
|
// Line content with syntax highlighting
|
|
114
110
|
const lineCode = document.createElement('span');
|
|
115
111
|
lineCode.className = 'jux-code-line-content';
|
|
116
|
-
lineCode.innerHTML =
|
|
112
|
+
lineCode.innerHTML = codeParser.renderLine(parsedLine);
|
|
117
113
|
lineEl.appendChild(lineCode);
|
|
118
114
|
return lineEl;
|
|
119
115
|
}
|
|
@@ -139,7 +135,7 @@ export class Code extends BaseComponent {
|
|
|
139
135
|
if (!Code._syntaxCSSInjected) {
|
|
140
136
|
const style = document.createElement('style');
|
|
141
137
|
style.id = 'jux-code-syntax-css';
|
|
142
|
-
style.textContent =
|
|
138
|
+
style.textContent = codeParser.getCSS();
|
|
143
139
|
document.head.appendChild(style);
|
|
144
140
|
Code._syntaxCSSInjected = true;
|
|
145
141
|
}
|
package/lib/components/code.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
-
import {
|
|
2
|
+
import { codeParser } from '../utils/codeparser.js'; // ✅ Default import
|
|
3
3
|
|
|
4
4
|
// Event definitions
|
|
5
5
|
const TRIGGER_EVENTS = [] as const;
|
|
@@ -103,8 +103,8 @@ export class Code extends BaseComponent<CodeState> {
|
|
|
103
103
|
/**
|
|
104
104
|
* Parse code content into individual lines with tokens
|
|
105
105
|
*/
|
|
106
|
-
private _parseLines(): ReturnType<typeof
|
|
107
|
-
return
|
|
106
|
+
private _parseLines(): ReturnType<typeof codeParser.parse> {
|
|
107
|
+
return codeParser.parse(this.state.content, this.state.language);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
@@ -124,21 +124,16 @@ export class Code extends BaseComponent<CodeState> {
|
|
|
124
124
|
parsedLines.forEach((parsedLine, index) => {
|
|
125
125
|
const lineNumber = startLine + index;
|
|
126
126
|
const isHighlighted = highlightLines.includes(lineNumber);
|
|
127
|
-
|
|
128
127
|
const lineEl = this._createLineElement(parsedLine, lineNumber, isHighlighted);
|
|
129
128
|
codeEl.appendChild(lineEl);
|
|
130
129
|
});
|
|
131
130
|
|
|
132
|
-
// Re-run Prism if available
|
|
133
|
-
if ((window as any).Prism && this._codeContainer) {
|
|
134
|
-
(window as any).Prism.highlightAllUnder(this._codeContainer);
|
|
135
|
-
}
|
|
136
131
|
}
|
|
137
132
|
|
|
138
133
|
/**
|
|
139
134
|
* Create a single line element with parsed tokens
|
|
140
135
|
*/
|
|
141
|
-
private _createLineElement(parsedLine: ReturnType<typeof
|
|
136
|
+
private _createLineElement(parsedLine: ReturnType<typeof codeParser.parse>[0], lineNumber: number, highlighted: boolean): HTMLElement {
|
|
142
137
|
const lineEl = document.createElement('div');
|
|
143
138
|
lineEl.className = 'jux-code-line';
|
|
144
139
|
lineEl.setAttribute('data-line', String(lineNumber));
|
|
@@ -158,7 +153,7 @@ export class Code extends BaseComponent<CodeState> {
|
|
|
158
153
|
// Line content with syntax highlighting
|
|
159
154
|
const lineCode = document.createElement('span');
|
|
160
155
|
lineCode.className = 'jux-code-line-content';
|
|
161
|
-
lineCode.innerHTML =
|
|
156
|
+
lineCode.innerHTML = codeParser.renderLine(parsedLine);
|
|
162
157
|
lineEl.appendChild(lineCode);
|
|
163
158
|
|
|
164
159
|
return lineEl;
|
|
@@ -189,7 +184,7 @@ export class Code extends BaseComponent<CodeState> {
|
|
|
189
184
|
if (!Code._syntaxCSSInjected) {
|
|
190
185
|
const style = document.createElement('style');
|
|
191
186
|
style.id = 'jux-code-syntax-css';
|
|
192
|
-
style.textContent =
|
|
187
|
+
style.textContent = codeParser.getCSS();
|
|
193
188
|
document.head.appendChild(style);
|
|
194
189
|
Code._syntaxCSSInjected = true;
|
|
195
190
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token type to CSS class mapping
|
|
3
|
+
*/
|
|
4
|
+
export declare const TOKEN_CLASS_MAP: Record<string, string>;
|
|
1
5
|
export interface ParsedToken {
|
|
2
6
|
type: string;
|
|
3
7
|
value: string;
|
|
@@ -12,17 +16,54 @@ export interface ParsedLine {
|
|
|
12
16
|
tokens: ParsedToken[];
|
|
13
17
|
raw: string;
|
|
14
18
|
}
|
|
19
|
+
export declare class CodeParser {
|
|
20
|
+
private static _cache;
|
|
21
|
+
/**
|
|
22
|
+
* Parse code with caching
|
|
23
|
+
*/
|
|
24
|
+
static parse(code: string, language?: string): ParsedLine[];
|
|
25
|
+
private static _parseCode;
|
|
26
|
+
/**
|
|
27
|
+
* ✅ NEW: Strip TypeScript type annotations for parsing
|
|
28
|
+
* This is a simple regex-based approach - not perfect but works for most cases
|
|
29
|
+
*/
|
|
30
|
+
private static _stripTypeScriptTypes;
|
|
31
|
+
/**
|
|
32
|
+
* Clear cache (useful for development)
|
|
33
|
+
*/
|
|
34
|
+
static clearCache(): void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get CSS class for a token
|
|
38
|
+
*/
|
|
39
|
+
export declare function getTokenClass(token: any): string;
|
|
15
40
|
/**
|
|
16
|
-
*
|
|
17
|
-
* Returns token-level information for syntax highlighting
|
|
41
|
+
* Check if a word is a JavaScript keyword
|
|
18
42
|
*/
|
|
19
|
-
export declare function
|
|
43
|
+
export declare function isKeyword(word: string): boolean;
|
|
20
44
|
/**
|
|
21
45
|
* Render a parsed line as HTML with spans
|
|
22
46
|
*/
|
|
23
47
|
export declare function renderLineWithTokens(parsedLine: ParsedLine): string;
|
|
48
|
+
/**
|
|
49
|
+
* Escape HTML entities
|
|
50
|
+
*/
|
|
51
|
+
export declare function escapeHtml(text: string): string;
|
|
24
52
|
/**
|
|
25
53
|
* Generate CSS for syntax highlighting
|
|
26
54
|
*/
|
|
27
55
|
export declare function getSyntaxHighlightCSS(): string;
|
|
56
|
+
/**
|
|
57
|
+
* Main parser export with utilities
|
|
58
|
+
*/
|
|
59
|
+
export declare const codeParser: {
|
|
60
|
+
parse: typeof CodeParser.parse;
|
|
61
|
+
renderLine: typeof renderLineWithTokens;
|
|
62
|
+
getCSS: typeof getSyntaxHighlightCSS;
|
|
63
|
+
getTokenClass: typeof getTokenClass;
|
|
64
|
+
isKeyword: typeof isKeyword;
|
|
65
|
+
escapeHtml: typeof escapeHtml;
|
|
66
|
+
TOKEN_CLASS_MAP: Record<string, string>;
|
|
67
|
+
};
|
|
68
|
+
export default CodeParser;
|
|
28
69
|
//# sourceMappingURL=codeparser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeparser.d.ts","sourceRoot":"","sources":["codeparser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codeparser.d.ts","sourceRoot":"","sources":["codeparser.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqClD,CAAC;AAEF,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAmC;IAExD;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAqB,GAAG,UAAU,EAAE;IAYzE,OAAO,CAAC,MAAM,CAAC,UAAU;IA6FzB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAcpC;;OAEG;IACH,MAAM,CAAC,UAAU,IAAI,IAAI;CAG5B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAUhD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS/C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAiCnE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAmB9C;AAID;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;CAQtB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
package/lib/utils/codeparser.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as acorn from 'acorn';
|
|
|
2
2
|
/**
|
|
3
3
|
* Token type to CSS class mapping
|
|
4
4
|
*/
|
|
5
|
-
const TOKEN_CLASS_MAP = {
|
|
5
|
+
export const TOKEN_CLASS_MAP = {
|
|
6
6
|
// Keywords
|
|
7
7
|
'Keyword': 'token-keyword',
|
|
8
8
|
'this': 'token-keyword',
|
|
@@ -36,80 +36,129 @@ const TOKEN_CLASS_MAP = {
|
|
|
36
36
|
'LineComment': 'token-comment',
|
|
37
37
|
'BlockComment': 'token-comment',
|
|
38
38
|
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
39
|
+
export class CodeParser {
|
|
40
|
+
/**
|
|
41
|
+
* Parse code with caching
|
|
42
|
+
*/
|
|
43
|
+
static parse(code, language = 'javascript') {
|
|
44
|
+
const cacheKey = `${language}:${code}`;
|
|
45
|
+
if (this._cache.has(cacheKey)) {
|
|
46
|
+
return this._cache.get(cacheKey);
|
|
47
|
+
}
|
|
48
|
+
const result = this._parseCode(code, language);
|
|
49
|
+
this._cache.set(cacheKey, result);
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
static _parseCode(code, language) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
const codeLines = code.split('\n');
|
|
55
|
+
// ✅ Skip parsing for non-JS languages
|
|
56
|
+
if (!['javascript', 'typescript', 'js', 'ts', 'jsx', 'tsx'].includes(language.toLowerCase())) {
|
|
57
|
+
codeLines.forEach((lineText, index) => {
|
|
58
|
+
lines.push({
|
|
59
|
+
lineNumber: index + 1,
|
|
60
|
+
tokens: [],
|
|
61
|
+
raw: lineText
|
|
62
62
|
});
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
// Sort tokens by position
|
|
66
|
-
tokens.sort((a, b) => a.start - b.start);
|
|
67
|
-
// Group tokens by line
|
|
68
|
-
const tokensByLine = new Map();
|
|
69
|
-
tokens.forEach(token => {
|
|
70
|
-
const line = token.loc.start.line;
|
|
71
|
-
const parsedToken = {
|
|
72
|
-
type: token.type.label || token.type,
|
|
73
|
-
value: token.value !== undefined ? String(token.value) : code.substring(token.start, token.end),
|
|
74
|
-
start: token.start,
|
|
75
|
-
end: token.end,
|
|
76
|
-
line: token.loc.start.line,
|
|
77
|
-
column: token.loc.start.column,
|
|
78
|
-
className: getTokenClass(token)
|
|
79
|
-
};
|
|
80
|
-
if (!tokensByLine.has(line)) {
|
|
81
|
-
tokensByLine.set(line, []);
|
|
82
|
-
}
|
|
83
|
-
tokensByLine.get(line).push(parsedToken);
|
|
84
|
-
});
|
|
85
|
-
// Build lines with tokens
|
|
86
|
-
codeLines.forEach((lineText, index) => {
|
|
87
|
-
const lineNumber = index + 1;
|
|
88
|
-
const lineTokens = tokensByLine.get(lineNumber) || [];
|
|
89
|
-
lines.push({
|
|
90
|
-
lineNumber,
|
|
91
|
-
tokens: lineTokens,
|
|
92
|
-
raw: lineText
|
|
93
63
|
});
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
64
|
+
return lines;
|
|
65
|
+
}
|
|
66
|
+
// ✅ Strip TypeScript types for parsing
|
|
67
|
+
const cleanedCode = language.toLowerCase().includes('typescript') || language.toLowerCase().includes('ts')
|
|
68
|
+
? this._stripTypeScriptTypes(code)
|
|
69
|
+
: code;
|
|
70
|
+
try {
|
|
71
|
+
// Parse with Acorn (supports ES2020+)
|
|
72
|
+
const tokens = [];
|
|
73
|
+
acorn.parse(cleanedCode, {
|
|
74
|
+
ecmaVersion: 2022,
|
|
75
|
+
sourceType: 'module',
|
|
76
|
+
locations: true,
|
|
77
|
+
ranges: true,
|
|
78
|
+
onToken: tokens,
|
|
79
|
+
onComment: (block, text, start, end, startLoc, endLoc) => {
|
|
80
|
+
tokens.push({
|
|
81
|
+
type: block ? 'BlockComment' : 'LineComment',
|
|
82
|
+
value: text,
|
|
83
|
+
start,
|
|
84
|
+
end,
|
|
85
|
+
loc: { start: startLoc, end: endLoc }
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Sort tokens by position
|
|
90
|
+
tokens.sort((a, b) => a.start - b.start);
|
|
91
|
+
// Group tokens by line
|
|
92
|
+
const tokensByLine = new Map();
|
|
93
|
+
tokens.forEach(token => {
|
|
94
|
+
const line = token.loc.start.line;
|
|
95
|
+
const parsedToken = {
|
|
96
|
+
type: token.type.label || token.type,
|
|
97
|
+
value: token.value !== undefined ? String(token.value) : cleanedCode.substring(token.start, token.end),
|
|
98
|
+
start: token.start,
|
|
99
|
+
end: token.end,
|
|
100
|
+
line: token.loc.start.line,
|
|
101
|
+
column: token.loc.start.column,
|
|
102
|
+
className: getTokenClass(token)
|
|
103
|
+
};
|
|
104
|
+
if (!tokensByLine.has(line)) {
|
|
105
|
+
tokensByLine.set(line, []);
|
|
106
|
+
}
|
|
107
|
+
tokensByLine.get(line).push(parsedToken);
|
|
108
|
+
});
|
|
109
|
+
// ✅ Build lines with tokens (use ORIGINAL code, not cleaned)
|
|
110
|
+
codeLines.forEach((lineText, index) => {
|
|
111
|
+
const lineNumber = index + 1;
|
|
112
|
+
const lineTokens = tokensByLine.get(lineNumber) || [];
|
|
113
|
+
lines.push({
|
|
114
|
+
lineNumber,
|
|
115
|
+
tokens: lineTokens,
|
|
116
|
+
raw: lineText // Use original line with types
|
|
117
|
+
});
|
|
104
118
|
});
|
|
105
|
-
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
// Fallback: if parsing fails, return plain lines
|
|
122
|
+
console.warn('[CodeParser] Parse failed, using plain text:', error);
|
|
123
|
+
codeLines.forEach((lineText, index) => {
|
|
124
|
+
lines.push({
|
|
125
|
+
lineNumber: index + 1,
|
|
126
|
+
tokens: [],
|
|
127
|
+
raw: lineText
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return lines;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* ✅ NEW: Strip TypeScript type annotations for parsing
|
|
135
|
+
* This is a simple regex-based approach - not perfect but works for most cases
|
|
136
|
+
*/
|
|
137
|
+
static _stripTypeScriptTypes(code) {
|
|
138
|
+
return code
|
|
139
|
+
// Remove type annotations from parameters: (name: string) -> (name)
|
|
140
|
+
.replace(/(\w+)\s*:\s*[\w<>\[\]|&]+/g, '$1')
|
|
141
|
+
// Remove return type annotations: ): string -> )
|
|
142
|
+
.replace(/\)\s*:\s*[\w<>\[\]|&]+/g, ')')
|
|
143
|
+
// Remove interface/type declarations (keep as comments to preserve line numbers)
|
|
144
|
+
.replace(/^(\s*)(interface|type)\s+\w+.*$/gm, '$1// $2 declaration')
|
|
145
|
+
// Remove as type assertions: value as string -> value
|
|
146
|
+
.replace(/\s+as\s+[\w<>\[\]|&]+/g, '')
|
|
147
|
+
// Remove angle bracket generics: Array<string> -> Array
|
|
148
|
+
.replace(/<[\w<>\[\]|&,\s]+>/g, '');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear cache (useful for development)
|
|
152
|
+
*/
|
|
153
|
+
static clearCache() {
|
|
154
|
+
this._cache.clear();
|
|
106
155
|
}
|
|
107
|
-
return lines;
|
|
108
156
|
}
|
|
157
|
+
CodeParser._cache = new Map();
|
|
109
158
|
/**
|
|
110
159
|
* Get CSS class for a token
|
|
111
160
|
*/
|
|
112
|
-
function getTokenClass(token) {
|
|
161
|
+
export function getTokenClass(token) {
|
|
113
162
|
const type = token.type.label || token.type;
|
|
114
163
|
// Check if it's a keyword
|
|
115
164
|
if (type === 'name' && token.value && isKeyword(token.value)) {
|
|
@@ -121,7 +170,7 @@ function getTokenClass(token) {
|
|
|
121
170
|
/**
|
|
122
171
|
* Check if a word is a JavaScript keyword
|
|
123
172
|
*/
|
|
124
|
-
function isKeyword(word) {
|
|
173
|
+
export function isKeyword(word) {
|
|
125
174
|
const keywords = [
|
|
126
175
|
'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
|
127
176
|
'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for',
|
|
@@ -165,7 +214,7 @@ export function renderLineWithTokens(parsedLine) {
|
|
|
165
214
|
/**
|
|
166
215
|
* Escape HTML entities
|
|
167
216
|
*/
|
|
168
|
-
function escapeHtml(text) {
|
|
217
|
+
export function escapeHtml(text) {
|
|
169
218
|
return text
|
|
170
219
|
.replace(/&/g, '&')
|
|
171
220
|
.replace(/</g, '<')
|
|
@@ -196,3 +245,16 @@ export function getSyntaxHighlightCSS() {
|
|
|
196
245
|
}
|
|
197
246
|
`;
|
|
198
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Main parser export with utilities
|
|
250
|
+
*/
|
|
251
|
+
export const codeParser = {
|
|
252
|
+
parse: CodeParser.parse,
|
|
253
|
+
renderLine: renderLineWithTokens,
|
|
254
|
+
getCSS: getSyntaxHighlightCSS,
|
|
255
|
+
getTokenClass,
|
|
256
|
+
isKeyword,
|
|
257
|
+
escapeHtml,
|
|
258
|
+
TOKEN_CLASS_MAP
|
|
259
|
+
};
|
|
260
|
+
export default CodeParser;
|
package/lib/utils/codeparser.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as acorn from 'acorn';
|
|
|
3
3
|
/**
|
|
4
4
|
* Token type to CSS class mapping
|
|
5
5
|
*/
|
|
6
|
-
const TOKEN_CLASS_MAP: Record<string, string> = {
|
|
6
|
+
export const TOKEN_CLASS_MAP: Record<string, string> = {
|
|
7
7
|
// Keywords
|
|
8
8
|
'Keyword': 'token-keyword',
|
|
9
9
|
'this': 'token-keyword',
|
|
@@ -58,90 +58,147 @@ export interface ParsedLine {
|
|
|
58
58
|
raw: string;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
61
|
+
export class CodeParser {
|
|
62
|
+
private static _cache = new Map<string, ParsedLine[]>();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Parse code with caching
|
|
66
|
+
*/
|
|
67
|
+
static parse(code: string, language: string = 'javascript'): ParsedLine[] {
|
|
68
|
+
const cacheKey = `${language}:${code}`;
|
|
69
|
+
|
|
70
|
+
if (this._cache.has(cacheKey)) {
|
|
71
|
+
return this._cache.get(cacheKey)!;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const result = this._parseCode(code, language);
|
|
75
|
+
this._cache.set(cacheKey, result);
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private static _parseCode(code: string, language: string): ParsedLine[] {
|
|
80
|
+
const lines: ParsedLine[] = [];
|
|
81
|
+
const codeLines = code.split('\n');
|
|
82
|
+
|
|
83
|
+
// ✅ Skip parsing for non-JS languages
|
|
84
|
+
if (!['javascript', 'typescript', 'js', 'ts', 'jsx', 'tsx'].includes(language.toLowerCase())) {
|
|
85
|
+
codeLines.forEach((lineText, index) => {
|
|
86
|
+
lines.push({
|
|
87
|
+
lineNumber: index + 1,
|
|
88
|
+
tokens: [],
|
|
89
|
+
raw: lineText
|
|
86
90
|
});
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Sort tokens by position
|
|
91
|
-
tokens.sort((a, b) => a.start - b.start);
|
|
92
|
-
|
|
93
|
-
// Group tokens by line
|
|
94
|
-
const tokensByLine: Map<number, ParsedToken[]> = new Map();
|
|
95
|
-
|
|
96
|
-
tokens.forEach(token => {
|
|
97
|
-
const line = token.loc.start.line;
|
|
98
|
-
const parsedToken: ParsedToken = {
|
|
99
|
-
type: token.type.label || token.type,
|
|
100
|
-
value: token.value !== undefined ? String(token.value) : code.substring(token.start, token.end),
|
|
101
|
-
start: token.start,
|
|
102
|
-
end: token.end,
|
|
103
|
-
line: token.loc.start.line,
|
|
104
|
-
column: token.loc.start.column,
|
|
105
|
-
className: getTokenClass(token)
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
if (!tokensByLine.has(line)) {
|
|
109
|
-
tokensByLine.set(line, []);
|
|
110
|
-
}
|
|
111
|
-
tokensByLine.get(line)!.push(parsedToken);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Build lines with tokens
|
|
115
|
-
codeLines.forEach((lineText, index) => {
|
|
116
|
-
const lineNumber = index + 1;
|
|
117
|
-
const lineTokens = tokensByLine.get(lineNumber) || [];
|
|
118
|
-
|
|
119
|
-
lines.push({
|
|
120
|
-
lineNumber,
|
|
121
|
-
tokens: lineTokens,
|
|
122
|
-
raw: lineText
|
|
123
91
|
});
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
92
|
+
return lines;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ✅ Strip TypeScript types for parsing
|
|
96
|
+
const cleanedCode = language.toLowerCase().includes('typescript') || language.toLowerCase().includes('ts')
|
|
97
|
+
? this._stripTypeScriptTypes(code)
|
|
98
|
+
: code;
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
// Parse with Acorn (supports ES2020+)
|
|
102
|
+
const tokens: any[] = [];
|
|
103
|
+
|
|
104
|
+
acorn.parse(cleanedCode, {
|
|
105
|
+
ecmaVersion: 2022,
|
|
106
|
+
sourceType: 'module',
|
|
107
|
+
locations: true,
|
|
108
|
+
ranges: true,
|
|
109
|
+
onToken: tokens,
|
|
110
|
+
onComment: (block, text, start, end, startLoc, endLoc) => {
|
|
111
|
+
tokens.push({
|
|
112
|
+
type: block ? 'BlockComment' : 'LineComment',
|
|
113
|
+
value: text,
|
|
114
|
+
start,
|
|
115
|
+
end,
|
|
116
|
+
loc: { start: startLoc, end: endLoc }
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Sort tokens by position
|
|
122
|
+
tokens.sort((a, b) => a.start - b.start);
|
|
123
|
+
|
|
124
|
+
// Group tokens by line
|
|
125
|
+
const tokensByLine: Map<number, ParsedToken[]> = new Map();
|
|
126
|
+
|
|
127
|
+
tokens.forEach(token => {
|
|
128
|
+
const line = token.loc.start.line;
|
|
129
|
+
const parsedToken: ParsedToken = {
|
|
130
|
+
type: token.type.label || token.type,
|
|
131
|
+
value: token.value !== undefined ? String(token.value) : cleanedCode.substring(token.start, token.end),
|
|
132
|
+
start: token.start,
|
|
133
|
+
end: token.end,
|
|
134
|
+
line: token.loc.start.line,
|
|
135
|
+
column: token.loc.start.column,
|
|
136
|
+
className: getTokenClass(token)
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
if (!tokensByLine.has(line)) {
|
|
140
|
+
tokensByLine.set(line, []);
|
|
141
|
+
}
|
|
142
|
+
tokensByLine.get(line)!.push(parsedToken);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// ✅ Build lines with tokens (use ORIGINAL code, not cleaned)
|
|
146
|
+
codeLines.forEach((lineText, index) => {
|
|
147
|
+
const lineNumber = index + 1;
|
|
148
|
+
const lineTokens = tokensByLine.get(lineNumber) || [];
|
|
149
|
+
|
|
150
|
+
lines.push({
|
|
151
|
+
lineNumber,
|
|
152
|
+
tokens: lineTokens,
|
|
153
|
+
raw: lineText // Use original line with types
|
|
154
|
+
});
|
|
134
155
|
});
|
|
135
|
-
|
|
156
|
+
|
|
157
|
+
} catch (error) {
|
|
158
|
+
// Fallback: if parsing fails, return plain lines
|
|
159
|
+
console.warn('[CodeParser] Parse failed, using plain text:', error);
|
|
160
|
+
codeLines.forEach((lineText, index) => {
|
|
161
|
+
lines.push({
|
|
162
|
+
lineNumber: index + 1,
|
|
163
|
+
tokens: [],
|
|
164
|
+
raw: lineText
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return lines;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* ✅ NEW: Strip TypeScript type annotations for parsing
|
|
174
|
+
* This is a simple regex-based approach - not perfect but works for most cases
|
|
175
|
+
*/
|
|
176
|
+
private static _stripTypeScriptTypes(code: string): string {
|
|
177
|
+
return code
|
|
178
|
+
// Remove type annotations from parameters: (name: string) -> (name)
|
|
179
|
+
.replace(/(\w+)\s*:\s*[\w<>\[\]|&]+/g, '$1')
|
|
180
|
+
// Remove return type annotations: ): string -> )
|
|
181
|
+
.replace(/\)\s*:\s*[\w<>\[\]|&]+/g, ')')
|
|
182
|
+
// Remove interface/type declarations (keep as comments to preserve line numbers)
|
|
183
|
+
.replace(/^(\s*)(interface|type)\s+\w+.*$/gm, '$1// $2 declaration')
|
|
184
|
+
// Remove as type assertions: value as string -> value
|
|
185
|
+
.replace(/\s+as\s+[\w<>\[\]|&]+/g, '')
|
|
186
|
+
// Remove angle bracket generics: Array<string> -> Array
|
|
187
|
+
.replace(/<[\w<>\[\]|&,\s]+>/g, '');
|
|
136
188
|
}
|
|
137
189
|
|
|
138
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Clear cache (useful for development)
|
|
192
|
+
*/
|
|
193
|
+
static clearCache(): void {
|
|
194
|
+
this._cache.clear();
|
|
195
|
+
}
|
|
139
196
|
}
|
|
140
197
|
|
|
141
198
|
/**
|
|
142
199
|
* Get CSS class for a token
|
|
143
200
|
*/
|
|
144
|
-
function getTokenClass(token: any): string {
|
|
201
|
+
export function getTokenClass(token: any): string {
|
|
145
202
|
const type = token.type.label || token.type;
|
|
146
203
|
|
|
147
204
|
// Check if it's a keyword
|
|
@@ -156,7 +213,7 @@ function getTokenClass(token: any): string {
|
|
|
156
213
|
/**
|
|
157
214
|
* Check if a word is a JavaScript keyword
|
|
158
215
|
*/
|
|
159
|
-
function isKeyword(word: string): boolean {
|
|
216
|
+
export function isKeyword(word: string): boolean {
|
|
160
217
|
const keywords = [
|
|
161
218
|
'await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
|
162
219
|
'default', 'delete', 'do', 'else', 'export', 'extends', 'finally', 'for',
|
|
@@ -208,7 +265,7 @@ export function renderLineWithTokens(parsedLine: ParsedLine): string {
|
|
|
208
265
|
/**
|
|
209
266
|
* Escape HTML entities
|
|
210
267
|
*/
|
|
211
|
-
function escapeHtml(text: string): string {
|
|
268
|
+
export function escapeHtml(text: string): string {
|
|
212
269
|
return text
|
|
213
270
|
.replace(/&/g, '&')
|
|
214
271
|
.replace(/</g, '<')
|
|
@@ -240,3 +297,20 @@ export function getSyntaxHighlightCSS(): string {
|
|
|
240
297
|
}
|
|
241
298
|
`;
|
|
242
299
|
}
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Main parser export with utilities
|
|
305
|
+
*/
|
|
306
|
+
export const codeParser = {
|
|
307
|
+
parse: CodeParser.parse,
|
|
308
|
+
renderLine: renderLineWithTokens,
|
|
309
|
+
getCSS: getSyntaxHighlightCSS,
|
|
310
|
+
getTokenClass,
|
|
311
|
+
isKeyword,
|
|
312
|
+
escapeHtml,
|
|
313
|
+
TOKEN_CLASS_MAP
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export default CodeParser;
|