@@ -17,11 +17,21 @@ export interface FormattingOptions {
17
17
pretty ?: boolean ;
18
18
}
19
19
20
+ /** Possible INI value types. */
21
+ type IniValue =
22
+ | string
23
+ | number
24
+ | boolean
25
+ | null
26
+ | undefined ;
27
+
28
+ /** Represents an INI section. */
29
+ type IniSection = Record < string , IniValue > ;
30
+
20
31
/** Options for parsing INI strings. */
21
- // deno-lint-ignore no-explicit-any
22
- interface ParseOptions < T = any > {
32
+ interface ParseOptions {
23
33
/** Provide custom parsing of the value in a key/value pair. */
24
- reviver ?: ReviverFunction < T > ;
34
+ reviver ?: ReviverFunction ;
25
35
}
26
36
27
37
/** Function for replacing JavaScript values with INI string values. */
@@ -33,12 +43,11 @@ export type ReplacerFunction = (
33
43
) => string ;
34
44
35
45
/** Function for replacing INI values with JavaScript values. */
36
- // deno-lint-ignore no-explicit-any
37
- export type ReviverFunction < T = any > = (
46
+ export type ReviverFunction = (
38
47
key : string ,
39
48
value : string ,
40
49
section ?: string ,
41
- ) => T ;
50
+ ) => unknown ;
42
51
43
52
const ASSIGNMENT_MARK = "=" ;
44
53
@@ -54,8 +63,7 @@ const NON_WHITESPACE_REGEXP = /\S/;
54
63
/**
55
64
* Class implementation for fine control of INI data structures.
56
65
*/
57
- // deno-lint-ignore no-explicit-any
58
- export class IniMap < T = any > {
66
+ export class IniMap {
59
67
#global = new Map < string , LineValue > ( ) ;
60
68
#sections = new Map < string , LineSection > ( ) ;
61
69
#lines: Line [ ] = [ ] ;
@@ -76,7 +84,7 @@ export class IniMap<T = any> {
76
84
* @param value The value to set
77
85
* @returns The map object itself
78
86
*/
79
- set ( key : string , value : unknown ) : this;
87
+ set ( key : string , value : IniValue ) : this;
80
88
/**
81
89
* Set the value of a section key in the INI.
82
90
*
@@ -85,9 +93,12 @@ export class IniMap<T = any> {
85
93
* @param value The value to set
86
94
* @return The map object itself
87
95
*/
88
- set ( section : string , key : string , value : unknown ) : this;
89
- // deno-lint-ignore no-explicit-any
90
- set ( keyOrSection : string , valueOrKey : any , value ?: any ) : this {
96
+ set ( section : string , key : string , value : IniValue ) : this;
97
+ set (
98
+ keyOrSection : string ,
99
+ valueOrKey : string | IniValue ,
100
+ value ?: IniValue ,
101
+ ) : this {
91
102
if ( typeof valueOrKey === "string" && value !== undefined ) {
92
103
const section = this . #getOrCreateSection( keyOrSection ) ;
93
104
const exists = section . map . get ( valueOrKey ) ;
@@ -230,8 +241,8 @@ export class IniMap<T = any> {
230
241
*
231
242
* @returns The object equivalent to this {@code IniMap}
232
243
*/
233
- toObject ( ) : Record < string , T | Record < string , T > > {
234
- const obj : Record < string , T | Record < string , T > > = { } ;
244
+ toObject < T extends object > ( ) : T {
245
+ const obj : T = { } as T ;
235
246
236
247
for ( const { key, val } of this . #global. values ( ) ) {
237
248
Object . defineProperty ( obj , key , {
@@ -242,7 +253,7 @@ export class IniMap<T = any> {
242
253
} ) ;
243
254
}
244
255
for ( const { sec, map } of this . #sections. values ( ) ) {
245
- const section : Record < string , T > = { } ;
256
+ const section : IniSection = { } ;
246
257
Object . defineProperty ( obj , sec , {
247
258
value : section ,
248
259
writable : true ,
@@ -269,9 +280,8 @@ export class IniMap<T = any> {
269
280
* @returns Ini string
270
281
*/
271
282
toString ( replacer ?: ReplacerFunction ) : string {
272
- const replacerFunc : ReplacerFunction = typeof replacer === "function"
273
- ? replacer
274
- : ( _key , value , _section ) => `${ value } ` ;
283
+ replacer ??= ( _key , value , _section ) => `${ value } ` ;
284
+
275
285
const pretty = this . #formatting?. pretty ?? false ;
276
286
const assignment = pretty ? ` ${ ASSIGNMENT_MARK } ` : ASSIGNMENT_MARK ;
277
287
const lines = this . #lines;
@@ -284,7 +294,7 @@ export class IniMap<T = any> {
284
294
return `[${ line . sec } ]` ;
285
295
case "value" :
286
296
return line . key + assignment +
287
- replacerFunc ( line . key , line . val , line . sec ) ;
297
+ replacer ( line . key , line . val , line . sec ) ;
288
298
}
289
299
} ) . join ( this . #formatting?. lineBreak ?? "\n" ) ;
290
300
}
@@ -300,14 +310,14 @@ export class IniMap<T = any> {
300
310
if ( typeof text !== "string" ) {
301
311
throw new SyntaxError ( `Unexpected token ${ text } in INI at line 0` ) ;
302
312
}
303
- const reviverFunc : ReviverFunction = typeof reviver === "function"
304
- ? reviver
305
- : ( _key , value , _section ) => {
306
- if ( ! isNaN ( + value ) && ! value . includes ( '"' ) ) return + value ;
307
- if ( value === "null" ) return null ;
308
- if ( value === "true" || value === "false" ) return value === "true" ;
309
- return trimQuotes ( value ) ;
310
- } ;
313
+
314
+ reviver ??= ( _key , value , _section ) => {
315
+ if ( ! isNaN ( + value ) && ! value . includes ( '"' ) ) return + value ;
316
+ if ( value === "null" ) return null ;
317
+ if ( value === "true" || value === "false" ) return value === "true" ;
318
+ return trimQuotes ( value ) ;
319
+ } ;
320
+
311
321
let lineNumber = 1 ;
312
322
let currentSection : LineSection | undefined ;
313
323
@@ -368,7 +378,7 @@ export class IniMap<T = any> {
368
378
num : lineNumber ,
369
379
sec : currentSection . sec ,
370
380
key,
371
- val : reviverFunc ( key , value , currentSection . sec ) ,
381
+ val : reviver ( key , value , currentSection . sec ) ,
372
382
} ;
373
383
currentSection . map . set ( key , lineValue ) ;
374
384
this . #lines. push ( lineValue ) ;
@@ -378,7 +388,7 @@ export class IniMap<T = any> {
378
388
type : "value" ,
379
389
num : lineNumber ,
380
390
key,
381
- val : reviverFunc ( key , value ) ,
391
+ val : reviver ( key , value ) ,
382
392
} ;
383
393
this . #global. set ( key , lineValue ) ;
384
394
this . #lines. push ( lineValue ) ;
@@ -409,22 +419,19 @@ export class IniMap<T = any> {
409
419
* @param formatting The options to use
410
420
* @returns The parsed {@code IniMap}
411
421
*/
422
+ static from ( input : object , formatting ?: FormattingOptions ) : IniMap ;
412
423
static from (
413
- input : Record < string , unknown > ,
414
- formatting ?: FormattingOptions ,
415
- ) : IniMap ;
416
- static from (
417
- // deno-lint-ignore no-explicit-any
418
- input : Record < string , any > | string ,
424
+ input : string | object ,
419
425
formatting ?: ParseOptions & FormattingOptions ,
420
426
) : IniMap {
421
427
const ini = new IniMap ( formatting ) ;
422
428
if ( typeof input === "object" && input !== null ) {
423
- // deno-lint-ignore no-explicit-any
424
- const isRecord = ( val : any ) : val is Record < string , any > =>
429
+ const isRecord = ( val : unknown ) : val is IniSection =>
425
430
typeof val === "object" && val !== null ;
426
- // deno-lint-ignore no-explicit-any
427
- const sort = ( [ _a , valA ] : [ string , any ] , [ _b , valB ] : [ string , any ] ) => {
431
+ const sort = (
432
+ [ _a , valA ] : [ string , unknown ] ,
433
+ [ _b , valB ] : [ string , unknown ] ,
434
+ ) => {
428
435
if ( isRecord ( valA ) ) return 1 ;
429
436
if ( isRecord ( valB ) ) return - 1 ;
430
437
return 0 ;
@@ -499,8 +506,7 @@ interface LineValue {
499
506
num : number ;
500
507
sec ?: string ;
501
508
key : string ;
502
- // deno-lint-ignore no-explicit-any
503
- val : any ;
509
+ val : unknown ;
504
510
}
505
511
506
512
type Line = LineComment | LineSection | LineValue ;
0 commit comments