sugar-high 0.1.0 → 0.2.0
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 +4 -2
- package/lib/index.mjs +77 -61
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Then make your own theme with customized colors by token type and put in global
|
|
|
33
33
|
* Class, number and null
|
|
34
34
|
* sign
|
|
35
35
|
* comment
|
|
36
|
-
*
|
|
36
|
+
* jsxliterals
|
|
37
37
|
*/
|
|
38
38
|
.sh__class {
|
|
39
39
|
color: #2d5e9d;
|
|
@@ -53,7 +53,9 @@ Then make your own theme with customized colors by token type and put in global
|
|
|
53
53
|
.sh__comment {
|
|
54
54
|
color: #a19595;
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
.sh__jsxliterals {
|
|
57
|
+
color: #03066e;
|
|
58
|
+
}
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
### LICENSE
|
package/lib/index.mjs
CHANGED
|
@@ -74,7 +74,7 @@ const signs = new Set([
|
|
|
74
74
|
'\\',
|
|
75
75
|
])
|
|
76
76
|
|
|
77
|
-
const types = [
|
|
77
|
+
export const types = [
|
|
78
78
|
'identifier',
|
|
79
79
|
'keyword',
|
|
80
80
|
'string',
|
|
@@ -83,6 +83,7 @@ const types = [
|
|
|
83
83
|
'comment',
|
|
84
84
|
'break',
|
|
85
85
|
'space',
|
|
86
|
+
'jsxliterals'
|
|
86
87
|
]
|
|
87
88
|
|
|
88
89
|
/**
|
|
@@ -95,6 +96,7 @@ const types = [
|
|
|
95
96
|
* 5 - comment
|
|
96
97
|
* 6 - break
|
|
97
98
|
* 7 - space
|
|
99
|
+
* 8 - jsx literals
|
|
98
100
|
*
|
|
99
101
|
*/
|
|
100
102
|
const [
|
|
@@ -106,6 +108,7 @@ const [
|
|
|
106
108
|
T_COMMENT,
|
|
107
109
|
T_BREAK,
|
|
108
110
|
T_SPACE,
|
|
111
|
+
T_JSX_LITERALS,
|
|
109
112
|
] = types.map((_, i) => i)
|
|
110
113
|
|
|
111
114
|
function isSpaces(str) {
|
|
@@ -124,7 +127,11 @@ function encode(str) {
|
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
function isIdentifierChar(chr) {
|
|
127
|
-
return
|
|
130
|
+
return /^[\w_$]$/.test(chr)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isIdentifier(str) {
|
|
134
|
+
return /[a-zA-Z_$]/.test(str[0]) && (str.length === 1 || /^[\w_$]+$/.test(str.slice(1)))
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
function isStringQuotation(chr) {
|
|
@@ -147,15 +154,9 @@ function isRegexStart(str) {
|
|
|
147
154
|
export function tokenize(code) {
|
|
148
155
|
let current = ''
|
|
149
156
|
let type = -1
|
|
157
|
+
let last = [null, null]
|
|
150
158
|
/** @type {Array<[number, string]>} */
|
|
151
159
|
const tokens = []
|
|
152
|
-
// string.type = 0 for string or string template
|
|
153
|
-
// string.type = 1 for regex
|
|
154
|
-
const string = { entered: false, type: 0 }
|
|
155
|
-
|
|
156
|
-
// comment.type = 0 for single line comments
|
|
157
|
-
// comment.type = 1 for multi-line comments
|
|
158
|
-
const comment = { entered: false, type: 0 }
|
|
159
160
|
|
|
160
161
|
// jsx.tag for entering open or closed tag
|
|
161
162
|
// jsx.child for entering children
|
|
@@ -166,25 +167,14 @@ export function tokenize(code) {
|
|
|
166
167
|
const inJsxLiterals = () => !jsx.tag && jsx.child && !jsx.expr
|
|
167
168
|
|
|
168
169
|
function classify(token) {
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
return T_COMMENT
|
|
172
|
-
} else if (keywords.has(token)) {
|
|
170
|
+
const chr0 = token[0]
|
|
171
|
+
if (keywords.has(token)) {
|
|
173
172
|
return T_KEYWORD
|
|
174
173
|
} else if (token === '\n') {
|
|
175
174
|
return T_BREAK
|
|
176
|
-
} else if (
|
|
177
|
-
(
|
|
178
|
-
// is quoted string
|
|
179
|
-
(isStringQuotation(chr0) && !isStringQuotation(chr1)) ||
|
|
180
|
-
// is regex
|
|
181
|
-
(!jsx.tag && isRegexStart(chr0 + chr1) && token[token.length - 1] === '/')
|
|
182
|
-
)
|
|
183
|
-
) {
|
|
184
|
-
return T_STRING
|
|
185
|
-
} else if (token === ' ') {
|
|
175
|
+
} else if (isSpaces(token)) {
|
|
186
176
|
return T_SPACE
|
|
187
|
-
} else if (signs.has(
|
|
177
|
+
} else if (token.split('').every(ch => signs.has(ch))) {
|
|
188
178
|
return T_SIGN
|
|
189
179
|
} else if (
|
|
190
180
|
!inJsxLiterals() &&
|
|
@@ -196,14 +186,19 @@ export function tokenize(code) {
|
|
|
196
186
|
) {
|
|
197
187
|
return T_CLS_NUMBER
|
|
198
188
|
} else {
|
|
199
|
-
return T_IDENTIFIER
|
|
189
|
+
return isIdentifier(token) ? T_IDENTIFIER : inJsxLiterals() ? T_JSX_LITERALS : T_STRING
|
|
200
190
|
}
|
|
201
191
|
}
|
|
202
192
|
|
|
203
|
-
const append = () => {
|
|
193
|
+
const append = (_type) => {
|
|
204
194
|
if (current) {
|
|
205
|
-
type = classify(current)
|
|
206
|
-
|
|
195
|
+
type = _type || classify(current)
|
|
196
|
+
/** @type [number, string] */
|
|
197
|
+
const pair = [type, current]
|
|
198
|
+
if (type !== T_SPACE && type !== T_BREAK) {
|
|
199
|
+
last = pair
|
|
200
|
+
}
|
|
201
|
+
tokens.push(pair)
|
|
207
202
|
}
|
|
208
203
|
current = ''
|
|
209
204
|
}
|
|
@@ -222,48 +217,69 @@ export function tokenize(code) {
|
|
|
222
217
|
jsx.tag = !(isOpenElementEnd || isCloseElementEnd)
|
|
223
218
|
}
|
|
224
219
|
// if it's not in a jsx tag declaration or a string, close child if next is jsx close tag
|
|
225
|
-
if (!jsx.tag &&
|
|
220
|
+
if (!jsx.tag && (curr === '<' && isIdentifierChar(next) || c_n === '</')) {
|
|
226
221
|
jsx.tag = true
|
|
227
222
|
jsx.child = false
|
|
228
223
|
}
|
|
229
224
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
) {
|
|
234
|
-
string.entered = true
|
|
235
|
-
string.type = isStringQuotation(curr) ? 0 : 1
|
|
225
|
+
const isQuotationChar = isStringQuotation(curr)
|
|
226
|
+
const isRegexChar = !jsx.tag && isRegexStart(c_n)
|
|
227
|
+
if (isQuotationChar || isRegexChar) {
|
|
236
228
|
append()
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
229
|
+
const [lastType, lastToken] = last
|
|
230
|
+
// Special cases that are not considered as regex:
|
|
231
|
+
// * (expr) / expr: `()[]` before `/` is still in expression
|
|
232
|
+
// * <non comment start>/ expr: non comment start before `/` is not regex
|
|
233
|
+
if (
|
|
234
|
+
isRegexChar &&
|
|
235
|
+
lastType &&
|
|
236
|
+
!(
|
|
237
|
+
(lastType === T_SIGN && !'()[]'.includes(lastToken)) ||
|
|
238
|
+
lastType === T_COMMENT
|
|
239
|
+
)
|
|
240
|
+
) {
|
|
241
|
+
current = curr
|
|
245
242
|
append()
|
|
243
|
+
continue
|
|
246
244
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
245
|
+
const start = i++
|
|
246
|
+
|
|
247
|
+
const isInline = () => i < code.length && code[i] !== '\n'
|
|
248
|
+
// string quotation
|
|
249
|
+
if (isQuotationChar) {
|
|
250
|
+
for (; isInline(); i++) {
|
|
251
|
+
if (isStringQuotation(code[i])) {
|
|
252
|
+
break
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
// regex
|
|
257
|
+
for (; isInline(); i++) {
|
|
258
|
+
if (code[i] === '/' && code[i - 1] !== '\\') {
|
|
259
|
+
// append regex flags
|
|
260
|
+
while (start !== i && /^[a-z]$/.test(code[i + 1]) && isInline()) {
|
|
261
|
+
i++
|
|
262
|
+
};
|
|
263
|
+
break
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (start !== i) {
|
|
268
|
+
current = code.slice(start, i + 1)
|
|
269
|
+
append(T_STRING)
|
|
270
|
+
} else {
|
|
271
|
+
current = curr
|
|
264
272
|
append()
|
|
265
|
-
i++
|
|
266
273
|
}
|
|
274
|
+
} else if (isCommentStart(c_n)) {
|
|
275
|
+
const start = i
|
|
276
|
+
if (next === '/') {
|
|
277
|
+
for (; i < code.length && code[i] !== '\n'; i++);
|
|
278
|
+
} else {
|
|
279
|
+
for (; i < code.length && code[i - 1] + code[i] !== '*/'; i++);
|
|
280
|
+
}
|
|
281
|
+
current = code.slice(start, i + 1)
|
|
282
|
+
append(T_COMMENT)
|
|
267
283
|
} else if (curr === ' ' || curr === '\n') {
|
|
268
284
|
if (
|
|
269
285
|
curr === ' ' &&
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sugar-high",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": "./lib/index.mjs",
|
|
6
6
|
"description": "Super lightweight JSX syntax highlighter",
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
],
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"scripts": {
|
|
14
|
+
"test": "vitest run",
|
|
14
15
|
"dev": "vite docs",
|
|
15
16
|
"build": "vite build docs"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
|
18
|
-
"vite": "2.
|
|
19
|
+
"vite": "^2.8.6",
|
|
20
|
+
"vitest": "^0.5.9"
|
|
19
21
|
}
|
|
20
22
|
}
|