1
- const getStream = require ( ' get-stream' )
2
- const path = require ( ' path' )
3
- const { promisify} = require ( ' util' )
4
- const yauzl = require ( ' yauzl' )
1
+ const getStream = require ( " get-stream" ) ;
2
+ const path = require ( " path" ) ;
3
+ const { promisify } = require ( " util" ) ;
4
+ const yauzl = require ( " yauzl" ) ;
5
5
6
- const { cache} = require ( ' ./cache' )
6
+ const { cache } = require ( " ./cache" ) ;
7
7
// for type definitions
8
- const { Entry} = require ( ' yauzl' )
8
+ const { Entry } = require ( " yauzl" ) ;
9
9
10
10
/**
11
11
* @typedef Entries {Record<string, string | undefined>}
@@ -17,6 +17,15 @@ const {Entry} = require('yauzl')
17
17
* @typedef Loader {function (resolve: PromiseResolver, PromiseReject): LoaderInstance}
18
18
*/
19
19
20
+ const encodingMap = {
21
+ "xmltest/valid/sa/049.xml" : "utf16le" ,
22
+ "xmltest/valid/sa/050.xml" : "utf16le" ,
23
+ "xmltest/valid/sa/051.xml" : "utf16le" ,
24
+ "xmltest/valid/sa/out/049.xml" : "utf16le" ,
25
+ "xmltest/valid/sa/out/050.xml" : "utf16le" ,
26
+ "xmltest/valid/sa/out/051.xml" : "utf16le" ,
27
+ } ;
28
+
20
29
/**
21
30
* Loads all file content from the zip file.
22
31
*
@@ -30,16 +39,23 @@ const contentLoader = (resolve, reject, encoding) => {
30
39
const data = { } ;
31
40
32
41
const end = ( ) => {
33
- resolve ( data )
34
- }
42
+ resolve ( data ) ;
43
+ } ;
35
44
36
45
const entry = async ( entry , readFile ) => {
37
- if ( ! entry . fileName . endsWith ( '/' ) ) {
38
- data [ entry . fileName ] = await getStream ( await readFile ( entry ) , { encoding} )
46
+ if ( ! entry . fileName . endsWith ( "/" ) ) {
47
+ const enc = encoding
48
+ ? encoding
49
+ : encodingMap [ entry . fileName ]
50
+ ? encodingMap [ entry . fileName ]
51
+ : "utf8" ;
52
+ data [ entry . fileName ] = await getStream ( await readFile ( entry ) , {
53
+ encoding : enc ,
54
+ } ) ;
39
55
}
40
- }
41
- return { end, entry}
42
- }
56
+ } ;
57
+ return { end, entry } ;
58
+ } ;
43
59
/**
44
60
* The module level cache for the zip file content.
45
61
*
@@ -62,17 +78,17 @@ contentLoader.CACHE = cache();
62
78
*/
63
79
const entriesLoader = ( resolve , reject ) => {
64
80
/** @type {Entries } */
65
- const data = { }
81
+ const data = { } ;
66
82
const end = ( ) => {
67
- resolve ( data )
68
- }
83
+ resolve ( data ) ;
84
+ } ;
69
85
const entry = ( entry ) => {
70
- data [ entry . fileName ] = entry . fileName . endsWith ( '/' )
71
- ? ''
72
- : path . basename ( entry . fileName )
73
- }
74
- return { end, entry}
75
- }
86
+ data [ entry . fileName ] = entry . fileName . endsWith ( "/" )
87
+ ? ""
88
+ : path . basename ( entry . fileName ) ;
89
+ } ;
90
+ return { end, entry } ;
91
+ } ;
76
92
entriesLoader . CACHE = cache ( ) ;
77
93
78
94
/**
@@ -92,31 +108,35 @@ entriesLoader.CACHE = cache();
92
108
* @param location {string} absolute path to zip file (default: xmltest.zip)
93
109
* @returns {Promise<Entries> }
94
110
*/
95
- const load = async ( loader = contentLoader , location = path . join ( __dirname , 'xmltest.zip' ) ) => {
111
+ const load = async (
112
+ loader = contentLoader ,
113
+ location = path . join ( __dirname , "xmltest.zip" ) ,
114
+ ) => {
96
115
if ( loader . CACHE && loader . CACHE . has ( location ) ) {
97
- return { ...loader . CACHE . get ( location ) }
116
+ return { ...loader . CACHE . get ( location ) } ;
98
117
}
99
118
100
- const zipfile = await promisify ( yauzl . open ) (
101
- location , { decodeStrings : true , lazyEntries : true }
102
- )
103
- const readFile = promisify ( zipfile . openReadStream . bind ( zipfile ) )
119
+ const zipfile = await promisify ( yauzl . open ) ( location , {
120
+ decodeStrings : true ,
121
+ lazyEntries : true ,
122
+ } ) ;
123
+ const readFile = promisify ( zipfile . openReadStream . bind ( zipfile ) ) ;
104
124
return new Promise ( ( resolve , reject ) => {
105
125
const resolver = loader . CACHE
106
126
? ( data ) => {
107
- loader . CACHE . set ( location , data ) ;
108
- resolve ( data ) ;
109
- }
127
+ loader . CACHE . set ( location , data ) ;
128
+ resolve ( data ) ;
129
+ }
110
130
: resolve ;
111
131
const handler = loader ( resolver , reject ) ;
112
- zipfile . on ( ' end' , handler . end ) ;
113
- zipfile . on ( ' entry' , async ( entry ) => {
132
+ zipfile . on ( " end" , handler . end ) ;
133
+ zipfile . on ( " entry" , async ( entry ) => {
114
134
await handler . entry ( entry , readFile ) ;
115
135
zipfile . readEntry ( ) ;
116
136
} ) ;
117
137
zipfile . readEntry ( ) ;
118
- } )
119
- }
138
+ } ) ;
139
+ } ;
120
140
121
141
/**
122
142
* A function that can be passed to functions like `Array.prototype.filter`
@@ -135,24 +155,24 @@ const load = async (loader = contentLoader, location = path.join(__dirname, 'xml
135
155
* @returns {Predicate }
136
156
*/
137
157
const combineFilters = ( ...tests ) => {
138
- const checks = tests . map ( test => {
139
- if ( typeof test === ' function' ) {
140
- return test
158
+ const checks = tests . map ( ( test ) => {
159
+ if ( typeof test === " function" ) {
160
+ return test ;
141
161
}
142
162
let result ;
143
- if ( typeof test . test === ' function' ) {
144
- result = s => test . test ( s )
145
- result . toString = ( ) => `${ test . toString } .test(str)`
163
+ if ( typeof test . test === " function" ) {
164
+ result = ( s ) => test . test ( s ) ;
165
+ result . toString = ( ) => `${ test . toString } .test(str)` ;
146
166
} else {
147
- result = s => s . includes ( test )
148
- result . toString = ( ) => `str.includes('${ test } ')`
167
+ result = ( s ) => s . includes ( test ) ;
168
+ result . toString = ( ) => `str.includes('${ test } ')` ;
149
169
}
150
170
return result ;
151
- } )
152
- const result = s => checks . every ( check => check ( s ) ) ;
153
- result . toString = ( ) => `[combineFilters:(str) => ${ checks . join ( ' && ' ) } ]`
171
+ } ) ;
172
+ const result = ( s ) => checks . every ( ( check ) => check ( s ) ) ;
173
+ result . toString = ( ) => `[combineFilters:(str) => ${ checks . join ( " && " ) } ]` ;
154
174
return result ;
155
- }
175
+ } ;
156
176
157
177
/**
158
178
* Helpful filters based on the directory structure and content of `xmltest.zip`.
@@ -165,7 +185,7 @@ const combineFilters = (...tests) => {
165
185
* @see ent
166
186
*/
167
187
const FILTERS = {
168
- INVALID : combineFilters ( ' xmltest/invalid' ) ,
188
+ INVALID : combineFilters ( " xmltest/invalid" ) ,
169
189
NOT_WF : {
170
190
EXT_SA : {
171
191
files : combineFilters ( / x m l t e s t \/ n o t - w f \/ e x t - s a \/ [ ^ / ] + $ / ) ,
@@ -175,33 +195,33 @@ const FILTERS = {
175
195
} ,
176
196
SA : {
177
197
files : combineFilters ( / x m l t e s t \/ n o t - w f \/ s a \/ [ ^ / ] + $ / ) ,
178
- }
198
+ } ,
179
199
} ,
180
200
VALID : {
181
201
EXT_SA : {
182
202
files : combineFilters ( / x m l t e s t \/ v a l i d \/ e x t - s a \/ [ ^ / ] + $ / ) ,
183
- OUT : combineFilters ( ' xmltest/valid/ext-sa/out' )
203
+ OUT : combineFilters ( " xmltest/valid/ext-sa/out" ) ,
184
204
} ,
185
205
NOT_SA : {
186
206
files : combineFilters ( / x m l t e s t \/ v a l i d \/ n o t - s a \/ [ ^ / ] + $ / ) ,
187
- OUT : combineFilters ( ' xmltest/valid/not-sa/out' )
207
+ OUT : combineFilters ( " xmltest/valid/not-sa/out" ) ,
188
208
} ,
189
209
SA : {
190
210
files : combineFilters ( / x m l t e s t \/ v a l i d \/ s a \/ [ ^ / ] + $ / ) ,
191
- OUT : combineFilters ( ' xmltest/valid/sa/out' )
192
- }
211
+ OUT : combineFilters ( " xmltest/valid/sa/out" ) ,
212
+ } ,
193
213
} ,
194
214
/**
195
215
* @param s {string}
196
216
* @returns {boolean }
197
217
*/
198
- ent : s => s . endsWith ( ' .ent' ) ,
218
+ ent : ( s ) => s . endsWith ( " .ent" ) ,
199
219
/**
200
220
* @param s {string}
201
221
* @returns {boolean }
202
222
*/
203
- xml : s => s . endsWith ( ' .xml' )
204
- }
223
+ xml : ( s ) => s . endsWith ( " .xml" ) ,
224
+ } ;
205
225
206
226
/**
207
227
* Converts path in zipfile (keys of entries or content)
@@ -214,16 +234,17 @@ const RELATED = {
214
234
* @param pathInZip {string}
215
235
* @returns {string }
216
236
*/
217
- ent : pathInZip => pathInZip . replace ( / \. x m l $ / , ' .ent' ) ,
237
+ ent : ( pathInZip ) => pathInZip . replace ( / \. x m l $ / , " .ent" ) ,
218
238
/**
219
239
* Returns the name of the related `./out/filename.xml` file with the same name as the given `.xml` file.
220
240
* Be aware that only the `valid` folders have such files.
221
241
*
222
242
* @param pathInZip {string}
223
243
* @returns {string }
224
244
*/
225
- out : pathInZip => [ path . dirname ( pathInZip ) , 'out' , path . basename ( pathInZip ) ] . join ( '/' )
226
- }
245
+ out : ( pathInZip ) =>
246
+ [ path . dirname ( pathInZip ) , "out" , path . basename ( pathInZip ) ] . join ( "/" ) ,
247
+ } ;
227
248
228
249
/**
229
250
* Filters `data` by applying `filters` to it's keys
@@ -236,22 +257,23 @@ const RELATED = {
236
257
* otherwise on object with all keys that match the filter.
237
258
*/
238
259
const getFiltered = ( data , filters ) => {
239
- if ( filters . length === 0 ) return { ...data }
240
- const key = filters [ 0 ]
241
- const isSingleExistingKey = filters . length === 1 && typeof key === 'string' && key in data
260
+ if ( filters . length === 0 ) return { ...data } ;
261
+ const key = filters [ 0 ] ;
262
+ const isSingleExistingKey =
263
+ filters . length === 1 && typeof key === "string" && key in data ;
242
264
const keys = isSingleExistingKey
243
265
? [ key ]
244
- : Object . keys ( data ) . filter ( combineFilters . apply ( null , filters ) )
266
+ : Object . keys ( data ) . filter ( combineFilters . apply ( null , filters ) ) ;
245
267
return keys . length === 1 && filters . length === 1
246
268
? data [ keys [ 0 ] ]
247
269
: keys . reduce (
248
- ( acc , key ) => {
249
- acc [ key ] = data [ key ]
250
- return acc
251
- } ,
252
- /** @type {Entries } */ { }
253
- )
254
- }
270
+ ( acc , key ) => {
271
+ acc [ key ] = data [ key ] ;
272
+ return acc ;
273
+ } ,
274
+ /** @type {Entries } */ { } ,
275
+ ) ;
276
+ } ;
255
277
256
278
/**
257
279
* Filters zip file content by applying `filters` to it's keys.
@@ -266,7 +288,7 @@ const getFiltered = (data, filters) => {
266
288
* if the only filter only results a single entry,
267
289
* otherwise on object with all keys that match the filter.
268
290
*/
269
- const getContent = async ( ...filters ) => getFiltered ( await load ( ) , filters )
291
+ const getContent = async ( ...filters ) => getFiltered ( await load ( ) , filters ) ;
270
292
271
293
/**
272
294
* Filters content of `xmltest.json` by applying `filters` to it's keys.
@@ -277,8 +299,8 @@ const getContent = async (...filters) => getFiltered(await load(), filters)
277
299
* if the only filter only results a single entry,
278
300
* otherwise on object with all keys that match the filter.
279
301
*/
280
- const getEntries = ( ...filters ) => getFiltered ( require ( './xmltest.json' )
281
- , filters )
302
+ const getEntries = ( ...filters ) =>
303
+ getFiltered ( require ( "./xmltest.json" ) , filters ) ;
282
304
283
305
/**
284
306
* Makes module executable using `runex`.
@@ -309,11 +331,12 @@ const run = async (...filters) => {
309
331
310
332
return getFiltered (
311
333
await load ( filters . length === 0 ? entriesLoader : contentLoader , file ) ,
312
- filters
334
+ filters ,
313
335
) ;
314
336
} ;
315
337
316
- const replaceWithWrappedCodePointAt = char => `{!${ char . codePointAt ( 0 ) . toString ( 16 ) } !}`
338
+ const replaceWithWrappedCodePointAt = ( char ) =>
339
+ `{!${ char . codePointAt ( 0 ) . toString ( 16 ) } !}` ;
317
340
318
341
/**
319
342
* Some xml documents (purposely) contain characters that are not visible
@@ -328,9 +351,11 @@ const replaceWithWrappedCodePointAt = char => `{!${char.codePointAt(0).toString(
328
351
* @param wrapper {function (string): string}
329
352
*/
330
353
const replaceNonTextChars = ( value , wrapper = replaceWithWrappedCodePointAt ) =>
331
- value === undefined || value === ''
354
+ value === undefined || value === ""
332
355
? value
333
- : value . toString ( ) . replace ( / [ \u0000 \u001B \u001F \uDC00 \uD800 \uFFFE \uFFFF ] / gu, wrapper )
356
+ : value
357
+ . toString ( )
358
+ . replace ( / [ \u0000 \u001B \u001F \uDC00 \uD800 \uFFFE \uFFFF ] / gu, wrapper ) ;
334
359
335
360
module . exports = {
336
361
combineFilters,
@@ -344,11 +369,11 @@ module.exports = {
344
369
entriesLoader,
345
370
replaceNonTextChars,
346
371
replaceWithWrappedCodePointAt,
347
- run
348
- }
372
+ run,
373
+ } ;
349
374
350
375
if ( require . main === module ) {
351
376
// if you don't want to use `runex` just "launch" this module/package:
352
377
// node xmltest ...
353
- module . exports . run ( ...process . argv . slice ( 2 ) ) . then ( console . log )
378
+ module . exports . run ( ...process . argv . slice ( 2 ) ) . then ( console . log ) ;
354
379
}
0 commit comments