single-file-core 1.2.24 → 1.2.26

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.
@@ -28,6 +28,7 @@ import { parse } from "./template-parser.js";
28
28
  // eslint-disable-next-line quotes
29
29
  const DEFAULT_REPLACED_CHARACTERS = ["~", "+", "\\\\", "?", "%", "*", ":", "|", '"', "<", ">", "\x00-\x1f", "\x7F"];
30
30
  const DEFAULT_REPLACEMENT_CHARACTER = "_";
31
+ const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
31
32
 
32
33
  const EMOJI_NAMES = {
33
34
  "😀": "grinning-face",
@@ -16867,7 +16868,7 @@ export { formatFilename, evalTemplate };
16867
16868
  async function formatFilename(content, doc, options, util) {
16868
16869
  let filename = (await evalTemplate(options.filenameTemplate, options, util, content, doc)) || "";
16869
16870
  if (options.replaceEmojisInFilename) {
16870
- EMOJIS.forEach(emoji => (filename = filename.replaceAll(emoji, " _" + EMOJI_NAMES[emoji] + "_ ")));
16871
+ EMOJIS.forEach(emoji => (filename = replaceAll(filename, emoji, " _" + EMOJI_NAMES[emoji] + "_ ")));
16871
16872
  }
16872
16873
  const replacementCharacter = options.filenameReplacementCharacter;
16873
16874
  filename = getValidFilename(filename, options.filenameReplacedCharacters, replacementCharacter);
@@ -16883,6 +16884,9 @@ async function formatFilename(content, doc, options, util) {
16883
16884
  if (!filename) {
16884
16885
  filename = "Unnamed page";
16885
16886
  }
16887
+ if (filename.startsWith(".")) {
16888
+ filename = "Unnamed page" + filename;
16889
+ }
16886
16890
  return filename.trim();
16887
16891
  }
16888
16892
 
@@ -16967,7 +16971,7 @@ async function evalTemplate(template = "", options, util, content, doc, dontRepl
16967
16971
  "lowercase": value => value.toLowerCase(),
16968
16972
  "uppercase": value => value.toUpperCase(),
16969
16973
  "capitalize": value => value.charAt(0).toUpperCase() + value.slice(1),
16970
- "replace": (value, searchValue, replaceValue) => searchValue && replaceValue ? value.replaceAll(searchValue, replaceValue) : value,
16974
+ "replace": (value, searchValue, replaceValue) => searchValue && replaceValue ? replaceAll(value, searchValue, replaceValue) : value,
16971
16975
  "trim": value => value.trim(),
16972
16976
  "trim-left": value => value.trimLeft(),
16973
16977
  "trim-right": value => value.trimRight(),
@@ -17009,17 +17013,19 @@ async function evalTemplate(template = "", options, util, content, doc, dontRepl
17009
17013
  return element && element.getAttribute(attribute);
17010
17014
  };
17011
17015
  }
17012
- template = template.replaceAll("\\%", "\\\\%");
17013
- template = template.replaceAll("\\{", "\\\\{");
17014
- template = template.replaceAll("\\|", "\\\\|");
17015
- template = template.replaceAll("\\>", "\\\\>");
17016
+ template = replaceAll(template, "\\%", "\\\\%");
17017
+ template = replaceAll(template, "\\{", "\\\\{");
17018
+ template = replaceAll(template, "\\|", "\\\\|");
17019
+ template = replaceAll(template, "\\>", "\\\\>");
17016
17020
  const result = (await parse(template, {
17017
17021
  async callFunction(name, [argument, optionalArguments], lengthData) {
17018
17022
  const fn = functions[name];
17019
17023
  if (fn) {
17020
17024
  argument = argument.replace(/\\\\(.)/g, "$1");
17021
- optionalArguments = optionalArguments.map(argument => argument.replace(/\\\\(.)/g, "$1"));
17022
- if (argument != undefined && argument != null && argument != "") {
17025
+ optionalArguments = optionalArguments
17026
+ .map(argument => argument.replace(/\\\\(.)/g, "$1"))
17027
+ .filter(argument => argument != undefined && argument != null && argument != "");
17028
+ if ((argument != undefined && argument != null && argument != "") || optionalArguments.length > 0) {
17023
17029
  try {
17024
17030
  return await getValue(() => fn(argument, ...optionalArguments), true, options.filenameReplacementCharacter, lengthData);
17025
17031
  } catch (error) {
@@ -17042,10 +17048,10 @@ async function evalTemplate(template = "", options, util, content, doc, dontRepl
17042
17048
  }
17043
17049
  }));
17044
17050
  let resultString = result.join("");
17045
- resultString = resultString.replaceAll("\\\\%", "%");
17046
- resultString = resultString.replaceAll("\\\\{", "{");
17047
- resultString = resultString.replaceAll("\\\\|", "|");
17048
- resultString = resultString.replaceAll("\\\\>", ">");
17051
+ resultString = replaceAll(resultString, "\\\\%", "%");
17052
+ resultString = replaceAll(resultString, "\\\\{", "{");
17053
+ resultString = replaceAll(resultString, "\\\\|", "|");
17054
+ resultString = replaceAll(resultString, "\\\\>", ">");
17049
17055
  return resultString;
17050
17056
 
17051
17057
  function addDateVariables(date, prefix = "") {
@@ -17072,6 +17078,15 @@ async function evalTemplate(template = "", options, util, content, doc, dontRepl
17072
17078
  }
17073
17079
  }
17074
17080
 
17081
+ function replaceAll(string, search, replacement) {
17082
+ if (typeof string.replaceAll == "function") {
17083
+ return string.replaceAll(search, replacement);
17084
+ } else {
17085
+ const searchRegExp = new RegExp(search.replace(REGEXP_ESCAPE, "\\$1"), "g");
17086
+ return string.replace(searchRegExp, replacement);
17087
+ }
17088
+ }
17089
+
17075
17090
  async function getValue(valueGetter, dontReplaceSlash, replacementCharacter, lengthData) {
17076
17091
  const { maxLength, maxCharLength } = extractMaxLength(lengthData);
17077
17092
  let value = (await valueGetter()) || "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "single-file-core",
3
- "version": "1.2.24",
3
+ "version": "1.2.26",
4
4
  "description": "SingleFile Core",
5
5
  "author": "Gildas Lormeau",
6
6
  "license": "AGPL-3.0-or-later",
@@ -70,6 +70,8 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
70
70
  const REGEXP_MATCH_INDEX = /index\.html$/;
71
71
  const REGEXP_MATCH_FRAMES = /frames\//;
72
72
  const CHARSET_UTF8 = ";charset=utf-8";
73
+ const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
74
+
73
75
  if (Array.isArray(content)) {
74
76
  content = new Blob([new Uint8Array(content)]);
75
77
  }
@@ -142,7 +144,7 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
142
144
  const position = textContent.indexOf(relativeFilename);
143
145
  if (position != -1) {
144
146
  parentResources.push(resourceFilename);
145
- textContent = textContent.replaceAll(relativeFilename, content);
147
+ textContent = replaceAll(textContent, relativeFilename, content);
146
148
  }
147
149
  }
148
150
  }
@@ -175,4 +177,13 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
175
177
  reader.onerror = reject;
176
178
  });
177
179
  }
180
+
181
+ function replaceAll(string, search, replacement) {
182
+ if (typeof string.replaceAll == "function") {
183
+ return string.replaceAll(search, replacement);
184
+ } else {
185
+ const searchRegExp = new RegExp(search.replace(REGEXP_ESCAPE, "\\$1"), "g");
186
+ return string.replace(searchRegExp, replacement);
187
+ }
188
+ }
178
189
  }
@@ -21,7 +21,7 @@
21
21
  * Source.
22
22
  */
23
23
 
24
- /* global globalThis, FileReader, TextDecoder, Node */
24
+ /* global globalThis, FileReader, Node */
25
25
 
26
26
  import {
27
27
  configure,
@@ -85,10 +85,11 @@ async function process(pageData, options, lastModDate = new Date()) {
85
85
  const substitutionsLF = [];
86
86
  if (options.extractDataFromPage) {
87
87
  if (!options.extractDataFromPageTags) {
88
- const textContent = new TextDecoder().decode(data);
88
+ let textContent = "";
89
+ data.slice(startOffset).forEach(charCode => textContent += String.fromCharCode(charCode));
89
90
  const matchEndTagComment = textContent.match(/-->/i);
90
91
  if (matchEndTagComment) {
91
- return findExtraDataTags(data, pageData, options, lastModDate);
92
+ return findExtraDataTags(textContent, pageData, options, lastModDate);
92
93
  }
93
94
  }
94
95
  for (let index = 0; index < data.length; index++) {
@@ -218,12 +219,11 @@ async function prependHTMLData(pageData, zipDataWriter, script, options) {
218
219
  return extraDataOffset;
219
220
  }
220
221
 
221
- function findExtraDataTags(data, pageData, options, lastModDate, indexExtractDataFromPageTags = 0) {
222
- const textContent = new TextDecoder().decode(data);
222
+ function findExtraDataTags(textContent, pageData, options, lastModDate, indexExtractDataFromPageTags = 0) {
223
223
  const matchEndTag = textContent.match(EXTRA_DATA_REGEXPS[indexExtractDataFromPageTags]);
224
224
  if (matchEndTag) {
225
225
  if (indexExtractDataFromPageTags < EXTRA_DATA_TAGS.length - 1) {
226
- return findExtraDataTags(data, pageData, options, lastModDate, indexExtractDataFromPageTags + 1);
226
+ return findExtraDataTags(textContent, pageData, options, lastModDate, indexExtractDataFromPageTags + 1);
227
227
  } else {
228
228
  options.extractDataFromPage = false;
229
229
  return process(pageData, options, lastModDate);
package/single-file.js CHANGED
@@ -111,6 +111,7 @@ async function getPageData(options = {}, initOptions, doc = globalThis.document,
111
111
  createRootDirectory: options.createRootDirectory,
112
112
  selfExtractingArchive: options.selfExtractingArchive,
113
113
  extractDataFromPage: options.extractDataFromPage,
114
+ preventAppendedData: options.preventAppendedData,
114
115
  insertCanonicalLink: options.insertCanonicalLink,
115
116
  insertMetaNoIndex: options.insertMetaNoIndex,
116
117
  password: options.password,