@@ -232,7 +232,8 @@ function* listPairs(lines: string[]): Generator<{
232
232
sep : string ,
233
233
value : string ,
234
234
skipSpace : boolean ,
235
- escapedNext : boolean
235
+ escapedNext : boolean ,
236
+ unicode ?: string
236
237
} =>
237
238
( { state : State . START , start : - 1 , key : '' , sep : '' , value : '' , skipSpace : true , escapedNext : false } )
238
239
@@ -245,6 +246,20 @@ function* listPairs(lines: string[]): Generator<{
245
246
}
246
247
state . skipSpace = false
247
248
249
+ // Parse unicode
250
+ if ( state . unicode ) {
251
+ // Handle incomplete sequence
252
+ if ( char === 'EOL' ) {
253
+ throw new Error ( `Invalid unicode sequence at line ${ line } ` )
254
+ }
255
+
256
+ // Append and consume until it has correct length
257
+ state . unicode += char
258
+ if ( state . unicode . length < 6 ) {
259
+ continue
260
+ }
261
+ }
262
+
248
263
// First char on the line
249
264
if ( state . state === State . START ) {
250
265
switch ( char ) {
@@ -272,6 +287,13 @@ function* listPairs(lines: string[]): Generator<{
272
287
273
288
// Key
274
289
if ( state . state === State . KEY ) {
290
+ // Special unicode handling
291
+ if ( state . unicode ) {
292
+ state . key += parseUnicode ( state . unicode , line )
293
+ state . unicode = undefined
294
+ continue
295
+ }
296
+
275
297
switch ( char ) {
276
298
case 'EOL' :
277
299
if ( state . escapedNext ) {
@@ -307,10 +329,20 @@ function* listPairs(lines: string[]): Generator<{
307
329
}
308
330
break
309
331
default :
310
- // Normal char
311
- // TODO handle unicode
312
- state . key += state . escapedNext ? unescapeChar ( char ) : char
313
- state . escapedNext = false
332
+ // Escape sequence
333
+ if ( state . escapedNext ) {
334
+ state . escapedNext = false
335
+ if ( char === 'u' ) {
336
+ // Unicode
337
+ state . unicode = '0x'
338
+ } else {
339
+ // Special char
340
+ state . key += unescapeChar ( char )
341
+ }
342
+ } else {
343
+ // Normal char
344
+ state . key += char
345
+ }
314
346
break
315
347
}
316
348
}
@@ -346,6 +378,13 @@ function* listPairs(lines: string[]): Generator<{
346
378
347
379
// Value
348
380
if ( state . state === State . VALUE ) {
381
+ // Special unicode handling
382
+ if ( state . unicode ) {
383
+ state . value += parseUnicode ( state . unicode , line )
384
+ state . unicode = undefined
385
+ continue
386
+ }
387
+
349
388
switch ( char ) {
350
389
case 'EOL' :
351
390
if ( state . escapedNext ) {
@@ -369,10 +408,19 @@ function* listPairs(lines: string[]): Generator<{
369
408
}
370
409
break
371
410
default :
372
- // Normal char
373
- // TODO handle unicode
374
- state . value += state . escapedNext ? unescapeChar ( char ) : char
375
- state . escapedNext = false
411
+ if ( state . escapedNext ) {
412
+ state . escapedNext = false
413
+ if ( char === 'u' ) {
414
+ // Unicode
415
+ state . unicode = '0x'
416
+ } else {
417
+ // Special char
418
+ state . value += unescapeChar ( char )
419
+ }
420
+ } else {
421
+ // Normal char
422
+ state . value += char
423
+ }
376
424
break
377
425
}
378
426
}
@@ -395,14 +443,12 @@ const unescapeChar = (c: string): string => {
395
443
}
396
444
}
397
445
398
- /**
399
- * Unescape key or value.
400
- *
401
- * @param str Escaped string.
402
- * @return Actual string.
403
- */
404
- export const unescape = ( str : string ) : string =>
405
- str . replace ( / \\ ( .) / g, s => unescapeChar ( s [ 1 ] ) )
446
+ const parseUnicode = ( sequence : string , line : number ) : string => {
447
+ if ( ! sequence . match ( / ^ 0 x [ \d a - f A - F ] { 4 } $ / ) ) {
448
+ throw new Error ( `Invalid unicode sequence at line ${ line } ` )
449
+ }
450
+ return String . fromCharCode ( parseInt ( sequence , 16 ) )
451
+ }
406
452
407
453
/**
408
454
* Escape property key.
0 commit comments