@vaadin-component-factory/vcf-pdf-viewer 1.0.2 → 1.1.1
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.
- package/package.json +3 -1
- package/pdfjs/dist/display_utils.js +714 -714
- package/pdfjs/dist/fetch_stream.js +293 -293
- package/pdfjs/dist/l10n_utils.js +122 -122
- package/pdfjs/dist/message_handler.js +524 -524
- package/pdfjs/dist/network.js +552 -552
- package/pdfjs/dist/network_utils.js +309 -309
- package/pdfjs/dist/node_stream.js +481 -481
- package/pdfjs/dist/pdf_link_service.js +534 -534
- package/pdfjs/dist/pdf_rendering_queue.js +154 -154
- package/pdfjs/dist/pdf_thumbnail_viewer.js +738 -738
- package/pdfjs/dist/pdf_viewer.js +3207 -3207
- package/pdfjs/dist/ui_utils.js +881 -881
- package/pdfjs/dist/util.js +991 -991
- package/pdfjs/dist/worker.js +60846 -60846
- package/src/vcf-pdf-viewer.js +48 -8
- package/theme/lumo/vcf-pdf-viewer-styles.js +6 -6
- package/theme/material/vcf-pdf-viewer-styles.js +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { c as assert, M as MissingPDFException, l as createPromiseCapability, A as AbortException } from './util.js';
|
|
2
|
-
import { v as validateRangeRequestCapabilities, e as extractFilenameFromHeader } from './network_utils.js';
|
|
3
|
-
import './display_utils.js';
|
|
4
|
-
|
|
1
|
+
import { c as assert, M as MissingPDFException, l as createPromiseCapability, A as AbortException } from './util.js';
|
|
2
|
+
import { v as validateRangeRequestCapabilities, e as extractFilenameFromHeader } from './network_utils.js';
|
|
3
|
+
import './display_utils.js';
|
|
4
|
+
|
|
5
5
|
/* Copyright 2012 Mozilla Foundation
|
|
6
6
|
*
|
|
7
7
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -15,480 +15,480 @@ import './display_utils.js';
|
|
|
15
15
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
16
|
* See the License for the specific language governing permissions and
|
|
17
17
|
* limitations under the License.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
|
21
|
-
throw new Error('Module "./node_stream.js" shall not be used with MOZCENTRAL builds.');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const fs = __non_webpack_require__("fs");
|
|
25
|
-
|
|
26
|
-
const http = __non_webpack_require__("http");
|
|
27
|
-
|
|
28
|
-
const https = __non_webpack_require__("https");
|
|
29
|
-
|
|
30
|
-
const url = __non_webpack_require__("url");
|
|
31
|
-
|
|
32
|
-
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
|
33
|
-
|
|
34
|
-
function parseUrl(sourceUrl) {
|
|
35
|
-
const parsedUrl = url.parse(sourceUrl);
|
|
36
|
-
|
|
37
|
-
if (parsedUrl.protocol === "file:" || parsedUrl.host) {
|
|
38
|
-
return parsedUrl;
|
|
39
|
-
} // Prepending 'file:///' to Windows absolute path.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (/^[a-z]:[/\\]/i.test(sourceUrl)) {
|
|
43
|
-
return url.parse(`file:///${sourceUrl}`);
|
|
44
|
-
} // Changes protocol to 'file:' if url refers to filesystem.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!parsedUrl.host) {
|
|
48
|
-
parsedUrl.protocol = "file:";
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return parsedUrl;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
class PDFNodeStream {
|
|
55
|
-
constructor(source) {
|
|
56
|
-
this.source = source;
|
|
57
|
-
this.url = parseUrl(source.url);
|
|
58
|
-
this.isHttp = this.url.protocol === "http:" || this.url.protocol === "https:"; // Check if url refers to filesystem.
|
|
59
|
-
|
|
60
|
-
this.isFsUrl = this.url.protocol === "file:";
|
|
61
|
-
this.httpHeaders = this.isHttp && source.httpHeaders || {};
|
|
62
|
-
this._fullRequestReader = null;
|
|
63
|
-
this._rangeRequestReaders = [];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
get _progressiveDataLength() {
|
|
67
|
-
var _this$_fullRequestRea, _this$_fullRequestRea2;
|
|
68
|
-
|
|
69
|
-
return (_this$_fullRequestRea = (_this$_fullRequestRea2 = this._fullRequestReader) === null || _this$_fullRequestRea2 === void 0 ? void 0 : _this$_fullRequestRea2._loaded) !== null && _this$_fullRequestRea !== void 0 ? _this$_fullRequestRea : 0;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
getFullReader() {
|
|
73
|
-
assert(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once.");
|
|
74
|
-
this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);
|
|
75
|
-
return this._fullRequestReader;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
getRangeReader(start, end) {
|
|
79
|
-
if (end <= this._progressiveDataLength) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);
|
|
84
|
-
|
|
85
|
-
this._rangeRequestReaders.push(rangeReader);
|
|
86
|
-
|
|
87
|
-
return rangeReader;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
cancelAllRequests(reason) {
|
|
91
|
-
if (this._fullRequestReader) {
|
|
92
|
-
this._fullRequestReader.cancel(reason);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
for (const reader of this._rangeRequestReaders.slice(0)) {
|
|
96
|
-
reader.cancel(reason);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
class BaseFullReader {
|
|
103
|
-
constructor(stream) {
|
|
104
|
-
this._url = stream.url;
|
|
105
|
-
this._done = false;
|
|
106
|
-
this._storedError = null;
|
|
107
|
-
this.onProgress = null;
|
|
108
|
-
const source = stream.source;
|
|
109
|
-
this._contentLength = source.length; // optional
|
|
110
|
-
|
|
111
|
-
this._loaded = 0;
|
|
112
|
-
this._filename = null;
|
|
113
|
-
this._disableRange = source.disableRange || false;
|
|
114
|
-
this._rangeChunkSize = source.rangeChunkSize;
|
|
115
|
-
|
|
116
|
-
if (!this._rangeChunkSize && !this._disableRange) {
|
|
117
|
-
this._disableRange = true;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
this._isStreamingSupported = !source.disableStream;
|
|
121
|
-
this._isRangeSupported = !source.disableRange;
|
|
122
|
-
this._readableStream = null;
|
|
123
|
-
this._readCapability = createPromiseCapability();
|
|
124
|
-
this._headersCapability = createPromiseCapability();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
get headersReady() {
|
|
128
|
-
return this._headersCapability.promise;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
get filename() {
|
|
132
|
-
return this._filename;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
get contentLength() {
|
|
136
|
-
return this._contentLength;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
get isRangeSupported() {
|
|
140
|
-
return this._isRangeSupported;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
get isStreamingSupported() {
|
|
144
|
-
return this._isStreamingSupported;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async read() {
|
|
148
|
-
await this._readCapability.promise;
|
|
149
|
-
|
|
150
|
-
if (this._done) {
|
|
151
|
-
return {
|
|
152
|
-
value: undefined,
|
|
153
|
-
done: true
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (this._storedError) {
|
|
158
|
-
throw this._storedError;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const chunk = this._readableStream.read();
|
|
162
|
-
|
|
163
|
-
if (chunk === null) {
|
|
164
|
-
this._readCapability = createPromiseCapability();
|
|
165
|
-
return this.read();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
this._loaded += chunk.length;
|
|
169
|
-
|
|
170
|
-
if (this.onProgress) {
|
|
171
|
-
this.onProgress({
|
|
172
|
-
loaded: this._loaded,
|
|
173
|
-
total: this._contentLength
|
|
174
|
-
});
|
|
175
|
-
} // Ensure that `read()` method returns ArrayBuffer.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const buffer = new Uint8Array(chunk).buffer;
|
|
179
|
-
return {
|
|
180
|
-
value: buffer,
|
|
181
|
-
done: false
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
cancel(reason) {
|
|
186
|
-
// Call `this._error()` method when cancel is called
|
|
187
|
-
// before _readableStream is set.
|
|
188
|
-
if (!this._readableStream) {
|
|
189
|
-
this._error(reason);
|
|
190
|
-
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
this._readableStream.destroy(reason);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
_error(reason) {
|
|
198
|
-
this._storedError = reason;
|
|
199
|
-
|
|
200
|
-
this._readCapability.resolve();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
_setReadableStream(readableStream) {
|
|
204
|
-
this._readableStream = readableStream;
|
|
205
|
-
readableStream.on("readable", () => {
|
|
206
|
-
this._readCapability.resolve();
|
|
207
|
-
});
|
|
208
|
-
readableStream.on("end", () => {
|
|
209
|
-
// Destroy readable to minimize resource usage.
|
|
210
|
-
readableStream.destroy();
|
|
211
|
-
this._done = true;
|
|
212
|
-
|
|
213
|
-
this._readCapability.resolve();
|
|
214
|
-
});
|
|
215
|
-
readableStream.on("error", reason => {
|
|
216
|
-
this._error(reason);
|
|
217
|
-
}); // We need to stop reading when range is supported and streaming is
|
|
218
|
-
// disabled.
|
|
219
|
-
|
|
220
|
-
if (!this._isStreamingSupported && this._isRangeSupported) {
|
|
221
|
-
this._error(new AbortException("streaming is disabled"));
|
|
222
|
-
} // Destroy ReadableStream if already in errored state.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (this._storedError) {
|
|
226
|
-
this._readableStream.destroy(this._storedError);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
class BaseRangeReader {
|
|
233
|
-
constructor(stream) {
|
|
234
|
-
this._url = stream.url;
|
|
235
|
-
this._done = false;
|
|
236
|
-
this._storedError = null;
|
|
237
|
-
this.onProgress = null;
|
|
238
|
-
this._loaded = 0;
|
|
239
|
-
this._readableStream = null;
|
|
240
|
-
this._readCapability = createPromiseCapability();
|
|
241
|
-
const source = stream.source;
|
|
242
|
-
this._isStreamingSupported = !source.disableStream;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
get isStreamingSupported() {
|
|
246
|
-
return this._isStreamingSupported;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async read() {
|
|
250
|
-
await this._readCapability.promise;
|
|
251
|
-
|
|
252
|
-
if (this._done) {
|
|
253
|
-
return {
|
|
254
|
-
value: undefined,
|
|
255
|
-
done: true
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (this._storedError) {
|
|
260
|
-
throw this._storedError;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const chunk = this._readableStream.read();
|
|
264
|
-
|
|
265
|
-
if (chunk === null) {
|
|
266
|
-
this._readCapability = createPromiseCapability();
|
|
267
|
-
return this.read();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
this._loaded += chunk.length;
|
|
271
|
-
|
|
272
|
-
if (this.onProgress) {
|
|
273
|
-
this.onProgress({
|
|
274
|
-
loaded: this._loaded
|
|
275
|
-
});
|
|
276
|
-
} // Ensure that `read()` method returns ArrayBuffer.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const buffer = new Uint8Array(chunk).buffer;
|
|
280
|
-
return {
|
|
281
|
-
value: buffer,
|
|
282
|
-
done: false
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
cancel(reason) {
|
|
287
|
-
// Call `this._error()` method when cancel is called
|
|
288
|
-
// before _readableStream is set.
|
|
289
|
-
if (!this._readableStream) {
|
|
290
|
-
this._error(reason);
|
|
291
|
-
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
this._readableStream.destroy(reason);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
_error(reason) {
|
|
299
|
-
this._storedError = reason;
|
|
300
|
-
|
|
301
|
-
this._readCapability.resolve();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
_setReadableStream(readableStream) {
|
|
305
|
-
this._readableStream = readableStream;
|
|
306
|
-
readableStream.on("readable", () => {
|
|
307
|
-
this._readCapability.resolve();
|
|
308
|
-
});
|
|
309
|
-
readableStream.on("end", () => {
|
|
310
|
-
// Destroy readableStream to minimize resource usage.
|
|
311
|
-
readableStream.destroy();
|
|
312
|
-
this._done = true;
|
|
313
|
-
|
|
314
|
-
this._readCapability.resolve();
|
|
315
|
-
});
|
|
316
|
-
readableStream.on("error", reason => {
|
|
317
|
-
this._error(reason);
|
|
318
|
-
}); // Destroy readableStream if already in errored state.
|
|
319
|
-
|
|
320
|
-
if (this._storedError) {
|
|
321
|
-
this._readableStream.destroy(this._storedError);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function createRequestOptions(parsedUrl, headers) {
|
|
328
|
-
return {
|
|
329
|
-
protocol: parsedUrl.protocol,
|
|
330
|
-
auth: parsedUrl.auth,
|
|
331
|
-
host: parsedUrl.hostname,
|
|
332
|
-
port: parsedUrl.port,
|
|
333
|
-
path: parsedUrl.path,
|
|
334
|
-
method: "GET",
|
|
335
|
-
headers
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
class PDFNodeStreamFullReader extends BaseFullReader {
|
|
340
|
-
constructor(stream) {
|
|
341
|
-
super(stream);
|
|
342
|
-
|
|
343
|
-
const handleResponse = response => {
|
|
344
|
-
if (response.statusCode === 404) {
|
|
345
|
-
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
|
346
|
-
this._storedError = error;
|
|
347
|
-
|
|
348
|
-
this._headersCapability.reject(error);
|
|
349
|
-
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
this._headersCapability.resolve();
|
|
354
|
-
|
|
355
|
-
this._setReadableStream(response);
|
|
356
|
-
|
|
357
|
-
const getResponseHeader = name => {
|
|
358
|
-
// Make sure that headers name are in lower case, as mentioned
|
|
359
|
-
// here: https://nodejs.org/api/http.html#http_message_headers.
|
|
360
|
-
return this._readableStream.headers[name.toLowerCase()];
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
const {
|
|
364
|
-
allowRangeRequests,
|
|
365
|
-
suggestedLength
|
|
366
|
-
} = validateRangeRequestCapabilities({
|
|
367
|
-
getResponseHeader,
|
|
368
|
-
isHttp: stream.isHttp,
|
|
369
|
-
rangeChunkSize: this._rangeChunkSize,
|
|
370
|
-
disableRange: this._disableRange
|
|
371
|
-
});
|
|
372
|
-
this._isRangeSupported = allowRangeRequests; // Setting right content length.
|
|
373
|
-
|
|
374
|
-
this._contentLength = suggestedLength || this._contentLength;
|
|
375
|
-
this._filename = extractFilenameFromHeader(getResponseHeader);
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
this._request = null;
|
|
379
|
-
|
|
380
|
-
if (this._url.protocol === "http:") {
|
|
381
|
-
this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
|
|
382
|
-
} else {
|
|
383
|
-
this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
this._request.on("error", reason => {
|
|
387
|
-
this._storedError = reason;
|
|
388
|
-
|
|
389
|
-
this._headersCapability.reject(reason);
|
|
390
|
-
}); // Note: `request.end(data)` is used to write `data` to request body
|
|
391
|
-
// and notify end of request. But one should always call `request.end()`
|
|
392
|
-
// even if there is no data to write -- (to notify the end of request).
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
this._request.end();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|
401
|
-
constructor(stream, start, end) {
|
|
402
|
-
super(stream);
|
|
403
|
-
this._httpHeaders = {};
|
|
404
|
-
|
|
405
|
-
for (const property in stream.httpHeaders) {
|
|
406
|
-
const value = stream.httpHeaders[property];
|
|
407
|
-
|
|
408
|
-
if (typeof value === "undefined") {
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
this._httpHeaders[property] = value;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
this._httpHeaders.Range = `bytes=${start}-${end - 1}`;
|
|
416
|
-
|
|
417
|
-
const handleResponse = response => {
|
|
418
|
-
if (response.statusCode === 404) {
|
|
419
|
-
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
|
420
|
-
this._storedError = error;
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
this._setReadableStream(response);
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
this._request = null;
|
|
428
|
-
|
|
429
|
-
if (this._url.protocol === "http:") {
|
|
430
|
-
this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
|
|
431
|
-
} else {
|
|
432
|
-
this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
this._request.on("error", reason => {
|
|
436
|
-
this._storedError = reason;
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
this._request.end();
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
class PDFNodeStreamFsFullReader extends BaseFullReader {
|
|
445
|
-
constructor(stream) {
|
|
446
|
-
super(stream);
|
|
447
|
-
let path = decodeURIComponent(this._url.path); // Remove the extra slash to get right path from url like `file:///C:/`
|
|
448
|
-
|
|
449
|
-
if (fileUriRegex.test(this._url.href)) {
|
|
450
|
-
path = path.replace(/^\//, "");
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
fs.lstat(path, (error, stat) => {
|
|
454
|
-
if (error) {
|
|
455
|
-
if (error.code === "ENOENT") {
|
|
456
|
-
error = new MissingPDFException(`Missing PDF "${path}".`);
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
this._storedError = error;
|
|
460
|
-
|
|
461
|
-
this._headersCapability.reject(error);
|
|
462
|
-
|
|
463
|
-
return;
|
|
464
|
-
} // Setting right content length.
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
this._contentLength = stat.size;
|
|
468
|
-
|
|
469
|
-
this._setReadableStream(fs.createReadStream(path));
|
|
470
|
-
|
|
471
|
-
this._headersCapability.resolve();
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
class PDFNodeStreamFsRangeReader extends BaseRangeReader {
|
|
478
|
-
constructor(stream, start, end) {
|
|
479
|
-
super(stream);
|
|
480
|
-
let path = decodeURIComponent(this._url.path); // Remove the extra slash to get right path from url like `file:///C:/`
|
|
481
|
-
|
|
482
|
-
if (fileUriRegex.test(this._url.href)) {
|
|
483
|
-
path = path.replace(/^\//, "");
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
this._setReadableStream(fs.createReadStream(path, {
|
|
487
|
-
start,
|
|
488
|
-
end: end - 1
|
|
489
|
-
}));
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
export { PDFNodeStream };
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
|
21
|
+
throw new Error('Module "./node_stream.js" shall not be used with MOZCENTRAL builds.');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const fs = __non_webpack_require__("fs");
|
|
25
|
+
|
|
26
|
+
const http = __non_webpack_require__("http");
|
|
27
|
+
|
|
28
|
+
const https = __non_webpack_require__("https");
|
|
29
|
+
|
|
30
|
+
const url = __non_webpack_require__("url");
|
|
31
|
+
|
|
32
|
+
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
|
33
|
+
|
|
34
|
+
function parseUrl(sourceUrl) {
|
|
35
|
+
const parsedUrl = url.parse(sourceUrl);
|
|
36
|
+
|
|
37
|
+
if (parsedUrl.protocol === "file:" || parsedUrl.host) {
|
|
38
|
+
return parsedUrl;
|
|
39
|
+
} // Prepending 'file:///' to Windows absolute path.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if (/^[a-z]:[/\\]/i.test(sourceUrl)) {
|
|
43
|
+
return url.parse(`file:///${sourceUrl}`);
|
|
44
|
+
} // Changes protocol to 'file:' if url refers to filesystem.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if (!parsedUrl.host) {
|
|
48
|
+
parsedUrl.protocol = "file:";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return parsedUrl;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
class PDFNodeStream {
|
|
55
|
+
constructor(source) {
|
|
56
|
+
this.source = source;
|
|
57
|
+
this.url = parseUrl(source.url);
|
|
58
|
+
this.isHttp = this.url.protocol === "http:" || this.url.protocol === "https:"; // Check if url refers to filesystem.
|
|
59
|
+
|
|
60
|
+
this.isFsUrl = this.url.protocol === "file:";
|
|
61
|
+
this.httpHeaders = this.isHttp && source.httpHeaders || {};
|
|
62
|
+
this._fullRequestReader = null;
|
|
63
|
+
this._rangeRequestReaders = [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
get _progressiveDataLength() {
|
|
67
|
+
var _this$_fullRequestRea, _this$_fullRequestRea2;
|
|
68
|
+
|
|
69
|
+
return (_this$_fullRequestRea = (_this$_fullRequestRea2 = this._fullRequestReader) === null || _this$_fullRequestRea2 === void 0 ? void 0 : _this$_fullRequestRea2._loaded) !== null && _this$_fullRequestRea !== void 0 ? _this$_fullRequestRea : 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getFullReader() {
|
|
73
|
+
assert(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once.");
|
|
74
|
+
this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);
|
|
75
|
+
return this._fullRequestReader;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getRangeReader(start, end) {
|
|
79
|
+
if (end <= this._progressiveDataLength) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);
|
|
84
|
+
|
|
85
|
+
this._rangeRequestReaders.push(rangeReader);
|
|
86
|
+
|
|
87
|
+
return rangeReader;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
cancelAllRequests(reason) {
|
|
91
|
+
if (this._fullRequestReader) {
|
|
92
|
+
this._fullRequestReader.cancel(reason);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for (const reader of this._rangeRequestReaders.slice(0)) {
|
|
96
|
+
reader.cancel(reason);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
class BaseFullReader {
|
|
103
|
+
constructor(stream) {
|
|
104
|
+
this._url = stream.url;
|
|
105
|
+
this._done = false;
|
|
106
|
+
this._storedError = null;
|
|
107
|
+
this.onProgress = null;
|
|
108
|
+
const source = stream.source;
|
|
109
|
+
this._contentLength = source.length; // optional
|
|
110
|
+
|
|
111
|
+
this._loaded = 0;
|
|
112
|
+
this._filename = null;
|
|
113
|
+
this._disableRange = source.disableRange || false;
|
|
114
|
+
this._rangeChunkSize = source.rangeChunkSize;
|
|
115
|
+
|
|
116
|
+
if (!this._rangeChunkSize && !this._disableRange) {
|
|
117
|
+
this._disableRange = true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this._isStreamingSupported = !source.disableStream;
|
|
121
|
+
this._isRangeSupported = !source.disableRange;
|
|
122
|
+
this._readableStream = null;
|
|
123
|
+
this._readCapability = createPromiseCapability();
|
|
124
|
+
this._headersCapability = createPromiseCapability();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
get headersReady() {
|
|
128
|
+
return this._headersCapability.promise;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
get filename() {
|
|
132
|
+
return this._filename;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get contentLength() {
|
|
136
|
+
return this._contentLength;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
get isRangeSupported() {
|
|
140
|
+
return this._isRangeSupported;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get isStreamingSupported() {
|
|
144
|
+
return this._isStreamingSupported;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async read() {
|
|
148
|
+
await this._readCapability.promise;
|
|
149
|
+
|
|
150
|
+
if (this._done) {
|
|
151
|
+
return {
|
|
152
|
+
value: undefined,
|
|
153
|
+
done: true
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (this._storedError) {
|
|
158
|
+
throw this._storedError;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const chunk = this._readableStream.read();
|
|
162
|
+
|
|
163
|
+
if (chunk === null) {
|
|
164
|
+
this._readCapability = createPromiseCapability();
|
|
165
|
+
return this.read();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
this._loaded += chunk.length;
|
|
169
|
+
|
|
170
|
+
if (this.onProgress) {
|
|
171
|
+
this.onProgress({
|
|
172
|
+
loaded: this._loaded,
|
|
173
|
+
total: this._contentLength
|
|
174
|
+
});
|
|
175
|
+
} // Ensure that `read()` method returns ArrayBuffer.
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
const buffer = new Uint8Array(chunk).buffer;
|
|
179
|
+
return {
|
|
180
|
+
value: buffer,
|
|
181
|
+
done: false
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
cancel(reason) {
|
|
186
|
+
// Call `this._error()` method when cancel is called
|
|
187
|
+
// before _readableStream is set.
|
|
188
|
+
if (!this._readableStream) {
|
|
189
|
+
this._error(reason);
|
|
190
|
+
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this._readableStream.destroy(reason);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
_error(reason) {
|
|
198
|
+
this._storedError = reason;
|
|
199
|
+
|
|
200
|
+
this._readCapability.resolve();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
_setReadableStream(readableStream) {
|
|
204
|
+
this._readableStream = readableStream;
|
|
205
|
+
readableStream.on("readable", () => {
|
|
206
|
+
this._readCapability.resolve();
|
|
207
|
+
});
|
|
208
|
+
readableStream.on("end", () => {
|
|
209
|
+
// Destroy readable to minimize resource usage.
|
|
210
|
+
readableStream.destroy();
|
|
211
|
+
this._done = true;
|
|
212
|
+
|
|
213
|
+
this._readCapability.resolve();
|
|
214
|
+
});
|
|
215
|
+
readableStream.on("error", reason => {
|
|
216
|
+
this._error(reason);
|
|
217
|
+
}); // We need to stop reading when range is supported and streaming is
|
|
218
|
+
// disabled.
|
|
219
|
+
|
|
220
|
+
if (!this._isStreamingSupported && this._isRangeSupported) {
|
|
221
|
+
this._error(new AbortException("streaming is disabled"));
|
|
222
|
+
} // Destroy ReadableStream if already in errored state.
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
if (this._storedError) {
|
|
226
|
+
this._readableStream.destroy(this._storedError);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
class BaseRangeReader {
|
|
233
|
+
constructor(stream) {
|
|
234
|
+
this._url = stream.url;
|
|
235
|
+
this._done = false;
|
|
236
|
+
this._storedError = null;
|
|
237
|
+
this.onProgress = null;
|
|
238
|
+
this._loaded = 0;
|
|
239
|
+
this._readableStream = null;
|
|
240
|
+
this._readCapability = createPromiseCapability();
|
|
241
|
+
const source = stream.source;
|
|
242
|
+
this._isStreamingSupported = !source.disableStream;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
get isStreamingSupported() {
|
|
246
|
+
return this._isStreamingSupported;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async read() {
|
|
250
|
+
await this._readCapability.promise;
|
|
251
|
+
|
|
252
|
+
if (this._done) {
|
|
253
|
+
return {
|
|
254
|
+
value: undefined,
|
|
255
|
+
done: true
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (this._storedError) {
|
|
260
|
+
throw this._storedError;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const chunk = this._readableStream.read();
|
|
264
|
+
|
|
265
|
+
if (chunk === null) {
|
|
266
|
+
this._readCapability = createPromiseCapability();
|
|
267
|
+
return this.read();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
this._loaded += chunk.length;
|
|
271
|
+
|
|
272
|
+
if (this.onProgress) {
|
|
273
|
+
this.onProgress({
|
|
274
|
+
loaded: this._loaded
|
|
275
|
+
});
|
|
276
|
+
} // Ensure that `read()` method returns ArrayBuffer.
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
const buffer = new Uint8Array(chunk).buffer;
|
|
280
|
+
return {
|
|
281
|
+
value: buffer,
|
|
282
|
+
done: false
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
cancel(reason) {
|
|
287
|
+
// Call `this._error()` method when cancel is called
|
|
288
|
+
// before _readableStream is set.
|
|
289
|
+
if (!this._readableStream) {
|
|
290
|
+
this._error(reason);
|
|
291
|
+
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
this._readableStream.destroy(reason);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
_error(reason) {
|
|
299
|
+
this._storedError = reason;
|
|
300
|
+
|
|
301
|
+
this._readCapability.resolve();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
_setReadableStream(readableStream) {
|
|
305
|
+
this._readableStream = readableStream;
|
|
306
|
+
readableStream.on("readable", () => {
|
|
307
|
+
this._readCapability.resolve();
|
|
308
|
+
});
|
|
309
|
+
readableStream.on("end", () => {
|
|
310
|
+
// Destroy readableStream to minimize resource usage.
|
|
311
|
+
readableStream.destroy();
|
|
312
|
+
this._done = true;
|
|
313
|
+
|
|
314
|
+
this._readCapability.resolve();
|
|
315
|
+
});
|
|
316
|
+
readableStream.on("error", reason => {
|
|
317
|
+
this._error(reason);
|
|
318
|
+
}); // Destroy readableStream if already in errored state.
|
|
319
|
+
|
|
320
|
+
if (this._storedError) {
|
|
321
|
+
this._readableStream.destroy(this._storedError);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function createRequestOptions(parsedUrl, headers) {
|
|
328
|
+
return {
|
|
329
|
+
protocol: parsedUrl.protocol,
|
|
330
|
+
auth: parsedUrl.auth,
|
|
331
|
+
host: parsedUrl.hostname,
|
|
332
|
+
port: parsedUrl.port,
|
|
333
|
+
path: parsedUrl.path,
|
|
334
|
+
method: "GET",
|
|
335
|
+
headers
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
class PDFNodeStreamFullReader extends BaseFullReader {
|
|
340
|
+
constructor(stream) {
|
|
341
|
+
super(stream);
|
|
342
|
+
|
|
343
|
+
const handleResponse = response => {
|
|
344
|
+
if (response.statusCode === 404) {
|
|
345
|
+
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
|
346
|
+
this._storedError = error;
|
|
347
|
+
|
|
348
|
+
this._headersCapability.reject(error);
|
|
349
|
+
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
this._headersCapability.resolve();
|
|
354
|
+
|
|
355
|
+
this._setReadableStream(response);
|
|
356
|
+
|
|
357
|
+
const getResponseHeader = name => {
|
|
358
|
+
// Make sure that headers name are in lower case, as mentioned
|
|
359
|
+
// here: https://nodejs.org/api/http.html#http_message_headers.
|
|
360
|
+
return this._readableStream.headers[name.toLowerCase()];
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const {
|
|
364
|
+
allowRangeRequests,
|
|
365
|
+
suggestedLength
|
|
366
|
+
} = validateRangeRequestCapabilities({
|
|
367
|
+
getResponseHeader,
|
|
368
|
+
isHttp: stream.isHttp,
|
|
369
|
+
rangeChunkSize: this._rangeChunkSize,
|
|
370
|
+
disableRange: this._disableRange
|
|
371
|
+
});
|
|
372
|
+
this._isRangeSupported = allowRangeRequests; // Setting right content length.
|
|
373
|
+
|
|
374
|
+
this._contentLength = suggestedLength || this._contentLength;
|
|
375
|
+
this._filename = extractFilenameFromHeader(getResponseHeader);
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
this._request = null;
|
|
379
|
+
|
|
380
|
+
if (this._url.protocol === "http:") {
|
|
381
|
+
this._request = http.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
|
|
382
|
+
} else {
|
|
383
|
+
this._request = https.request(createRequestOptions(this._url, stream.httpHeaders), handleResponse);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
this._request.on("error", reason => {
|
|
387
|
+
this._storedError = reason;
|
|
388
|
+
|
|
389
|
+
this._headersCapability.reject(reason);
|
|
390
|
+
}); // Note: `request.end(data)` is used to write `data` to request body
|
|
391
|
+
// and notify end of request. But one should always call `request.end()`
|
|
392
|
+
// even if there is no data to write -- (to notify the end of request).
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
this._request.end();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|
401
|
+
constructor(stream, start, end) {
|
|
402
|
+
super(stream);
|
|
403
|
+
this._httpHeaders = {};
|
|
404
|
+
|
|
405
|
+
for (const property in stream.httpHeaders) {
|
|
406
|
+
const value = stream.httpHeaders[property];
|
|
407
|
+
|
|
408
|
+
if (typeof value === "undefined") {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
this._httpHeaders[property] = value;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this._httpHeaders.Range = `bytes=${start}-${end - 1}`;
|
|
416
|
+
|
|
417
|
+
const handleResponse = response => {
|
|
418
|
+
if (response.statusCode === 404) {
|
|
419
|
+
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
|
420
|
+
this._storedError = error;
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
this._setReadableStream(response);
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
this._request = null;
|
|
428
|
+
|
|
429
|
+
if (this._url.protocol === "http:") {
|
|
430
|
+
this._request = http.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
|
|
431
|
+
} else {
|
|
432
|
+
this._request = https.request(createRequestOptions(this._url, this._httpHeaders), handleResponse);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
this._request.on("error", reason => {
|
|
436
|
+
this._storedError = reason;
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
this._request.end();
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
class PDFNodeStreamFsFullReader extends BaseFullReader {
|
|
445
|
+
constructor(stream) {
|
|
446
|
+
super(stream);
|
|
447
|
+
let path = decodeURIComponent(this._url.path); // Remove the extra slash to get right path from url like `file:///C:/`
|
|
448
|
+
|
|
449
|
+
if (fileUriRegex.test(this._url.href)) {
|
|
450
|
+
path = path.replace(/^\//, "");
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
fs.lstat(path, (error, stat) => {
|
|
454
|
+
if (error) {
|
|
455
|
+
if (error.code === "ENOENT") {
|
|
456
|
+
error = new MissingPDFException(`Missing PDF "${path}".`);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
this._storedError = error;
|
|
460
|
+
|
|
461
|
+
this._headersCapability.reject(error);
|
|
462
|
+
|
|
463
|
+
return;
|
|
464
|
+
} // Setting right content length.
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
this._contentLength = stat.size;
|
|
468
|
+
|
|
469
|
+
this._setReadableStream(fs.createReadStream(path));
|
|
470
|
+
|
|
471
|
+
this._headersCapability.resolve();
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
class PDFNodeStreamFsRangeReader extends BaseRangeReader {
|
|
478
|
+
constructor(stream, start, end) {
|
|
479
|
+
super(stream);
|
|
480
|
+
let path = decodeURIComponent(this._url.path); // Remove the extra slash to get right path from url like `file:///C:/`
|
|
481
|
+
|
|
482
|
+
if (fileUriRegex.test(this._url.href)) {
|
|
483
|
+
path = path.replace(/^\//, "");
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
this._setReadableStream(fs.createReadStream(path, {
|
|
487
|
+
start,
|
|
488
|
+
end: end - 1
|
|
489
|
+
}));
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export { PDFNodeStream };
|