single-file-core 1.3.0 → 1.3.2

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/core/index.js CHANGED
@@ -336,9 +336,9 @@ class BatchRequest {
336
336
  this.duplicates = new Map();
337
337
  }
338
338
 
339
- addURL(resourceURL, { asBinary, expectedType, groupDuplicates, baseURI, blockMixedContent } = {}) {
339
+ addURL(resourceURL, { asBinary, expectedType, groupDuplicates, baseURI, blockMixedContent, contentType } = {}) {
340
340
  return new Promise((resolve, reject) => {
341
- const requestKey = JSON.stringify([resourceURL, asBinary, expectedType, baseURI, blockMixedContent]);
341
+ const requestKey = JSON.stringify([resourceURL, asBinary, expectedType, baseURI, blockMixedContent, contentType]);
342
342
  let resourceRequests = this.requests.get(requestKey);
343
343
  if (!resourceRequests) {
344
344
  resourceRequests = [];
@@ -365,7 +365,7 @@ class BatchRequest {
365
365
  const resourceURLs = [...this.requests.keys()];
366
366
  let indexResource = 0;
367
367
  return Promise.all(resourceURLs.map(async requestKey => {
368
- const [resourceURL, asBinary, expectedType, baseURI, blockMixedContent] = JSON.parse(requestKey);
368
+ const [resourceURL, asBinary, expectedType, baseURI, blockMixedContent, contentType] = JSON.parse(requestKey);
369
369
  const resourceRequests = this.requests.get(requestKey);
370
370
  try {
371
371
  const currentIndexResource = indexResource;
@@ -374,6 +374,7 @@ class BatchRequest {
374
374
  asBinary,
375
375
  inline: !options.compressContent,
376
376
  expectedType,
377
+ contentType,
377
378
  maxResourceSize: options.maxResourceSize,
378
379
  maxResourceSizeEnabled: options.maxResourceSizeEnabled,
379
380
  frameId: options.windowId,
package/core/infobar.js CHANGED
@@ -154,7 +154,8 @@ function appendInfobar(doc, options, useShadowRoot) {
154
154
  infoData = options.saveDate;
155
155
  }
156
156
  infoData = infoData || "No info";
157
- const infobarElement = createElement(doc, INFOBAR_TAGNAME, doc.body);
157
+ const parentElement = doc.body.tagName == "BODY" ? doc.body : doc.documentElement;
158
+ const infobarElement = createElement(doc, INFOBAR_TAGNAME, parentElement);
158
159
  let infobarContainer;
159
160
  if (useShadowRoot) {
160
161
  infobarContainer = infobarElement.attachShadow({ mode: "open" });
@@ -210,7 +211,6 @@ function appendInfobar(doc, options, useShadowRoot) {
210
211
  shadowRootContent.appendChild(scriptElement);
211
212
  infobarContainer.innerHTML = shadowRootContent.outerHTML;
212
213
  }
213
- doc.body.appendChild(infobarElement);
214
214
  }
215
215
  }
216
216
 
@@ -305,9 +305,11 @@ function getProcessorHelperClass(utilInstance) {
305
305
  // ignored
306
306
  }
307
307
  if (testValidURL(resourceURL)) {
308
+ const declaredContentType = ["OBJECT", "EMBED"].includes(resourceElement.tagName.toUpperCase()) ? resourceElement.getAttribute("type") : "";
309
+ const groupDuplicates = options.groupDuplicateImages && resourceElement.tagName.toUpperCase() == "IMG" && attributeName == "src";
308
310
  let { content, indexResource, duplicate } = await batchRequest.addURL(
309
311
  resourceURL,
310
- { asBinary: true, expectedType, groupDuplicates: options.groupDuplicateImages && resourceElement.tagName.toUpperCase() == "IMG" && attributeName == "src" });
312
+ { asBinary: true, expectedType, contentType: declaredContentType, groupDuplicates });
311
313
  if (originURL) {
312
314
  if (this.testEmptyResource(content)) {
313
315
  try {
@@ -321,6 +323,7 @@ function getProcessorHelperClass(utilInstance) {
321
323
  asBinary: true,
322
324
  inline: true,
323
325
  expectedType,
326
+ contentType: declaredContentType,
324
327
  maxResourceSize: options.maxResourceSize,
325
328
  maxResourceSizeEnabled: options.maxResourceSizeEnabled,
326
329
  frameId: options.windowId,
@@ -77,9 +77,9 @@ function getProcessorHelperClass(utilInstance) {
77
77
  if (element.tagName.toUpperCase() == "LINK") {
78
78
  await this.resolveLinkStylesheetURLs(stylesheetInfo, element, element.href, baseURI, options, workStyleElement, resources, stylesheets);
79
79
  } else {
80
- stylesheets.set({ element }, stylesheetInfo);
81
80
  stylesheetInfo.stylesheet = cssTree.parse(element.textContent, { context: "stylesheet", parseCustomProperty: true });
82
81
  await this.resolveImportURLs(stylesheetInfo, baseURI, options, workStyleElement, resources, stylesheets);
82
+ stylesheets.set({ element }, stylesheetInfo);
83
83
  }
84
84
  } else {
85
85
  if (element.tagName.toUpperCase() == "LINK") {
@@ -92,7 +92,6 @@ function getProcessorHelperClass(utilInstance) {
92
92
 
93
93
  replaceStylesheets(doc, stylesheets, options, resources) {
94
94
  const entries = Array.from(stylesheets);
95
- entries.reverse();
96
95
  for (const [key, stylesheetInfo] of entries) {
97
96
  if (key.urlNode) {
98
97
  const name = "stylesheet_" + resources.stylesheets.size + ".css";
@@ -149,7 +148,6 @@ function getProcessorHelperClass(utilInstance) {
149
148
  scoped,
150
149
  mediaText
151
150
  };
152
- stylesheets.set({ urlNode }, stylesheetInfo);
153
151
  const content = await this.getStylesheetContent(resourceURL, options);
154
152
  stylesheetInfo.url = resourceURL = content.resourceURL;
155
153
  const existingStylesheet = Array.from(stylesheets).find(([, stylesheetInfo]) => stylesheetInfo.resourceURL == resourceURL);
@@ -159,6 +157,7 @@ function getProcessorHelperClass(utilInstance) {
159
157
  content.data = getUpdatedResourceContent(resourceURL, content, options);
160
158
  stylesheetInfo.stylesheet = cssTree.parse(content.data, { context: "stylesheet", parseCustomProperty: true });
161
159
  await this.resolveImportURLs(stylesheetInfo, resourceURL, options, workStylesheet, resources, stylesheets);
160
+ stylesheets.set({ urlNode }, stylesheetInfo);
162
161
  }
163
162
  }
164
163
  }
@@ -178,7 +177,6 @@ function getProcessorHelperClass(utilInstance) {
178
177
  mediaText: stylesheetInfo.mediaText
179
178
  });
180
179
  } else {
181
- stylesheets.set({ element }, stylesheetInfo);
182
180
  const content = await util.getContent(resourceURL, {
183
181
  maxResourceSize: options.maxResourceSize,
184
182
  maxResourceSizeEnabled: options.maxResourceSizeEnabled,
@@ -207,6 +205,7 @@ function getProcessorHelperClass(utilInstance) {
207
205
  content.data = getUpdatedResourceContent(content.resourceURL, content, options);
208
206
  stylesheetInfo.stylesheet = cssTree.parse(content.data, { context: "stylesheet", parseCustomProperty: true });
209
207
  await this.resolveImportURLs(stylesheetInfo, resourceURL, options, workStylesheet, resources, stylesheets);
208
+ stylesheets.set({ element }, stylesheetInfo);
210
209
  }
211
210
  }
212
211
  }
@@ -281,8 +280,9 @@ function getProcessorHelperClass(utilInstance) {
281
280
  // ignored
282
281
  }
283
282
  if (testValidURL(resourceURL)) {
283
+ const declaredContentType = ["OBJECT", "EMBED"].includes(resourceElement.tagName.toUpperCase()) ? resourceElement.getAttribute("type") : "";
284
284
  let { content, indexResource, extension, contentType } = await batchRequest.addURL(resourceURL,
285
- { asBinary: true, expectedType });
285
+ { asBinary: true, expectedType, contentType: declaredContentType });
286
286
  if (originURL) {
287
287
  if (this.testEmptyResource(content)) {
288
288
  try {
@@ -295,6 +295,7 @@ function getProcessorHelperClass(utilInstance) {
295
295
  content = (await util.getContent(resourceURL, {
296
296
  asBinary: true,
297
297
  expectedType,
298
+ contentType: declaredContentType,
298
299
  maxResourceSize: options.maxResourceSize,
299
300
  maxResourceSizeEnabled: options.maxResourceSizeEnabled,
300
301
  frameId: options.windowId,
package/core/util.js CHANGED
@@ -286,7 +286,10 @@ function getInstance(utilOptions) {
286
286
  // ignored
287
287
  }
288
288
  if (!contentType || (contentType == CONTENT_TYPE_OCTET_STREAM && options.asBinary)) {
289
- contentType = guessMIMEType(options.expectedType, buffer, options.asBinary);
289
+ contentType = guessMIMEType(options.expectedType, buffer);
290
+ if (!contentType) {
291
+ contentType = options.contentType ? options.contentType : options.asBinary ? CONTENT_TYPE_OCTET_STREAM : "";
292
+ }
290
293
  }
291
294
  if (!charset && options.charset) {
292
295
  charset = options.charset;
@@ -366,7 +369,7 @@ async function getFetchResponse(resourceURL, options, data, charset, contentType
366
369
  return { data, resourceURL, charset, contentType };
367
370
  }
368
371
 
369
- function guessMIMEType(expectedType, buffer, asBinary) {
372
+ function guessMIMEType(expectedType, buffer) {
370
373
  if (expectedType == "image") {
371
374
  if (compareBytes([255, 255, 255, 255], [0, 0, 1, 0])) {
372
375
  return "image/x-icon";
@@ -463,7 +466,6 @@ function guessMIMEType(expectedType, buffer, asBinary) {
463
466
  return "audio/3gpp";
464
467
  }
465
468
  }
466
- return asBinary ? CONTENT_TYPE_OCTET_STREAM : "";
467
469
 
468
470
  function compareBytes(mask, pattern) {
469
471
  let patternMatch = true, index = 0;
@@ -16900,8 +16900,9 @@ async function evalTemplate(template = "", options, content, doc, dontReplaceSla
16900
16900
  const dontReplaceSlashIfUndefined = dontReplaceSlash === undefined ? true : dontReplaceSlash;
16901
16901
  const urlSuffix = PUBLIC_SUFFIX_LIST.find(urlTopLevelDomainName => url.hostname.endsWith("." + urlTopLevelDomainName) && urlTopLevelDomainName);
16902
16902
  const urlDomainName = urlSuffix ? url.hostname.substring(0, url.hostname.length - urlSuffix.length - 1) : url.hostname;
16903
- let urlSubDomains = urlDomainName.substring(0, urlDomainName.lastIndexOf("."));
16904
- const urlDomain = urlDomainName.substring(urlSubDomains.length + 1);
16903
+ const indexLastDotCharacter = urlDomainName.lastIndexOf(".");
16904
+ let urlSubDomains = urlDomainName.substring(0, indexLastDotCharacter == -1 ? 0 : indexLastDotCharacter);
16905
+ const urlDomain = urlDomainName.substring(urlSubDomains.length ? urlSubDomains.length + 1 : 0);
16905
16906
  const urlRoot = urlDomain + "." + urlSuffix;
16906
16907
  if (urlSubDomains.startsWith("www.")) {
16907
16908
  urlSubDomains = urlSubDomains.substring(4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-core",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "SingleFile Core",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",
@@ -62,7 +62,8 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
62
62
  "ttf": "font/ttf",
63
63
  "woff": "font/woff",
64
64
  "woff2": "font/woff2",
65
- "eot": "application/vnd.ms-fontobject"
65
+ "eot": "application/vnd.ms-fontobject",
66
+ "pdf": "application/pdf"
66
67
  };
67
68
  const REGEXP_MATCH_STYLESHEET = /stylesheet_[0-9]+\.css/;
68
69
  const REGEXP_MATCH_SCRIPT = /scripts\/[0-9]+\.js/;