Skip to content

Commit d413e12

Browse files
authored
Merge pull request #1127 from alubbe/saxes
[WIP] Replace sax with saxes
2 parents 1cc3c18 + 5169531 commit d413e12

File tree

9 files changed

+73
-54
lines changed

9 files changed

+73
-54
lines changed

lib/stream/xlsx/hyperlink-reader.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const {EventEmitter} = require('events');
2-
const Sax = require('sax');
2+
const SAXStream = require('../../utils/sax-stream');
33

44
const Enums = require('../../doc/enums');
55
const RelType = require('../../xlsx/rel-type');
@@ -42,8 +42,8 @@ class HyperlinkReader extends EventEmitter {
4242
return;
4343
}
4444

45-
const parser = Sax.createStream(true, {});
46-
parser.on('opentag', node => {
45+
const saxStream = new SAXStream();
46+
saxStream.sax.on('opentag', node => {
4747
if (node.name === 'Relationship') {
4848
const rId = node.attributes.Id;
4949
switch (node.attributes.Type) {
@@ -69,13 +69,13 @@ class HyperlinkReader extends EventEmitter {
6969
}
7070
});
7171

72-
parser.on('end', () => {
72+
saxStream.sax.on('end', () => {
7373
this.emit('finished');
7474
});
7575

7676
// create a down-stream flow-control to regulate the stream
7777
const flowControl = this._workbook.flowControl.createChild();
78-
flowControl.pipe(parser, {sync: true});
78+
flowControl.pipe(saxStream, {sync: true});
7979
entry.pipe(flowControl);
8080
}
8181
}

lib/stream/xlsx/workbook-reader.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ const fs = require('fs');
22
const {EventEmitter} = require('events');
33
const Stream = require('stream');
44
const unzip = require('unzipper');
5-
const Sax = require('sax');
65
const tmp = require('tmp');
6+
const SAXStream = require('../../utils/sax-stream');
77

88
const FlowControl = require('../../utils/flow-control');
99

@@ -206,18 +206,18 @@ class WorkbookReader extends EventEmitter {
206206
return;
207207
}
208208

209-
const parser = Sax.createStream(true, {});
209+
const saxStream = new SAXStream();
210210
let inT = false;
211211
let t = null;
212212
let index = 0;
213-
parser.on('opentag', node => {
213+
saxStream.sax.on('opentag', node => {
214214
if (node.name === 't') {
215215
t = null;
216216
inT = true;
217217
}
218218
});
219-
parser.on('closetag', name => {
220-
if (inT && name === 't') {
219+
saxStream.sax.on('closetag', node => {
220+
if (inT && node.name === 't') {
221221
if (sharedStrings) {
222222
sharedStrings.push(t);
223223
} else {
@@ -226,13 +226,13 @@ class WorkbookReader extends EventEmitter {
226226
t = null;
227227
}
228228
});
229-
parser.on('text', text => {
229+
saxStream.sax.on('text', text => {
230230
t = t ? t + text : text;
231231
});
232-
parser.on('error', error => {
232+
saxStream.sax.on('error', error => {
233233
this.emit('error', error);
234234
});
235-
entry.pipe(parser);
235+
entry.pipe(saxStream);
236236
}
237237

238238
_parseStyles(entry, options) {

lib/stream/xlsx/worksheet-reader.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const {EventEmitter} = require('events');
2-
const Sax = require('sax');
2+
const SAXStream = require('../../utils/sax-stream');
33

44
const _ = require('../../utils/under-dash');
55
const utils = require('../../utils/utils');
@@ -139,8 +139,8 @@ class WorksheetReader extends EventEmitter {
139139
let c = null;
140140
let current = null;
141141

142-
const parser = Sax.createStream(true, {});
143-
parser.on('opentag', node => {
142+
const saxStream = new SAXStream();
143+
saxStream.sax.on('opentag', node => {
144144
if (emitSheet) {
145145
switch (node.name) {
146146
case 'cols':
@@ -231,17 +231,20 @@ class WorksheetReader extends EventEmitter {
231231
});
232232

233233
// only text data is for sheet values
234-
parser.on('text', text => {
234+
saxStream.sax.on('text', text => {
235235
if (emitSheet) {
236236
if (current) {
237237
current.text += text;
238238
}
239239
}
240240
});
241241

242-
parser.on('closetag', name => {
242+
saxStream.sax.on('closetag', node => {
243243
if (emitSheet) {
244-
switch (name) {
244+
switch (node.name) {
245+
case 'worksheet':
246+
saxStream.sax.close();
247+
break;
245248
case 'cols':
246249
inCols = false;
247250
this._columns = Column.fromModel(cols);
@@ -330,7 +333,7 @@ class WorksheetReader extends EventEmitter {
330333
}
331334
}
332335
if (emitHyperlinks || hyperlinks) {
333-
switch (name) {
336+
switch (node.name) {
334337
case 'hyperlinks':
335338
inHyperlinks = false;
336339
break;
@@ -339,16 +342,17 @@ class WorksheetReader extends EventEmitter {
339342
}
340343
}
341344
});
342-
parser.on('error', error => {
345+
saxStream.sax.on('error', error => {
343346
this.emit('error', error);
344347
});
345-
parser.on('end', () => {
348+
saxStream.sax.on('end', () => {
346349
this.emit('finished');
347350
});
348351

349352
// create a down-stream flow-control to regulate the stream
350353
const flowControl = this.workbook.flowControl.createChild();
351-
flowControl.pipe(parser, {sync: true});
354+
355+
flowControl.pipe(saxStream, {sync: true});
352356
entry.pipe(flowControl);
353357
}
354358
}

lib/utils/sax-stream.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const {Writable} = require('stream');
2+
const saxes = require('saxes');
3+
4+
module.exports = class SAXStream extends Writable {
5+
constructor() {
6+
super();
7+
this.sax = new saxes.SaxesParser();
8+
}
9+
10+
_write(chunk, _enc, cb) {
11+
this.sax.write(chunk.toString());
12+
if (typeof cb === 'function') cb();
13+
}
14+
};

lib/xlsx/xform/base-xform.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
const Sax = require('sax');
2-
1+
const SAXStream = require('../../utils/sax-stream');
32
const XmlStream = require('../../utils/xml-stream');
43

54
/* 'virtual' methods used as a form of documentation */
@@ -57,55 +56,58 @@ class BaseXform {
5756
this.model = Object.assign(this.model || {}, obj);
5857
}
5958

60-
parse(parser, stream) {
59+
parse(saxStream, stream) {
6160
return new Promise((resolve, reject) => {
6261
const abort = error => {
6362
// Abandon ship! Prevent the parser from consuming any more resources
64-
parser.removeAllListeners();
65-
parser.on('error', () => {}); // Ignore any parse errors from the chunk being processed
66-
stream.unpipe(parser);
63+
saxStream.sax.off('opentag');
64+
saxStream.sax.off('text');
65+
saxStream.sax.off('closetag');
66+
saxStream.sax.off('error');
67+
saxStream.sax.off('end');
68+
saxStream.sax.on('error', () => {}); // Ignore any parse errors from the chunk being processed
69+
if (stream) {
70+
stream.unpipe(saxStream);
71+
}
6772
reject(error);
6873
};
6974

70-
parser.on('opentag', node => {
75+
saxStream.sax.on('opentag', node => {
7176
try {
72-
// console.log('opentag', node.name);
7377
this.parseOpen(node);
7478
} catch (error) {
7579
abort(error);
7680
}
7781
});
78-
parser.on('text', text => {
82+
saxStream.sax.on('text', text => {
7983
try {
8084
this.parseText(text);
8185
} catch (error) {
8286
abort(error);
8387
}
8488
});
85-
parser.on('closetag', name => {
89+
saxStream.sax.on('closetag', node => {
8690
try {
87-
// console.log('closetag', name);
88-
if (!this.parseClose(name)) {
91+
if (!this.parseClose(node.name)) {
8992
resolve(this.model);
9093
}
9194
} catch (error) {
9295
abort(error);
9396
}
9497
});
95-
parser.on('end', () => {
96-
// console.log('end');
98+
saxStream.sax.on('end', () => {
9799
resolve(this.model);
98100
});
99-
parser.on('error', error => {
101+
saxStream.sax.on('error', error => {
100102
abort(error);
101103
});
102104
});
103105
}
104106

105107
parseStream(stream) {
106-
const parser = Sax.createStream(true, {});
107-
const promise = this.parse(parser, stream);
108-
stream.pipe(parser);
108+
const saxStream = new SAXStream();
109+
const promise = this.parse(saxStream, stream);
110+
stream.pipe(saxStream);
109111

110112
return promise;
111113
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
"fast-csv": "^3.4.0",
9696
"jszip": "^3.1.5",
9797
"proxyquire": "^2.1.3",
98-
"sax": "^1.2.4",
98+
"saxes": "5.0.0-rc.2",
9999
"tmp": "^0.1.0",
100100
"unzipper": "^0.9.12",
101101
"uuid": "^3.3.3"

spec/integration/pr/pr-896/test-pr-896.spec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ const {expect} = chai;
1414

1515
const TEST_XLSX_FILE_NAME = './spec/out/wb.test.xlsx';
1616
const RT_ARR = [
17-
{text: 'First Line:\r\n', font: {bold: true}},
18-
{text: 'Second Line\r\n'},
19-
{text: 'Third Line\r\n'},
17+
{text: 'First Line:\n', font: {bold: true}},
18+
{text: 'Second Line\n'},
19+
{text: 'Third Line\n'},
2020
{text: 'Last Line'},
2121
];
2222
const TEST_VALUE = {

spec/integration/workbook-xlsx-reader.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ describe('WorkbookReader', () => {
276276
},
277277
err => {
278278
expect(err.message).to.equal(
279-
'Text data outside of root node.\nLine: 1\nColumn: 1\nChar: f'
279+
'3:1: text data outside of root node.'
280280
);
281281
// Wait a tick before checking for an unhandled rejection
282282
return new Promise(setImmediate);

spec/unit/xlsx/xform/test-xform-helper.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const Sax = require('sax');
21
const {cloneDeep, each} = require('../../../utils/under-dash');
32
const CompyXform = require('./compy-xform');
43

4+
const SAXStream = verquire('utils/sax-stream');
55
const XmlStream = verquire('utils/xml-stream');
66
const BooleanXform = verquire('xlsx/xform/simple/boolean-xform');
77

@@ -130,10 +130,9 @@ const its = {
130130
},
131131
],
132132
});
133-
const parser = Sax.createStream(true);
134-
133+
const saxStream = new SAXStream();
135134
xform
136-
.parse(parser)
135+
.parse(saxStream)
137136
.then(model => {
138137
// console.log('parsed Model', JSON.stringify(model));
139138
// console.log('expected Model', JSON.stringify(result));
@@ -147,7 +146,7 @@ const its = {
147146
resolve();
148147
})
149148
.catch(reject);
150-
parser.write(xml);
149+
saxStream.write(xml);
151150
}));
152151
},
153152

@@ -157,11 +156,11 @@ const its = {
157156
const xml = getExpectation(expectation, 'xml');
158157
const result = getExpectation(expectation, 'parsedModel');
159158

160-
const parser = Sax.createStream(true);
159+
const saxStream = new SAXStream();
161160
const xform = expectation.create();
162161

163162
xform
164-
.parse(parser)
163+
.parse(saxStream)
165164
.then(model => {
166165
// eliminate the undefined
167166
const clone = cloneDeep(model, false);
@@ -173,7 +172,7 @@ const its = {
173172
})
174173
.catch(reject);
175174

176-
parser.write(xml);
175+
saxStream.write(xml);
177176
}));
178177
},
179178

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy