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 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;AAElD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAGzC,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiDf,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;IAyBrB;;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"}
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"}
@@ -1,5 +1,5 @@
1
1
  import { BaseComponent } from './base/BaseComponent.js';
2
- import { parseCode, renderLineWithTokens, getSyntaxHighlightCSS } from '../utils/codeparser.js';
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 parseCode(this.state.content, this.state.language);
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 = renderLineWithTokens(parsedLine);
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 = getSyntaxHighlightCSS();
138
+ style.textContent = codeParser.getCSS();
143
139
  document.head.appendChild(style);
144
140
  Code._syntaxCSSInjected = true;
145
141
  }
@@ -1,5 +1,5 @@
1
1
  import { BaseComponent } from './base/BaseComponent.js';
2
- import { parseCode, renderLineWithTokens, getSyntaxHighlightCSS } from '../utils/codeparser.js';
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 parseCode> {
107
- return parseCode(this.state.content, this.state.language);
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 parseCode>[0], lineNumber: number, highlighted: boolean): HTMLElement {
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 = renderLineWithTokens(parsedLine);
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 = getSyntaxHighlightCSS();
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
- * Parse JavaScript/TypeScript code using Acorn
17
- * Returns token-level information for syntax highlighting
41
+ * Check if a word is a JavaScript keyword
18
42
  */
19
- export declare function parseCode(code: string, language?: string): ParsedLine[];
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":"AA4CA,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;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAqB,GAAG,UAAU,EAAE,CA0ErF;AA+BD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAiCnE;AAcD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAmB9C"}
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"}
@@ -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
- * Parse JavaScript/TypeScript code using Acorn
41
- * Returns token-level information for syntax highlighting
42
- */
43
- export function parseCode(code, language = 'javascript') {
44
- const lines = [];
45
- const codeLines = code.split('\n');
46
- try {
47
- // Parse with Acorn (supports ES2020+)
48
- const tokens = [];
49
- acorn.parse(code, {
50
- ecmaVersion: 2022,
51
- sourceType: 'module',
52
- locations: true,
53
- ranges: true,
54
- onToken: tokens,
55
- onComment: (block, text, start, end, startLoc, endLoc) => {
56
- tokens.push({
57
- type: block ? 'BlockComment' : 'LineComment',
58
- value: text,
59
- start,
60
- end,
61
- loc: { start: startLoc, end: endLoc }
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
- catch (error) {
97
- // Fallback: if parsing fails, return plain lines
98
- console.warn('[CodeParser] Parse failed, using plain text:', error);
99
- codeLines.forEach((lineText, index) => {
100
- lines.push({
101
- lineNumber: index + 1,
102
- tokens: [],
103
- raw: lineText
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, '&amp;')
171
220
  .replace(/</g, '&lt;')
@@ -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;
@@ -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
- * Parse JavaScript/TypeScript code using Acorn
63
- * Returns token-level information for syntax highlighting
64
- */
65
- export function parseCode(code: string, language: string = 'javascript'): ParsedLine[] {
66
- const lines: ParsedLine[] = [];
67
- const codeLines = code.split('\n');
68
-
69
- try {
70
- // Parse with Acorn (supports ES2020+)
71
- const tokens: any[] = [];
72
-
73
- acorn.parse(code, {
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 }
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
- } catch (error) {
127
- // Fallback: if parsing fails, return plain lines
128
- console.warn('[CodeParser] Parse failed, using plain text:', error);
129
- codeLines.forEach((lineText, index) => {
130
- lines.push({
131
- lineNumber: index + 1,
132
- tokens: [],
133
- raw: lineText
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
- return lines;
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, '&amp;')
214
271
  .replace(/</g, '&lt;')
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.45",
3
+ "version": "1.1.47",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",