sugar-high 0.4.1 → 0.4.2

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.
Files changed (2) hide show
  1. package/lib/index.mjs +107 -47
  2. package/package.json +2 -2
package/lib/index.mjs CHANGED
@@ -168,16 +168,21 @@ export function tokenize(code) {
168
168
  /** @type {Array<[number, string]>} */
169
169
  const tokens = []
170
170
 
171
- // jsx.tag for entering open or closed tags
172
- // jsx.close for is the closing sign of open or close tags
173
- // jsx.child for entering children
174
- // jsx.expr for entering {expression}
175
- // jsx.end for entering close tag
176
- /** @type {{ tag: boolean; close: boolean; child: boolean; expr: boolean; end: boolean }} */
177
- const jsx = { tag: false, close: false, child: false, expr: false, end: false }
178
-
179
- const inJsxTag = () => jsx.tag || jsx.close
180
- const inJsxLiterals = () => !inJsxTag() && jsx.child && !jsx.expr
171
+ let __jsxEnter = false
172
+ /**
173
+ * @type {0 | 1 | 2}
174
+ * 0 for not in jsx
175
+ * 1 for open jsx tag
176
+ * 2 for closing jsx tag
177
+ **/
178
+ let __jsxTag = 0
179
+ let __jsxExpr = false
180
+
181
+ // only match paired (open + close) tags, not self-closing tags
182
+ let __jsxStack = 0
183
+ const __jsxChild = () => __jsxEnter && !__jsxExpr && !__jsxTag
184
+ const inJsxTag = () => __jsxTag && !__jsxChild()
185
+ const inJsxLiterals = () => !__jsxTag && __jsxChild() && !__jsxExpr && __jsxStack > 0
181
186
 
182
187
  /**
183
188
  *
@@ -185,7 +190,10 @@ export function tokenize(code) {
185
190
  * @returns {number}
186
191
  */
187
192
  function classify(token) {
188
- if (keywords.has(token)) {
193
+ const isJsxLiterals = inJsxLiterals()
194
+ if (isJsxLiterals) {
195
+ return T_JSX_LITERALS
196
+ } else if (keywords.has(token)) {
189
197
  return last[1] === '.' ? T_IDENTIFIER : T_KEYWORD
190
198
  } else if (token === '\n') {
191
199
  return T_BREAK
@@ -193,8 +201,6 @@ export function tokenize(code) {
193
201
  return T_SPACE
194
202
  } else if (token.split('').every(ch => signs.has(ch))) {
195
203
  return T_SIGN
196
- } else if (inJsxLiterals()) {
197
- return T_JSX_LITERALS
198
204
  } else if (isCls(token)) {
199
205
  return inJsxTag() ? T_IDENTIFIER : T_CLS_NUMBER
200
206
  } else {
@@ -220,35 +226,85 @@ export function tokenize(code) {
220
226
  const next = code[i + 1]
221
227
  const p_c = prev + curr // previous and current
222
228
  const c_n = curr + next // current and next
223
- const isJsxLiterals = inJsxLiterals()
224
229
 
225
- if (jsx.close && (last[1] === '>' || last[1] === '/>')) {
226
- jsx.close = false
227
- }
228
230
 
229
- if (!jsx.tag && (c_n === '</' || c_n === '/>')) {
230
- jsx.end = true
231
+ if (__jsxChild()) {
232
+ if (curr === '{') {
233
+ append()
234
+ current = curr
235
+ append(T_SIGN)
236
+ __jsxExpr = true
237
+ continue
238
+ }
231
239
  }
232
240
 
233
- if (jsx.tag) {
234
- const isOpenElementEnd = curr === '>'
235
- const isCloseElementEnd = p_c === '/>'
236
- jsx.child = !jsx.end && (isOpenElementEnd && !isCloseElementEnd)
241
+ if (__jsxEnter) {
242
+ // <: open tag sign
243
+ if (!__jsxTag && curr === '<') {
244
+ append()
245
+ __jsxTag = 1
246
+ current = curr
247
+ if (next === '/') {
248
+ __jsxTag = 2
249
+ current = c_n
250
+ i++
251
+ }
252
+ append(T_SIGN)
253
+ continue
254
+ }
255
+ if (__jsxTag) {
256
+ // >: open tag close sign or closing tag closing sign
257
+ if (curr === '>' && prev !== '/') {
258
+ append()
259
+ if (__jsxTag === 1) {
260
+ __jsxTag = 0
261
+ __jsxStack++
262
+ } else {
263
+ __jsxTag = 0
264
+ __jsxEnter = false
265
+ }
266
+ current = curr
267
+ append(T_SIGN)
268
+ continue
269
+ }
270
+
271
+ // >: tag self close sign or close tag sign
272
+ if (c_n === '/>' || c_n === '</') {
273
+ append()
274
+ if (c_n === '/>') {
275
+ __jsxTag = 0
276
+ }
277
+ if (c_n === '</') {
278
+ __jsxStack--
279
+ }
280
+ current = c_n
281
+ i++
282
+ append(T_SIGN)
283
+ continue
284
+ }
237
285
 
238
- jsx.tag = !(isOpenElementEnd || isCloseElementEnd)
239
- jsx.close = isOpenElementEnd || isCloseElementEnd
240
- if (jsx.end && (isCloseElementEnd || isOpenElementEnd)) {
241
- jsx.end = false
286
+ // <: open tag sign
287
+ if (curr === '<') {
288
+ append()
289
+ current = curr
290
+ append(T_SIGN)
291
+ continue
292
+ }
242
293
  }
243
294
  }
295
+
244
296
  // if it's not in a jsx tag declaration or a string, close child if next is jsx close tag
245
- if (!jsx.tag && (curr === '<' && isIdentifierChar(next) || c_n === '</')) {
246
- jsx.tag = true
247
- jsx.child = false
297
+ if (!__jsxTag && (curr === '<' && isIdentifierChar(next) || c_n === '</')) {
298
+ __jsxTag = next === '/' ? 2 : 1
299
+
300
+ if (curr === '<' && next !== '/') {
301
+ __jsxEnter = true
302
+ }
248
303
  }
249
304
 
250
305
  const isQuotationChar = isStringQuotation(curr)
251
- const isRegexChar = !jsx.tag && isRegexStart(c_n)
306
+ const isRegexChar = !__jsxEnter && isRegexStart(c_n)
307
+ const isJsxLiterals = inJsxLiterals()
252
308
  if (isQuotationChar || isRegexChar) {
253
309
  append()
254
310
  const [lastType, lastToken] = last
@@ -327,27 +383,38 @@ export function tokenize(code) {
327
383
  )
328
384
  ) {
329
385
  current += curr
386
+ if (next === '<') {
387
+ append()
388
+ }
330
389
  } else {
331
390
  append()
332
391
  current = curr
333
392
  append()
334
393
  }
335
394
  } else {
336
- if (
395
+ if (__jsxExpr && curr === '}') {
396
+ append()
397
+ current = curr
398
+ append()
399
+ __jsxExpr = false
400
+ } else if (
337
401
  // it's jsx literals and is not a jsx bracket
338
402
  (isJsxLiterals && !jsxBrackets.has(curr)) ||
339
403
  // same type char as previous one in current token
340
- isWord(curr) === isWord(current[current.length - 1]) &&
341
- !signs.has(curr)
404
+ ((isWord(curr) === isWord(current[current.length - 1]) || __jsxChild()) && !signs.has(curr))
342
405
  ) {
343
406
  current += curr
344
- if (next === '<') {
345
- append(T_JSX_LITERALS);
346
- }
347
407
  } else {
348
- append(c_n === '</' ? T_JSX_LITERALS : undefined)
349
- current = curr
350
- if (c_n === '</' || c_n === '/>') {
408
+ if (p_c === '</') {
409
+ current = p_c
410
+ }
411
+ append()
412
+
413
+ if (p_c !== '</') {
414
+ current = curr
415
+
416
+ }
417
+ if ((c_n === '</' || c_n === '/>')) {
351
418
  current = c_n
352
419
  append()
353
420
  i++
@@ -355,13 +422,6 @@ export function tokenize(code) {
355
422
  else if (jsxBrackets.has(curr)) append()
356
423
  }
357
424
  }
358
-
359
- if (jsx.child && curr === '{') {
360
- jsx.expr = true
361
- }
362
- if (jsx.child && jsx.expr && curr === '}') {
363
- jsx.expr = false
364
- }
365
425
  }
366
426
 
367
427
  append()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sugar-high",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "exports": "./lib/index.mjs",
6
6
  "description": "Super lightweight JSX syntax highlighter",
@@ -16,7 +16,7 @@
16
16
  "build": "next build docs"
17
17
  },
18
18
  "devDependencies": {
19
- "codice": "^0.0.3",
19
+ "codice": "^0.0.9",
20
20
  "next": "12.1.6-canary.6",
21
21
  "react": "18.0.0",
22
22
  "react-dom": "18.0.0",