single-file-core 1.2.8 → 1.2.9
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,99 @@ 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
|
-
resources.push({ filename: entry.filename,
|
|
109
|
+
resources.push({ filename: entry.filename, url: entry.comment, content, mimeType, textContent, parentResources: [] });
|
|
105
110
|
}));
|
|
106
111
|
await zipReader.close();
|
|
107
|
-
let docContent, origDocContent, url;
|
|
108
112
|
resources = resources.sort((resourceLeft, resourceRight) => resourceRight.filename.length - resourceLeft.filename.length);
|
|
109
|
-
const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
|
|
110
113
|
for (const resource of resources) {
|
|
111
|
-
|
|
114
|
+
let { textContent, mimeType, filename } = resource;
|
|
115
|
+
if (textContent !== undefined) {
|
|
112
116
|
let prefixPath = "";
|
|
113
|
-
const prefixPathMatch =
|
|
117
|
+
const prefixPathMatch = filename.match(/(.*\/)[^/]+$/);
|
|
114
118
|
if (prefixPathMatch && prefixPathMatch[1]) {
|
|
115
119
|
prefixPath = prefixPathMatch[1];
|
|
116
120
|
}
|
|
117
|
-
if (
|
|
118
|
-
origDocContent =
|
|
121
|
+
if (filename.match(REGEXP_MATCH_ROOT_INDEX)) {
|
|
122
|
+
origDocContent = textContent;
|
|
119
123
|
}
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
if (!filename.match(REGEXP_MATCH_SCRIPT)) {
|
|
125
|
+
const resourceFilename = filename;
|
|
122
126
|
await Promise.all(resources.map(async innerResource => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
127
|
+
const { filename, parentResources, content } = innerResource;
|
|
128
|
+
if (filename.startsWith(prefixPath) && filename != resourceFilename) {
|
|
129
|
+
const relativeFilename = filename.substring(prefixPath.length);
|
|
130
|
+
if (!relativeFilename.match(/manifest\.json$/)) {
|
|
131
|
+
const searchRegExp = new RegExp(relativeFilename.replace(REGEXP_ESCAPE, "\\$1"), "g");
|
|
132
|
+
const position = textContent.search(searchRegExp);
|
|
128
133
|
if (position != -1) {
|
|
129
|
-
|
|
130
|
-
|
|
134
|
+
parentResources.push(resourceFilename);
|
|
135
|
+
textContent = textContent.replace(searchRegExp, content);
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
}));
|
|
135
|
-
resource.content = await getDataURI(
|
|
140
|
+
resource.content = await getDataURI(textContent, mimeType);
|
|
141
|
+
resource.textContent = textContent;
|
|
136
142
|
}
|
|
137
|
-
if (
|
|
143
|
+
if (filename.match(REGEXP_MATCH_INDEX)) {
|
|
138
144
|
if (shadowRootScriptURL) {
|
|
139
|
-
resource.textContent =
|
|
145
|
+
resource.textContent = textContent.replace(/<script data-template-shadow-root.*<\/script>/g, "<script data-template-shadow-root src=" + shadowRootScriptURL + "></" + "script>");
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
|
-
if (
|
|
143
|
-
docContent =
|
|
148
|
+
if (filename.match(REGEXP_MATCH_ROOT_INDEX)) {
|
|
149
|
+
docContent = textContent;
|
|
144
150
|
url = resource.url;
|
|
145
151
|
}
|
|
146
152
|
}
|
|
@@ -151,8 +157,8 @@ async function extract(content, { password, prompt = () => { }, shadowRootScript
|
|
|
151
157
|
const reader = new FileReader();
|
|
152
158
|
reader.readAsDataURL(new Blob([textContent], { type: mimeType }));
|
|
153
159
|
return new Promise((resolve, reject) => {
|
|
154
|
-
reader.
|
|
155
|
-
reader.
|
|
160
|
+
reader.onload = () => resolve(reader.result);
|
|
161
|
+
reader.onerror = reject;
|
|
156
162
|
});
|
|
157
163
|
}
|
|
158
164
|
}
|