single-file-core 1.2.8 → 1.2.10
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.
|
@@ -125,6 +125,7 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
125
125
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("embed[src*=\".pdf\"]"), "src", baseURI, options, null, resources, styles, batchRequest));
|
|
126
126
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("audio[src], audio > source[src]"), "src", baseURI, options, "audio", resources, styles, batchRequest));
|
|
127
127
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("video[src], video > source[src]"), "src", baseURI, options, "video", resources, styles, batchRequest));
|
|
128
|
+
resourcePromises.push(this.processAttribute(doc.querySelectorAll("audio track[src], video track[src]"), "src", baseURI, options, null, resources, styles, batchRequest));
|
|
128
129
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("model[src]"), "src", baseURI, options, null, resources, styles, batchRequest));
|
|
129
130
|
await Promise.all(resourcePromises);
|
|
130
131
|
if (options.saveFavicon) {
|
|
@@ -382,7 +383,7 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
382
383
|
resourceElement.setAttribute("data-sf-original-" + attributeName, resourceURL);
|
|
383
384
|
}
|
|
384
385
|
delete resourceElement.dataset.singleFileOriginURL;
|
|
385
|
-
if (!options["block" + expectedType.charAt(0).toUpperCase() + expectedType.substring(1) + "s"]) {
|
|
386
|
+
if (!expectedType || !options["block" + expectedType.charAt(0).toUpperCase() + expectedType.substring(1) + "s"]) {
|
|
386
387
|
if (!testIgnoredPath(resourceURL)) {
|
|
387
388
|
setAttributeEmpty(resourceElement, attributeName, expectedType);
|
|
388
389
|
if (testValidPath(resourceURL)) {
|
|
@@ -114,6 +114,7 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
114
114
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("embed[src*=\".pdf\"]"), "src", baseURI, options, null, resources, batchRequest));
|
|
115
115
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("audio[src], audio > source[src]"), "src", baseURI, options, "audio", resources, batchRequest));
|
|
116
116
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("video[src], video > source[src]"), "src", baseURI, options, "video", resources, batchRequest));
|
|
117
|
+
resourcePromises.push(this.processAttribute(doc.querySelectorAll("audio track[src], video track[src]"), "src", baseURI, options, null, resources, batchRequest));
|
|
117
118
|
resourcePromises.push(this.processAttribute(doc.querySelectorAll("model[src]"), "src", baseURI, options, null, resources, batchRequest));
|
|
118
119
|
await Promise.all(resourcePromises);
|
|
119
120
|
if (options.saveFavicon) {
|
|
@@ -360,7 +361,7 @@ function getProcessorHelperClass(utilInstance) {
|
|
|
360
361
|
resourceElement.setAttribute("data-sf-original-" + attributeName, resourceURL);
|
|
361
362
|
}
|
|
362
363
|
delete resourceElement.dataset.singleFileOriginURL;
|
|
363
|
-
if (!options["block" + expectedType.charAt(0).toUpperCase() + expectedType.substring(1) + "s"]) {
|
|
364
|
+
if (!expectedType || !options["block" + expectedType.charAt(0).toUpperCase() + expectedType.substring(1) + "s"]) {
|
|
364
365
|
if (!testIgnoredPath(resourceURL)) {
|
|
365
366
|
setAttributeEmpty(resourceElement, attributeName, expectedType);
|
|
366
367
|
if (testValidPath(resourceURL)) {
|
package/package.json
CHANGED
|
@@ -54,93 +54,100 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
|
|
|
54
54
|
"wav": "audio/wav",
|
|
55
55
|
"weba": "audio/webm"
|
|
56
56
|
};
|
|
57
|
+
const REGEXP_MATCH_STYLESHEET = /stylesheet_[0-9]+\.css/;
|
|
58
|
+
const REGEXP_MATCH_SCRIPT = /scripts\/[0-9]+\.js/;
|
|
59
|
+
const REGEXP_MATCH_ROOT_INDEX = /^([0-9_]+\/)?index\.html$/;
|
|
60
|
+
const REGEXP_MATCH_INDEX = /index\.html$/;
|
|
61
|
+
const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
|
|
62
|
+
const CHARSET_UTF8 = ";charset=utf-8";
|
|
57
63
|
if (Array.isArray(content)) {
|
|
58
64
|
content = new Blob([new Uint8Array(content)]);
|
|
59
65
|
}
|
|
60
66
|
zip.configure(zipOptions);
|
|
61
67
|
const blobReader = new zip.BlobReader(content);
|
|
62
|
-
let resources = [];
|
|
63
68
|
const zipReader = new zip.ZipReader(blobReader);
|
|
64
69
|
const entries = await zipReader.getEntries();
|
|
65
70
|
const options = { password };
|
|
71
|
+
let docContent, origDocContent, url, resources = [];
|
|
66
72
|
await Promise.all(entries.map(async entry => {
|
|
67
|
-
|
|
73
|
+
const { filename } = entry;
|
|
74
|
+
let dataWriter, content, textContent, mimeType;
|
|
68
75
|
if (!options.password && entry.encrypted) {
|
|
69
76
|
options.password = prompt("Please enter the password to view the page");
|
|
70
77
|
}
|
|
71
|
-
|
|
72
|
-
let mimeType;
|
|
73
|
-
if (entry.filename.match(/index\.html$/) || entry.filename.match(/stylesheet_[0-9]+\.css/) || entry.filename.match(/scripts\/[0-9]+\.js/)) {
|
|
78
|
+
if (filename.match(REGEXP_MATCH_INDEX) || filename.match(REGEXP_MATCH_STYLESHEET) || filename.match(REGEXP_MATCH_SCRIPT)) {
|
|
74
79
|
dataWriter = new zip.TextWriter();
|
|
75
80
|
textContent = await entry.getData(dataWriter, options);
|
|
76
|
-
if (
|
|
77
|
-
mimeType = "text/html
|
|
81
|
+
if (filename.match(REGEXP_MATCH_INDEX)) {
|
|
82
|
+
mimeType = "text/html" + CHARSET_UTF8;
|
|
78
83
|
} else {
|
|
79
|
-
if (
|
|
80
|
-
mimeType = "text/css
|
|
81
|
-
} else if (
|
|
82
|
-
mimeType = "text/javascript
|
|
84
|
+
if (filename.match(REGEXP_MATCH_STYLESHEET)) {
|
|
85
|
+
mimeType = "text/css" + CHARSET_UTF8;
|
|
86
|
+
} else if (filename.match(REGEXP_MATCH_SCRIPT)) {
|
|
87
|
+
mimeType = "text/javascript" + CHARSET_UTF8;
|
|
83
88
|
}
|
|
84
89
|
if (textContent !== undefined) {
|
|
85
|
-
content =
|
|
90
|
+
content = await getDataURI(textContent, mimeType);
|
|
86
91
|
} else {
|
|
87
92
|
content = "data:text/plain,";
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
} else {
|
|
91
|
-
const extension =
|
|
96
|
+
const extension = filename.match(/\.([^.]+)/);
|
|
92
97
|
if (extension && extension[1] && KNOWN_MIMETYPES[extension[1]]) {
|
|
93
98
|
mimeType = KNOWN_MIMETYPES[extension[1]];
|
|
94
99
|
} else {
|
|
95
100
|
mimeType = "application/octet-stream";
|
|
96
101
|
}
|
|
97
|
-
if (
|
|
102
|
+
if (filename.match(/frames\//) || noBlobURL) {
|
|
98
103
|
content = await entry.getData(new zip.Data64URIWriter(mimeType), options);
|
|
99
104
|
} else {
|
|
100
|
-
blob = await entry.getData(new zip.BlobWriter(mimeType), options);
|
|
105
|
+
const blob = await entry.getData(new zip.BlobWriter(mimeType), options);
|
|
101
106
|
content = URL.createObjectURL(blob);
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
|
-
|
|
109
|
+
const name = entry.filename.match(/^([0-9_]+\/)?(.*)$/)[2];
|
|
110
|
+
resources.push({ filename: entry.filename, name, url: entry.comment, content, mimeType, textContent, parentResources: [] });
|
|
105
111
|
}));
|
|
106
112
|
await zipReader.close();
|
|
107
|
-
let docContent, origDocContent, url;
|
|
108
113
|
resources = resources.sort((resourceLeft, resourceRight) => resourceRight.filename.length - resourceLeft.filename.length);
|
|
109
|
-
const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
|
|
110
114
|
for (const resource of resources) {
|
|
111
|
-
|
|
115
|
+
let { textContent, mimeType, filename } = resource;
|
|
116
|
+
if (textContent !== undefined) {
|
|
112
117
|
let prefixPath = "";
|
|
113
|
-
const prefixPathMatch =
|
|
118
|
+
const prefixPathMatch = filename.match(/(.*\/)[^/]+$/);
|
|
114
119
|
if (prefixPathMatch && prefixPathMatch[1]) {
|
|
115
120
|
prefixPath = prefixPathMatch[1];
|
|
116
121
|
}
|
|
117
|
-
if (
|
|
118
|
-
origDocContent =
|
|
122
|
+
if (filename.match(REGEXP_MATCH_ROOT_INDEX)) {
|
|
123
|
+
origDocContent = textContent;
|
|
119
124
|
}
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
if (!filename.match(REGEXP_MATCH_SCRIPT)) {
|
|
126
|
+
const resourceFilename = filename;
|
|
122
127
|
await Promise.all(resources.map(async innerResource => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
+
const { filename, parentResources, content } = innerResource;
|
|
129
|
+
if (filename.startsWith(prefixPath) && filename != resourceFilename) {
|
|
130
|
+
const relativeFilename = filename.substring(prefixPath.length);
|
|
131
|
+
if (!relativeFilename.match(/manifest\.json$/)) {
|
|
132
|
+
const searchRegExp = new RegExp(relativeFilename.replace(REGEXP_ESCAPE, "\\$1"), "g");
|
|
133
|
+
const position = textContent.search(searchRegExp);
|
|
128
134
|
if (position != -1) {
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
parentResources.push(resourceFilename);
|
|
136
|
+
textContent = textContent.replace(searchRegExp, content);
|
|
131
137
|
}
|
|
132
138
|
}
|
|
133
139
|
}
|
|
134
140
|
}));
|
|
135
|
-
resource.content = await getDataURI(
|
|
141
|
+
resource.content = await getDataURI(textContent, mimeType);
|
|
142
|
+
resource.textContent = textContent;
|
|
136
143
|
}
|
|
137
|
-
if (
|
|
144
|
+
if (filename.match(REGEXP_MATCH_INDEX)) {
|
|
138
145
|
if (shadowRootScriptURL) {
|
|
139
|
-
resource.textContent =
|
|
146
|
+
resource.textContent = textContent.replace(/<script data-template-shadow-root.*<\/script>/g, "<script data-template-shadow-root src=" + shadowRootScriptURL + "></" + "script>");
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
|
-
if (
|
|
143
|
-
docContent =
|
|
149
|
+
if (filename.match(REGEXP_MATCH_ROOT_INDEX)) {
|
|
150
|
+
docContent = textContent;
|
|
144
151
|
url = resource.url;
|
|
145
152
|
}
|
|
146
153
|
}
|
|
@@ -151,8 +158,8 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
|
|
|
151
158
|
const reader = new FileReader();
|
|
152
159
|
reader.readAsDataURL(new Blob([textContent], { type: mimeType }));
|
|
153
160
|
return new Promise((resolve, reject) => {
|
|
154
|
-
reader.
|
|
155
|
-
reader.
|
|
161
|
+
reader.onload = () => resolve(reader.result);
|
|
162
|
+
reader.onerror = reject;
|
|
156
163
|
});
|
|
157
164
|
}
|
|
158
165
|
}
|