sugar-high 2.2.2 → 2.3.1
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 +27 -1
- package/lib/core.d.ts +7 -1
- package/lib/core.js +6 -2
- package/lib/index.d.ts +2 -0
- package/lib/lang/lua.d.ts +10 -0
- package/lib/lang/lua.js +45 -0
- package/lib/lang/markdown.d.ts +1 -0
- package/lib/lang/markdown.js +83 -0
- package/lib/lang/zig.d.ts +5 -0
- package/lib/lang/zig.js +29 -0
- package/lib/lang.js +4 -2
- package/lib/presets/clike-base.js +2 -2
- package/lib/presets/configs.js +6 -2
- package/lib/presets/javascript-runtime.js +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,32 @@ returns HTML without requiring a DOM.
|
|
|
9
9
|
|
|
10
10
|

|
|
11
11
|
|
|
12
|
+
## Benchmarks
|
|
13
|
+
|
|
14
|
+
Sugar High, PrismJS, and highlight.js highlighting the same generated TypeScript files:
|
|
15
|
+
|
|
16
|
+
<!-- benchmark:start -->
|
|
17
|
+
Measured 2026-09-04 with Node v24.18.0, darwin arm64, Apple M4 Pro.
|
|
18
|
+
|
|
19
|
+
| TypeScript | Sugar High 2.2.2 | PrismJS 1.30.0 | highlight.js 11.12.0 |
|
|
20
|
+
| --- | ---: | ---: | ---: |
|
|
21
|
+
| Minified (KiB) | 9.90 | 14.63 | 29.54 |
|
|
22
|
+
| Gzip (KiB) | 4.35 | 5.47 | 11.12 |
|
|
23
|
+
| 11 KiB | 1.78 | 1.18 | 2.11 |
|
|
24
|
+
| 100 KiB | 18.02 | 15.25 | 23.05 |
|
|
25
|
+
| 500 KiB | 90.98 | 96.41 | 118.39 |
|
|
26
|
+
|
|
27
|
+
Median milliseconds per file; lower is better. 5 timed samples after warmup.
|
|
28
|
+
Sizes are TypeScript-only browser bundles, minified with Bun; gzip uses level 9. Theme CSS is excluded.
|
|
29
|
+
Loading and initialization are excluded. Each library highlights the same generated TypeScript
|
|
30
|
+
into HTML using an explicit language. Grammars and HTML output differ; this is not a measure
|
|
31
|
+
of highlighting quality or browser rendering speed. Results vary by machine and workload.
|
|
32
|
+
<!-- benchmark:end -->
|
|
33
|
+
|
|
34
|
+
Run `pnpm --filter sugar-high benchmark:large --write` to refresh this table and the
|
|
35
|
+
[website comparison](https://sugar-high.vercel.app/#benchmarks) from the same measurement.
|
|
36
|
+
See [benchmark methodology and options](../../docs/BENCHMARK.md).
|
|
37
|
+
|
|
12
38
|
## Install
|
|
13
39
|
|
|
14
40
|
```sh
|
|
@@ -57,7 +83,7 @@ behavior.
|
|
|
57
83
|
|
|
58
84
|
`javascript`, `typescript`, `css`, `python`, `c`, `go`, `java`, `rust`, `json`, `diff`, `shell`,
|
|
59
85
|
`cpp`, `csharp`, `sql`, `html`, `yaml`, `markdown`, `plaintext`, `ruby`, `kotlin`, `swift`, `php`,
|
|
60
|
-
`toml`, `powershell`, `dockerfile`, `graphql`, and `
|
|
86
|
+
`toml`, `powershell`, `dockerfile`, `graphql`, `hcl`, `zig`, and `lua`.
|
|
61
87
|
|
|
62
88
|
Related dialects share one implementation: JavaScript includes JSX, TypeScript includes TSX, JSON
|
|
63
89
|
includes JSONC comments, Shell includes sh/Bash/Zsh, and HCL includes Terraform.
|
package/lib/core.d.ts
CHANGED
|
@@ -89,7 +89,13 @@ export type ParseOptions = {
|
|
|
89
89
|
keywords?: Set<string>
|
|
90
90
|
typeKeywords?: Set<string>
|
|
91
91
|
onCommentStart?: (curr: string, next: string, index: number, code: string) => number | boolean
|
|
92
|
-
onCommentEnd?: (
|
|
92
|
+
onCommentEnd?: (
|
|
93
|
+
prev: string,
|
|
94
|
+
curr: string,
|
|
95
|
+
index: number,
|
|
96
|
+
code: string,
|
|
97
|
+
start: number,
|
|
98
|
+
) => number | boolean
|
|
93
99
|
onLiteral?: (curr: string, index: number, code: string) => number | null | undefined
|
|
94
100
|
onQuote?: (curr: string, index: number, code: string) => number | null | undefined
|
|
95
101
|
quotedKeys?: boolean
|
package/lib/core.js
CHANGED
|
@@ -53,7 +53,7 @@ function tokenize(code, options) {
|
|
|
53
53
|
if (commentType) {
|
|
54
54
|
const start = i++
|
|
55
55
|
while (i < code.length) {
|
|
56
|
-
if (onCommentEnd(code[i - 1], code[i], i, code) == commentType) {
|
|
56
|
+
if (onCommentEnd(code[i - 1], code[i], i, code, start) == commentType) {
|
|
57
57
|
i++
|
|
58
58
|
break
|
|
59
59
|
}
|
|
@@ -110,6 +110,10 @@ function tokenize(code, options) {
|
|
|
110
110
|
if (isWord(curr)) {
|
|
111
111
|
const start = i++
|
|
112
112
|
while (i < code.length && isWord(code[i])) i++
|
|
113
|
+
if (/^\d/.test(curr) && code[i] === '.' && /\d/.test(code[i + 1] || '')) {
|
|
114
|
+
i++
|
|
115
|
+
while (i < code.length && isWord(code[i])) i++
|
|
116
|
+
}
|
|
113
117
|
const value = code.slice(start, i)
|
|
114
118
|
const normalized = normalize(value)
|
|
115
119
|
const type = typeKeywords.has(normalized)
|
|
@@ -154,7 +158,7 @@ export { generate, parse, render, SugarHigh, tokenize }
|
|
|
154
158
|
* @property {Set<string>} [keywords]
|
|
155
159
|
* @property {Set<string>} [typeKeywords]
|
|
156
160
|
* @property {(curr: string, next: string, index: number, code: string) => number | boolean} [onCommentStart]
|
|
157
|
-
* @property {(prev: string, curr: string, index: number, code: string) => number | boolean} [onCommentEnd]
|
|
161
|
+
* @property {(prev: string, curr: string, index: number, code: string, start: number) => number | boolean} [onCommentEnd]
|
|
158
162
|
* @property {(curr: string, index: number, code: string) => number | null | undefined} [onLiteral]
|
|
159
163
|
* @property {(curr: string, index: number, code: string) => number | null | undefined} [onQuote]
|
|
160
164
|
* @property {boolean} [quotedKeys]
|
package/lib/index.d.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const keywords: Set<string>;
|
|
2
|
+
export function onCommentStart(curr: string, next: string, index: number, code: string): number;
|
|
3
|
+
export function onCommentEnd(
|
|
4
|
+
prev: string,
|
|
5
|
+
curr: string,
|
|
6
|
+
index: number,
|
|
7
|
+
code: string,
|
|
8
|
+
start: number,
|
|
9
|
+
): number;
|
|
10
|
+
export function onLiteral(curr: string, index: number, code: string): number;
|
package/lib/lang/lua.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const keywords = new Set([
|
|
4
|
+
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'goto', 'if', 'in',
|
|
5
|
+
'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
|
|
6
|
+
])
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} curr
|
|
10
|
+
* @param {string} next
|
|
11
|
+
* @param {number} index
|
|
12
|
+
* @param {string} code
|
|
13
|
+
*/
|
|
14
|
+
export function onCommentStart(curr, next, index, code) {
|
|
15
|
+
if (curr === '#' && index === 0 && next === '!') return 1
|
|
16
|
+
if (curr + next !== '--') return 0
|
|
17
|
+
return /^--\[=*\[/.test(code.slice(index)) ? 2 : 1
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} _prev
|
|
22
|
+
* @param {string} curr
|
|
23
|
+
* @param {number} index
|
|
24
|
+
* @param {string} code
|
|
25
|
+
* @param {number} start
|
|
26
|
+
*/
|
|
27
|
+
export function onCommentEnd(_prev, curr, index, code, start) {
|
|
28
|
+
if (curr === '\n') return 1
|
|
29
|
+
if (curr !== ']') return 0
|
|
30
|
+
const opener = code.slice(start).match(/^--\[(=*)\[/)
|
|
31
|
+
if (!opener) return 0
|
|
32
|
+
const closing = `]${opener[1]}]`
|
|
33
|
+
if (code.slice(index - closing.length + 1, index + 1) === closing) return 2
|
|
34
|
+
return 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** @param {string} curr @param {number} index @param {string} code */
|
|
38
|
+
export function onLiteral(curr, index, code) {
|
|
39
|
+
if (curr !== '[') return 0
|
|
40
|
+
const opener = code.slice(index).match(/^\[(=*)\[/)
|
|
41
|
+
if (!opener) return 0
|
|
42
|
+
const closing = `]${opener[1]}]`
|
|
43
|
+
const end = code.indexOf(closing, index + opener[0].length)
|
|
44
|
+
return end === -1 ? code.length - index : end + closing.length - index
|
|
45
|
+
}
|
package/lib/lang/markdown.d.ts
CHANGED
package/lib/lang/markdown.js
CHANGED
|
@@ -1,8 +1,91 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
import { T_IDENTIFIER, T_SIGN } from '../shared.js'
|
|
2
3
|
import { onCommentEnd, onCommentStart } from '../presets/plain-base.js'
|
|
3
4
|
|
|
4
5
|
export const keywords = new Set([])
|
|
5
6
|
|
|
7
|
+
/** @param {string} code */
|
|
8
|
+
export const tokenize = (code) => {
|
|
9
|
+
/** @type {Array<[number, string]>} */
|
|
10
|
+
const tokens = []
|
|
11
|
+
let fence = ''
|
|
12
|
+
let fenceQuoted = false
|
|
13
|
+
|
|
14
|
+
/** @param {number} type @param {string} value */
|
|
15
|
+
const append = (type, value) => {
|
|
16
|
+
if (!value) return
|
|
17
|
+
const previous = tokens[tokens.length - 1]
|
|
18
|
+
if (previous?.[0] === type) previous[1] += value
|
|
19
|
+
else tokens.push([type, value])
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const part of code.match(/[^\n]*(?:\n|$)/g) || []) {
|
|
23
|
+
if (!part) continue
|
|
24
|
+
const newline = part.endsWith('\n') ? '\n' : ''
|
|
25
|
+
const line = newline ? part.slice(0, -1) : part
|
|
26
|
+
/** @type {Array<[number, number]>} */
|
|
27
|
+
const ranges = []
|
|
28
|
+
const container = line.match(/^(?: {0,3}>[ \t]?)*/)?.[0] || ''
|
|
29
|
+
if (!fence || fenceQuoted) {
|
|
30
|
+
for (const match of container.matchAll(/>/g)) {
|
|
31
|
+
ranges.push([match.index, match.index + 1])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let start = container.length
|
|
36
|
+
let spaces = 0
|
|
37
|
+
while (spaces < 3 && line[start] === ' ') {
|
|
38
|
+
start++
|
|
39
|
+
spaces++
|
|
40
|
+
}
|
|
41
|
+
const fenceMarker = line.slice(start).match(/^(`{3,}|~{3,})/)?.[1]
|
|
42
|
+
|
|
43
|
+
if (fence) {
|
|
44
|
+
if (
|
|
45
|
+
fenceMarker?.[0] === fence[0] &&
|
|
46
|
+
fenceMarker.length >= fence.length &&
|
|
47
|
+
/^\s*$/.test(line.slice(start + fenceMarker.length))
|
|
48
|
+
) {
|
|
49
|
+
ranges.push([start, start + fenceMarker.length])
|
|
50
|
+
fence = ''
|
|
51
|
+
fenceQuoted = false
|
|
52
|
+
}
|
|
53
|
+
} else if (fenceMarker) {
|
|
54
|
+
ranges.push([start, start + fenceMarker.length])
|
|
55
|
+
fence = fenceMarker
|
|
56
|
+
fenceQuoted = container.includes('>')
|
|
57
|
+
} else {
|
|
58
|
+
const prefix = line.slice(start).match(
|
|
59
|
+
/^(#{1,6}(?=\s)|(?:[-+*]|\d+[.)])(?=\s)|(?:(?:\*\s*){3,}|(?:-\s*){3,}|(?:_\s*){3,})$)/,
|
|
60
|
+
)?.[1]
|
|
61
|
+
if (prefix) ranges.push([start, start + prefix.length])
|
|
62
|
+
|
|
63
|
+
for (const match of line.matchAll(/(`+)(.*?)\1|(\*{1,3}|_{1,3}|~{2})(?=\S)(.*?\S)\3/g)) {
|
|
64
|
+
const marker = match[1] || match[3]
|
|
65
|
+
if (
|
|
66
|
+
line[match.index - 1] === '\\' ||
|
|
67
|
+
(marker[0] === '_' && /\w/.test(line[match.index - 1] || ''))
|
|
68
|
+
) continue
|
|
69
|
+
ranges.push(
|
|
70
|
+
[match.index, match.index + marker.length],
|
|
71
|
+
[match.index + match[0].length - marker.length, match.index + match[0].length],
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let offset = 0
|
|
77
|
+
for (const [rangeStart, rangeEnd] of ranges.sort((a, b) => a[0] - b[0])) {
|
|
78
|
+
if (rangeStart < offset) continue
|
|
79
|
+
append(T_IDENTIFIER, line.slice(offset, rangeStart))
|
|
80
|
+
append(T_SIGN, line.slice(rangeStart, rangeEnd))
|
|
81
|
+
offset = rangeEnd
|
|
82
|
+
}
|
|
83
|
+
append(T_IDENTIFIER, line.slice(offset) + newline)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return tokens
|
|
87
|
+
}
|
|
88
|
+
|
|
6
89
|
export const annotateLine = (line) => {
|
|
7
90
|
let annotation = ''
|
|
8
91
|
if (/^#{1,6}\s/.test(line.value)) annotation = 'markdown-heading'
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const keywords: Set<string>;
|
|
2
|
+
export const typeKeywords: Set<string>;
|
|
3
|
+
export function onCommentStart(curr: string, next: string): number;
|
|
4
|
+
export function onCommentEnd(prev: string, curr: string): number;
|
|
5
|
+
export function onLiteral(curr: string, index: number, code: string): number;
|
package/lib/lang/zig.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const keywords = new Set([
|
|
4
|
+
'addrspace', 'align', 'allowzero', 'and', 'anyframe', 'anytype', 'asm', 'async', 'await', 'break',
|
|
5
|
+
'callconv', 'catch', 'comptime', 'const', 'continue', 'defer', 'else', 'enum', 'errdefer', 'error',
|
|
6
|
+
'export', 'extern', 'false', 'fn', 'for', 'if', 'inline', 'linksection', 'noalias', 'noinline',
|
|
7
|
+
'nosuspend', 'null', 'opaque', 'or', 'orelse', 'packed', 'pub', 'resume', 'return', 'struct',
|
|
8
|
+
'suspend', 'switch', 'test', 'threadlocal', 'true', 'try', 'undefined', 'union', 'unreachable',
|
|
9
|
+
'usingnamespace', 'var', 'volatile', 'while',
|
|
10
|
+
])
|
|
11
|
+
|
|
12
|
+
export const typeKeywords = new Set([
|
|
13
|
+
'anyerror', 'anyopaque', 'bool', 'c_char', 'c_int', 'c_long', 'c_longdouble', 'c_longlong',
|
|
14
|
+
'c_short', 'c_uint', 'c_ulong', 'c_ulonglong', 'c_ushort', 'comptime_float', 'comptime_int',
|
|
15
|
+
'f16', 'f32', 'f64', 'f80', 'f128', 'i8', 'i16', 'i32', 'i64', 'i128', 'isize', 'noreturn',
|
|
16
|
+
'type', 'u8', 'u16', 'u32', 'u64', 'u128', 'usize', 'void',
|
|
17
|
+
])
|
|
18
|
+
|
|
19
|
+
export const onCommentStart = (curr, next) => curr + next === '//' ? 1 : 0
|
|
20
|
+
export const onCommentEnd = (_prev, curr) => curr === '\n' ? 1 : 0
|
|
21
|
+
|
|
22
|
+
/** @param {string} curr @param {number} index @param {string} code */
|
|
23
|
+
export function onLiteral(curr, index, code) {
|
|
24
|
+
if (curr !== '\\' || code[index + 1] !== '\\') return 0
|
|
25
|
+
const lineStart = code.lastIndexOf('\n', index - 1) + 1
|
|
26
|
+
if (code.slice(lineStart, index).trim()) return 0
|
|
27
|
+
const lineEnd = code.indexOf('\n', index + 2)
|
|
28
|
+
return (lineEnd === -1 ? code.length : lineEnd) - index
|
|
29
|
+
}
|
package/lib/lang.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
c, cpp, csharp, css, diff, dockerfile, go, graphql, hcl, html, java, javascript, json,
|
|
5
|
-
kotlin, markdown, nonJavaScript, php, plaintext, powershell, python, ruby, rust, shell, sql,
|
|
6
|
-
swift, toml, typescript, yaml,
|
|
5
|
+
kotlin, lua, markdown, nonJavaScript, php, plaintext, powershell, python, ruby, rust, shell, sql,
|
|
6
|
+
swift, toml, typescript, yaml, zig,
|
|
7
7
|
} from './presets/configs.js'
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -45,6 +45,8 @@ const languages = [
|
|
|
45
45
|
{ id: 'dockerfile', extension: 'dockerfile', aliases: ['docker'], config: nonJavaScript(dockerfile) },
|
|
46
46
|
{ id: 'graphql', extension: 'graphql', aliases: ['gql'], config: nonJavaScript(graphql) },
|
|
47
47
|
{ id: 'hcl', extension: 'hcl', aliases: ['terraform', 'tf'], config: nonJavaScript(hcl) },
|
|
48
|
+
{ id: 'zig', extension: 'zig', aliases: [], config: nonJavaScript(zig) },
|
|
49
|
+
{ id: 'lua', extension: 'lua', aliases: [], config: nonJavaScript(lua) },
|
|
48
50
|
]
|
|
49
51
|
|
|
50
52
|
/** @param {string} value */
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
export const onCommentStart = (currentChar, nextChar) => {
|
|
3
3
|
const pair = currentChar + nextChar
|
|
4
4
|
if (pair === '//') return 1
|
|
5
|
-
if (pair === '/*') return
|
|
5
|
+
if (pair === '/*') return 2
|
|
6
6
|
return 0
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export const onCommentEnd = (prevChar, currChar) => {
|
|
10
10
|
if (currChar === '\n') return 1
|
|
11
|
-
return prevChar + currChar === '*/' ?
|
|
11
|
+
return prevChar + currChar === '*/' ? 2 : 0
|
|
12
12
|
}
|
package/lib/presets/configs.js
CHANGED
|
@@ -14,6 +14,7 @@ import * as java from '../lang/java.js'
|
|
|
14
14
|
import * as javascript from '../lang/javascript.js'
|
|
15
15
|
import * as json from '../lang/json.js'
|
|
16
16
|
import * as kotlin from '../lang/kotlin.js'
|
|
17
|
+
import * as lua from '../lang/lua.js'
|
|
17
18
|
import * as markdown from '../lang/markdown.js'
|
|
18
19
|
import * as php from '../lang/php.js'
|
|
19
20
|
import * as plaintext from '../lang/plaintext.js'
|
|
@@ -27,6 +28,7 @@ import * as swift from '../lang/swift.js'
|
|
|
27
28
|
import * as toml from '../lang/toml.js'
|
|
28
29
|
import * as typescript from '../lang/typescript.js'
|
|
29
30
|
import * as yaml from '../lang/yaml.js'
|
|
31
|
+
import * as zig from '../lang/zig.js'
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* Disable JavaScript-only scanner modes for a non-JavaScript language.
|
|
@@ -71,6 +73,8 @@ function createConfigs() {
|
|
|
71
73
|
dockerfile: nonJavaScript(dockerfile),
|
|
72
74
|
graphql: nonJavaScript(graphql),
|
|
73
75
|
hcl: nonJavaScript(hcl),
|
|
76
|
+
zig: nonJavaScript(zig),
|
|
77
|
+
lua: nonJavaScript(lua),
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
|
|
@@ -83,6 +87,6 @@ function configFor(name) {
|
|
|
83
87
|
|
|
84
88
|
export {
|
|
85
89
|
c, configFor, configs, cpp, csharp, css, diff, dockerfile, go, graphql, hcl, html, java,
|
|
86
|
-
javascript, json, kotlin, markdown, nonJavaScript, php, plaintext, powershell, python, ruby,
|
|
87
|
-
rust, shell, sql, swift, toml, typescript, yaml,
|
|
90
|
+
javascript, json, kotlin, lua, markdown, nonJavaScript, php, plaintext, powershell, python, ruby,
|
|
91
|
+
rust, shell, sql, swift, toml, typescript, yaml, zig,
|
|
88
92
|
}
|
|
@@ -283,6 +283,7 @@ function tokenize(code, options) {
|
|
|
283
283
|
/** @type {0 | 1 | 2} 0 = none; 1 = inside `<open`; 2 = inside `</close` */
|
|
284
284
|
let __jsxTag = 0
|
|
285
285
|
let __jsxExpr = false
|
|
286
|
+
let __jsxTagExpr = 0
|
|
286
287
|
|
|
287
288
|
/** Nested `<open>…</open>` depth (content between tags, including nested elements). */
|
|
288
289
|
let __jsxStack = 0
|
|
@@ -323,6 +324,8 @@ function tokenize(code, options) {
|
|
|
323
324
|
// classify jsx open tag
|
|
324
325
|
if ((lastToken === '<' || lastToken === '</'))
|
|
325
326
|
return T_ENTITY
|
|
327
|
+
if (!__jsxTagExpr && /^\s+$/.test(tokens[tokens.length - 1]?.[1] || ''))
|
|
328
|
+
return T_PROPERTY
|
|
326
329
|
}
|
|
327
330
|
}
|
|
328
331
|
// Then determine if they're jsx literals
|
|
@@ -343,7 +346,7 @@ function tokenize(code, options) {
|
|
|
343
346
|
} else if (token.split('').every(isSign)) {
|
|
344
347
|
return T_SIGN
|
|
345
348
|
} else if (isCls(token)) {
|
|
346
|
-
return inJsxTag() ? T_IDENTIFIER : T_CLS_NUMBER
|
|
349
|
+
return inJsxTag() && !__jsxTagExpr ? T_IDENTIFIER : T_CLS_NUMBER
|
|
347
350
|
} else {
|
|
348
351
|
if (isIdentifier(token)) {
|
|
349
352
|
const isLastPropDot = last[1] === '.' && isIdentifier(beforeLast[1])
|
|
@@ -372,6 +375,10 @@ function tokenize(code, options) {
|
|
|
372
375
|
beforeLast = last
|
|
373
376
|
last = pair
|
|
374
377
|
}
|
|
378
|
+
if (inJsxTag() && type === T_SIGN) {
|
|
379
|
+
if (current === '{') __jsxTagExpr++
|
|
380
|
+
if (current === '}') __jsxTagExpr--
|
|
381
|
+
}
|
|
375
382
|
tokens.push(pair)
|
|
376
383
|
}
|
|
377
384
|
current = ''
|